• update error?

    r20 python
    10
    0 Votes
    10 Posts
    2k Views
    JH23J
    I want to finish with this in case someone reads it. Years ago, I asked about the outdated methods when using these techniques. I tried to adjust the depth of the IK spline controls with the actual length of the spline itself. Today, I understand my mistake, as I was trying something that didn’t make logical sense. At the time, I thought it was the best option for what I was looking for. In short, this was never a problem, and the low response time is normal because the length depends on the depth of the controls. I thought there would be a solution, but choosing this path was not useful. In conclusion, what eventually satisfied my requirements was directly referencing the angles of the controls, meaning identifying how oriented each control is to another. I took this angle and used it as a factor to multiply by the depth. This model is much more logical and doesn’t have any flaws. At the time, I couldn’t think of a direct solution, but I didn’t want to leave this post like that. Thanks anyway, Ferdinand, for trying to help me. Cheers JH
  • Polygon Islands Convenience Method?

    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!
  • How to create UV of obj.

    windows python 2025
    4
    0 Votes
    4 Posts
    680 Views
    M
    I use this to Thank You Ferdinand. This is how I imagine an SDK example should look like .... a simplest version , an altered simple version and a complex touching the boundaries of the subject. I am thankful and praise your work .... ! cheers mogh
  • create link parameter accept Alembic tag

    r21 2025 c++
    3
    0 Votes
    3 Posts
    600 Views
    B
    @m_adam, Thank you! Yes, Message(GeListNode* node, Int32 type, void* data) works for me. I'm wondering shall my plugin just return true after processing MSG_DESCRIPTION_CHECKDRAGANDDROP in the Message() function (set the value of DescriptionCheckDragAndDrop::_result) or still call SUPER::Message(node, type, data); at the end? It looks to me that calling SUPER::Message(node, type, data); at the end still works. But the example in MSG_DESCRIPTION_CHECKDRAGANDDROP Message doesn't call SUPER::Message(node, type, data);. Thanks!
  • Read Alembic tag's data

    r21 2025 c++
    3
    0 Votes
    3 Posts
    574 Views
    B
    @m_adam, Thank you very much, this works for me!
  • Plugin does not appear in Expression on client's Cinema 4D

    s26 2024 c++ windows
    24
    1
    0 Votes
    24 Posts
    4k Views
    Y
    Oh, you've edited your previous message! Thanks! I will try it.
  • Order Of Hierarchy Updates For Fieldobjects

    2025 c++
    3
    0 Votes
    3 Posts
    539 Views
    J
    @ferdinand Thanks for the response. That's what I was afraid the situation would be, I believe I have a work around that will be able to fulfill what I need it to do. John Thomas
  • Volume Builder Type Fog Should it be solid?

    c++ 2024
    3
    1
    0 Votes
    3 Posts
    541 Views
    D
    Hi @m_adam , Thank you so much! That was exactly what I needed. Dan
  • How to store "cached" data in the document from the scenehook?

    c++
    17
    0 Votes
    17 Posts
    2k Views
    H
    Hi Ferdinand, Yes, I remember reading about that, so the IDs for this container data is 5060 and 5061 (I work in IP telephony as my day job so this is surely no coincidence), but I even tried to move them to 50060 and 50061 and the freeze still happens. I will pack up the project shortly and email it in.
  • How to drag rows in Treeview

    2024 python
    4
    1
    0 Votes
    4 Posts
    588 Views
    chuanzhenC
    @ferdinand Thanks for your help!
  • 0 Votes
    10 Posts
    1k Views
    B
    Thank you very much for all your detailed explanation, @ferdinand!
  • 0 Votes
    4 Posts
    534 Views
    ferdinandF
    Hey @vhardy, yes, @m_adam as supporting expressions on his Todo list for the VS Code bridge. But it is not very high in our priority list, you are the first user requesting it. I gave the subject a gentle nudge in our task tracking. FYI: Generally we do not make any guarantees if or when we will implement something. Cheers, Ferdinand
  • Merging files with PLUGINFLAG_SCENELOADER_MERGEORIGINAL

    2025 c++
    3
    0 Votes
    3 Posts
    566 Views
    ferdinandF
    Hey, so I talked with Fritz, I got the direction right, but there are some relevant details. When you set the flag for an importer hook, it signals that you do not want Cinema 4D to carry out the automatic scene color conversion along the conversion path implied in the settings. So, when you have a importer, and it does NOT set the flag, and you would import a scene with these settings: [image: 1740580639731-c3e3d6f8-2734-41d2-abfb-f7af807c12f8-image.png] Cinema 4D would transform all scene colors from sRGB-2.1 to the Render Space. When you DO set the flag, Cinema 4D will NOT do that, and the importer is expected to handle that. So, when you need to set this flag, this implicitly means that something with your scene data is not correct, they are not meant to be sRGB. You can of course also change the respective setting, Raw for example means as always no conversion. Without a bit more details about your scene data and its provenance, it is hard to give here good advice. Cheers, Ferdinand PS: I might update the im/exporter examples at some point to showcase the custom case, but the default should be to NOT to set the flag, and let the intended color management of Cinema 4D do its work.
  • GeListNode from ShaderData::Read function does not have a document?

    c++
    3
    0 Votes
    3 Posts
    555 Views
    M
    Hi, yes, this is expected, and documented in NodeData::Read() / NodeData::Write() Manual. With that's said Read/Write is supposed to serialize data of your object (most of the time member variable) to the c4d file (the HyperFile), so accessing the BaseDocument is a sign of a bad design. May I ask why do you really want to access the BaseDocument in the Read function? Cheers, Maxime edit (@ferdinand): Just to be clear here, as we briefly talked about this in our morning meeting, what the docs write there is in a certain sense legacy information. When a branch, e.g., the Xbase (shader) branch of a material is being deserialized, the to be deserialized node is inserted into the branch and with that will have access to a document. But what @m_adam wrote is of course true, the document in this context is the fruit from the forbidden tree, as the node is not yet fully deserialized and certain parts of the GeListHead::Read, GeListNode::Read, BaseList2D::Read, ..., YourPluginLayer::Read deserialization chain might pull all sorts of tricks to carry out the deserialization, including temporarily removing the node from the scene graph. The documentation is therefore effectively still correct, as deserializing a node should never rely on the document context and accessing the document is forbidden in that context.
  • 0 Votes
    7 Posts
    1k Views
    M
    Ok Understood, Ok I guess that explains my "nice" comb from the cache and my jagged flip/flop . sometimes zero comb from the "full" matrix normal ... I also have different tangents from manually "calculating" them then v3, v2. But I will make a "sanity" check this weekend (feed manual matrixes into my code instead of spline "point" matrixes), before I post about this. Thanks Ferdinand I'll divide and conquer away.
  • Storage issues with plugin settings

    2023 python windows
    3
    2
    0 Votes
    3 Posts
    628 Views
    N
    Thank you for @Dunhou answer. It was ultimately completed in JSON format
  • 0 Votes
    2 Posts
    558 Views
    ferdinandF
    Hello @patrick_cue, Welcome to the Maxon developers forum and its community, it is great to have you with us! Getting Started Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules. Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment. Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support. Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads. It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: Asking Questions. About your First Question Please do not use other topics for your support requests, especially when they are bug tickets. Asking a follow-up questions such as "when will this be fixed" or "does this also apply to situation B" in a foreign topic is allowed and even encouraged. But a specific case with your specific code and data always warrants a new thread. Please also familiarize yourself with Support Procedures: Asking Questions, as while it its clear that you put effort into make yourself understood (thanks!), this is also bordering a bit on the too much information. The bug tracked by the other topic, is that there is currently no way in the Python API to use c4d.documents.RenderDocument in an OCIO document (i.e., every document since 2025.0) and then display that bitmap with the correct colors via c4d.bitmaps.ShowBitmap. It is important to understand that: The bitmap data generated is just fine, when you save the bitmap to disk, everything is correct. It is just that the Picture Viewer does not display it incorrectly. The reason for that is that in Python OCIO is not fully exposed in 2025.1.0 and you cannot set the OCIO profiles of the rendered bitmap there. Internally, we have been working on an OCIO port for Python allowing for color conversions and more things, including OCIO managing bitmaps. We also added a function to bake a display and view transform into an sRGB image - another route how this RenderDocument issue can be solved. The goal is to publish this with an upcoming version of the Python SDK, ideally the next, but as always we cannot make any guarantees. You cannot fix this issue yourself in 2025.1.0 and lower. Cheers, Ferdinand
  • Image Viewer API

    2024 s26 python
    6
    0 Votes
    6 Posts
    866 Views
    K
    @i_mazlov Thanks for the reply. I may have described it wrong. I am talking about the image viewer. It seems that there is currently no API interface to get the number of frames rendered, nor can I get the total number of frames in the rendering settings.
  • 0 Votes
    3 Posts
    654 Views
    i_mazlovI
    Hi @Neekoe, That's great to hear you've managed to solve the issue! For your future postings please note that according to our Support Procedures: We cannot debug your code for you and instead provide answers to specific problems. This effectively means that you're welcome to ask your questions and attach the code snippet that demonstrates your question or issue you're struggling with. However, we cannot debug your entire codebase, so you have to isolate your specific question and the corresponding part of code yourself before asking the question. Cheers, Ilia
  • TagData Plugin with Gui not using *.res

    python
    3
    0 Votes
    3 Posts
    560 Views
    M
    Understood Thanks.