• External dependencies question

    Cinema 4D SDK python
    3
    0 Votes
    3 Posts
    704 Views
    M
    Hi @mfersaoui there is nothing wrong with the way you are doing, but I would like to point out that the sys.path is a global variable shared over the current python environment. Meaning that 3rd party will be able also to import your own module so it's recommended to have an ambiguous name (e.g. if your module1.py is called util.py) people will be able to do import util and this can be really misleading so it's preferred to have a unique name (maybe you can start with a prefix). Finally, the solution offered by @mp5gosu is the cleanest one as it will create a local import space, so your util.py will only be importable by your own pyp file that actually calls the local import so it's so far the cleanest way as you are not "polluting" the global sys.path. But which one is the best, only you can decide according to what you are aiming to produce. Cheers, Maxime.
  • 0 Votes
    4 Posts
    511 Views
    ferdinandF
    Hi @blastframe, yes, that would be one, and probably the more modern way to do it. I personally like also an explicit call to the base implementation. I think it is more readable for someone else reading your code. But that is probably a rather subjective choice. So for clarity, I am speaking about something like this: foo = bar * baz return c4d.gui.GeUserArea.InputEvent(self, msg) There is of course the advantage of super taking care of calling the proper implementation(s) for you which is not taken care of by this approach, but you cannot have everything and in this case things are rather unambiguous for us here Cheers, Ferdinand
  • Run plugin every frame

    Moved Cinema 4D SDK
    3
    0 Votes
    3 Posts
    484 Views
    R
    After a few mails with Ferdinand I switched to a Tag plugin solution. This does the job perfectly. So the solution was not to use an Object data solution but a TagData. Thanx!
  • Undo Problem For TagData Plugin

    Cinema 4D SDK python r23
    4
    1
    0 Votes
    4 Posts
    616 Views
    ManuelM
    hi, @beatgram said in Undo Problem For TagData Plugin: So these bracket notation style is safer than using BaseContainer in any case? this should be exactly the same. Sorry i didn't got time to warp my head around it. Cheers, Manuel
  • Erratic Keyboard Messages in GeDialog

    Cinema 4D SDK python r23 windows
    7
    0 Votes
    7 Posts
    1k Views
    ?
    @mp5gosu Sorry, I missed it! That works! In case other devs have a solution, I'll mark yours as the right answer. Thank you!
  • 0 Votes
    3 Posts
    459 Views
    ?
    @ferdinand Thank you, Ferdinand for the thorough answer and ideas for workarounds. I don't quite have my head around how to use threading in Cinema 4D yet but you've inspired me to look into it. Thank you!
  • UVW coordinates in ShaderData.Output()

    Cinema 4D SDK r23 c++ python
    12
    3
    0 Votes
    12 Posts
    2k Views
    ManuelM
    hi, I don't see how we could do it with the Draw Method in a efficient way. Cheers, Manuel
  • Dialog Plugin with Progress Bar or SetStatusBar

    Cinema 4D SDK python
    12
    0 Votes
    12 Posts
    2k Views
    ferdinandF
    Hello @HerrMay, thank you for your reply. Please note that we prefer users to flag topics as solved, as doing it ourselves always comes with the danger of erroneously flagging a posting as solved. Please refer to our Forum Guidelines - Forum Feature: Ask as Question in case you do not know how to do this. Cheers, Ferdinand
  • CUSTOMGUI_FONTCHOOSER Text Disappears

    Cinema 4D SDK python windows r23
    5
    0 Votes
    5 Posts
    558 Views
    ferdinandF
    Hi @blastframe, so this is a bug that happens independently of Python. It also not connected to your example using a dangling dialog, but to the fact that it is using a dialog. When you implement some form of NodeData plugin and a FONT resource element in it, this bug won't happen. I have opened a bug report for this. For now you would have to either use my little workaround or move outside of a GeDialog environment an implement the whole plugin as some form of NodeData plugin. If a dialog is of high priority for you, you could also display an instance of that node in a DescriptionCustomGui inside your dialog. Which should work and somewhat be a mix of both options. Cheers, Ferdinand
  • Scaling a GeUserArea in a ScrollGroup

    Cinema 4D SDK python windows r23
    5
    0 Votes
    5 Posts
    933 Views
    ferdinandF
    Hello @blastframe, I forgot to put the final outcome for this here. So, after some back and forth we decided to not fix this for reasons I unfortunately cannot disclose. But we will update the documentation in an upcoming release to avoid this being as opaque as it currently is. This is probably not what you hoped for, but currently the best course of actions for us. Thank you for your understanding, Ferdinand
  • 0 Votes
    4 Posts
    762 Views
    M
    Hi @mp5gosu , I will set the topic as closed. Note that the fix will not come in the next update but don't worry we have it logged and it's on our list of things to fix in the future. Cheers, Maxime.
  • Polygon Islands Convenience Method?

    Cinema 4D SDK r23 python
    7
    1
    0 Votes
    7 Posts
    2k Views
    E
    Here is something I recently used to count UV Islands as well as get some other info import c4d from collections import defaultdict def get_uv_islands(obj, tol=1e-5): """ Compute UV islands for the given polygon object using its UVW tag. This version retrieves the UV dictionary for each polygon using uvTag.GetSlow(polyIndex), then groups connected polygons (sharing at least one UV coordinate) into islands using an iterative flood-fill algorithm. """ uvw_tag = obj.GetTag(c4d.Tuvw) if uvw_tag is None: c4d.gui.MessageDialog("The object does not have a UVW tag.") return None poly_count = obj.GetPolygonCount() # Build maps: # - face_to_uvs: mapping from polygon index to its set of rounded UV keys. # - uv_to_faces: reverse mapping from each UV key to the set of polygon indices using that UV. face_to_uvs = defaultdict(set) uv_to_faces = defaultdict(set) def uv_key(vec): # Round UV vector components to mitigate floating-point precision issues. return (round(vec.x, 5), round(vec.y, 5)) # Build connectivity maps based on each polygon's UV data. for poly_index in range(poly_count): poly = obj.GetPolygon(poly_index) uv_data = obj.GetTag(c4d.Tuvw).GetSlow(poly_index) # If the polygon is a triangle, remove the extraneous 'd' key. if poly.IsTriangle() and 'd' in uv_data: del uv_data['d'] for key in uv_data: uv_vec = uv_data[key] key_tuple = uv_key(uv_vec) face_to_uvs[poly_index].add(key_tuple) uv_to_faces[key_tuple].add(poly_index) # Use an iterative flood-fill to group connected faces. islands = [] faces_left = set(range(poly_count)) while faces_left: island = [] start_face = next(iter(faces_left)) # Pick an arbitrary face from unvisited ones. stack = [start_face] while stack: face_idx = stack.pop() if face_idx not in faces_left: continue faces_left.remove(face_idx) island.append(face_idx) # For every UV key in this face, add all neighboring faces. for uv_val in face_to_uvs[face_idx]: for neighbor in uv_to_faces[uv_val]: if neighbor in faces_left: stack.append(neighbor) islands.append(island) return islands def get_island_uv_center(obj, uvw_tag, island): """ Given a polygon object, its UVW tag, and an island (list of polygon indices), compute the UV bounding box and center. """ # Initialize min/max with infinities. min_u = float('inf') max_u = -float('inf') min_v = float('inf') max_v = -float('inf') # Gather unique UV coordinates from all faces in the island. unique_uvs = {} for face_idx in island: poly = obj.GetPolygon(face_idx) uv_data = uvw_tag.GetSlow(face_idx) if poly.IsTriangle() and 'd' in uv_data: del uv_data['d'] for key in uv_data: uv = uv_data[key] key_tuple = (round(uv.x, 6), round(uv.y, 6)) unique_uvs[key_tuple] = uv # Compute the bounding box. for uv in unique_uvs.values(): if uv.x < min_u: min_u = uv.x if uv.x > max_u: max_u = uv.x if uv.y < min_v: min_v = uv.y if uv.y > max_v: max_v = uv.y center_u = (min_u + max_u) / 2.0 # Invert V axis so the center is correct in UV space. center_v = 1.0 - ((min_v + max_v) / 2.0) return center_u, center_v, min_u, max_u, min_v, max_v def main(): doc = c4d.documents.GetActiveDocument() obj = doc.GetActiveObject() if obj is None: c4d.gui.MessageDialog("Please select a polygon object.") return uvw_tag = obj.GetTag(c4d.Tuvw) if uvw_tag is None: c4d.gui.MessageDialog("The object does not have a UVW tag!") return islands = get_uv_islands(obj) if islands is None: return num_islands = len(islands) print("Number of UV islands:", num_islands) for idx, island in enumerate(islands): center_u, center_v, min_u, max_u, min_v, max_v = get_island_uv_center(obj, uvw_tag, island) print("Island", idx, "has faces:", island) print("Island Num",idx," Bounding Box: U [{:.6f}, {:.6f}], V [{:.6f}, {:.6f}]".format(min_u, max_u, min_v, max_v)) print(" Center: U = {:.6f}, V = {:.6f}".format(center_u, center_v)) if __name__=='__main__': main() Output looks something like Number of UV islands: 2 Island 0 has faces: [0, 5, 3, 4] Island Num 0 Bounding Box: U [0.004902, 0.495098], V [0.004902, 0.740196] Center: U = 0.250000, V = 0.627451 Island 1 has faces: [1, 2] Island Num 1 Bounding Box: U [0.004902, 0.495098], V [0.750000, 0.995098] Center: U = 0.250000, V = 0.127451 Hope it is useful!
  • SSL TLSV1_ALERT_PROTOCOL_VERSION Error on Mac

    Cinema 4D SDK r19 python macos
    3
    0 Votes
    3 Posts
    1k Views
    ?
    @m_adam Thank you, Maxime! Have a good weekend.
  • Handles in R18

    Cinema 4D SDK python r19 windows
    3
    1
    0 Votes
    3 Posts
    683 Views
    ?
    Thank you for letting me know, @ferdinand !
  • 0 Votes
    6 Posts
    1k Views
    P
    forget about it. i removed the c4d.OBJECT_INPUT flag during development and forgot to add it back.
  • How to know baking is end with BakeTextureTag?

    Cinema 4D SDK python r19
    7
    0 Votes
    7 Posts
    1k Views
    M
    Hi @velbie with the latest update of Cinema 4D (R24 SP1), the BAKE_TEX_AO_VERTEXMAPS issue is fixed. Cheers, Maxime.
  • Querying and Storing Object Information

    Moved Cinema 4D SDK python
    9
    0 Votes
    9 Posts
    2k Views
    ferdinandF
    Hi @Sturdy_Penguin , without further questions or feedback, we will consider this thread as solved by Monday and flag it accordingly. Cheers, Ferdinand
  • 0 Votes
    8 Posts
    1k Views
    beatgramB
    @Cairyn Thank you so much for helping me again!
  • 0 Votes
    4 Posts
    982 Views
    M
    thank you for your help, I am trying to understand ... am I right in the assumption that this is not "clean code" in a pythonic sense ? kind regards
  • Gets the point weight of the Field object.

    Cinema 4D SDK
    2
    0 Votes
    2 Posts
    555 Views
    ferdinandF
    Hi @x_nerve, thank you for reaching out to us. The most straightforward way to sample a FieldObject is FieldObject.Sample; there are also other sample methods attached to the various fields related classes, most notably c4d.FieldList. We have two examples in the Python SDK examples which showcase field sampling, fieldlist_sampling_r20 and fieldobject_sampling_20. You also mention "Is there a way to get the weight of the cube field points?"; you are probably aware of this, but since your phrasing could imply otherwise, it seems noteworthy to point out that fields are not discrete. So in other words, there is no finite amount of points you can exhaustively sample for a field object, since the object is non-discrete. You have to pick a point or a set of points you want to sample for a field object, which can be any point in in the value range c4d.Vector can handle. If there are any questions left, please do not hesitate to ask. Cheers, Ferdinand