• Simulating mouse movement in C4D

    Cinema 4D SDK python r25 windows
    5
    0 Votes
    5 Posts
    3k Views
    D
    Hi @ferdinand, Thank you so much for the comprehensive reply! Given all this I don't think it would make sense to keep trying to unit test this particular part of our code with Python. The last approach you highlighted with testing directly on the C++ side seems like the best option, so I'll give that a try. I'll have to see how to integrate this test with the rest of the unit tests (we have a lot and they're all in Python) but hopefully that won't be too much of a problem. Thanks again for all the help, Daniel
  • Can't snap to Generator output spline

    Cinema 4D SDK r25 python windows
    4
    0 Votes
    4 Posts
    1k Views
    ferdinandF
    Hey @Madara, in short, a Python generator object is not meant to generate splines. You can collapse the cache of your constructed spline and return its LineObject cache instead of the spline itself. For an example, see [1]. In your case that would be connect_obj. This will work in the sense that the generator cache will be then like a SplineObject cache and when you 'Current State to Object' your generator, it will behave like a spline and give you the interpolated editable linear spline and not a spline generator. However, spline snapping not only inspects caches, but also checks if OBJECT_ISSPLINE is true. So, you cannot bamboozle it by faking a SplineObject cache. You will have to implement a proper spline plugin for what you want to do, as you can overwrite there GetContour Cheers, Ferdinand PS: Your code contains multiple elements that can crash Cinema 4D and/or corrupt the loaded document. Specifically, these sections: if link_clone: #Parametric object pobj = u.SendModelingCommand( command = c4d.MCOMMAND_CURRENTSTATETOOBJECT, list = [connect_obj], mode = c4d.MODELINGCOMMANDMODE_ALL, doc = op.GetMain()) connect_obj = pobj[0] ... offspline = u.SendModelingCommand( c4d.MCOMMAND_SPLINE_CREATEOUTLINE, [connect_obj], c4d.MODELINGCOMMANDMODE_ALL, bc=settings, doc=doc) A Python generator's main() function is subject to the threading restrictions of Cinema 4D because it is just a wrapper for ObjectData.GetVirtualObjects. Executing SendModelingCommand in a threaded context is fine, but you cannot do it on the active document (both doc and op.GetDocument() are the active document). This is here even worsened by the fact that that the objects in list are not actually part of the document you pass as doc. To circumvent that you must create your own document just as I have in [1] with temp. Find a more detailed example of that technique in smc_extrude_s26.py. [1] import c4d op: c4d.BaseObject # The Python generator object. def main() -> c4d.BaseObject: """ """ # A user data Boolean to toggle collapsing the cache of this generator. collapse: bool = op[c4d.ID_USERDATA, 1] spline: c4d.BaseObject = c4d.BaseObject(c4d.Osplinecircle) if not spline: return c4d.BaseObject(c4d.Onull) # Just return the circle spline itself when #collapse is false. if not collapse: return spline # Otherwise grab the LineObject cache of the spline and return a copy of it. temp: c4d.documents.BaseDocument = c4d.documents.BaseDocument() temp.InsertObject(spline) temp.ExecutePasses(c4d.threading.GeGetCurrentThread(), False, False, True, c4d.BUILDFLAGS_NONE) cache: c4d.LineObject | None = spline.GetCache() if not isinstance(cache, c4d.LineObject): return c4d.BaseObject(c4d.Onull) return cache.GetClone(c4d.COPYFLAGS_NONE)
  • abc exported object names

    Moved Bugs r25 python
    3
    2
    1 Votes
    3 Posts
    1k Views
    S
    super, thanks
  • 0 Votes
    5 Posts
    1k Views
    fwilleke80F
    @jana sorry, I forgot to flag it myself. All solved, thank you
  • Setting texture path to a RS Domelight with python

    Cinema 4D SDK r25 python
    2
    0 Votes
    2 Posts
    2k Views
    ferdinandF
    Hello @Ryan_Territory, Welcome to the Plugin Café forum and the Cinema 4D development community, it is great to have you with us! Getting Started Before creating your next postings, we would recommend making yourself accustomed with our Forum and Support Guidelines, as they line out details about the Maxon SDK Group support procedures. Of special importance are: Support Procedures: Scope of Support: Lines out the things we will do and what we will not do. Support Procedures: Confidential Data: Most questions should be accompanied by code but code cannot always be shared publicly. This section explains how to share code confidentially with Maxon. Forum Structure and Features: Lines out how the forum works. Structure of a Question: Lines out how to ask a good technical question. It is not mandatory to follow this exactly, but you should follow the idea of keeping things short and mentioning your primary question in a clear manner. About your First Question This exact question of yours has been asked before here for C++. Find a Python variant of the code below. For the technical details, I would recommend reading the older thread. Cheers, Ferdinand Result: [image: 1685984571549-557e9ddd-793a-4d07-aa6e-5ffd7ad05687-image.png] Code: import c4d # Define #Orslight, only must be done in pre 2023.0 API versions. c4d.Orslight: int = 1036751 def main(): doc = c4d.documents.GetActiveDocument() # Create Light light = c4d.BaseObject(c4d.Orslight) # Set the attributes light[c4d.REDSHIFT_LIGHT_TYPE] = c4d.REDSHIFT_LIGHT_TYPE_DOME # Define the texture parameter ID. texturePathId: c4d.DescID = c4d.DescID( # 1st DescLevel for the outer unexposed datatype of "Texture". c4d.DescLevel( c4d.REDSHIFT_LIGHT_DOME_TEX0, # The parameter ID (12000) for "Texture" 1036765, # The datatype ID for for "Texture", this type is not exposed, # we must use the raw ID. c4d.Orslight # The creator ID, Orslight in this case. ), # 2nd DescLevel for the inner exposed datatype of "Texture.Path". c4d.DescLevel( c4d.REDSHIFT_FILE_PATH, # The sub-channel parameter ID (1000) for "Texture.Path" c4d.DTYPE_STRING, # The data type ID of this component, string in this case. 0 # The creator ID, I just went with undefined here. )) light[texturePathId] = "asset:///file_c622e9ad3ea0e159" # Insert the light into the scene doc.InsertObject(light) c4d.EventAdd() if __name__=='__main__': main()
  • Getting rid of the burger icon in a dialog

    Cinema 4D SDK r25 c++
    12
    0 Votes
    12 Posts
    3k Views
    fwilleke80F
    Woot, it works!
  • TreeView DropDown Menu

    Cinema 4D SDK
    5
    0 Votes
    5 Posts
    1k Views
    ferdinandF
    Hey, yes it is. The trick is c4d.LV_CHECKBOX_HIDE, the relevant bits happen in GetDropDownMenu. Cheers, Ferdinand I removed the command, you can directly run this in the script manager: import c4d PLUGIN_ID = 12345678 PLUGIN_NAME = "ListView Dropdown Prototype" ID_TREE_VIEW = 1000 ID_FILE_NAME = 1001 ID_IMPORT_OPTION = 1002 ID_IMPORT_OPTION_DEFAULT = 1100 ID_IMPORT_OPTION_HIGH = 1101 ID_IMPORT_OPTION_MEDIUM = 1102 ID_IMPORT_OPTION_LOW = 1103 dummyfile_list = ["hud.stp", "material_reference.wrl", "front_axle.stp", "body.wrl", "wheel_variant.stp"] class DummyFile: def __init__(self, file_name, import_option="Default"): self.file_name = file_name self.import_option = import_option class DummyFileListView(c4d.gui.TreeViewFunctions): def __init__(self, dialog): self.dialog = dialog self.files = [DummyFile(file_name) for file_name in dummyfile_list] def GetFirst(self, root, userdata): return self.files[0] if self.files else None def GetNext(self, root, userdata, dummy_file): current_index = self.files.index(dummy_file) next_index = current_index + 1 return self.files[next_index] if next_index < len(self.files) else None def GetDown(self, root, userdata, dummy_file): return None def GetId(self, root, userdata, dummy_file): return id(dummy_file) def GetName(self, root, userdata, dummy_file): return dummy_file.file_name def IsSelected(self, root, userdata, dummy_file): return False def GetColumnWidth(self, root, userdata, dummy_file, column_id, area): if column_id == ID_FILE_NAME: return area.DrawGetTextWidth(dummy_file.file_name) + 24 if column_id == ID_IMPORT_OPTION: return 120 return 96 def GetDropDownMenu(self, root, userdata, dummy_file, column_id, menu_info): if column_id != ID_IMPORT_OPTION: menu_info["state"] = c4d.LV_CHECKBOX_HIDE return if not dummy_file.file_name.lower().endswith(".stp"): menu_info["state"] = c4d.LV_CHECKBOX_HIDE return options = { ID_IMPORT_OPTION_DEFAULT: "Default", ID_IMPORT_OPTION_HIGH: "High", ID_IMPORT_OPTION_MEDIUM: "Medium", ID_IMPORT_OPTION_LOW: "Low", } for option_id, label in options.items(): menu_info["menu"].SetString(option_id, label) menu_info["entry"] = next( option_id for option_id, label in options.items() if label == dummy_file.import_option ) menu_info["state"] = c4d.LV_CHECKBOX_ENABLED def SetDropDownMenu(self, root, userdata, dummy_file, column_id, entry): if column_id != ID_IMPORT_OPTION: return #this is logical but does not do the trick .... if not dummy_file.file_name.lower().endswith(".stp"): return options = { ID_IMPORT_OPTION_DEFAULT: "Default", ID_IMPORT_OPTION_HIGH: "High", ID_IMPORT_OPTION_MEDIUM: "Medium", ID_IMPORT_OPTION_LOW: "Low", } dummy_file.import_option = options.get(entry, dummy_file.import_option) self.dialog.tree_view.Refresh() class ListViewDropdownDialog(c4d.gui.GeDialog): def __init__(self): self.tree_view = None self.file_list_view = DummyFileListView(self) def CreateLayout(self): self.SetTitle(PLUGIN_NAME) tree_view_settings = c4d.BaseContainer() tree_view_settings.SetBool(c4d.TREEVIEW_BORDER, c4d.BORDER_THIN_IN) tree_view_settings.SetBool(c4d.TREEVIEW_HAS_HEADER, True) tree_view_settings.SetBool(c4d.TREEVIEW_HIDE_LINES, True) tree_view_settings.SetBool(c4d.TREEVIEW_RESIZE_HEADER, True) tree_view_settings.SetBool(c4d.TREEVIEW_FIXED_LAYOUT, True) tree_view_settings.SetBool(c4d.TREEVIEW_ALTERNATE_BG, True) if c4d.GetC4DVersion() >= 24000: tree_view_settings.SetInt32(c4d.TREEVIEW_VERTICAL_SPACE, 4) self.tree_view = self.AddCustomGui(ID_TREE_VIEW, c4d.CUSTOMGUI_TREEVIEW, "", c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 500, 220, tree_view_settings, ) if not self.tree_view: return False layout = c4d.BaseContainer() layout.SetLong(ID_FILE_NAME, c4d.LV_TREE) layout.SetLong(ID_IMPORT_OPTION, c4d.LV_DROPDOWN) self.tree_view.SetLayout(2, layout) self.tree_view.SetHeaderText(ID_FILE_NAME, "Dummy file") self.tree_view.SetHeaderText(ID_IMPORT_OPTION, "STP import option") self.tree_view.SetRoot(self.tree_view, self.file_list_view, None) return True def InitValues(self): self.tree_view.Refresh() return True if __name__ == "__main__": dialog = ListViewDropdownDialog() dialog.Open(c4d.DLG_TYPE_MODAL, 0, -1, -1, 500, 220)
  • Detect CTRL + RightMouseButton in SceneHook

    Cinema 4D SDK r25 c++ 2023
    3
    0 Votes
    3 Posts
    1k Views
    C4DSC
    Thanks for taking the time to respond, even during the weekend. I must say this is quite embarrassing: I already had forgotten about the response in the other thread, and it's not even 3 weeks old. I sincerely apologize for wasting your time with this duplicate thread. I can confirm the GetInputState is working fine, no need to waste more of your time trying it out. Thanks again.
  • PointObject.CalcVertexMap(self, modifier)

    Cinema 4D SDK python r25
    5
    0 Votes
    5 Posts
    1k Views
    A
    @m_adam hi Maxime, thank you for your availability. Bacca's answer immediately cleared my mind on the subject, just as I was reading the other thread. I usually use the traditional method of calculating vertexmaps in the presence of obstacles. I thought CalcVertexMap did just that (the restriction tag is not mentioned in the SDK, so I couldn't figure out how to use it) but my curiosity is just didactic. Ciao Gianluca
  • Removing IsolateObjects document

    Cinema 4D SDK r23 r25 c++ 2023 r20
    3
    0 Votes
    3 Posts
    1k Views
    ManuelM
    hi, yes, KillDocument is not necessary in that case. Cheers, Manuel
  • How to detect CTRL being pressed in a GeDialog

    Cinema 4D SDK r23 r25 2023 c++
    4
    0 Votes
    4 Posts
    2k Views
    C4DSC
    Thanks @m_adam I can confirm that the following does work with R20, R23 and 2023 Int32 MyDialog::Message(const BaseContainer& msg, BaseContainer& result) { BaseContainer keyChannels; if (GetInputState(BFM_INPUT_KEYBOARD, QCTRL, keyChannels)) { Bool ctrlModifier = (keyChannels.GetInt32(BFM_INPUT_QUALIFIER) & QCTRL) != 0;
  • Tree-Generator

    Moved General Talk r25
    8
    1
    0 Votes
    8 Posts
    5k Views
    R
    @love_me_render Thank you very much
  • Keyframing the source file on an ImageTexture shader

    Cinema 4D SDK r25
    3
    0 Votes
    3 Posts
    931 Views
    mocolocoM
    Hi, A simple addition on CTrack and DescId as I was also faced to this a time ago. You can consult the @ferdinand's explanations and exemples on CTrack to the following post : https://developers.maxon.net/forum/topic/14315/solved-how-to-setup-a-ctrack-on-tag-plugin-ui-slider-with-extended-details/8 Cheers, Christophe
  • Set PYP file syntax highlighting in VS Code?

    General Talk r25 python
    4
    0 Votes
    4 Posts
    1k Views
    M
    Btw if you install the Cinema 4D Vs Code extension, pyp extension should be added as Python.
  • Implement A Usage Counter?

    General Talk python r25
    3
    0 Votes
    3 Posts
    806 Views
    B
    @ferdinand Thanks for the pointers. I'll try to look up those options. Will close this thread now.
  • Add Additional Script Path?

    General Talk r25 python
    3
    0 Votes
    3 Posts
    738 Views
    B
    @m_adam Thanks for the response. Modifying the environment varialbles works for my use case. Closing the thread now.
  • Compiling for R20... linker error in maxon::String

    Cinema 4D SDK r20 r25 c++
    5
    0 Votes
    5 Posts
    2k Views
    M
    Hello @fwilleke80 , without further questions or postings, we will consider this topic as solved by Thursday 01/06/2023 and flag it accordingly. Thank you for your understanding, Maxime.
  • Actively Link Hair Guides to a Spline or Alembic?

    Cinema 4D SDK r25 python
    3
    0 Votes
    3 Posts
    949 Views
    B
    Hi @ferdinand Thanks for the response and heads up on the crashes. RE: you want to control hair guide vertices programmatically Yep yep you are right on this part. Basically, have a geometric hair animated and simulated for preview. But rendered on the actual hair object. This is the workflow for other DCC, and the more logical one. This way you separate the hair source and hair generation. It's easier to debug. Anyhow, for looking at your python example, this should get me by on my current use case. Thanks for your illustration as always! Will close thread now.
  • Node Method IsValid() Throws ValueError

    Cinema 4D SDK python r25
    5
    0 Votes
    5 Posts
    558 Views
    B
    @m_adam Gotcha. Thanks for the heads up!
  • Swap Out Joint Axis Rotation?

    Cinema 4D SDK r25 python
    7
    0 Votes
    7 Posts
    805 Views
    B
    @manuel Interesting. Thanks for the heads up. It works now as expected. Closing the thread.