• How to press the "Apply" button in the DescriptionToolData?

    c++ python
    2
    1
    0 Votes
    2 Posts
    446 Views
    ferdinandF
    Hello @LingZA, Thank you for reaching out to us. Thank you for posting your solution, much appreciated! I have provided below a variant of your example which without having the C++ Example Pick Object Tool installed. In case someone is wondering how to find out such a thing, you would have to look into the description of a tool, e.g. the extrude tool ... toolextrude.res: CONTAINER xbeveltool { NAME xbeveltool; GROUP MDATA_BEVEL_GROUP_OPTION { DEFAULT 1; LONG MDATA_BEVEL_MASTER_MODE // ... } INCLUDE ToolBase; // Includes the gadgets that are common to all description tools. } to find out that they all include all ToolBase which then looks like this: toolbase.res: CONTAINER ToolBase { NAME ToolBase; GROUP MDATA_MAINGROUP { DEFAULT 1; } GROUP MDATA_COMMANDGROUP { DEFAULT 1; GROUP { // SEPARATOR { LINE; } BOOL MDATA_INTERACTIVE { } SEPARATOR { } GROUP { COLUMNS 2; DEFAULT 1; BUTTON MDATA_APPLY { FIT_H; } BUTTON MDATA_NEWTRANSFORM { FIT_H; } } } } SUBCONTAINER ID_SNAPSETTINGS { } } Cheers, Ferdinand Code: """Actives and runs the extrude tool. """ import c4d ID_EXTRUDE_TOOL: int = 1011183 def main() -> None: c4d.CallCommand(ID_EXTRUDE_TOOL) tool = c4d.plugins.FindPlugin(ID_EXTRUDE_TOOL, c4d.PLUGINTYPE_TOOL) tool[c4d.MDATA_INTERACTIVE] = True c4d.EventAdd() if tool is not None: c4d.CallButton(tool, c4d.MDATA_APPLY) c4d.CallButton(tool, c4d.MDATA_NEWTRANSFORM) c4d.EventAdd() if __name__ == '__main__': main()
  • How to weld two points to the last selected point?

    windows s26 2023 python
    5
    0 Votes
    5 Posts
    994 Views
    i_mazlovI
    Yes, you found the thread about point selection just right!
  • GetActiveToolData() doesn't work for Mirror Tool

    windows s26 python 2023
    5
    0 Votes
    5 Posts
    902 Views
    G
    I want to mirror a polygon selection along specified modeling axis, but i'm kinda stuck since i can't apply the dedicated Mirror Tool, the basic Scale Tool also doesn't allow to set the tool settings...
  • 0 Votes
    5 Posts
    972 Views
    i_mazlovI
    Hi @LingZA , Sorry for the delayed answer. Could you please explain the result that you're trying to achieve? It looks now that you would like to implement a modeling tool similar to Bevel, when you would like to firstly select points/edges/polys and secondly apply some changes to them. If that's the case, then you need to implement the part of your tool that selects objects. Please have a look at BaseSelect. You can also explore Flatten Polygons example. You can find a sample code snippet below that simply selects all of the edges of the polygon. You need to be in "Edges" mode for that. Additionally you can emulate the polygon highlighting yourself. Regarding the flags: PLUGINFLAG_TOOL_EDITSTATES - designates that the tool supports deformed editing PLUGINFLAG_TOOL_SWITCHACTION - allows to adjust the active tool. This works in tandem with the MSG_TOOL_SWITCHACTION message type. Namely, when the modifier (aka qualifier) key is pressed, the plugin receives this message such that it can react on this key press. PLUGINFLAG_TOOL_NO_TOPOLOGY_EDIT - flag that informs cinema that the tool doesn't perform any topology modifications (i.e. doesn't add/remove/reassign of the polygons) PLUGINFLAG_TOOL_TWEAK - if you click on the element that isn't currently selected, it will select it for you (so your tool can work with this selection), and will deselect it once your tool finishes PLUGINFLAG_TOOL_TWEAK_NO_HIGHLIGHT - same as above but without highlighting the temporarily selected element PLUGINFLAG_TOOL_DRAW_MULTIPLANE - some legacy flag that is (or at least should be) deprecated Cheers, Ilia [image: 1698935992814-cinema_4d_ezzrkgku0y.gif] import c4d PLUGIN_ID = 1234321 # Be sure to use a unique ID obtained from www.plugincafe.com class MyTool(c4d.plugins.ToolData): def __init__(self): self.selectionRadius = 10 self.highlightedPolygon: int = -1 def GetState(self, doc): if doc.GetMode() != c4d.Medges: return False return c4d.CMD_ENABLED def MouseInput(self, doc, data, bd, win, msg): # Only handle left click if msg[c4d.BFM_INPUT_CHANNEL] != c4d.BFM_INPUT_MOUSELEFT: return True # Get active object op = doc.GetActiveObject() if not op: return True if self.highlightedPolygon < 0: return True # Initialize helping Neighbor struct nbr = c4d.utils.Neighbor() nbr.Init(op) polyInfo = nbr.GetPolyInfo(self.highlightedPolygon) # get polygon information bs = c4d.BaseSelect() opPolygon: c4d.CPolygon = op.GetPolygon(self.highlightedPolygon) # Iterate over sides for side in range(4): # Skip last edge if polygon is a triangle if side == 2 and opPolygon.c == opPolygon.d: continue # Select edge edgeIdx = polyInfo['edge'][side] bs.Select(edgeIdx) # Apply selection op.SetSelectedEdges(nbr, bs, c4d.EDGESELECTIONTYPE_SELECTION) c4d.EventAdd() return True def Draw(self, doc, data, bd, bh, bt, flags): selectionColor = c4d.GetViewColor(c4d.VIEWCOLOR_SELECTION_PREVIEW) if flags & c4d.TOOLDRAWFLAGS_HIGHLIGHT: # if the DrawPass is the Highlight one if self.highlightedPolygon >= 0: # Get active object op = doc.GetActiveObject() if not op: return True bd.SetMatrix_Matrix(op, op.GetMg()) # draw in global coordinates # Get points and polygon from the object opPoints: list[c4d.Vector] = op.GetAllPoints() opPolygon: c4d.CPolygon = op.GetPolygon(self.highlightedPolygon) points = [opPoints[idx] for idx in (opPolygon.a, opPolygon.b, opPolygon.c, opPolygon.d)] colors = [selectionColor for _ in points] if len(points) == 3 or len(points) == 4: bd.DrawPolygon(points, colors) # draw the polygon highlight # Draw the outline bd.SetPen(c4d.Vector(0, 1, 0)) for point1Idx in range(-1, len(points) - 1): point1, point2 = points[point1Idx], points[point1Idx + 1] bd.DrawLine(point1, point2, c4d.NOCLIP_D) return c4d.TOOLDRAW_HIGHLIGHTS def GetCursorInfo(self, doc, data, bd, x, y, bc): self.highlightedPolygon = -1 # If the cursor has left a user area, simply return True if bc.GetId() == c4d.BFM_CURSORINFO_REMOVE or doc.GetMode() != c4d.Medges: return True # Get active object op = doc.GetActiveObject() if not op: return True # Calculates the width and height of the screen bd: c4d.BaseDraw = doc.GetActiveBaseDraw() frame = bd.GetFrame() l, r, t, b = frame["cl"], frame["cr"], frame["ct"], frame["cb"] width, height = r - l + 1, b - t + 1 # Initialize viewport select vpSelect = c4d.utils.ViewportSelect() vpSelect.Init(width, height, bd, [op], c4d.Medges, True, c4d.VIEWPORTSELECTFLAGS_IGNORE_HIDDEN_SEL) c4d.SpecialEventAdd(c4d.EVMSG_UPDATEHIGHLIGHT) # pushing highlighting event to cinema # Looking for the nearest polygon and saving it's index in self.highlightedPolygon polyInfo = vpSelect.GetNearestPolygon(op, int(x), int(y), self.selectionRadius) if not polyInfo or 'i' not in polyInfo: return True polygonIdx = polyInfo['i'] if (polygonIdx < 0 or polygonIdx >= op.GetPolygonCount()): return True self.highlightedPolygon = polygonIdx return True if __name__ == "__main__": c4d.plugins.RegisterToolPlugin(id=PLUGIN_ID, str="MyTool", info=0, icon=None, help="", dat=MyTool())
  • c4d.MCOMMAND_EXPLODESEGMENTS makes target object dead

    macos python 2024
    6
    0 Votes
    6 Posts
    1k Views
    bacaB
    @ferdinand said in c4d.MCOMMAND_EXPLODESEGMENTS makes target object dead: Select 0th polygon in a mesh. SMC: MCOMMAND_SELECTCONNECTED SMC: MCOMMAND_SPLIT Delete the selected polygons. When no polygons are left, exit, otherwise goto 1. Oh, great idea. Not that elegant, but seems legit. Thanks again.
  • Legacy Code still a thing?

    2024 c++ windows
    11
    0 Votes
    11 Posts
    2k Views
    Y
    Oh sorry, thank you. I totally missed that.
  • Error building R25 macOS - TypeTraitExpr

    r25 c++ macos
    7
    1
    0 Votes
    7 Posts
    1k Views
    rsodreR
    Thanks for all the tips @ferdinand The solution was Catalina + XCode 12.4
  • How to use GenerateDragArray() with Node Editor?

    windows 2024 python
    6
    1
    0 Votes
    6 Posts
    947 Views
    DunhouD
    Thanks for that @ferdinand @m_adam , yes, Ferdinand is right, Maxime's point is too "pro" for me, and with some maxon decorators I never used in some way mess me up, with Ferdinand's "rookie" like explain that I can understand this more, thanks for your both respected work. Cheers~ DunHou
  • Howto add headers & dividers for a ShowPopupDialog?

    windows s26 python
    13
    0 Votes
    13 Posts
    2k Views
    G
    It works as expected in C4D 2024, but not in the previous versions.
  • 1 Votes
    3 Posts
    639 Views
    moghurtM
    @m_adam m_adam resolved the issue perfectly. Thanks for the great support!
  • How to Apply a modeling command?

    s26 windows python
    3
    0 Votes
    3 Posts
    542 Views
    G
    Thanks man, i'll take a look at it!
  • How to set options when saving TIF file

    2023 c++
    2
    1
    0 Votes
    2 Posts
    431 Views
    ferdinandF
    Hello @kbar, Thank you for reaching out to us. You cannot do what you want to do from the classic API. When we use the classic API interface BaseBitmap::Save internally, we always pass nullptr or the empty container when saving a FILTER_TIF. There is unfortunately no classic API translation layer anymore for this aspect of TIFF saving. But you can get the underlying ImageRef with BaseBitmap::GetImageRef and then use the Image API directly to save things as you want them to be saved: Saving an ImageRef to Disk maxon::MEDIASESSION::TIFF::EXPORT Namespace Note that other than in the classic API, image data is expressed by more than one type in the maxon API. To save a plain ImageRef, you will have first to insert it into a ImageTextureRef via ::AddChildren, as only it has the ::Save method. Cheers, Ferdinand
  • How do you manipulate the points on a spline?

    2023 windows python
    3
    0 Votes
    3 Posts
    559 Views
    M
    Hi @ll2pakll, I am glad that you solved your issue. Message(c4d.MSG_UPDATE) is indeed required to finalize your spline editing. If you want a complete example on spline editing please take a look at geometry_splineobject.py example. Cheers, Maxime.
  • How to create a radial (pie) menu?

    windows s26 python
    6
    0 Votes
    6 Posts
    2k Views
    G
    Thanks for your detailed answers, i hoped there is a simpler way to do it)... Pie menus is a very common thing nowadays, why maxon developers haven't implemented it already? In modo for example you can create pie menus, popups...etc without any coding. Not every user is ready/have the time/etc to learn python to build a simple popup, but almost every user needs to customize their working software. I really hope you'll implement these features soon.
  • OBJ Import setting not changing

    python 2024 windows
    5
    0 Votes
    5 Posts
    920 Views
    ferdinandF
    Hey @del, Thank you for pointing out that this part of our examples, I overlooked this aspect this morning. I have fixed the issue in our local repository for import_obj_r13.py. The updated line is: objImport[c4d.OBJIMPORTOPTIONS_PHONG_ANGLE_DEFAULT] = c4d.utils.DegToRad(22.5) and it will go live with the next docs update. I cannot update the legacy version of the SDK in import_OBJ.py as I lack the permissions to write there even in our local repository. Cheers, Ferdinand
  • Check if a texture is missing

    python 2024 macos
    2
    0 Votes
    2 Posts
    623 Views
    ferdinandF
    Hello @visualride, Thank you for reaching out to us. I would recommend having a look at c4d.documents.GetAllAssetsNew . Helpful might also be the thread Get all Textures for a Material. It is one of the multiple threads where I showcased the usage of GetAllAssetsNew (search for GetAllAssetsNew and my user name to find the other threads). In this thread you can see here how to read the exists field in asset data to know if Cinema 4D can find that asset. But asset handling can get complex when node materials are involved as shown here (also a good place to better understand the data associated with MSG_GETALLASSETS). The thread shows also a simpler approach using BaseDocument.GetAllTextures. You can then just check with os.exists if the paths do exist. You might have to deal with relative paths here, depending on the document. Cheers, Ferdinand
  • Problem with MessageData plugin

    2023 windows python
    5
    0 Votes
    5 Posts
    990 Views
    gheyretG
    Hi @ferdinand Thank you so much for your explain, i understand what's happen now. Cheers
  • How to access PLA data

    c++
    19
    0 Votes
    19 Posts
    3k Views
    F
    Hi @ferdinand , Thanks very much for all of your time and tips!! Facundo
  • Adding a STATICTEXT element to a Description... changes in C4D 2024?

    2024 c++
    10
    0 Votes
    10 Posts
    2k Views
    fwilleke80F
    Very informative, thank you Ferdinand!
  • Custom Build C4D.2024.py310 ?

    2024 python
    7
    0 Votes
    7 Posts
    2k Views
    gheyretG
    Hi @Unit-Image-Dev Thank you for your reply. That's so cool! and i will try it.