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
    1. Maxon Developers Forum
    2. C4DS
    3. Best
    • Profile
    • Following 0
    • Followers 1
    • Topics 96
    • Posts 404
    • Best 51
    • Controversial 0
    • Groups 0

    Best posts made by C4DS

    • RE: Send message to tooldata

      If I remember correctly we did discuss the other way (from CommandData to ToolData) quite a while ago (see https://developers.maxon.net/forum/topic/10044/13513_using-objectmessage). But I guess using this same technique could still be applicable to your current request.

      Most important is to understand that a CoreMessage is not captured by a ToolData. This type of message can only be captured by a MessageData plugin, where you then could "translate" it into a message that actually is sent to the ToolData.

      What I have been successful in using is, performing following from the "transmitter":

      BasePlugin* tool = FindPlugin(TOOL_PLUGIN_ID, PLUGINTYPE::TOOL);
      if (tool)
      	tool->Message(TOOL_MSG_PREPAREDATA);
      
      

      Where TOOL_PLUGIN_ID is the plugin ID of the ToolData, and TOOL_MSG_PREPAREDATA is a custom defined message, using a unique plugin ID.

      And then using following in the "receiver" ToolData:

      Bool MyToolData::Message(BaseDocument *doc, BaseContainer &data, Int32 type, void *t_data)
      {
      	if (type == TOOL_MSG_PREPAREDATA)
      	{
      		PrepareData();
      	}
      
      	return DescriptionToolData::Message(doc, data, type, t_data);
      }
      
      
      posted in Cinema 4D SDK
      C4DSC
      C4DS
    • RE: Shortcuts for buttons from gui.GeDialog

      You cannot assign shortcuts to buttons.
      An alternative solution (which I have used in the past) is to create a CommandData plugin for each button, and let the CommandData::Execute call the button. Or instead of a CommandData plugin you could also create a separate script for each button.
      Either way, these can then be assigned a shortcut.

      posted in Cinema 4D SDK
      C4DSC
      C4DS
    • RE: Bug on GetActiveObjects() on R20.057?

      @bentraje said in Bug on GetActiveObjects() on R20.057?:

      objSel = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_SELECTIONORDER)
      print objSel[0]
      print objSel[1]

      Works fine by me.

      I have a cube and a plane primitive. With the two selected, I get a printout for both. No out of range.
      Running 20.057 (on Windows).

      <c4d.BaseObject object called 'Plane/Plane' with ID 5168 at 0x0000004C44847570>
      <c4d.BaseObject object called 'Cube/Cube' with ID 5159 at 0x0000004C448476D0>
      
      

      When I only select a single object then I get an out of range (obviously):

      IndexError: list index out of range
      

      EDIT:
      Hang on, when I make one the child of the other and have both selected, I do get an out of range.
      But this is obvious, since your active objects flag doesn't mention children. As such, you do only have a single parent object selected.

      To take children into account as being detected as selected, you need:

       objSel = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_SELECTIONORDER | c4d.GETACTIVEOBJECTFLAGS_CHILDREN )
      
      
      posted in Cinema 4D SDK
      C4DSC
      C4DS
    • RE: Toggle Attribute Manager from Tool to Object Mode and Vice Versa
      import c4d
      
      def main():
          c4d.gui.ActiveObjectManager_SetObject(c4d.ACTIVEOBJECTMODE_OBJECT, op, 0, c4d.ACTIVEOBJECTMANAGER_SETOBJECTS_OPEN)
      
      if __name__=='__main__':
          main()
      
      posted in Cinema 4D SDK
      C4DSC
      C4DS
    • RE: Recent spam boom

      spam frenzy all over again, lately.

      posted in General Talk
      C4DSC
      C4DS
    • RE: detect the selection of an object

      I have been in need of something similar as well. And if I remember correctly it has been discussed a few years ago.
      Reason is that a ToolData or DescriptionToolData might need to initialize some stuff depending the currently active object. When the user selects a different object in the ObjectManager, the ToolData might need to reinitialize some stuff.

      The solution proposed in the past was to use a MessageData and listen to EVMSG_CHANGE to check if a different object has been selected using the object's "unique" id and then trigger the ToolData by sending a SpecialEvent ... or something.

      It is quite a complex implementation that seems to work, but probably is very error prone.
      I wish we would have had some kind of message telling the active object selection was changed (from inside the ToolData), not via-via. And definitely not using such a hacky and complex solution.
      It has been a while, but I seem to remember that the whole use of the object's unique id was rather flawed as the id didn't exactly seem to be that unique after all.

      Anyway, I am still hoping for a nice solution to detect when user changes the current active object. But it seems to not be possible after all.

      posted in Cinema 4D SDK
      C4DSC
      C4DS
    • Best Wishes to the team

      I am less active since a few months, and this will probably not change any time soon, but let that not restrict me for sending Best Wishes for 2021 to everyone of the SDK team.
      Not only to those more present and visible in the forums, but also to those behind the scenes that keep everything running.

      Thank you for your 2020 support and best wishes for 2021.

      posted in General Talk
      C4DSC
      C4DS
    • RE: Calling a Tool (Naming Tool) and Modify the Parameters

      You need to obtain the tool's data in order to be able to modify/set it.
      The callcommand just activates the tool.

      import c4d
      
      def main():
      
          # activate the command
          c4d.CallCommand(1019952)
      
          # change its settings
          nTool = c4d.plugins.GetToolData(doc, 1019952)
          nTool[c4d.ID_CA_JOINT_NAMING_REPLACE] = "_L_"
          nTool[c4d.ID_CA_JOINT_NAMING_REPLACE_WITH] = "_R_"
      
      # Execute main()
      if __name__=='__main__':
          main()
      
      posted in Cinema 4D SDK
      C4DSC
      C4DS
    • RE: Calling a Tool (Naming Tool) and Modify the Parameters

      In the above code "nTool" is a BaseContainer, that won't work.

      I also found the following in the legacy forum

      import c4d
      
      def main():
          
          toolID = 1019952
          c4d.CallCommand(toolID) 
      
          tool=c4d.plugins.FindPlugin(toolID, c4d.PLUGINTYPE_TOOL)  
          tool[c4d.ID_CA_JOINT_NAMING_REPLACE] = "_L_" 
          tool[c4d.ID_CA_JOINT_NAMING_REPLACE_WITH]= "_R_"
          c4d.CallButton(tool, c4d.ID_CA_JOINT_NAMING_REPLACE_APPLY)  
          
          c4d.EventAdd()
      
      

      Another take on modifying the settings, since the "tool" returned from FindPlugin is a BasePlugin which is derived from BaseList2D, exactly what we need for the CallButton

      posted in Cinema 4D SDK
      C4DSC
      C4DS
    • RE: Unusual Remove() Results

      The geometry of an object is stored in hidden tags (points and polygons, namely)
      These are not visible, nor selectable ... and thus can theoretically not be deleted by user. But you still can access these via Python, or C++. As such, when removing all tags you also remove critical ones, that are needed by the object in order to exist.

      posted in Cinema 4D SDK
      C4DSC
      C4DS
    • RE: Discover when a tag has been disabled
      1. It depends where you want to know the tag was disabled? It also depends if you want to get triggered by the tag being enabled/disabled, or simply wants to check at given time if tag is enabled/disabled?

      If you want to know from within the TagData-derived object the enable state of the tag you can (with a method receiving a GeListNode* node as argument) do:

      BaseTag* tag = (BaseTag*)node;
      
      Bool enabled = false;
      if (tag)
      {
      	GeData d;
      	tag->GetParameter(<your tag's ENABLE-id>, d, DESCFLAGS_GET::NONE);
      	enabled = d.GetBool();
      }
      ...
      

      If you want to get triggered by the change of state then:

      Bool YourTagDataDerivedClass::Message(GeListNode* node, Int32 type, void* data)
      {
      	if (type == MSG_DESCRIPTION_POSTSETPARAMETER)
      	{
      		DescriptionPostSetValue* postsetval = static_cast<DescriptionPostSetValue*>(data);
      		if (postsetval && (*postsetval->descid == DescID(<your tag's ENABLE-id>)))
      
      ... and same as above: you get the state of the enable-parameter
      
      • or -
      Bool YourTagDataDerivedClass::SetDParameter(GeListNode* node, const DescID& id, const GeData& t_data, DESCFLAGS_SET& flags)
      {
      	if (!node)
      		return false;
      
      	const Int32& gadgetID = id[0].id;
      	switch (gadgetID)
      	{
      		case <your tag's ENABLE-id>:
      			enabled = t_data.GetBool();
      
      
      1. I guess the button in front of the "Enable" label is the keyframe button, so you can animate the tag being enabled/disabled over time.
      posted in Cinema 4D SDK
      C4DSC
      C4DS
    • RE: Access Class B's function inside Class A?

      Another solution, in your specific scenario, where you don't really need to access a method but want to trigger the GeDialog in some way, is to message the dialog as discussed here.

      In short: your treeview sends a message, and the dialog reacts to the message by performing the refresh layout.

      posted in General Talk
      C4DSC
      C4DS
    • RE: PYP script doesn't show up in extensions

      A file with extension .pyp is not a script but a plugin.
      As far as I understand the script manager will only list scripts with extension .py
      The .pyp file you have should be located in the plugins folder, and should then show up in the Extensions menu of Cinema4D.
      You cannot make a plugin run from within the script manager.

      posted in Bugs
      C4DSC
      C4DS
    • Move/Copy Constructors documentation

      First of all I am trying to add a "documentation issue" tag, but cannot find anything related to documentation, only issue. So forgive my limited tagging.

      Right then, the actual issue I am facing:
      I am trying to provide a base class and a derived class, and following the "Move/Copy Constructors" page from the R19 SDK documentation. (Cannot seem to find this in the R20 documentation).

      Anyway, I follow the directives to provide a move and assignment operator, and do this in the base and derived class. All fine.
      The base class is POD class, and technically doesn't require a move/copy constructor, but since the derived one needs this, I also perform the move of the base in the derived move constructor:

      Base::Base(Base&& src) :
      	member1(std::move(src.member1)),
      	member2(std::move(src.member2))
      {}
      
      Derived::Derived(Derived&& src) :
      	Base(std::move(src)),
      	memberA(std::move(src.memberA)),
      	memberB(std::move(src.memberB))
      {}
      

      But when it comes to the CopyFrom method, I am somewhat confused.
      Performing only the necessary copy on the derived member does clear out the base class member
      when adding an instanciated derived class to a BaseArray.

      So I thought to perform the copy of the base members inside the CopyFrom of the derived class.

      maxon::Bool Derived::CopyFrom(const Derived& src)
      {
      	// copy members of the base class
      	member1 = src.member1;
      	member2 = src.member2;
      	// etc
      
      	// copy members of the derived class
      	memberA = src.memberA;
      	memberB = src.memberB;
      	// etc
      	return TRUE;
      }
      

      This seems to work, but I would prefer some sort of copying to be provided by the base class, which I could call somehow from within the derived class.

      As such I went ahead and did:

      maxon::Bool Base::CopyFrom(const Base& src)
      {
      	member1 = src.member1;
      	member2 = src.member2;
      	// etc
      	return TRUE;
      }
      
      maxon::Bool Derived::CopyFrom(const Derived& src)
      {
      	Base::CopyFrom(src);
      
      	memberA = src.memberA;
      	memberB = src.memberB;
      	// etc
      	return TRUE;
      }
      
      

      Where member1, member2 are members of the Base class, and memberA, memberB are members of the Derived class.

      So, you might think "Well, what's the question"?
      To which I will have to admit having actually resolved the question I had, while writing this post ...
      Still, I didn't want to deprive others potentially looking for an answer to this (already answered) question.

      posted in Cinema 4D SDK r19 r20 c++
      C4DSC
      C4DS
    • RE: How to load a file with python and turn it into the active document ?

      I have replied your post at C4DCafe.

      "The c4d.documents.LoadDocument returns you a BaseDocument, which you then need as argument for the InsertBaseDocument and SetActiveDocument."

      posted in General Talk
      C4DSC
      C4DS
    • Confusing ToolData content

      I am playing with the Attribute Manager, and tried reading out the ToolData of some selection tools using following script:

      # Read out the BaseContainer from ToolData
      import c4d
      
      def main():
          print " --- read ToolData BaseContainer ---"
          toolID = doc.GetAction()
          tool = c4d.plugins.FindPlugin(toolID, c4d.PLUGINTYPE_TOOL)
          print "Active tool = %s (%i)" % (tool.GetName(), toolID)
          # parse the tooldata
          toolbc = c4d.plugins.GetToolData(doc, toolID)
          i=0
          for elementID, value in toolbc:
              elementType = toolbc.GetType(elementID)
              print "%i ID: %i, Type: %i, Value: " % (i, elementID, elementType), value
              i+=1
      
      if __name__=='__main__':
          main()
      

      The output for the Live Selection tool was as expected. All attributes of the tool being visualized in the Attribute Manager can be found back in the printed output.
      But then I selected the Rectangle Selection and executed the script once more. To my surprise very few attributes were printed out. Same for the Lasso Selection and Polygon Selection.

       --- read ToolData BaseContainer ---
      Active tool = Live Selection (200000083)
      0 ID: 2108, Type: 15, Value:  1
      1 ID: 2109, Type: 15, Value:  10
      2 ID: 2200, Type: 15, Value:  0
      3 ID: 2124, Type: 15, Value:  0
      4 ID: 2125, Type: 19, Value:  1.0
      5 ID: 2169, Type: 15, Value:  1
      6 ID: 2163, Type: 15, Value:  0
      7 ID: 2164, Type: 15, Value:  0
      8 ID: 2201, Type: 15, Value:  0
      9 ID: 2202, Type: 19, Value:  100.0
      10 ID: 2203, Type: 19, Value:  1.0
      11 ID: 2204, Type: 15, Value:  0
      12 ID: 2205, Type: 15, Value:  0
      13 ID: 2206, Type: 15, Value:  0
      14 ID: 2207, Type: 19, Value:  0.5
      15 ID: 2209, Type: 15, Value:  1
      16 ID: 2208, Type: 1009060, Value:  <c4d.SplineData object at 0x000000B81496D250>
      17 ID: 2129, Type: 15, Value:  0
      18 ID: 2130, Type: 19, Value:  1.0
      19 ID: 2131, Type: 19, Value:  0.0
      20 ID: 2132, Type: 19, Value:  1.0
      21 ID: 20000, Type: 15, Value:  2
      22 ID: 20001, Type: 15, Value:  0
      23 ID: 20003, Type: 19, Value:  0.0
      24 ID: 20004, Type: 19, Value:  0.0
      25 ID: 20005, Type: 19, Value:  0.0
      26 ID: 20006, Type: 15, Value:  0
      27 ID: 705, Type: 15, Value:  1
      28 ID: 20002, Type: 15, Value:  0
       --- read ToolData BaseContainer ---
      Active tool = Rectangle Selection (200000084)
      0 ID: 2107, Type: 15, Value:  1
      1 ID: 2106, Type: 15, Value:  0
      2 ID: 705, Type: 15, Value:  1
       --- read ToolData BaseContainer ---
      Active tool = Lasso Selection (200000085)
      0 ID: 705, Type: 15, Value:  1
       --- read ToolData BaseContainer ---
      Active tool = Polygon Selection (200000086)
      0 ID: 705, Type: 15, Value:  1
      

      So, I am rather confused about the content of the ToolData for the last 3 selection tools.
      These printed output don't reflect the tool's attributes seen in the Attribute Manager. Are these attributes stored somewhere else perhaps?
      Or is my script wrong in some way?

      posted in Cinema 4D SDK python c++ r19 r20
      C4DSC
      C4DS
    • Search results

      Might I make a suggestion for the search functionality?

      There is the option to show the result of a search as posts or as topics.
      I am fine with the "topics" option only showing the topic title.

      However, when one uses the "posts" option it would be quite useful to limit the post to -let's say- the first 10 lines.
      If the post contains a lot of code, I don't want to see all this in the search result.

      To illustrate my point:
      try a search on "bitmapbutton array" and choose "posts" as result option ...

      The first topic will probably be:
      DDesc BitmapButtons when changed
      and you will need to scroll quite some time to get to the second topic:
      BitmapButton image change works in R13 but not R14
      which also is a lengthy post on itself.
      ... and so on and so forth.

      Could there be a way to limit the number of text shown per post? Or at least exclude any code (or collapsing that code) when listing the search result.

      Thanks in advance.

      posted in General Talk
      C4DSC
      C4DS
    • RE: CallButton in C++

      The tool was set active (manually and via CallCommand).
      But not working in R16, not working in R19.

      posted in Cinema 4D SDK
      C4DSC
      C4DS
    • RE: Seasonal Greetings

      I 'll follow with best wishes.
      And also a big thank you to the SDK team, for all the time and effort you put in providing answers, tips, and what not.

      posted in General Talk
      C4DSC
      C4DS
    • RE: Confusing ToolData content

      I am looking into the GetDescription solution you discussed. It takes a little more to translate from Python to C++, but I see the possibilities. Although this introduces more clutter to sift through.
      I guess I was spoiled with the result I got from just testing out the Live Selection and Extrude tools, in order to see how to design the whole framework behind.
      Didn't think other (native) tools would be so problematic.

      I am not working on some kind of undo system, more a workflow enhancement.
      My Dials plugin allows to quickly set up a set of most used tools. People refer to it as a radial menu, but it definitely is not.
      One of its feature was the ability to provide for a set of "favorites" where most used settings for tool could easily be "cached" and quickly retrieved.
      From my modeling times (before I started spending most of my time on plugin development) I remember having constantly the need to have 2 or 3 bevel settings at hand. As such I needed to modify the values constantly. With the introduction of Dials and its favorites, I now would simply store a few settings and retrieve them on the fly.

      A quick work-in-progress demonstration (of the favorites idea) if I may ...

      Hope this helps put the "get basecontainer" idea into context.

      posted in Cinema 4D SDK
      C4DSC
      C4DS