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. bentraje
    3. Topics
    B
    • Profile
    • Following 0
    • Followers 1
    • Topics 241
    • Posts 738
    • Best 17
    • Controversial 0
    • Groups 0

    Topics created by bentraje

    • B

      Query Morph Order Based on the UI Order?

      Cinema 4D SDK
      • 2024 python • • bentraje
      3
      0
      Votes
      3
      Posts
      629
      Views

      B

      Hi @ferdinand

      Thanks for the response.
      Found a workaround it.
      Basically, just name the poses properly in a sorting order.
      Query the GetName() method and perform my own sorting.

      Regards,
      Ben

    • B

      Access Unfreeze All in the Object's Coordinate Tab?

      Cinema 4D SDK
      • 2023 windows python • • bentraje
      3
      0
      Votes
      3
      Posts
      552
      Views

      B

      @ferdinand

      Gotcha. Thanks for the response.
      c4d.CallButton(op, c4d.ID_BASEOBJECT_FROZEN_RESET) works as expected.

    • B

      GetCache Does Not Work Inside the Python Generator

      Cinema 4D SDK
      • r21 r25 python • • bentraje
      10
      0
      Votes
      10
      Posts
      1.8k
      Views

      ferdinandF

      Hey @bentraje,

      I am glad that you found your solution, and yes, you are absolutely right, it should be GeGetCurrentThread . I fixed that in my pseudo-code.

      Cheers,
      Ferdiand

    • B

      Easier Way to Offset an Animation of an Object?

      Cinema 4D SDK
      • python r25 windows r21 • • bentraje
      4
      0
      Votes
      4
      Posts
      1.1k
      Views

      B

      @ferdinand

      yea python is much more forgiving than C++. i was just wondering if there was an already existing API for such task. šŸ‘

    • B

      Get the Neighboring Keys from a Selected Key?

      Cinema 4D SDK
      • 2024 2023 python • • bentraje
      5
      0
      Votes
      5
      Posts
      953
      Views

      B

      Hi @ferdinand

      Apologies for the late response.

      RE: You should show me how you access that key.
      My bad. But it's on the previous thread you answered by manually selecting a keyframe and storign it in a variable.
      https://developers.maxon.net/forum/topic/15344/get-selected-keyframes/3

      RE: I just showed you above how to operate with percentage values in Cinema 4D.
      My bad. I missed it. I was looking immediately at the declaration.

      keyA: c4d.CKey keyB: c4d.CKey

      which I only want one key to be declared.

      ===

      In summary, the GetNext() and GetPred() solved the problem in getting the Neighboring Keys from a Selected Key.

    • B

      Get Selected Keyframes?

      Cinema 4D SDK
      • 2023 2024 python • • bentraje
      6
      0
      Votes
      6
      Posts
      1.2k
      Views

      ferdinandF

      Hey @bentraje,

      yes, we are aware that internal and private tags are something that plagues our documentation as they often have been abused by developers to skip documentation. But that is not so easy to fix.

      I for example did and still do not know the purpose NBIT_TLX_SELECT2 either. I was just experienced enough with the C4D API to poke in this place first.

      Physically fixing the docs, i.e., adding a blab here or there, is not the problem. The problem is to evaluate if the private tag in C++ (which then radiates into Python) is well founded or not, especially for ancient things like this. I would have to read a lot of code to make an assessment if this should be private or not, and even then would not be sure. And even an 'Expresses the selection state of f-curve keys. @markprivate' is problematic because for that I would have to be sure that it does not have a weird side effect.

      Cheers,
      Ferdinand

    • B

      Get All Nodes inside an Xpresso Tag?

      Cinema 4D SDK
      • 2023 python • • bentraje
      3
      0
      Votes
      3
      Posts
      667
      Views

      M

      Hi yes, GvNode are BaseList2D and GeListNode, like material, object, tags.
      There is the same discussion going on, so you may find it interesting Issue collecting all the shaders in a material.

      Cheers,
      Maxime.

    • B

      Arrange All Nodes Command/API in Xpresso?

      Cinema 4D SDK
      • 2023 python • • bentraje
      3
      0
      Votes
      3
      Posts
      599
      Views

      B

      Thanks for the confirmation.
      I guess I'll just let the users do some reordering the nodes themselves. lol
      The nodes are creating procedurally so the nodes are just stacked on top of each other. haha

    • B

      Easier Way to Modify Pose Morph Strength Based on Name?

      Cinema 4D SDK
      • 2023 python • • bentraje
      3
      0
      Votes
      3
      Posts
      660
      Views

      B

      @i_mazlov
      Ah yes, my pose morph names are standardized so there should be no duplicated/redundant names.
      And yea, thanks for mentioning the dictionary route. Totally overlooked that.
      That could indeed be an easier way to set/get some values.

      Thanks!

    • B

      Other methods for material[c4d.ID_MATERIALASSIGNMENTS]?

      Cinema 4D SDK
      • python 2023 • • bentraje
      7
      0
      Votes
      7
      Posts
      1.1k
      Views

      B

      @ferdinand

      Gotcha. Thanks. Will close this thread now.

    • B

      How to Use GetConnectionValue/s() or GetConnection()?

      Cinema 4D SDK
      • 2023 python • • bentraje
      11
      0
      Votes
      11
      Posts
      1.8k
      Views

      indexofrefractionI

      @ferdinand
      first of all, I understand your frustration, we just yesterday talked about the state of the Nodes API and are well aware of its hurdles for anything but super-experts.

      you can say that aloud!
      the whole system is very hard to understand. the only thing i got is all we know about traditional materials and even shaders is for the bin. node support evolved over time and most node examples do not work for people still using older c4d versions. also there are misc 3rd-party renderers that use different kinds of nodes / node systems. Drag & drop of attributes to the console doesn't work anymore, as well. the days of easy scripting are gone.. 😵

    • B

      Cancel Option for Progress Bar Dialog?

      Cinema 4D SDK
      • 2023 • • bentraje
      4
      0
      Votes
      4
      Posts
      911
      Views

      ferdinandF

      Hey @bentraje,

      I would recommend using the example I posted above, only that you replace the MessageData instance with a GeDialog instance. The other thread looks overly specific, a bit overengineered with the decorator, to be a good basic example.

      I do not have the time to write a full working example right now, but in pseudo code it would look as shown at the end of the posting. I cannot make much out of random error messages you give me. An AttributeError means that an object does not have an attribute, be it a field/property (myObject._data, myObject.Data) or a function (myObject.SendMessage), so it means that you have not declared MyThread.SendMessage and yet try to call it. As always, we also cannot debug your code for you.

      Cheers,
      Ferdinand

      Code:
      ⚠ This is untested 'pseudo-code', I wrote this 'blind'. It demonstrates a pattern and is not meant to be executable code.

      """Provides an example for a thread executing multiple tasks and expressing the execution state to the outside world. """ import c4d import typing class WorkerThread (c4d.threading.C4DThread): """Wraps the execution of multiple tasks expressed by a set of data in a thread. The thread exposes the total amount of tasks, already done tasks, and their results to outside observers. """ def __init__(self, data: typing.Collection) -> None: """Initializes the worker. """ self._data : typing.Collection = data # Stuff to do. self._results: list[any] = [] # Results of stuff that has been done. self._taskCount: int = len(data) # Number of things to do in total. self._finishedTaskCount: int = 0 # Number of things that already have been done. def Main(self) -> None: """Carries out the tasks. """ for item in self._data: self._results.append(self.Compute(item)) # this takes a long time to do. self._finishedTaskCount += 1 def Compute(self, *args) -> any: """Represents a computation step. """ return 0 # Read-only properties to access the data of the thread from another thread. You could also just # let the other thread directly access members (thread._results) or also use fancier things like # locks/semaphores to make this "nicer". This is a question of taste, read-only properties are # somewhat a middle ground. @property def Results(self) -> tuple[any]: return tuple(self._results) @property def TaskCount(self) -> int: return self._taskCount @property def FinishedTaskCount(self) -> int: return self._finishedTaskCount class MyTaskDialog (c4d.gui.GeDialog): """Realizes a dialog that runs a thread wrapping multiple tasks. """ ID_NEW_THREAD: int = 1000 # Id of a gadget which invokes adding a new thread. def __init__(self) -> None: """ """ # The worker thread of the dialog, could also be multiple threads as in the other example, # I kept it simple here. self._workerThread: WorkerThread | None = None super().__init__() def Command(self, mid: int, msg: c4d.BaseContainer) -> bool: """Called by Cinema 4D on GUI interactions. """ # Something with ID_NEW_THREAD has been pressed, we start try to start a new thread with the # dummy data [1, 2, 3]. if mid == MyTaskDialog.ID_NEW_THREAD and not self.StartWorkerThread([1, 2, 3]): # Do something on failure. pass return super().Command(mid, msg) def StartWorkerThread(self, data: typing.Collection, evalFrequency: int = 250) -> bool: """Starts a new worker thread and sets the evaluation frequency. """ # There is already an ongoing thread. if isinstance(self._workerThread, WorkerThread): return False # Create and start the new thread. self._workerThread = WorkerThread(data) self._workerThread.Start() self.SetTimer(max(100, evalFrequency)) return True def Timer(self, msg: c4d.BaseContainer) -> None: """Called by Cinema 4D for each timer tick. """ # Should never happen and (most) GUI functions do this own their own, more a formality. if not c4d.threading.GeIsMainThreadAndNoDrawThread(): return t: WorkerThread = self._workerThread # The thread is still running, just update the UI with the status of the thread. if t.IsRunning(): c4d.StatusSetSpin() c4d.StatusSetText(f"Running tasks: {t.FinishedTaskCount}/{t.TaskCount}") # The thread has finished, do something with the result, shut off the timer, and clear out # the UI. else: results: any = t.Results print(results) t.End() self._workerThread = None self.SetTimer(0) c4d.StatusClear()
    • B

      GetMg() doesn't update on objects affected with Align to Spline Tag?

      Cinema 4D SDK
      • python 2023 • • bentraje
      3
      0
      Votes
      3
      Posts
      603
      Views

      B

      @i_mazlov

      Gotcha. Thanks. Works as expected.

    • B

      Can I convert several PYP files to one PYPV file?

      Cinema 4D SDK
      • 2023 • • bentraje
      9
      0
      Votes
      9
      Posts
      1.6k
      Views

      B

      Closing the thread with the following conclusion.

      No native way to do it in C4D. Manually have to merge them then convert that one file to PYP.
      So have to manage separate project files. One for source ones and one for merging several PY files.

    • B

      Release API for Modifying Camera Selection on Render Queue

      Cinema 4D SDK
      • 2023 python • • bentraje
      5
      0
      Votes
      5
      Posts
      796
      Views

      B

      Thanks for the update @m_adam

    • B

      Unsolo a Node?

      Cinema 4D SDK
      • python 2023 • • bentraje
      5
      0
      Votes
      5
      Posts
      807
      Views

      B

      @m_adam

      Thanks. Works as expected!

    • B

      List All Nodes With No Filter?

      Cinema 4D SDK
      • python 2023 • • bentraje
      3
      0
      Votes
      3
      Posts
      606
      Views

      B

      RE: Yes, GraphModelHelper.ListAllNodes requires at least one attribute to be set in the data dictionary.

      Gotcha. Thanks for the clarification.
      Anyway, the suggested alternative (i.e. write a separate iterator) still works as expected. Same as before.

    • B

      Relative File Path Not Recognize by Plug-in?

      Cinema 4D SDK
      • 2023 python • • bentraje
      5
      0
      Votes
      5
      Posts
      977
      Views

      ferdinandF

      Hello @bentraje,

      Yes, the Python variant of GeGetPluginPath is not that useful as it just calls the C++ implementation which will then return the Python module path because the Python module is the C++ plugin which is calling GeGetPluginPath in that case. I will make the function description a bit more clear about that and also add a little example snippet for the module attribute __file__.

      And as what I would consider a fun fact:

      The __file__ attribute of modules is one of the many things where the language Python took inspiration from C/C++. In C++, __FILE__ is the macro which refers to the source file it is referenced in. I used this for example recently in the C++ Color Management examples to load an ICC file which is located next to a source file. But since users are usually not in the habit of compiling their C++ code themselves, or if they do, then want to move the resulting binary to a different place, __FILE__ is much less useful than __file__ as C++ there is a difference between the source and the executable.

      Cheers,
      Ferdinand

    • B

      Run a GUI Dialog AFTER C4D Launches not BEFORE?

      Cinema 4D SDK
      • python 2023 • • bentraje
      7
      0
      Votes
      7
      Posts
      1.3k
      Views

      B

      @ferdinand

      Thanks for the response.

      With the illustration code you provided, I misunderstood the documentation. Thanks for the clarification.

      Basically, I thought the

      PluginMessage/RegisterPlugin functions should be method (i.e. they should be under the class of the plugin data, command data etc).

      They actually live outside the classes.

      It now works as expected.
      Thanks! šŸ™‚

    • B

      Changing DataType of a Value Node

      Cinema 4D SDK
      • 2023 python • • bentraje
      3
      0
      Votes
      3
      Posts
      512
      Views

      ManuelM

      Hi @bentraje,

      Nodes and ports are GraphNode. A GraphNode can store any kind of maxon Data. Using SetValue or SetDefaultValue on the "True Node" level will not change the value of a port. That is why you still need to find the port you want to change the value.

      SetDefaultValue internally encapsulate the value in a maxon.Data and use the SetValue function to define the value for the ID DESCRIPTION::DATA::BASE::DEFAULTVALUE.

      I do not see any advantage using SetValue instead of SetDefaultValue.

      While the GraphNode can receive any kind of Maxon Data, you can still define the DataType it should use. You must use the function SetValue to define the ID "fixedtype". In c++ you would do something like this: port.SetValue(nodes::FixedPortType, GetDataType<neutron::OBJECT_FLAGS>()) iferr_return;.
      Unfortunately, you cannot do it with python because you cannot define the datatype.

      If the Datatype is not defined, it will be deducted from the incoming or outgoing connection.

      In the case of the "Type" node, you are defining the port's value with this ID "net.maxon.parametrictype.vec<2,float>". This ID will allow the system to call the right CoreNode to manage this kind of DataType. The Datatype of this port is maxon::Id.

      I hope it is a bit clearer. I will try to add that to one of our manuals or in the documentation itself.

      Cheers,
      Manuel