Snap object in mouse input



  • On 05/01/2013 at 12:00, xxxxxxxx wrote:

    Hi :D

    i have used the free script code "SplineDraw" by   Scott Ayers
    http://sites.google.com/site/scottayersmedia/SplineDraw_Python.zip?attredirects=0

    My code, move the active object on mouse position.
    but the snap not work... 
    is there a way to snap the active object to another object?
    Thanks :D

    import c4d
    import os
    import time
    from c4d import gui, plugins, bitmaps
      
    PLUGIN_ID = 1028184
      
    #for GeLoadString values must match with the header file
    IDS_SPLINEDRAW = 50000
    MY_COMBOBUTTON = 100012
    MY_EDITNUMBER = 100013
      
      
    def ArrangeJoints(doc,obj) :        #This method will be used to arrange the drawn object in a parent->child tree later on
        obj = doc.GetFirstObject()
        child = obj.GetDown()
      
        while child:      
            child.SetBit(c4d.BIT_ACTIVE)
            m = child.GetMg()
            if child.GetNext() is not None:
                next = child.GetNext()
                child.InsertUnder(next)
                child.SetMg(m)          
            child = child.GetNext()
    		
      
    class SettingsDialog(gui.SubDialog) :
      
        myDict = {'Axis_Snap':0, 'spacevalue':0}     #Create a dictionary that will hold the names & values we'll use to plugin values into the gui items
      
        def __init__(self, arg) :
            self.myDict = arg
      
    		
        def InitDialog(self) :
            bc = c4d.plugins.GetToolData(c4d.documents.GetActiveDocument(),PLUGIN_ID)  #Gets the tools container data if needed
            if bc == None: return False
            return True		
      
        def CreateLayout(self) :
    	
            self.GroupBegin(id=1000, flags=c4d.BFH_SCALEFIT, cols=2, rows=1)
            self.GroupBorderSpace(10, 10, 10, 10)
            self.element = self.AddStaticText(id=1001, flags=c4d.BFH_MASK, initw=120, name="Drawing Mode", borderstyle=c4d.BORDER_NONE)
    		
            self.AddComboBox(MY_COMBOBUTTON, c4d.BFH_CENTER, 150, 15, specialalign=False) #Adds combobox button gizmo to the GUI
            self.AddChild(MY_COMBOBUTTON, 0, "FaceScreen&i" + str(c4d.RESOURCEIMAGE_MOVE) + "&")      #Adds the move icon to the first button option
            self.AddChild(MY_COMBOBUTTON, 1, "Lock Along Z" ) 
            self.AddChild(MY_COMBOBUTTON, 2, "Lock On Floor")
            self.AddChild(MY_COMBOBUTTON, 3, "Lock Along X") 
            self.SetLong(MY_COMBOBUTTON, self.myDict['Axis_Snap'])                                #Sets the button to the value of the Axis_Snap variable
      
            self.element = self.AddStaticText(id=1002, flags=c4d.BFH_MASK, initw=120, name="Spacing", borderstyle=c4d.BORDER_NONE)        
            self.AddEditNumberArrows(MY_EDITNUMBER, c4d.BFH_MASK, 20, 0)                         #width=20, height=0
            self.SetReal(MY_EDITNUMBER, self.myDict['spacevalue'], 0.0, 100, 1)		         #min=0.0, max=0.25, step=.01	
            self.GroupEnd()
            return True
    	
    		
        def InitValues(self) :
            self.SetLong(MY_COMBOBUTTON, 0) #Sets the combobox to the first option when plugin opens
            return True
      
        def Command(self, id, msg) :
      
            if id==MY_COMBOBUTTON: self.myDict['Axis_Snap'] = self.GetLong(MY_COMBOBUTTON)            #If the button is changed. Get the new value
            if id==MY_EDITNUMBER: self.myDict['spacevalue'] = self.GetReal(MY_EDITNUMBER)             #If the value is changed. Get the new value
            
            return True
      
      
    class SplineDraw(plugins.ToolData) :
        """Inherit from ToolData to create your own tool"""
      
        def __init__(self) :
            self.data = dict(Axis_Snap=0, spacevalue=0.0) 
    		
        
        def GetState(self, doc) :
            if doc.GetMode()==c4d.Mpaint: return 0
            return c4d.CMD_ENABLED
        
        
        def KeyboardInput(self, doc, data, bd, win, msg) :
            key = msg.GetLong(c4d.BFM_INPUT_CHANNEL)
            cstr = msg.GetString(c4d.BFM_INPUT_ASC)
            if key==c4d.KEY_ESC:
                #do what you want            
                #return True to signal that the key is processed
                return True
            return False
      
      
        def MouseInput(self, doc, data, bd, win, msg) :
            mx = msg[c4d.BFM_INPUT_X]
            my = msg[c4d.BFM_INPUT_Y]
      
            device = 0
            if msg[c4d.BFM_INPUT_CHANNEL]==c4d.BFM_INPUT_MOUSELEFT:
                device = c4d.KEY_MLEFT
            elif msg[c4d.BFM_INPUT_CHANNEL]==c4d.BFM_INPUT_MOUSERIGHT:
                 device = c4d.KEY_MRIGHT
            else:
                return True	
    			
    		
            axis = self.data['Axis_Snap']               #Get the Axis_Snap key name from myDict in the subdialog and assign it to a variable
            spacing = self.data['spacevalue']		    #Get the spacevalue key name from myDict in the subdialog and assign it to a variable
    		
    		#Spline stuff here 
            doc.StartUndo()	
            	
    		
            dx = 0.0
            dy = 0.0
            
            win.MouseDragStart(button=device, mx=int(mx), my=int(my), flags=c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE)
            result, dx, dy, channel = win.MouseDrag()
            while result==c4d.MOUSEDRAGRESULT_CONTINUE:
    		
                mx += dx
                my += dy             
     
                cursorpos = bd.SW(c4d.Vector(mx,my,400))     #screen to world conversion
    			
                if(axis == 1) : 
                    cursorpos.x = 0
    				
                elif(axis == 2) : 
                    cursorpos.y = 0                          #Constrain drawing along an axis based on the comboButton's value
    				
                elif(axis == 3) : 
                    cursorpos.z = 0	
    				
      
                joint = doc.GetActiveObject()             #Add joints which we will later convert to a spline
                doc.AddUndo(c4d.UNDOTYPE_NEW, joint)
                bc = joint.GetData() 
                joint.SetAbsPos(cursorpos)
                joint.SetData(bc)
                joint.Message(c4d.MSG_UPDATE)    
    			
      
                c4d.DrawViews(c4d.DA_ONLY_ACTIVE_VIEW|c4d.DA_NO_THREAD|c4d.DA_NO_ANIMATION)
                result, dx, dy, channel = win.MouseDrag()
            
            if win.MouseDragEnd()==c4d.MOUSEDRAGRESULT_ESCAPE:
            print "Hello World"
            c4d.EventAdd()
            return True
        
        
        def Draw(self, doc, data, bd, bh, bt, flags) : 
            return c4d.TOOLDRAW_HANDLES|c4d.TOOLDRAW_AXIS
        
        
        def GetCursorInfo(self, doc, data, bd, x, y, bc) :
            if bc.GetId()==c4d.BFM_CURSORINFO_REMOVE:
                return True
            
            bc.SetString(c4d.RESULT_BUBBLEHELP, plugins.GeLoadString(IDS_SPLINEDRAW))
            bc.SetLong(c4d.RESULT_CURSOR, c4d.MOUSE_SPLINETOOLS)
            return True
      
      
        def AllocSubDialog(self, bc) : 
            return SettingsDialog(self.data) #always return new instance(self.data)
      
      
    if __name__ == "__main__":
        bmp = bitmaps.BaseBitmap()
        dir, file = os.path.split(__file__)
        fn = os.path.join(dir, "res", "Icon.tif")
        bmp.InitWith(fn)
        plugins.RegisterToolPlugin(id=PLUGIN_ID, str="SplineDraw",info=0, icon=bmp, help="Statusbar Text",dat=SplineDraw()) 
    


  • On 08/01/2013 at 09:05, xxxxxxxx wrote:

    up ^_^



  • On 08/01/2013 at 09:19, xxxxxxxx wrote:

    What do you mean with "the snap does not work"? You are not even trying to snap the
    object, just setting it to the cursor position.

    joint.SetAbsPos(cursorpos)

    If you want to to snap to a grid with a spacing of 50 units (just for the sake of example), you
    need to adjust the position vector.

    def snap_value(value, step) :
          rest = value % step
          on_grid = value - rest

    if rest / float(step) >= 0.5:
              on_grid += step

    return on_grid

    def snap_grid(vector, gridsize) :
          vector = c4d.Vector(vector)
          vector.x = snap_value(vector.x, gridsize)
          vector.y = snap_value(vector.y, gridsize)
          vector.z = snap_value(vector.z, gridsize)
          return vector

    # ...

    gridsize = 50
      position = snap_grid(cursorpos)
      joint.SetAbsPos(position)

    See the full code here.

    -Niklas



  • On 08/01/2013 at 09:41, xxxxxxxx wrote:

    Thanks NiklasR, excuse my bad English ... I would like to know how to snap the active object on another object...



  • On 08/01/2013 at 09:45, xxxxxxxx wrote:

    And what do you mean with "snapping it to another object"? To what part of the other object?
    The other objects' position, points, surface, or whatever?

    -Nik



  • On 08/01/2013 at 09:56, xxxxxxxx wrote:

    Surface 👍



  • On 08/01/2013 at 10:15, xxxxxxxx wrote:

    You need to use the c4d.utils.GeRayCollider class to find an intersection on the surface of the
    destination-object, intersected by the line defined by the mouse-position in global space and
    the camera position.

    op = doc.GetActiveObject()
          op_next = op.GetNext()
          if not op_next:
              return True

    # Convert op_next to a polygon object.
          # Simplified here, just for demonstration purpose.
          op_next = op_next.GetCache()
          if not op_next or not op_next.CheckType(c4d.Opolygon) :
              print "Cache is not existent or is not a polygon object."
              return True
         
          win.MouseDragStart(button=device, mx=int(mx), my=int(my), flags=c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE)
          result, dx, dy, channel = win.MouseDrag()
          while result==c4d.MOUSEDRAGRESULT_CONTINUE:
              mx += dx
              my += dy            
     
              cursorpos = bd.SW(c4d.Vector(mx,my,500))     #screen to world conversion
              if(axis == 1) :
                  cursorpos.x = 0
              elif(axis == 2) :
                  cursorpos.y = 0                          #Constrain drawing along an axis based on the comboButton's value
              elif(axis == 3) :
                  cursorpos.z = 0

    cam_pos = bd.GetSceneCamera(doc).GetAbsPos()
              collider = c4d.utils.GeRayCollider()
              collider.Init(op_next)

    length = 500000
              direction = -(cam_pos - cursorpos).GetNormalized()

    did_intersect = collider.Intersect(cam_pos, direction, length)
              if did_intersect:
                  position = collider.GetNearestIntersection()['hitpos']
                  print "Intersection at", position
              else:
                  print "No intersection."
                  position = cursorpos

    doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
              op.SetAbsPos(position)
              op.Message(c4d.MSG_UPDATE)

    c4d.DrawViews(c4d.DA_ONLY_ACTIVE_VIEW|c4d.DA_NO_THREAD|c4d.DA_NO_ANIMATION)
              result, dx, dy, channel = win.MouseDrag()

    -Nik



  • On 08/01/2013 at 10:25, xxxxxxxx wrote:

    what do you mean with surface snapping :)

    1. snap onto the polygon polygon centers, which is basically just a weighted
    point snapping. get the vectors between your snap position and  the points of your
    snapping objects, select the three shortest vectors out of that list, get the polygon,
    use the points to calc the center.

    2. actually snap onto the closest point on a polygon (in a retopo fashion). you would 
    have to dig yourself through this. i have actually done this once, but i cannot share
    the code but i still have the links i relied on then. you hvae basically do everything like
    for no. 1 and then solve the the closest point in triangle problem.

    http://www.geometrictools.com/Documentation/DistancePoint3Triangle3.pdf
    http://www.gamedev.net/topic/552906-closest-point-on-triangle/
    http://www.blackpawn.com/texts/pointinpoly/default.html

    edit : ok that is also a way. i am usally not so good at this wrap your head arround math stuff, 
    but won't a camera 'normal' based snapping lead to funny results ?  the point which is sitting
    perpendicular on the viewplane does not have to be closest point, which at least I would
    associate with polygon snapping. i would call it view dependent obstacle snapping or something 
    like that :) or am i missing something here (again) ?



  • On 08/01/2013 at 10:42, xxxxxxxx wrote:

    Hi Ferdinand,

    I'm not sure what you mean with "camera 'normal' based snappin lead to funny results". Possibly
    I just should get some sleep, but would you mind to elaborate a little bit more on what you are
    talking about? 🙂

    Thanks for the resources, I've always been interested into that topic but these links are new
    to me!

    -Nik



  • On 08/01/2013 at 10:48, xxxxxxxx wrote:

    Thank you so much for your help, now everything is much more understandable ^_^

    Thanks NiklasR 👍 and Thanks littledevil 👍



  • On 08/01/2013 at 10:53, xxxxxxxx wrote:

    as I already said this might be based on a misconeption of your code,
    but this is what is was talking about. (awesome paint pic inc.) :

    the red line is what your code will return for my understanding, the green line is
    the closest point on surface. at least i would consider the red result as unwanted
    or 'funny'.

    edit : i hope this does make any sense for someone else than me :)



  • On 09/01/2013 at 11:33, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    You need to use the c4d.utils.GeRayCollider class to find an intersection on the surface of the
    destination-object, intersected by the line defined by the mouse-position in global space and
    the camera position.

    op = doc.GetActiveObject()
          op_next = op.GetNext()
          if not op_next:
              return True

    # Convert op_next to a polygon object.
          # Simplified here, just for demonstration purpose.
          op_next = op_next.GetCache()
          if not op_next or not op_next.CheckType(c4d.Opolygon) :
              print "Cache is not existent or is not a polygon object."
              return True
         
          win.MouseDragStart(button=device, mx=int(mx), my=int(my), flags=c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE)
          result, dx, dy, channel = win.MouseDrag()
          while result==c4d.MOUSEDRAGRESULT_CONTINUE:
              mx += dx
              my += dy            
     
              cursorpos = bd.SW(c4d.Vector(mx,my,500))     #screen to world conversion
              if(axis == 1) :
                  cursorpos.x = 0
              elif(axis == 2) :
                  cursorpos.y = 0                          #Constrain drawing along an axis based on the comboButton's value
              elif(axis == 3) :
                  cursorpos.z = 0

    cam_pos = bd.GetSceneCamera(doc).GetAbsPos()
              collider = c4d.utils.GeRayCollider()
              collider.Init(op_next)

    length = 500000
              direction = -(cam_pos - cursorpos).GetNormalized()

    did_intersect = collider.Intersect(cam_pos, direction, length)
              if did_intersect:
                  position = collider.GetNearestIntersection()['hitpos']
                  print "Intersection at", position
              else:
                  print "No intersection."
                  position = cursorpos

    doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
              op.SetAbsPos(position)
              op.Message(c4d.MSG_UPDATE)

    c4d.DrawViews(c4d.DA_ONLY_ACTIVE_VIEW|c4d.DA_NO_THREAD|c4d.DA_NO_ANIMATION)
              result, dx, dy, channel = win.MouseDrag()

    -Nik

    I again disorder 🙂
    I wanted that the active object changed the axis alignment, as the normal to the surfaced intersection?
    example:

    the current code

    my request:

    The axis changed by surface normal...



  • On 09/01/2013 at 11:48, xxxxxxxx wrote:

    What about trying it yourself? 😉
    Slight tip: The dictionary returned by GeRayCollider.GetNearestIntersection() contains information
    like what polygon was interesected. You can then compute the normal of that polygon and rotate
    the destination object accordingly.

    @ littledevil :
    Well, we don't want the closes point on the surface, do we? I'm sorry, I don't see why the green
    line is the one we would like to use instead of the red line.. :// I also don't get how you would
    come to that green line, I don't see any relation to the camera position or view-direction or similar.

    Hope that doesn't sound offending or so, because that was not my intention. I always
    appreciate constructive criticism or questions. :)
    Best,
    -Niklas



  • On 09/01/2013 at 12:13, xxxxxxxx wrote:

    NiklasR we are successful!🤝  Thank you for your precious help 🍺🍺



  • On 12/01/2013 at 03:43, xxxxxxxx wrote:

    i have modified the  **op_next  **with Linkbox but... no work...
    The object is not recognized...

    I've never had much luck with the linkbox 😂

    MY_LINKBOX = 100014

    def CreateLayout(self) :
            self.GroupBegin(id=1000, flags=c4d.BFH_SCALEFIT, cols=1, rows=1)
            self.GroupBorderSpace(10, 10, 10, 10)
            self.element = self.AddStaticText(id=1001, flags=c4d.BFH_MASK, initw=120, name="Inserire Oggetto:", borderstyle=c4d.BORDER_NONE)
            self.linkBox = self.AddCustomGui(MY_LINKBOX, c4d.CUSTOMGUI_LINKBOX, "", c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, 0, 0)
            self.GroupEnd()
            return True

    def MouseInput(self, doc, data, bd, win, msg) :
            mx = msg[c4d.BFM_INPUT_X]
            my = msg[c4d.BFM_INPUT_Y]
     
            device = 0
            if msg[c4d.BFM_INPUT_CHANNEL]==c4d.BFM_INPUT_MOUSELEFT:
                device = c4d.KEY_MLEFT
            elif msg[c4d.BFM_INPUT_CHANNEL]==c4d.BFM_INPUT_MOUSERIGHT:
                 device = c4d.KEY_MRIGHT
            else:
                return True

    op = doc.GetActiveObject()
            op_next = self.linkBox.GetLink()
            if not op_next:
    return True

    win.MouseDragStart(button=device, mx=int(mx), my=int(my), flags=c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE)
            result, dx, dy, channel = win.MouseDrag()
            while result==c4d.MOUSEDRAGRESULT_CONTINUE:
                mx += dx
                my += dy

    cursorpos = bd.SW(c4d.Vector(mx,my,500))     #screen to world conversion

    cam_pos = bd.GetSceneCamera(doc).GetAbsPos()
                collider = c4d.utils.GeRayCollider()
                collider.Init(op_next)

    length = 500000
                direction = -(cam_pos - cursorpos).GetNormalized()

    did_intersect = collider.Intersect(cam_pos, direction, length)
                if did_intersect:
                    position = collider.GetNearestIntersection()["hitpos"]
                    print "Intersection at", position
                else:
                    print "No intersection."
                    position = cursorpos

    doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
                op.SetAbsPos(position)
                op.Message(c4d.MSG_UPDATE)

    c4d.DrawViews(c4d.DA_ONLY_ACTIVE_VIEW|c4d.DA_NO_THREAD|c4d.DA_NO_ANIMATION)
                result, dx, dy, channel = win.MouseDrag()



  • On 12/01/2013 at 07:22, xxxxxxxx wrote:

    try :

    op_next = self.linkBox.GetLink(c4d.documents.GetActiveDocument(), c4d.Obase)
    


  • On 12/01/2013 at 09:11, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    try :

    op_next = self.linkBox.GetLink(c4d.documents.GetActiveDocument(), c4d.Obase)

    "object has no attribute 'linkBox'"....  
    I am beginning to think that linkbox they hate me 😂

    Thanks littledevil, you are a generous person, always ready to help all friends in this forum 👍



  • On 12/01/2013 at 10:37, xxxxxxxx wrote:

    could be some kind of call order problem. try something like this

    class myclass(c4d.Something) :
    	def __init__(self) :
    		self.linkBox = None
    	
    	def CreateLayout(self, *args) :
    		self.linkBox = Something
    	
    	def AnotherMethod(self) :
    		if (not self.linkBox) :
    			return False
    		else:
    			x = self.linkBox.Do(blah)
    

    MouseInput might be called the first time before CreateLayout has been called and as you 
    haven't defined linkBox as a variable in the class constructor it does not yet exist at that point.



  • On 12/01/2013 at 12:08, xxxxxxxx wrote:

    littledevil, i have pasted the entire code. 
    You can control it and correct it?
    I would like to understand where I'm wrong ...
    Thanks for your help 🍺

    import os
    import sys
    import c4d
    from c4d import plugins, utils, bitmaps, gui, documents
     
    PLUGIN_ID = 10000008 # THIS id IS FOR TESTING PUPOSES ONLY!!!
     
    #for GeLoadString values must match with the header file
    IDS_ESTENSIONE = 100000
    MY_LINKBOX = 100015
      
      
    class SettingsDialog(gui.SubDialog) :
     
     
        def CreateLayout(self) :
            self.GroupBegin(id=1000, flags=c4d.BFH_SCALEFIT, cols=1, rows=1)
            self.GroupBorderSpace(10, 10, 10, 10)
            self.element = self.AddStaticText(id=1001, flags=c4d.BFH_MASK, initw=120, name="Inserire Oggetto:", borderstyle=c4d.BORDER_NONE)
     **        self.linkBox = self.AddCustomGui(MY_LINKBOX, c4d.CUSTOMGUI_LINKBOX, "", c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, 0, 0)**
      
    		
    		
            self.GroupEnd()
            return True
        def InitValues(self) :
            
            return True
     
        def Command(self, id, msg) :
     
            return True
     
    class Caleidos(plugins.ToolData) :
      
        def __init__(self) :
            self.data = 0
      
        def KeyboardInput(self, doc, data, bd, win, msg) :
            key = msg.GetLong(c4d.BFM_INPUT_CHANNEL)
            cstr = msg.GetString(c4d.BFM_INPUT_ASC)
            if key==c4d.KEY_ESC:
                #do what you want            
                #return True to signal that the key is processed
                return True
            return False
     
     
        def MouseInput(self, doc, data, bd, win, msg) :
    	
    		if msg.GetLong(c4d.BFM_INPUT_CHANNEL)==c4d.BFM_INPUT_MOUSELEFT:
    			print "Begin Mouse Left Pressed"
    			while True:
    			
    				bc = c4d.BaseContainer()
    				if gui.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, bc) :
    					if bc.GetLong(c4d.BFM_INPUT_CHANNEL)==c4d.BFM_INPUT_MOUSELEFT:
    						print "Mouse Left Pressed"
    			
    						mx = msg[c4d.BFM_INPUT_X]
    						my = msg[c4d.BFM_INPUT_Y]
    				 
    						device = 0
    						if msg[c4d.BFM_INPUT_CHANNEL]==c4d.BFM_INPUT_MOUSELEFT:
    							device = c4d.KEY_MLEFT
    						elif msg[c4d.BFM_INPUT_CHANNEL]==c4d.BFM_INPUT_MOUSERIGHT:
    							 device = c4d.KEY_MRIGHT
    						else:
    							return True
      
    							
    						doc.GetActiveObject()
    						doc.StartUndo() 
    						myobject = **self.linkBox.GetLink()**
      
      
    						op = myobject
    						op_next = doc.GetActiveObject()
    						
    						win.MouseDragStart(button=device, mx=int(mx), my=int(my), flags=c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE)
    						result, dx, dy, channel = win.MouseDrag()
    						while result==c4d.MOUSEDRAGRESULT_CONTINUE:
    							mx += dx
    							my += dy            
      
    							cursorpos = bd.SW(c4d.Vector(mx,my,500))     #screen to world conversion
    							cam_pos = bd.GetSceneCamera(doc).GetAbsPos()
    							collider = c4d.utils.GeRayCollider()
    							collider.Init(op_next)
    							length = 500000
    							direction = -(cam_pos - cursorpos).GetNormalized()
    							did_intersect = collider.Intersect(cam_pos, direction, length)
    							if did_intersect:
    								position = collider.GetNearestIntersection()["hitpos"]
    								print "Intersection at", position
    							else:
    								print "No intersection."
    								position = cursorpos
    							doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
    							op.SetAbsPos(position)
    							op.Message(c4d.MSG_UPDATE)  
    							c4d.DrawViews(c4d.DA_ONLY_ACTIVE_VIEW|c4d.DA_NO_THREAD|c4d.DA_NO_ANIMATION)
    							result, dx, dy, channel = win.MouseDrag()
       						if not bc.GetBool(c4d.BFM_INPUT_VALUE) : break
    			print "End Mouse Left Pressed"
        def AllocSubDialog(self, bc) :
            return SettingsDialog(self.data) #always return new instance(self.data)
     
     
      
    if __name__ == "__main__":
        bmp = bitmaps.BaseBitmap()
        dir, file = os.path.split(__file__)
        fn = os.path.join(dir, "res", "Icon.tif")
        bmp.InitWith(fn)
        plugins.RegisterToolPlugin(id=PLUGIN_ID, str="Caleidos",info=0, icon=bmp, help="Statusbar Text",dat=Caleidos())
      
    
    


  • On 12/01/2013 at 13:03, xxxxxxxx wrote:

    this obviously won't work. i think you do not really understand what self means in python.
    it is similar to this in c# or java. it is a referecne to the actual instance of the class from which
    the code is being executed from. you are doing more or less this :

    class clsA() :
    	def __init__(self, x) :
    		self.X = x
      
    class clsB() :
    	def someMethod() :
    		# raises a runtime error as class b does not have a memeber called X
    		print self.X
    

    you have either make your dialog class instance a globally available variable (but this
    could be considered as really bad style) :

    class clsA() :
        def __init__(self, x) :
            self.X = x
      
    class clsB() :
        def do (self, classAinstance) :
            print classAinstance.X
           
    def main() :
        A = clsA()
        B = clsB()
        B.do(A)
    

    or you have to make an instance of your GeDialog class a memeber of your
    ToolData class.

    class ToolDataClass() :
        def __init__(self) :
            self.dialog = None
            self.data = None
        
        def doSomething(self) :
            if (self.dialog) :
                print self.Dialog.linkBox.GetLink(document, c4d.Obase)
            else:
                print 'dialog has not been raised yet.'
            
        def AllocSubDialog(self, bc) :
            self.Dialog = SettingsDialog(self.data)
            return self.Dialog
    

    edit : fixed a typo,  should be if (self.dialog) : of course and not if(self.data) :


Log in to reply