• c4d.documents.SaveProject() preventing future save commands

    2023 python
    2
    0 Votes
    2 Posts
    618 Views
    ferdinandF
    Hello @Aeoll-0, Thank you for reaching out to us. You should be a bit more specific about the circumstances and which you are using the command. As declared in our Support Guidelines, you should always post executable code, as we are otherwise are guessing what you are doing. The self.filedir implies that this happens in a method, which in turn could mean that you are trying to do this off-main-thread. This is not allowed. I also gave it a spin myself, and for me it works. Note that after the operation, the opened file is not the old file anymore. So, when you had a \data\a\myfile.c4d and saved to backup\a\, the opened file will be backup\a\myfile.c4d and not \data\a\myfile.c4d. Because of that, such newly "exported" documents will also induce thumbnail rendering. When you are trying to save many documents at once in this manner, the thumbnail rendering could make Cinema unresponsive. The path into which you want to dump things must also exist, Cinema 4D cannot create it for you. I have tested this in 2023.2.2 and 2024.1.0 and found no problems in both versions. Cheers, Ferdinand Result: [image: 1699977932661-34f18c02-cc1d-42ef-94ac-d50f2ad57195-image.png] Successfully saved project to: 'e:\projects\foo\', exporting the assets: [{'filename': 'e:\\projects\\foo\\myfile.c4d', 'assetname': 'myfile.c4d', 'channelId': 0, 'netRequestOnDemand': False}, {'filename': 'e:\\projects\\foo\\tex\\Maxon-Computer-Logo.jpg', 'assetname': 'E:\\temp\\Maxon-Computer-Logo.jpg', 'channelId': 0, 'netRequestOnDemand': True}]. Code: import c4d import os doc: c4d.documents.BaseDocument # The active document def main() -> None: """ """ # Cinema 4D cannot create the directory path for us, we must ensure that #path does exist. path: str = "e:\\projects\\foo\\" if not os.path.exists(path): os.makedirs(path) # Your settings. flags: int = (c4d.SAVEPROJECT_ASSETS | c4d.SAVEPROJECT_SCENEFILE | c4d.SAVEPROJECT_USEDOCUMENTNAMEASFILENAME) data: list = [doc, flags, path, [], []] # Invoke the command and raise errors on failure or missing assets. if not c4d.documents.SaveProject(*data): raise IOError(f"Could not save project to: '{path}'.") if data[4]: raise IOError(f"Failed to export the following assets: {data[4]}") # Success :) print (f"Successfully saved project to: '{path}', exporting the assets: {data[3]}.") if __name__ == '__main__': main()
  • Frequent updates on Posemorph tag

    python
    5
    0 Votes
    5 Posts
    1k Views
    i_mazlovI
    Hi @matrixloong , Please excuse the delayed answer. The real-time scenario is one of those that might not go very smoothly in cinema (check the links in my previous message). It was already discussed in the thread: Is it possible to control Camera with keyboard WASD like a FPS game? Ferdinand showed there one of the possible solutions to achieve live interactions on the scene using interaction dialog. You can use the simplified version of it below. Cheers, Ilia Run this code from the script manager and select an object in the object manager. import c4d, time, math doc: c4d.documents.BaseDocument # The active document class InteractionDialog(c4d.gui.GeDialog): TIMER_DELAY = 40 def CreateLayout(self): return True def InitValues(self): self._doc: c4d.BaseDocument = doc self.SetTimer(InteractionDialog.TIMER_DELAY) self._time = None self._lastTime = None self._angle = 0 return True def Timer(self, msg): # Initialize the time for the first frame a key is being pressed. if self._lastTime is None: self._lastTime = time.time() return None # The delta between now and the last evaluation dt = time.time() - self._lastTime self.DoSomething(dt) self._lastTime = time.time() def DoSomething(self, dt): op: c4d.BaseObject = self._doc.GetActiveObject() if not op: return PI2 = 2 * math.pi angleIncrement = dt * PI2 / 2 self._angle += angleIncrement if self._angle >= PI2: self._angle -= PI2 ml: c4d.Matrix = op.GetMl() bb: c4d.Vector = op.GetRad() pos: c4d.Vector = ml.off pos.x = bb.x * math.sin(self._angle) ml.off = pos op.SetMl(ml) c4d.EventAdd() if __name__ == '__main__': global dialog dialog = InteractionDialog(doc) dialog.Open(c4d.DLG_TYPE_ASYNC)
  • How to hide object local coordinates

    python
    5
    1
    0 Votes
    5 Posts
    1k Views
    i_mazlovI
    @chuanzhen , Sorry for the delayed answer. The layer.locked behavior is integrated deeply in the internal code of cinema bypassing common cinema pipelines. Unfortunately, there's no good way to imitate such behavior without using layers. In case you decide to proceed with the layer approach, there's an example in github repo highlighting the usage of SetLayerData() function: layer_creates_r13.py. Cheers, Ilia
  • Create Xpresso Python node

    python 2024
    3
    0 Votes
    3 Posts
    596 Views
    B
    WOW!!! It turns out that there is a node specifically for python. But in the documentation, in the list GV Node Types, it is not indicated. This fact forced me to look for workarounds. Thanks for the help
  • Failed to Connect to Cinema 4D, with port: 7788

    python 2023 2024
    3
    0 Votes
    3 Posts
    765 Views
    RenatoTR
    ah! Thanks a lot!
  • Python Xpresso Node

    windows python 2023
    5
    0 Votes
    5 Posts
    1k Views
    M
    Hi @Brakusha, welcome in plugin cafe ! c4d.ID_OPERATOR_COFFEE is working in all versions, please open a new topic with a code that demonstrate the issue and with a short explanation about what you want to achieve. I would also highly recommend you to read our Support Guideline to know how to get the best support from us. Cheers, Maxime.
  • Message on "Quit and Free License"

    c++
    2
    0 Votes
    2 Posts
    577 Views
    ferdinandF
    Hey @kbar, Thank you for reaching out to us. In the public API there is only what you can find in Plugin Licensing Manual. The natural solution for this would be an observable to which you can attach, but there is none in the public API. What you could do is try workarounds: Register a MessageData plugin and check periodically yourself. This might work okay for certain license change events, but when the license change induces a shutdown of Cinema 4D (a user released a license for example), you might get event starved. So, this is not great. Hook into the shutdown of Cinema 4D itself. When we want to specifically target the event that a license is being released, we can build upon the fact that Cinema 4D will then shut down. MAXON_INITIALIZATION: This is a bad choice in this case, because when the shutdown delegate of MAXON_INITIALIZATION is running, most registries already have been shut down. So, I would not be surprised, if all the license stuff is not working anymore at this point (I have not checked though). The advantage is here that MAXON_INITIALIZATION often makes for nicer looking code than PluginMessage. PluginMessage: Hook into the shutdown sequence of Cinema 4D, and check the license state there. C4DPL_ENDACTIVITY is the best event to start with. The problem is here that I do not know how licenses behave when a user releases a license. The idea would be to check for example on shutdown, if there is still a commercial license bound to this instance: // Create the ID for a commercial Cinema 4D license. maxon::InternedId feature; feature.Init("net.maxon.license.app.cinema4d-release~commercial"_s) iferr_return; // Check if the given #feature is active in the current license of this instance. if (!CheckLicenseFeature(feature)) ReleasePluginLicense(userId); But it could very well be that it takes some time before a released license 'kicks in' in a shutdown process and that you must go further into no-mans-land than C4DPL_ENDACTIVITY (where more and more services will be shut down). Internally, we have a licensing API which has observables which communicate such events. I will bring up the subject internally if we can make the framework fully or partially public. Cheers, Ferdinand
  • Converting image bit depth

    c++
    4
    0 Votes
    4 Posts
    723 Views
    ferdinandF
    Hey @WickedP, Good to hear that you solved your problem. And I know that the color management and pixel format stuff can be a royal pain in the ***, you have my sympathies. Things tend to also get REALLY lovely when you also must deal with OCIO. Please do not hesitate to reach out again when you run in further troubles. Cheers, ferdinand
  • Force polygon object to generate it's cache

    python 2024
    7
    0 Votes
    7 Posts
    1k Views
    bacaB
    Thanks @ferdinand, Thats gone too far, we can close this subj now. I think I have a solution already. I just wasn't clear enough in the beginning, I just wanted to know if PolygonObject can be forced to produce it's cache object by a command. I made an experiment where I spawn flat geometries between other flat geometries. Like planes in-between of deformed soft body planes. Here's working example: Setup: [image: 1699565133962-417b1a04-77c9-4163-bc6f-36c2800323f5-image.png] And simulation: [image: 1699565001814-cloth_multiply__03_.gif] Once you clone original geometry — it's flat, and there would be intersections and simulation will be broken. So you need to blend newborn geo point positions in-between of existing geometry points. Once you blend it — there are no intersections, it nicely continue with soft body simulation. But softbody dynamics build constraints for every new object. And if geometry first appears as deformed — wrong constraints are initialized, and each new object becomes crumpled real quick. Also there's "Mix Animation" -> "Follow Shape" checkbox, which rebuild constraints (or adjusts them - who knows?) — and it reads original point positions, as I understood. So I had to have both — original geo, and cache. Where cache used to simulate geometry in 3D, and original object (CacheParent?) will be used for constraints.
  • How to draw a primitive object in BaseDraw

    python 2023 2024 s26
    3
    0 Votes
    3 Posts
    637 Views
    gheyretG
    Hi @ferdinand Thank you for your reply and guidance. I'll get around to it. Cheers Gheyret
  • 0 Votes
    3 Posts
    622 Views
    S
    @i_mazlov sorry I thought I deleted this post as I solved the issue. Anyway to anyone who stumbles upon this question here's how I solved it: for i,pt in enumerate(points_list[::-1]): off = c4d.Vector(distance * i,0,0 ) mg = pt.GetMg() mg.off = off print(rotation.x) rm = c4d.utils.HPBToMatrix(rotation) pt.SetMg(mg * rm) So basically if the objects are inserted in the hierarchy and you start from the last one with the transformations this will work just like in the OM.
  • Why won't my python generator update? R2024

    python s26 windows
    5
    0 Votes
    5 Posts
    1k Views
    S
    @baca @ferdinand Thank you both. It was the fact that the user data was not collected in the main function. Silly I didn't catch that. It's working fine now.
  • TimeLine Window Custom open

    2024 python
    7
    2
    0 Votes
    7 Posts
    1k Views
    chuanzhenC
    @kangddan @Dunhou
  • 2024 NodeData Init isCloneInit argument for older version

    2024 python
    4
    0 Votes
    4 Posts
    904 Views
    mikeudinM
    @baca Thank you! Works like a charm!
  • 0 Votes
    3 Posts
    684 Views
    H
    Hi @ferdinand, ah okay I see. Some part of me already suspected it could be a bug. Thanks for taking the time to look into it. Regarding the scope of question. You are absolutely right. And while I understand that it can make answering branching questions hard, it is sometimes not that easy to split things up. But all good, no offense taken. One last thing, I know you guys are not here to develop solutions or come up with algorithms. Still, I was wondering if a possible solution could be to move the selected points to a custom vector position and afterwards simply send an "Optimize" modeling command? Cheers, Sebastian
  • Icons reuse

    windows 2024 python
    3
    0 Votes
    3 Posts
    628 Views
    DunhouD
    Hi @ferdinand , Thanks for your explain, I would convert the svg files to png then regist them for a temp solution, and wait the attribute valid in python. Thanks always for your awesome works. Cheers~ DunHou
  • Check the state of record modes with python?

    2024 python
    2
    0 Votes
    2 Posts
    473 Views
    B
    ah ok I figured it out. its possible to check those with the c4d.IsCommandChecked() function.
  • How to control a posemorph tag

    python
    4
    1
    0 Votes
    4 Posts
    895 Views
    M
    thanks a lot, your post is working for me.
  • some icon index not find

    python
    3
    1
    0 Votes
    3 Posts
    469 Views
    chuanzhenC
    @ferdinand Thanks
  • Colorchooser in 2024

    2024 python
    2
    0 Votes
    2 Posts
    426 Views
    M
    Hi @mikeudin thanks a lot for the report, this is a regression due to a last minute optimization within the internal Python API parsing done for which bring around 20% performance boost of the Python Effector in 2024.0. So any other classic API (c4d module) previously accepting a maxon.Vector or maxon.Color/A as an argument will be impacted (only ColorSwatchGroup.SetColor and ColorSwatchGroup.AddColor are affected by these changes) With that's said I was never a big fan of mixed datatype from classic API and maxon API, so even if this is a regression I think I prefer the new behavior. I will discuss that internally and see what is the outcome. I will keep you posted. Cheers, Maxime.