Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Snap object in mouse input

    PYTHON Development
    0
    25
    15.9k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

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

      Hi 😄

      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 😄

      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()) 
      
      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

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

        up ^_^

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          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

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            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...

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              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

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

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

                Surface 👍

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  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

                  1 Reply Last reply Reply Quote 0
                  • H
                    Helper
                    last edited by

                    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) ?

                    1 Reply Last reply Reply Quote 0
                    • H
                      Helper
                      last edited by

                      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

                      1 Reply Last reply Reply Quote 0
                      • H
                        Helper
                        last edited by

                        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 👍

                        1 Reply Last reply Reply Quote 0
                        • H
                          Helper
                          last edited by

                          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 🙂

                          1 Reply Last reply Reply Quote 0
                          • H
                            Helper
                            last edited by

                            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...

                            1 Reply Last reply Reply Quote 0
                            • H
                              Helper
                              last edited by

                              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

                              1 Reply Last reply Reply Quote 0
                              • H
                                Helper
                                last edited by

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

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

                                1 Reply Last reply Reply Quote 0
                                • H
                                  Helper
                                  last edited by

                                  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()

                                  1 Reply Last reply Reply Quote 0
                                  • H
                                    Helper
                                    last edited by

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

                                    try :

                                    op_next = self.linkBox.GetLink(c4d.documents.GetActiveDocument(), c4d.Obase)
                                    
                                    1 Reply Last reply Reply Quote 0
                                    • H
                                      Helper
                                      last edited by

                                      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 👍

                                      1 Reply Last reply Reply Quote 0
                                      • H
                                        Helper
                                        last edited by

                                        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.

                                        1 Reply Last reply Reply Quote 0
                                        • H
                                          Helper
                                          last edited by

                                          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())
                                            
                                          
                                          
                                          1 Reply Last reply Reply Quote 0
                                          • H
                                            Helper
                                            last edited by

                                            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) :

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post