Redraw UserArea while Dragging

On 02/04/2013 at 16:11, xxxxxxxx wrote:

Hello everybody,

i want my userarea to redraw while mousedragging, but I dont get it. Ive already managed to get into a dragging loop with updating mouse position. Ive found this ... >If one is designing a real element, for example a slider, one might also want to send regular messages to the parent dialog. These are sent with SendParentMessage() and appear as calls to Command() in the dialog, just as with any regular element:

     // Create an action message,   // with the user area's id:   var action = new(BaseContainer, BFM_ACTION);   action->SetData(BFM_ACTION_ID, GetId());      while(TRUE)   {     // Poll the mouse as above and draw the slider.        // Send a message to the parent dialog, so that     // it knows that the user is dragging the slider:     action->SetData(BFM_ACTION_INDRAG, TRUE);     SendParentMessage(action);   }      // Notify the dialog that the dragging is finished:   action->SetData(BFM_ACTION_INDRAG, FALSE);   SendParentMessage(action);

... but Im not able to translate to python.
Can anyone help?

My attempt:

state = c4d.BaseContainer()  
while self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, state) :  
  
      if state.GetLong(c4d.BFM_INPUT_VALUE)==0: break  
  
      mouse_x=state.GetLong(c4d.BFM_INPUT_X)  
      mouse_y=state.GetLong(c4d.BFM_INPUT_Y)  
  
      # Do Stuff  
  
      action = c4d.BaseContainer(c4d.BFM_ACTION)  
      action.SetLong(c4d.BFM_ACTION_ID, self.GetId())  
      action.SetLong(c4d.BFM_ACTION_INDRAG, True)  
      self.SendParentMessage(action)  
  
      self.Redraw()  
  
action.SetLong(c4d.BFM_ACTION_INDRAG, False)  
self.SendParentMessage(action)

Greetings
rown

On 03/04/2013 at 16:31, xxxxxxxx wrote:

I did it ...

import c4d  
from c4d import bitmaps, gui, plugins, utils  
import collections, os  
  
PLUGIN_ID = 10000056 #TestID only!!!!!!!!!!!!  
  
  
class Area(gui.GeUserArea) :  
  
  def DrawMsg(self, x1, y1, x2, y2, msg) :  
      state=c4d.BaseContainer()  
      action = c4d.BaseContainer(c4d.BFM_ACTION)  
      action.SetLong(c4d.BFM_ACTION_ID, self.GetId())  
  
      while self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, state) :  
        if state.GetLong(c4d.BFM_INPUT_VALUE)==0: break  
  
        x=state.GetLong(c4d.BFM_INPUT_X)  
        y=state.GetLong(c4d.BFM_INPUT_Y)  
  
        self.Draw(x,y)  
        action.SetLong(c4d.BFM_ACTION_INDRAG, True)  
        self.SendParentMessage(action)  
  
      action.SetLong(c4d.BFM_ACTION_INDRAG, False)  
      self.SendParentMessage(action)  
  
  def Draw(self, x, y) :  
      self.DrawSetPen(c4d.Vector(127.0/255))  
      self.DrawSetTextCol(c4d.Vector(255.0/255),c4d.Vector(0.0/255))  
  
      self.DrawRectangle(0,0,500,500)  
      self.DrawText("TEST", x, y-20, flags=c4d.DRAWTEXT_STD_ALIGN)  
  
      return True  
        
  def InputEvent(self, msg) :  
      self.Redraw()  
      return True  
  
class MyDialog(gui.GeDialog) :  
  
  def __init__(self, area) :  
      self.area = area  
  
  def CreateLayout(self) :  
      self.SetTitle("Table")  
  
      self.AddUserArea(1000, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT)  
      self.AttachUserArea(self.area, 1000)  
      self.GroupEnd()  
  
      return True  
  
  def Command(self, id, msg) :  
      print id  
      return True  
  
class Test(plugins.CommandData) :  
    
  area = Area()  
  dialog = None  
  
  def Execute(self, doc) :  
      if self.dialog is None: self.dialog = MyDialog(self.area)  
      return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=500, defaulth=500)  
  def RestoreLayout(self, sec_ref) :  
      if self.dialog is None: self.dialog = MyDialog(self.area)  
      return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)  
  
if __name__ == "__main__":  
   bmp = bitmaps.BaseBitmap()  
   dir, f = os.path.split(__file__)  
   fn = os.path.join(dir, "res", "icon.tif")  
   bmp.InitWith(fn)  
   plugins.RegisterCommandPlugin(id=PLUGIN_ID,   
                                str="Test01",  
                                info=0,  
                                help="Test01",   
                                dat=Test(),  
                                icon=bmp)

Since I added Command() in GeDialog it works. But it doesnt work well. If I remove 'print id' from Command() it doesnt work. And if I use 'GeUserArea.OffScreenOn([ x , y , w , h ])' it doesnt work.

On 03/04/2013 at 18:59, xxxxxxxx wrote:

I don't think we're allowed to use the overridden Draw() method with the user area.

This is a different way to write your code:

import c4d  
from c4d import bitmaps, gui, plugins, utils  
import collections, os  
  
PLUGIN_ID = 10000010 #TestID only!!!!!!!!!!!!  
  
class Area(gui.GeUserArea) :  
  
  def DrawMsg(self, x1, y1, x2, y2, msg) :   
  
      self.DrawSetPen(c4d.Vector(.2))                                  #Set the Background Color  
      self.DrawRectangle(x1, y1, x2, y2)                               #Draws the UA rectangle area  
        
      self.DrawSetPen(c4d.Vector(1,0,0))                               #Sets the color to red  
      self.DrawRectangle(80,80,100,100)                                #Draws a little rectangle in the UA  
        
      self.DrawSetTextCol(c4d.Vector(1,1,1), c4d.Vector(0,0,0))        #Sets the foreground & background color of the text  
      self.DrawText("Hello", 0, 0, flags=c4d.DRAWTEXT_STD_ALIGN)         #Draws the text at the coords 0x,0y  
        
  def InputEvent(self, msg) :  
   
      action = c4d.BaseContainer(c4d.BFM_ACTION)  
      action.SetLong(c4d.BFM_ACTION_ID, self.GetId())  
  
      while self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, msg) :    #While the left mouse button is held down  
        if msg.GetLong(c4d.BFM_INPUT_VALUE)==0: break  
  
        mx=msg.GetLong(c4d.BFM_INPUT_X)                         #Get the mouse coords.  
        my=msg.GetLong(c4d.BFM_INPUT_Y)   
        action.SetLong(c4d.BFM_ACTION_INDRAG, True)  
        self.SendParentMessage(action)                          #Sends a message to the parent dialog that the mouse is dragging in the UA  
        self.Redraw()                                           #Redraw while the left mouse button is held down  
  
      action.SetLong(c4d.BFM_ACTION_INDRAG, False)  
      self.SendParentMessage(action)                            #Sends a message to the parent dialog that the mouse has stopped dragging in the UA  
        
      return True  
        
  
class MyDialog(gui.GeDialog) :  
  
  def __init__(self, area) :  
      self.area = area  
  
  def CreateLayout(self) :  
      self.SetTitle("My UserArea")  
  
      self.AddUserArea(1000, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT)  
      self.AttachUserArea(self.area, 1000)  
      self.GroupEnd()  
  
      return True  
  
  def Command(self, id, msg) :  
      print id                     #Prints the ID of the UA  
      return True  
  
class Test(plugins.CommandData) :  
    
  area = Area()  
  dialog = None  
  
  def Execute(self, doc) :  
      if self.dialog is None: self.dialog = MyDialog(self.area)  
      return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=500, defaulth=500)  
  def RestoreLayout(self, sec_ref) :  
      if self.dialog is None: self.dialog = MyDialog(self.area)  
      return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)  
  
if __name__ == "__main__":  
   bmp = bitmaps.BaseBitmap()  
   dir, f = os.path.split(__file__)  
   fn = os.path.join(dir, "res", "icon.tif")  
   bmp.InitWith(fn)  
   plugins.RegisterCommandPlugin(id=PLUGIN_ID,   
                                str="Test01",  
                                info=0,  
                                help="Test01",   
                                dat=Test(),  
                                icon=bmp)

-ScottA

On 03/04/2013 at 23:21, xxxxxxxx wrote:

Scott, from what I see in your code, you are not moving the drawn content depending on the drag
offset? I may be wrong and didn't find it, though. Anyway, there is no "Draw()" method in the
GeUserArea class as far as I can tell.

Best,
-Niklas

On 04/04/2013 at 07:56, xxxxxxxx wrote:

His code does not have anything that moves the drawn content either.
I simply re-wrote his code in a more stable manner.
But if that's a problem. Here's an example that lets the user drag the text around in the UA with the left mouse button:

import c4d  
from c4d import bitmaps, gui, plugins, utils  
import collections, os  
  
PLUGIN_ID = 10000010 #TestID only!!!!!!!!!!!!  
  
class Area(gui.GeUserArea) :  
  
  xValue = 0  
  yValue = 0  
  
  def DrawMsg(self, x1, y1, x2, y2, msg) :   
  
      self.DrawSetPen(c4d.Vector(.2))                                  #Set the Background Color  
      self.DrawRectangle(x1, y1, x2, y2)                               #Draws the UA rectangle area  
        
      self.DrawSetPen(c4d.Vector(1,0,0))                               #Sets the color to red  
      self.DrawRectangle(80,80,100,100)                                #Draws a little rectangle in the UA  
        
      self.DrawSetTextCol(c4d.Vector(1,1,1), c4d.Vector(0,0,0))        #Sets the foreground & background color of the text  
      self.DrawText("Hello", self.xValue, self.yValue, flags=c4d.DRAWTEXT_STD_ALIGN)    #Draws the text at the current mouse coords  
        
  def InputEvent(self, msg) :  
   
      action = c4d.BaseContainer(c4d.BFM_ACTION)  
      action.SetLong(c4d.BFM_ACTION_ID, self.GetId())  
  
      while self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, msg) :    #While the left mouse button is held down  
        if msg.GetLong(c4d.BFM_INPUT_VALUE)==0: break  
  
        mouseX=msg.GetLong(c4d.BFM_INPUT_X)                     #Get the global mouse coords.  
        mouseY=msg.GetLong(c4d.BFM_INPUT_Y)  
        localPos = self.Global2Local()                          #Convert the mouse positions from global to local  
        mouseX += localPos['x']                                 #The mouse's local coords.  
        mouseY += localPos['y']  
       
        self.xValue = mouseX                                    #Class variables are set to same as mouse coords. so the DrawMsg() can use them  
        self.yValue = mouseY  
          
        action.SetLong(c4d.BFM_ACTION_INDRAG, True)  
        self.SendParentMessage(action)                          #Sends a message to the parent dialog that the mouse is dragging in the UA  
        self.Redraw()                                           #Redraw while the left mouse button is held down  
  
      action.SetLong(c4d.BFM_ACTION_INDRAG, False)  
      self.SendParentMessage(action)                            #Sends a message to the parent dialog that the mouse has stopped dragging in the UA  
        
      return True  
        
  
class MyDialog(gui.GeDialog) :  
  
  def __init__(self, area) :  
      self.area = area  
  
  def CreateLayout(self) :  
      self.SetTitle("My UserArea")  
  
      self.AddUserArea(1000, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT)  
      self.AttachUserArea(self.area, 1000)  
      self.GroupEnd()  
  
      return True  
  
  def Command(self, id, msg) :  
      print id                     #Prints the ID of the UA  
      return True  
  
class Test(plugins.CommandData) :  
    
  area = Area()  
  dialog = None  
  
  def Execute(self, doc) :  
      if self.dialog is None: self.dialog = MyDialog(self.area)  
      return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=500, defaulth=500)  
  def RestoreLayout(self, sec_ref) :  
      if self.dialog is None: self.dialog = MyDialog(self.area)  
      return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)  
  
if __name__ == "__main__":  
   bmp = bitmaps.BaseBitmap()  
   dir, f = os.path.split(__file__)  
   fn = os.path.join(dir, "res", "icon.tif")  
   bmp.InitWith(fn)  
   plugins.RegisterCommandPlugin(id=PLUGIN_ID,   
                                str="Test01",  
                                info=0,  
                                help="Test01",   
                                dat=Test(),  
                                icon=bmp)

-ScottA

On 04/04/2013 at 08:53, xxxxxxxx wrote:

Hey Scott,

it wasnt a problem. I thank you very much. It helps alot!

class Area(gui.GeUserArea) :  
  
  mx = 0  
  my = 0  
  
  def DrawMsg(self, x1, y1, x2, y2, msg) :   
      self.OffScreenOn(x1, y1, x2, y2)  
  
      self.DrawSetPen(c4d.Vector(.2))                                  #Set the Background Color  
      self.DrawRectangle(x1, y1, x2, y2)                               #Draws the UA rectangle area  
        
      self.DrawSetPen(c4d.Vector(1,0,0))                               #Sets the color to red  
      self.DrawRectangle(80,80,100,100)                                #Draws a little rectangle in the UA  
        
      self.DrawSetTextCol(c4d.Vector(1,1,1), c4d.Vector(0,0,0))        #Sets the foreground & background color of the text  
      self.DrawText("Hello", self.mx, self.my, flags=c4d.DRAWTEXT_STD_ALIGN)         #Draws the text at the coords 0x,0y  
        
  def InputEvent(self, msg) :  
      print "Input"  
   
      action = c4d.BaseContainer(c4d.BFM_ACTION)  
      action.SetLong(c4d.BFM_ACTION_ID, self.GetId())  
  
      while self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, msg) :    #While the left mouse button is held down  
        if msg.GetLong(c4d.BFM_INPUT_VALUE)==0: break  
  
        self.mx=msg.GetLong(c4d.BFM_INPUT_X)                         #Get the mouse coords.  
        self.my=msg.GetLong(c4d.BFM_INPUT_Y)   
        action.SetLong(c4d.BFM_ACTION_INDRAG, True)  
        self.SendParentMessage(action)                          #Sends a message to the parent dialog that the mouse is dragging in the UA  
        self.Redraw()                                           #Redraw while the left mouse button is held down  
  
      action.SetLong(c4d.BFM_ACTION_INDRAG, False)  
      self.SendParentMessage(action)                            #Sends a message to the parent dialog that the mouse has stopped dragging in the UA  
        
      return True  
  
  
class MyDialog(gui.GeDialog) :  
  
  def __init__(self, area) :  
      self.area = area  
  
  def CreateLayout(self) :  
      self.SetTitle("Table")  
  
      self.AddUserArea(1000, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT)  
      self.AttachUserArea(self.area, 1000)  
      self.GroupEnd()  
  
      return True  
  
  def Command(self, id, msg) :  
      return True

Greetings
rown

On 04/04/2013 at 08:54, xxxxxxxx wrote:

Originally posted by xxxxxxxx

His code does not have anything that moves the drawn content either.

It actually does:

    def DrawMsg(self, x1, y1, x2, y2, msg) :
    
    
            state=c4d.BaseContainer()  
          action = c4d.BaseContainer(c4d.BFM_ACTION)  
          action.SetLong(c4d.BFM_ACTION_ID, self.GetId())  
      
          while self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, state) :  
            if state.GetLong(c4d.BFM_INPUT_VALUE)==0: break  
      
     **           x=state.GetLong(c4d.BFM_INPUT_X)  
            y=state.GetLong(c4d.BFM_INPUT_Y)  
      
            self.Draw(x,y)**  
            action.SetLong(c4d.BFM_ACTION_INDRAG, True)  
            self.SendParentMessage(action)  
      
          action.SetLong(c4d.BFM_ACTION_INDRAG, False)  
          self.SendParentMessage(action)