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. orestiskon
    3. Topics
    • Profile
    • Following 0
    • Followers 0
    • Topics 22
    • Posts 64
    • Best 4
    • Controversial 0
    • Groups 0

    Topics created by orestiskon

    • orestiskonO

      How to get Redshift material assignments

      Cinema 4D SDK
      • python • • orestiskon
      4
      0
      Votes
      4
      Posts
      734
      Views

      ManuelM

      hi,

      I got some feedback from the devs. The function ObjectFromIndex have a parameter to define the document. That mean the list can contain material tags from a different document. The "problem" is that ObjectFromIndex return the number of tags in the list, and not only the number of tags in the list that are present in the current document. Old Redshift materials have a mechanism to optimized and avoid rendering the preview thumbnail on the attribut manager when it is not necessary. That mechanism renders the material on a different document. That is why the entry on the list is "None" because the tag is not present in the document passed to the function ObjectFromIndex.

      Cheers,
      Manuel

    • orestiskonO

      C4D Freezes after consecutive Import/Export

      Cinema 4D SDK
      • python • • orestiskon
      4
      0
      Votes
      4
      Posts
      852
      Views

      ferdinandF

      Hello @orestiskon,

      without any further questions, we will consider this topic as solved by Tuesday, November the 2nd and flag it accordingly.

      Thank you for your understanding,
      Ferdinand

    • orestiskonO

      Get identical document as the Render document

      Cinema 4D SDK
      • python • • orestiskon
      5
      0
      Votes
      5
      Posts
      893
      Views

      ferdinandF

      Hello @orestiskon,

      without any further questions, we will consider this topic as solved by Tuesday, November the 2nd and flag it accordingly.

      Thank you for your understanding,
      Ferdinand

    • orestiskonO

      How to check if document is rendering?

      Cinema 4D SDK
      • python • • orestiskon
      6
      0
      Votes
      6
      Posts
      1.2k
      Views

      P

      Hey sorry for gravedigging.

      i have the problem that my tag plugin recognises the difference between rendering and not rendering. unfortunately it also always changes the state in the doc itself and not only in the doc that is rendered

      grafik.png

    • orestiskonO

      Creating "Objects" on Python tag

      Cinema 4D SDK
      • python • • orestiskon
      3
      0
      Votes
      3
      Posts
      497
      Views

      orestiskonO

      @m_adam That clears it up, thanks Maxime!

    • orestiskonO

      Where to find .res documentation?

      Cinema 4D SDK
      • • • orestiskon
      3
      0
      Votes
      3
      Posts
      466
      Views

      orestiskonO

      @m_magalhaes Thanks Manuel!

    • orestiskonO

      Faster way of converting dict of Vector3 to Vector4

      Cinema 4D SDK
      • python • • orestiskon
      3
      0
      Votes
      3
      Posts
      556
      Views

      orestiskonO

      @m_adam Thanks a lot for the benchmarking Maxime. I was planning to go for the string method, I'm surprised it's not faster.

      I wasn't planning to use this for a plugin, not to mention C++, but it's good information to have.

    • orestiskonO

      Calculation Errors and Best Practices

      Cinema 4D SDK
      • • • orestiskon
      5
      0
      Votes
      5
      Posts
      853
      Views

      ferdinandF

      Hello @orestiskon,

      well, are you experiencing "drift"? I am not 100% sure what you mean by drift, but I assume you mean just an error with that.

      As I lined out above, floating point error at 64 bits is usually not something you have to worry about in the scenario of what you are doing. There will be an error, but if you are only interested in visually representing something, it will be negligible when you meet the conditions I did line out above. I also do not get quite why you have to store the scale of the matrix. When you transform an input matrix with another matrix that has the scale of (1,1,1), then scale of the result will have the same scale as the input matrix, since x * 1 is still x.

      In general, you try to avoid doing multiple arithmetic operations in a row (see example at the end). Which is also the reason I proposed interpolations. But again, for just moving a cube around, you should be fine.

      Cheers,
      Ferdinand

      """Showcases the impact of doing the same calculation in 'different' ways. """ import math # List of ten 1.1's, 1.1 cannot be represented by 64 bit floats. items = [1.1] * 10 # This will amass the precision error of ten additions of a not representable # value. print (sum(items)) # This won't. print ((1.1 * 10)) # And this won't either. print (9.9 + 1.1) # One of Python's floating point tricks, fsum is addition with an error term. print (math.fsum(items)) 10.999999999999998 11.0 11.0 11.0
    • orestiskonO

      Arranging Objects by order of Object Manager

      Cinema 4D SDK
      • python • • orestiskon
      10
      0
      Votes
      10
      Posts
      1.9k
      Views

      ferdinandF

      Hello @orestiskon,

      without any further questions, we will consider this topic as solved by Monday, the 25th and flag it accordingly.

      Thank you for your understanding,
      Ferdinand

    • orestiskonO

      Hide "Camera Dependent" from PriorityData

      Cinema 4D SDK
      • python • • orestiskon
      3
      0
      Votes
      3
      Posts
      479
      Views

      orestiskonO

      Thanks Maxime,
      "NOCAMERA;" worked, and the priority was a typo, now it does work!

    • orestiskonO

      Interfacing with Gumroad's API

      General Talk
      • python • • orestiskon
      16
      0
      Votes
      16
      Posts
      4.0k
      Views

      kbarK

      Just one last comment on this licensing issue.

      I have a video that tells users how to install and license my own plugins for R21 upwards.

      It has been viewed 33,882 times as of today. It is my most watched video every month.

      I don’t have that many customers or sales.

      These views are from regular C4D users using Google to figure out what to do now since the old way is gone.

    • orestiskonO

      How to Hide Generator Plugin from the menu?

      Cinema 4D SDK
      • python • • orestiskon
      5
      0
      Votes
      5
      Posts
      715
      Views

      M

      Unfortually no you can't.

    • orestiskonO

      Some basic questions on BaseContainer

      Cinema 4D SDK
      • python • • orestiskon
      8
      0
      Votes
      8
      Posts
      1.4k
      Views

      ferdinandF

      Hi @orestiskon,

      thank you for flagging the topic as answered.

      Cheers,
      Ferdinand

    • orestiskonO

      Best Practice to transfer a variable from another function?

      Cinema 4D SDK
      • python sdk • • orestiskon
      3
      0
      Votes
      3
      Posts
      465
      Views

      orestiskonO

      Thanks Manuel, yes that's how I ended up doing it in the end.

      I thought it would've been simpler to extract a variable from the main function, since it had already calculated. All I would need is to save the variable somewhere where the button function can read it, so this is where I tried the global variables but it didn't work.

    • orestiskonO

      How to get all elements from BaseSelect

      Cinema 4D SDK
      • • • orestiskon
      3
      0
      Votes
      3
      Posts
      573
      Views

      orestiskonO

      Thanks @ferdinand , I misinterpreted the GetRange argument. That clears it up, and thanks for the example as well, it's very useful!

    • orestiskonO

      How to refresh a deleted object link in Python?

      Cinema 4D SDK
      • • • orestiskon
      6
      0
      Votes
      6
      Posts
      1.3k
      Views

      X

      Hi:

      It feels like a good question, otherwise I wouldn't have known that XPresso had this problem.I think your problem is that XPresso Tag adds links to user data.If you add user data links to Python nodes, you will have no problem putting splines in the links.Or drag the spline directly to XPresso manager, output the object, there will be no problem.

      import c4d #Welcome to the world of Python def main(): #global spline global obj global time spline = op[c4d.ID_USERDATA,1] if spline != None: SplineHelp = c4d.utils.SplineHelp() SplineHelp.InitSpline(spline) offset = SplineHelp.GetOffsetFromReal(time, 0) pos = SplineHelp.GetPos(offset) #print(pos) obj.SetAbsPos(pos)

      7854567857885.jpg

    • orestiskonO

      Python: Global Variable vs Plugin ID

      General Talk
      • python sdk • • orestiskon
      6
      0
      Votes
      6
      Posts
      1.8k
      Views

      M

      Hi while previous answers give some hints I would like to provide more in-depth answers to these questions.

      First, what is a global variable?
      In Python, a global variable is a variable that is stored in the dictionary returned by "globals()".
      The globals() function returns a dictionary that is local to the current Python Scope.
      Note that a Python scope only lives for a given time and is not persistent.
      This means it doesn't save its state or current data to a file so if you restart Cinema 4D, it starts with a fresh new Python Scope) but as long as the host object of the Python Scope is alive the data will be stored.

      So few things to know about Python implementation within Cinema 4D.
      Each BaseList2D that implements a Python implementation (Python Generator, Python Scripting Tag, Python Xpresso, Field Layer) has its own Python Scope.
      That means if I have two Python Generator they don't share the same Python Scope. But they both have a distinct one.

      Now in a case of a plugin, it's a bit tricky, if you use a global variable let's say in an ObjectData.
      The global variable will be available for all instances (BaseObject) of this ObjectData. This is because a BaseObject is an instance of an ObjectData implementation.
      And since there is only one implementation (your ObjectData that uses the global variable) they all use the same global variable.

      Now when you refer to plugin ID, it's a kind of term abuse.
      A plugin ID is a unique ID (aka a number who is unique into Cinema 4D context).
      And can be retrieved from https://developers.maxon.net/forum/pid (you must be logged).

      So a Plugin ID can be used to register a plugin.
      When you write BaseObject(100000) Cinema 4D will look at the ObjectData that is registered at the ID 100000 and create a BaseObject that will implement this particular ObjectData.
      But you can also use a PluginId (or aka a Unique ID) to register a data into a BaseContainer.

      But what is a BaseContainer?
      BaseDocument, Objects, tag and pretty much everything a user can find in C4D inherit from BaseList2D, and get a BaseContainer.
      A BaseContainer is a kind of array (or a dictionary in python), where data are stored according to a given ID.
      This BaseContainer is owned by the host BaseList2D (seems logical but it's an important point).
      This way Cinema 4D has a generic way of storing and reading data. So Cinema 4D can automate few things such as saving automatically the data stored in this BaseContainer into a File (aka Cinema 4D File) and read them back when loading the Cinema 4D file.

      So back to our topic, if we assign a particular value to a "Plugin ID/Unique ID" you can assume that nothing within in Cinema 4D will overwrite this particular value.
      (Third-party developer can access this data however and may erase them, so that's why we recommend using a Unique ID when you store data in a BaseContainer, this way you are sure to not erase other people data and you're is ok).
      Of course, this works because everyone plays the game if I can tell.

      Now back to the initial questions.
      What's the use case of a global variable in Python in Cinema 4D ecosystem?

      Storing data across multiple frames. (Can also be done with a BaseContainer, but you have to convert to a DataType that BaseContaienr accept, so list, dict are not supported so you have to "bake" which is slow) Data are only alive for the current lifetime of the host and in maximum the Cinema 4D session.

      What's the use case of data stored in a BaseContainer in Cinema 4D?

      Storing data across multiple frames. (See the previous point in some case it may be ineffective). Storing persistent data over multiple Cinema 4D sessions (the data will be stored in the host, e.g. the Python Generator Object by itself, so if you open the file in Cinema 4D, the Python Generator will restore the data in the BaseContainer). Exposing data to others (Maybe other Objects want to know the current value stored in a particular Python Generator Object).

      Finally, BaseContainer should be primarily chosen but as stated in some condition it makes more sense to use a global variable.

      And here is how to define a global variable within a Python Generator:

      import c4d # Checks if the test variables exist in the global dict, if not assign a value of 10 global test if 'test' not in globals(): test = 10 def main(): global test print test return c4d.BaseObject(c4d.Ocube)

      I hope it answers your questions. Additionally please read BaseContainer Manual.

      Cheers,
      Maxime.

    • orestiskonO

      Getting cache of a Python Generator under a Python Generator

      Cinema 4D SDK
      • python sdk • • orestiskon
      3
      0
      Votes
      3
      Posts
      684
      Views

      M

      Hi @orestiskon SendModelingCommand and especially CurrentStateToObject need the object to be actually in the passed document.

      So you need to create a temporary doc and use it to operates.
      As bellow:

      import c4d def currentState(obj) : return c4d.utils.SendModelingCommand(c4d.MCOMMAND_CURRENTSTATETOOBJECT,[obj],c4d.MODELINGCOMMANDMODE_ALL,c4d.BaseContainer(),obj.GetDocument())[0] def main(): # Retrieve the python generator obj = op.GetDown() if obj is None: return objClone = obj.GetClone() if objClone is None: raise RuntimeError("Failed to clone the object") # Make the children Python Generator disapear obj.Touch() # Creates a temporary document that will be used to evaluate the cache of the object tempDoc = c4d.documents.BaseDocument() if tempDoc is None: raise RuntimeError("Failed to create a temporary doc") # Inserts the child python generator that exists only in memory into our tempo doc tempDoc.InsertObject(objClone) returnedObj = currentState(objClone) return currentState(objClone)

      Cheers,
      Maxime.

    • orestiskonO

      Python Generator: Getting polygon data from new generators

      Cinema 4D SDK
      • python sdk • • orestiskon
      6
      0
      Votes
      6
      Posts
      1.3k
      Views

      ferdinandF

      I did that for the same reason @m_adam created a copy in his version: A node can only be member of one document at a time and also only be inserted exactly one time into the same document (long way of saying that Cinema is monohierachical).

      Cheers
      zipit

    • orestiskonO

      Python Tag: Matrix is always dirty? (or vice versa)

      Cinema 4D SDK
      • sdk python • • orestiskon
      9
      0
      Votes
      9
      Posts
      1.3k
      Views

      M

      Hi @orestiskon I'm afraid there is nothing much more to say except what @zipit said.

      Just a few notes:

      IsDirty is build to be used within a generator to check the current object only. GetDirty retrieves an integer value ta represents the dirty state of an object. It can be used to retrieve DirtyCount from outside.

      Now take into consideration that the matrix object is kind of special since in reality, it creates nothing. But only feed some MoData and display them (but create no geometry). So how does an object that creates nothing can have its cache dirty? That's why it's up to the object that modifies the MoData (stored in its hidden tag ID_MOTAGDATA) to tell the matrix its content is dirty so other people that rely on this matrix know about it.

      Additionally to what @zipit said (which will work in any case and it's preferred)
      You can also consider checking for the dirtiness of the linked effector (but this will not consider Field).
      Here an example in a Python Generator

      import c4d def CheckDirtyObj(obj, uuid, flag): """ Checks if an object by comparing the current Dirt Value with the one stored in the current op.BaseContainer :param obj: The BaseList2D to retrieve the dirty state from. :param uuid: The uuid used to store in the BaseContainer. :param flag: The dirtiness flag to check for. :return: True if the object is dirty, False otherwise. """ def GetBc(): """ Retrieves a BC stored in the object BC, or create it if it does not exist yet :return: A BaseContainer where value can be stored. """ bcId = 100001 # Make sure to obtain an UNIQUE ID in plugincafe.com bc = op.GetDataInstance().GetContainerInstance(bcId) if bc is None: op.GetDataInstance().SetContainer(bcId, c4d.BaseContainer()) bc = op.GetDataInstance().GetContainerInstance(bcId) if bc is None: raise RuntimeError("Unable to create BaseContainer") return bc # Retrieves the stored value and the true DirtyCount storedDirtyCount = GetBc().GetInt32(uuid, -1) dirtyCount = obj.GetDirty(flag) # Compares them, update stored value and return if storedDirtyCount != dirtyCount: GetBc().SetInt32(uuid, dirtyCount) return True return False def main(): # Retrieve attached object and check if it's a matrix object matrixObj = op[c4d.ID_USERDATA, 1] if matrixObj is None or not matrixObj.CheckType(1018545): return c4d.BaseObject(c4d.Onull) # Retrieve the current cache opCache = op.GetCache() # We need a new object if one of the next reason are False # The Cache is not valid # The Parameter or Matrix of the current generator changed # The Parameter or Matrix of the linked Matrix changed needNewObj = opCache is None needNewObj |= not opCache.IsAlive() needNewObj |= op.IsDirty(c4d.DIRTYFLAGS_DATA | c4d.DIRTYFLAGS_MATRIX) needNewObj |= CheckDirtyObj(matrixObj, 0, c4d.DIRTYFLAGS_DATA | c4d.DIRTYFLAGS_MATRIX) # The Parameter or Matrix of effectors of the linked Matrix changed objList = matrixObj[c4d.ID_MG_MOTIONGENERATOR_EFFECTORLIST] for objIndex in xrange(objList.GetObjectCount()): # If the effector is disabled in the effector list, skip it if not objList.GetFlags(objIndex): continue # If the effector is not valid or not enabled, skip it obj = objList.ObjectFromIndex(op.GetDocument(), objIndex) if obj is None or not obj.IsAlive() or not obj.GetDeformMode(): continue # Check for the dirty value stored (+1 because we already used ID 0 for the matrix object) needNewObj |= CheckDirtyObj(obj, objIndex + 1, c4d.DIRTYFLAGS_DATA | c4d.DIRTYFLAGS_MATRIX) if not needNewObj: print "Old Obj" return opCache print "Generated New Object" return c4d.BaseObject(c4d.Ocube)

      Cheers,
      Maxime.