• Update generator plugin with FieldList sub-objects being updated

    python
    5
    0 Votes
    5 Posts
    538 Views
    bacaB
    Thamks @zipit, it works. Just noticed it has to be adjusted with GetClone(), otherwise I'm getting "link is not alive" error def get_field_layers(op): """ Returns all field layers that are referenced in a field list. """ def flatten_tree(node): """ Listifies a GeListNode tree. """ res = [] while node: res.append(node.GetClone()) for child in node.GetChildren(): res += flatten_tree(child) node = node.GetNext() return res # get the GeListHead for the FieldList root = op.GetLayersRoot() if root is None: return [] # Get the first node under the GeListHead first = root.GetFirst() if first is None: return []
  • Add and Remove Edge Loops Poly Object

    python r19
    12
    1
    0 Votes
    12 Posts
    3k Views
    A
    Hi @r_gigante, Not to worry! I understand! Thanks for your help! Andre
  • Prevent Projects from opening if dragged.

    python sdk
    5
    0 Votes
    5 Posts
    874 Views
    lasselauchL
    @mp5gosu Whooop! Thanks, Robert! You have to return a tuple so return (c4d.NOTOK, False) does the trick for me. Thank you!!! Cheers, Lasse
  • Set Xray in GetVirtualObjects()

    6
    0 Votes
    6 Posts
    777 Views
    RenatoTR
    Thanks R, the insert was an error, i already corrected. OBJECT_USECACHECOLOR work as expected Cheers Renato
  • Changing parameters broken in S22

    5
    0 Votes
    5 Posts
    913 Views
    M
    @m_adam Thanks for clarifying!
  • Using "config" plugins to modify the loading queue in R19

    Moved r19 c++
    4
    0 Votes
    4 Posts
    1k Views
    r_giganteR
    Hi @hazzzel, thanks for reaching out us. The QueryStartupOrder() has been introduced in R20 and there's no way to call it on previous releases. As suggested by @kbar , you're instead supposed to make use of the SetPluginPriority() as shown in the Plugin Functions Manual / Priority section to properly specify the plugin priority and control the loading time. Cheers, R
  • Custom mouse icon, define touch point.

    4
    0 Votes
    4 Posts
    705 Views
    RenatoTR
    Anyway, i'll add my custom offset to the mouse coordinate to match the point from the center, as seem by default.
  • SnapCore and Intersect

    4
    0 Votes
    4 Posts
    594 Views
    RenatoTR
    Hi Maxime. Thanks for reply. At last I used the BVHTree for that.
  • Creating a Script to Automatically Change Asset File Paths

    2
    0 Votes
    2 Posts
    630 Views
    r_giganteR
    Hi @ktheorin1, thanks for reaching out us and welcome to the Forum. To find all the assets in a given scene you can use the BaseDocument::GetAllAssetsNew() which returns you a list of dictionaries with all the assets contained in a document. The example below retrieves all the textures in the active document and append the string "_replaced" at the end of it def main(): textures = list() # execute the GetAllAssetsNew for the current document c4d.documents.GetAllAssetsNew(doc, False, "", c4d.ASSETDATA_FLAG_TEXTURESONLY, textures) for t in textures: textureOwner = t["owner"] textureURL = maxon.Url(t["filename"]) # get the texture suffix textureSuffix = textureURL.GetSuffix() # remove the suffix from the URL textureURL.ClearSuffix() # replace the name by adding the word "_replaced" textureURL.SetName(textureURL.GetName() + "_replaced") # set again the suffix to the URL textureURL.SetSuffix(textureSuffix) #update the textureOwner parameter textureOwner[c4d.BITMAPSHADER_FILENAME] = textureURL.GetSystemPath() # notify Cinema about the changes c4d.EventAdd() It's also worthy having a look at the maxon::Url to handy manage the path of the retrieved textures. Cheers, R
  • Detecting unsaved changes

    3
    0 Votes
    3 Posts
    625 Views
    P
    Is BaseDocument.GetChanged() what you want? See Changed Mode.
  • 0 Votes
    6 Posts
    1k Views
    ferdinandF
    Hi, I am sorry, I hate it myself when people talk in acronyms, assuming everyone knows what they are referring to. PNG stands for Pseudo-random Number Generator. Here is an example for a simple trigonometric pseudo random hash function. Cheers, zipit """A simple example for a very simple "one-at-a-time" Pseudo-random Number Generator (PNG). It is basically just one line of code, which you can find on line 32. """ import c4d import math def hash_11(x, seed=1234, magic=(1234.4567, 98765.4321)): """Returns a pseudo random floating point hash for a floating point number. The hash will lie int the interval [-1, 1] and the function is a very simple generator that exploits the periodicity of the trigonometric functions. A more sophisticated approach would be to exploit avalanche behavior in bit-shift operations on binary data, like the Jenkins Rotation does for example. The postfix in the name (_11) is a common way to denote the inputs and outputs for PNGs. 11 means that it will take one (real) number and return one (real) number. 13 means that it takes one and returns three, i.e. returns an (euclidean) vector. Args: x (float): The value to hash into a pseudo random number. seed (int, optional): The seed value. This could also be a float. magic (tuple, optional): The magic numbers. The second one should be bigger then the first and both should be real numbers. Returns: float: The pseudo random hash for x in the interval [-1, 1]. """ return math.modf(math.sin(x + seed + magic[0]) * magic[1])[0] def hash_13(x, seed=1234, magic=(1234.4567, 98765.4321)): """Returns a pseudo random vector hash for a floating point number. Wraps around hash_11. Returns: c4d.Vector: The pseudo random hash for x in the interval [-1, 1]. """ vx = hash_11(x, seed, magic) vy = hash_11(x + vx, seed, magic) vz = hash_11(x + vy, seed, magic) return c4d.Vector(vx, vy, vz) def main(): """Entry point. """ # Some very crude statistics for the hashes. samples = int(1E6) # Generate 1E6 of each numbers = {i: hash_11(i) for i in range(samples)} vectors = {i: hash_13(i) for i in range(samples)} # Compute their arithmetic mean. amean_numbers = sum(numbers.values()) * (1./samples) amean_vectors = sum(vectors.values()) * (1./samples) # Report the results. print "First three random numbers: ", numbers.values()[:3] print "First three random vectors: ", vectors.values()[:3] msg = "Arithmetic mean of all random numbers (should converge to zero): " print msg, amean_numbers msg = "Arithmetic mean of all random vectors (should converge to zero): " print msg, amean_vectors if __name__ == "__main__": main() First three random numbers: [-0.8036933662078809, 0.20401213006516628, 0.6249060598929645] First three random vectors: [Vector(-0.804, -0.022, -0.872), Vector(0.204, 0.541, 0.115), Vector(0.625, 0.782, 0.896)] Arithmetic mean of all random numbers (should converge to zero): -0.000127638074863 Arithmetic mean of all random vectors (should converge to zero): Vector(0, 0, 0)
  • << Multiple Values>> in Attribute Manager

    c++ r20 sdk
    3
    0 Votes
    3 Posts
    476 Views
    D
    Thanks! That's exactly what I needed!
  • Python 3.7.7 will be in the next release of Cinema 4D

    6
    1
    0 Votes
    6 Posts
    1k Views
    ?
    I have been looking at my plugins and my biggest question so far is how to handle urllib2 in a way that will work with both Python 2.7 and 3.7.7. Everything else just seems to be adding parentheses to print functions. I found this Cheat Sheet: Writing Python 2-3 compatible code that suggests: # Python 2 and 3: easiest option from future.standard_library import install_aliases install_aliases() from urllib.parse import urlparse, urlencode from urllib.request import urlopen, Request from urllib.error import HTTPError However, trying that in Cinema 4D threw this error: ImportError: No module named future.standard_library Fortunately, there are some alternatives to try, like # Python 2 and 3: alternative 4 try: from urllib.parse import urlparse, urlencode from urllib.request import urlopen, Request from urllib.error import HTTPError except ImportError: from urlparse import urlparse from urllib import urlencode from urllib2 import urlopen, Request, HTTPError From that article: "urllib is the hardest module to use from Python 2/3 compatible code."
  • SetAllPoints() Not Working On An Object With Skin/Bind

    r21 python
    9
    0 Votes
    9 Posts
    1k Views
    B
    @m_adam Thanks for the response. RE: without enabling the Post Deformers option. It seems like so. I initially thought I could reverse engineer it by getting the point's skin influence (its joint and its weight) and in a way factor it with the intended world vector. However, I gave up since I realize point can have several joints and several weight. Haha Don't get me wrong, enabling the post deformer works as expected. The problem comes because of its inherent nature "calculate the points position of the morph after they are deformed by a Deformer." It presupposes that the (near) last deformation comes from the pose morph. For example, Squash/Stretch>Bulge>Bend>Twist>Pose Morph. However, there are cases where the intended deformation is Pose Morph>Squash/Stretch>Bulge>Bend>Twist. So having the post deformer off while still getting the world position desired gives a bit of flexibility. Anyhow, thanks again for the help. I'll just use the post deformer for now and see where I get stuck. Have a great day ahead!
  • gui.ColorDialog() offers no options

    3
    0 Votes
    3 Posts
    611 Views
    M
    And I should have opened my eyes previously, but c4d.POPUP_BELOW shouldn't be used but instead color=gui.ColorDialog(0). I will improve the python documentation n this regards, for more information see the c++ doc about GeColorChoose. So this is not a bug. Cheers, Maxime.
  • Max value of an EditNumberArrows in TagData

    s22 python
    3
    0 Votes
    3 Posts
    356 Views
    ?
    @m_adam Thanks, Maxime!
  • Mute Object Animation

    r21 python
    5
    0 Votes
    5 Posts
    453 Views
    B
    @zipit Gotcha. Thanks for the reminder
  • Best coding practices

    python
    3
    0 Votes
    3 Posts
    611 Views
    mfersaouiM
    @zipit Thank you much.
  • Close Cinema 4D with C++ plugin??

    c++ r21
    3
    0 Votes
    3 Posts
    415 Views
    J
    That is a great idea! Thank you!
  • Getting and setting frame range from RenderData

    2
    0 Votes
    2 Posts
    645 Views
    r_giganteR
    Hi @nicholas_yue thanks for reaching out us. Although I'm not sure if your post was meant as a question or as a statement I'm going, nevertheless, to share some thoughts. The data you're looking for are stored in the RenderData BaseContainer and you can set/get them using the usual method. A full exmaple is available on PluginCafe Github Repo. Put down in words the code might looks like something as: def printRDataInfo(in_rdata): # BaseTime values are printed as frame print in_rdata[c4d.RDATA_FRAMEFROM].GetFrame(doc.GetFps()) print in_rdata[c4d.RDATA_FRAMETO].GetFrame(doc.GetFps()) print in_rdata[c4d.RDATA_FRAMESTEP] # Main function def main(): # retrieve the RenderData instance rdata = doc.GetActiveRenderData() #just print the default values print "default rdata from/to/step values" printRDataInfo(rdata) # start is at sec 1 rdata[c4d.RDATA_FRAMEFROM] = c4d.BaseTime(1) # end is at sec 2 rdata[c4d.RDATA_FRAMETO] = c4d.BaseTime(2) rdata[c4d.RDATA_FRAMESTEP] = 1 #just print again the values print "first change with values to secs" printRDataInfo(rdata) # start is at frame 5 rdata[c4d.RDATA_FRAMEFROM] = c4d.BaseTime( 5.0, doc.GetFps()) # end is at frame 15 rdata[c4d.RDATA_FRAMETO] = c4d.BaseTime( 15.0, doc.GetFps()) rdata[c4d.RDATA_FRAMESTEP] = 1 #just print again the values print "second change with values to frames" printRDataInfo(rdata) Cheers, R