Grabbing a GeUserArea when using InputEvent
-
Hello,
Please excuse my multiple posts about the GeUserArea in a Scrollgroup, but I was unable to find any information about the following in the documentation or the forum.By default, the GeUserArea in a ScrollGroup in this script can be grabbed by middle-mouse button clicking and dragging.
In my plugin however, I need to override the GeUserArea:InputEvent method. This seems to be where the grabbing functionality exists. How can I add the middle-mouse grab to my InputEvent override? Thank you!
import c4d import random from c4d import gui GADGET_ID_GEUSERAREA = 10000 SCROLL_ID = 10001 SLIDER_ID = 10002 class ExampleGeUserArea(c4d.gui.GeUserArea): width = 400 height = 500 bmp_cache = None def GetBitmap(self): bmp = c4d.bitmaps.BaseBitmap() bmp.Init(self.width, self.height) for h in range(self.height): for w in range(self.width): r = random.randint(0, 70) bmp.SetPixel(w, h, r, r, r) return bmp def DrawMsg(self, x1, y1, x2, y2, msg): self.OffScreenOn() self.SetClippingRegion(x1, y1, x2, y2) self.DrawSetPen(c4d.Vector(1, 0, 0)) self.DrawRectangle(x1, y1, x2, y2) if self.bmp_cache == None: self.bmp_cache = self.GetBitmap() self.DrawBitmap(self.bmp_cache, x1, y1, x2, y2, 0, 0, w=self.bmp_cache.GetBw(), h=self.bmp_cache.GetBh(), mode=c4d.BMP_NORMAL) """ def InputEvent(self, msg): #This stops the grab functionality device = msg.GetLong(c4d.BFM_INPUT_DEVICE) channel = msg.GetLong(c4d.BFM_INPUT_CHANNEL) if device == c4d.BFM_INPUT_MOUSE and channel == c4d.BFM_INPUT_MOUSEMIDDLE: print (device,channel) return True """ def Message(self, msg, result): # Catch the draw message to cancel it (return True) # and call ourself the DrawMsg with the dimension we expect if msg.GetId() == c4d.BFM_DRAW: self.DrawMsg(0, 0, self.width, self.height, c4d.BaseContainer()) return True return c4d.gui.GeUserArea.Message(self, msg, result) def GetMinSize(self): return self.width, self.height class ExampleDialog(c4d.gui.GeDialog): geUserArea = ExampleGeUserArea() def _centerAlignScrollGroup(self): _, _, sgw, sgh = self.GetItemDim(SCROLL_ID).values() _, _, uaw, uah = self.GetItemDim(GADGET_ID_GEUSERAREA).values() sax1, say1, sax2, say2 = self.GetVisibleArea(SCROLL_ID).values() dx, dy = sgw - (sax2 - sax1), sgh - (say2 - say1) # 16, 15 sgw -= dx sgh -= dy x, y = int((uaw - sgw) * .5), int((uah - sgh) * .5) self.SetVisibleArea(SCROLL_ID, x, y, x + sgw, y + sgh) def DrawUA(self, scale): self.geUserArea.width = int(400*scale) self.geUserArea.height = int(500*scale) self.LayoutChanged(SCROLL_ID) def CreateLayout(self): self.SetTitle("GeUserArea") if self.ScrollGroupBegin(SCROLL_ID, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, c4d.SCROLLGROUP_HORIZ | c4d.SCROLLGROUP_VERT): self.AddUserArea(GADGET_ID_GEUSERAREA, c4d.BFH_CENTER | c4d.BFH_SCALE | c4d.BFV_CENTER | c4d.BFV_SCALE, initw=gui.SizePix(400), inith=gui.SizePix(500)) self.AttachUserArea(self.geUserArea, GADGET_ID_GEUSERAREA) self.GroupEnd() self.AddEditSlider(SLIDER_ID, c4d.BFH_SCALEFIT | c4d.BFV_CENTER) return True def InitValues(self): self.SetFloat(SLIDER_ID, 1.0, min=0.01, max=2, step=0.01) self._centerAlignScrollGroup() return True def Command(self, id, msg): if id == SLIDER_ID: self.DrawUA(msg[c4d.BFM_ACTION_VALUE]) self._centerAlignScrollGroup() return True def main(): global dlg dlg = ExampleDialog() dlg.Open(c4d.DLG_TYPE_ASYNC, pluginid=1234567, defaultw=300, defaulth=300) if __name__ == "__main__": main()
-
Hi @blastframe,
thank you for reaching out to us. You are returning
True
in your commentedInputEvent
which consumes that event. So you have to returnFalse
and it will work like you want it to work. Although not being stated in the documents, I would also say a call to the base/super implementation would not hurt here for retrieving the return value.Cheers,
Ferdinand -
@ferdinand That was so simple, thank you!
How would I call the Base/Super Implementation in this case? Do you mean something like this?
def InputEvent(self, msg): # override code goes here return super().InputEvent(msg)
-
Hi @blastframe,
yes, that would be one, and probably the more modern way to do it. I personally like also an explicit call to the base implementation. I think it is more readable for someone else reading your code. But that is probably a rather subjective choice. So for clarity, I am speaking about something like this:
foo = bar * baz return c4d.gui.GeUserArea.InputEvent(self, msg)
There is of course the advantage of
super
taking care of calling the proper implementation(s) for you which is not taken care of by this approach, but you cannot have everything and in this case things are rather unambiguous for us hereCheers,
Ferdinand