Not the answer I was hoping for, but helpful nonetheless! Thank you.
Posts made by dskeith
-
RE: Node Editor API - View Bounds, Node Positions, Node Sizes
-
RE: Node Editor API - Active Node Editor Graph?
Gotcha. So, at least for now, we can't develop tools/commands for manipulating nodes in the "active" node editor. Thanks for the thorough response! The
GetSceneNodesGraph
method is really useful, might be worth adding it into the API as a convenience function. Same for aGetActiveMaterialNodeGraph()
or something similar for materials. -
Node Editor API - View Bounds, Node Positions, Node Sizes
I'm looking to create some node alignment scripts (Align Vertical, Align Horizontal), and to do that, I believe I'll need the following information:
Get Methods
- Current Node Editor + View Context (asked in a separate post)
- Selected Nodes within the Currently Active Node Editor + Context
- Node Position (Along with information on where the axis is relative to the node)
- Node Width/Height (So that I can calculate bounds and add even gaps between nodes)
- Node Editor Bounds (What's visible min/max)
- Grid spacing + positioning
- Nearest Grid Point (for snapping to grid if Snap to Grid is on/active)
Set Methods
- Node position (ideally w/ option to snap to the nearest grid point)
- Node Editor Bounds / Zoom + Pos
Question
Which (if any) of the above methods currently exist?
I'll edit this post if my own research turns up anything useful.
Related
-
RE: Node Editor API - Active Node Editor Graph?
Realizing there are even more considerations:
- Is there a concept of "sub-graphs"? For example, if the user has navigated inside of a group in the Node Editor, and they run "Select Node Parents" it will also select parents outside of the currently visible group. Whereas, they probably only want to select the parents visible within their current context.
-
RE: Node Editor API - Active Node Editor Graph?
Now that I'm realizing you can have multiple open Node Editors, some w/ locking, some without, I can imagine this being a similar challenge to the "Which timeline is active?" problem.
How to Get the Selected Keyframes in Active Timeline/FCurve Manager | PluginCafé
Get Active Timeline Request | PluginCafé -
RE: Node Editor API - Active Node Editor Graph?
Here's the code working for materials. How would I expand it to also work with Scene Nodes and, ideally, to work with the currently active node editor?
"""Name-en-US: Select Node Children Description-en-US: Selects Child Nodes Copyright: MAXON Computer GmbH Author: Donovan Keith Adapted from a script by Copyright: MAXON Computer GmbH Author: Manuel Magalhaes Version: 0.1.0 ## Changelog - v0.1.0: Initial Release """ import c4d import maxon def main(): c4d.GetActiveNodeSpaceId() # Get the Active Material # ISSUE: It's possible to have the node editor editing a material even if its not active/selected (Asset Mode, Lock mode, etc) mat = doc.GetActiveMaterial() if mat is None: raise ValueError("There is no selected BaseMaterial") # Retrieve the reference of the material as a node Material. nodeMaterial = mat.GetNodeMaterialReference() if nodeMaterial is None: raise ValueError("Can't retrieve nodeMaterial reference") # Retrieve the current node space Id nodespaceId = c4d.GetActiveNodeSpaceId() # Retrieve the graph corresponding to that nodeSpace. graph = nodeMaterial.GetGraph(nodespaceId) if graph is None: raise ValueError("Can't retrieve the graph of this nimbus ref") with graph.BeginTransaction() as transaction: selected_nodes = [] maxon.GraphModelHelper.GetSelectedNodes(graph, maxon.NODE_KIND.NODE, selected_nodes) predecessors = [] for node in selected_nodes: maxon.GraphModelHelper.GetAllPredecessors(node, maxon.NODE_KIND.NODE, predecessors) for predecessor in predecessors: maxon.GraphModelHelper.SelectNode(predecessor) transaction.Commit() # Pushes an update event to Cinema 4D c4d.EventAdd() if __name__ == "__main__": main()
-
Node Editor API - Active Node Editor Graph?
Hi,
Is there a way to access the current/active graph in the Node Editor via the Python API? I'm trying to write some node layout helpers (Align Horizontal/Vertical) but I'm not finding the information I'm looking for.
- How can I get the current graph that's visible/active in the Node editor?
c4d.GetActiveNodeSpaceId()
doesn't change when I switch from material nodes to scene nodes.- Even for a materials-only mode, the selection state of a material doesn't indicate which graph is currently selected.
- How do we determine which of the open node editors is active (like in Edit Asset mode)?
- How can I get the current graph that's visible/active in the Node editor?
-
RE: Polygon Islands Convenience Method?
Wow! What an incredible set of answers. You've each addressed a different thing I intended to do with these polygon groups once I had access to them.
Thank you @ferdinand @m_adam and @pyr!
-
Polygon Islands Convenience Method?
Hi!
Is there an available convenience method for getting all polygon islands in a polygon object? It seems like one exists internally for things like the
Texture > View > Multi-Color Islands
option.Specifically, I'm looking for polygon islands/shells, but an additional command/option for UV Islands would be great too.
If one doesn't exist, I'd like to request that one be added to the Python SDK.
Thank you,
Donovan
-
Left-Hand Local Coordinates to Right-Hand Local Coordinates?
Hi,
I'm trying to export object an animated hierarchy of objects from Cinema 4D's left coordinates (z+ = forward) with HPB rotations to Three.js's right-hand coordinates (z+ = backward) with XYZ rotations.
Unfortunately, I'm a bit beyond my depth with the matrix math and conversions involved. I'd like to take my C4D local coords write them out as local coords in this other system.
Any tips on how to approach this?
ThanksDonovan
PS: Looks like we need an S22 tag in the tags option.
-
RE: Copying All Compatible Properties from One Object to Another?
Realizing I never responded to this Thank you @m_magalhaes, @mikegold10, and @PluginStudent.
I ended up manually making a list of the parameters I wanted to copy and iterating through all of them. Not ideal, but at least glad to know there wasn't an automated method I was missing.
-
How to Solo a Layer
Hi,
I just spent a bit of time debugging a couple issues when trying to Solo a Layer in the Layer Manager, and figured I would post my findings to save someone else some trouble:
Q: How do you solo a layer?
layer_root = doc.GetLayerObjectRoot() if not layer_root: return # Get the first layer in the scene layer = layer_root.GetDown() if not layer: return # Be sure to use the `rawdata` flag so that you get the stored layer state, not the "effective" layer state layer_data = layer.GetLayerData(doc, rawdata=True) start_solo_state = layer_data["solo"] solo_state = True layer_data["solo"] = True # SetLayerData needs a complete LayerData dict, it doesn't work with something like `{"solo": True}` # doing that will force all other layer state flags to be False layer.SetLayerData(doc, layer_data) # This isn't documented near SetLayerData, but you must call this method or C4D won't know to update the # solo state of layers in the scene. set_or_clear = doc.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_SET) # Let C4D know something has changed to trigger a redraw c4d.EventAdd()
Documentation Request:
Please update the docs for SetLayerData to include an example like the above, and make a note that if you plan to SetLayerData you should call GetLayerData withrawdata=True
.Thanks,
Donovan
-- Edit 2020/03/20 --
Actually this isn't working well in all circumstances. If all layers are unsoloed I'm not getting the expected refresh.
Okay, I think I figured out the issue (but haven't updated the logic above to account for it):
If you turn off solo on all layers, you need to use
doc.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_CLEAR)
, but if even one layer has the solo flag on, you need to usedoc.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_SET)
....I think.
-
RE: c4dpy.exe and VS Code on Windows?
@m_adam Thank you for the prompt and thorough reply. I believe I've followed your instructions exactly, but unfortunately: no luck.
I even went so far as to completely remove all other Python installations and reinstall C4D via installer.
It just doesn't seem to be recognizing C4D's embedded python as a valid python installation for some reason. I have confirmed that c4dpy.exe (renamed python.exe) has successfully logged in and is functioning as an interactive intepreter (and in PyCharm).
Any other ideas?
UPDATE: VS Code does seem to be invoking c4dpy, but I'm ~15min into this process with CPU usage pegged near 75% without visible progress:
-
c4dpy.exe and VS Code on Windows?
Hi,
Has anyone had any luck getting R21's
c4dpy.exe
to work with the current release of VS Code? I've followed the installation instructions but I'm consistently prompted to "Select Python Interpreter", even though I've set"python.pythonPath": "C:/Program Files/Maxon Cinema 4D R21/c4dpy.exe"
in the VS Code application and workspace settings.I've been able to get it running in PyCharm, but VS Code doesn't seem to recognize c4dpy.exe as a valid python interpreter.
Any suggestions or insights would be greatly appreciated.
Thanks,Donovan
-
Updating Tool Settings?
Hi,
I'm currently porting a COFFEE script to Python and it seems that accessing/updating tool settings is much more complicated in Python than COFFEE.
I initially tried something like:
active_tool = doc.GetActiveToolData() active_tool[c4d.MDATA_AXIS_MODE] == 8 # Free Axis Mode c4d.EventAdd()
But it had no effect. I eventually found my way to this post which led me to a solution like this:
def tool(): """Retrieves the currently active tool. Doing so allows you to modify tool settings unlike GetActiveToolData()""" active_tool_id = doc.GetAction() if not active_tool_id: return active_tool = c4d.plugins.FindPlugin(active_tool_id, c4d.PLUGINTYPE_TOOL) return active_tool def main(): """Switch from Free Mode to Axis mode and vice/versa. """ active_tool = tool() if active_tool is None: return active_tool[c4d.MDATA_AXIS_MODE] == 8 # Free Axis Mode c4d.EventAdd()
Questions / Requests
- QUESTION: Is there a way of knowing when I should change settings with
ActiveToolData()
vs having to find an instance of the tool/plugin itself? - IDEA: Please add a section to the docs on how to update tool settings.
- IDEA: Please add a helper function like
tool()
to the API for accessing the currently active tool, the present method is a bit convoluted for something people will want to do so frequently.
Thank you,
Donovan Keith
- QUESTION: Is there a way of knowing when I should change settings with
-
RE: Using c4dpy to show Class Documentation?
Hi Maxime - thank you very much for the response, and I'm glad to hear you're considering it for the future.
-
BaseDocument.StartPickSession() Documentation
Hi,
I'm trying to work with doc.StartPickSession(callback, multi) and I'm running into some questions.
Trying this simple code...
import c4d from c4d import gui def OnPick(active, multi): print "active: ", active print "multi: ", multi # Main function def main(): doc.StartPickSession(OnPick, multi=True) # Execute main() if __name__=='__main__': main()
I'm able to start a multi-object pick session, but once I double-click to complete it, I get this error:
TypeError: OnPick() takes exactly 2 arguments (3 given)
After a bit of detective work, it seems that adding a
mystery
variable to my callback functiondef OnPick(mystery, active, multi):
fixes the error. When I run this:import c4d from c4d import gui def OnPick(mystery, active, multi): print "mystery: ", mystery print "active: ", active print "multi: ", multi # Main function def main(): doc.StartPickSession(OnPick, multi=True) # Execute main() if __name__=='__main__': main()
I get this console output:
mystery: 0 active: [<c4d.BaseObject object called 'Cube/Cube' with ID 5159 at 0x00000290184D2B90>, <c4d.BaseObject object called 'Cube.1/Cube' with ID 5159 at 0x00000290184D2130>, <c4d.BaseObject object called 'Cube.2/Cube' with ID 5159 at 0x00000290184D2170>] multi: True
After a bit more detective work, it seems that
mystery
is0
if I complete the pick-session by double-clicking, and it's1
if I pressEsc
to finish the pick session.Questions
- What is the
mystery
variable, and what is it actually returning. - Is there a way to trigger a multi-pick session where the user doesn't have to hold down shift/ctrl to select multiple elements?
- I'm noticing some weirdness in terms of which objects are selected in the Editor/Viewport after a pick session (especially if I end it by pressing
Esc
). What messages/redraws do I need to call after a pick session? Do I need to handle undo or will C4D?
Thanks,
Donovan
- What is the
-
RE: Documentation Plugin
Really cool Kent! Thank you for sharing.
Questions:
- Does your plugin provide any sort of automation for adding "Show Help" links in C4D to specific parameters?
Feature requests:
- Automatically fill in the image Alt-Text for the linked command icons with the name of the command/parameter.
- Auto List Parameters: Add a list of every parameter in a plugin's dialog/description so that we can easily document elements and see what isn't yet documented.
-
Forum Index CSS Styling
Hi,
I know that design is subjective, but I'd like to request that you change the CSS styling of the topic headings from
UPPERCASE
toCapitalize
. At least from my perspective, it's much easier to read and scan for topics of interest when each word is clearly broken up with spacing & sizing.Current:
Proposed:
I believe this is the CSS selector:
-
RE: R20 Script State Function
- Only passing True, False and c4d.CMD_ENABLED|c4d.CMD_VALUE will effect the icon state correct? it can't be done outside of the state() function?
Yes. You may be able to perform calculations elsewhere and store a state value in the document's container that you access in the
state()
method, but I don't believe you can change the state elsewhere.- I noticed when I put a print function inside of the state() function it seemed to loop endlessly? if I use this code:
Yes, it's "looping" every time the Cinema 4D interface updates/redraws.
Background
The
state()
function is seemingly run every time Cinema 4D's interface is redrawn. It's really there for determining whether a command that requires an object be selected is enabled or not. As it's run so frequently, any code you put in there could slow down all of C4D, so ensure that your state check is actually important, and if so, do your check as quickly as possible.Example
For example, a script that prints the name of the selected object should only be enabled when an object is selected.
"""Name-en-US: Echo Name Description-en-US: Opens a message dialog with the name of the selected object. """ import c4d from c4d import gui def state(): """Gray out icon if no objects are selected, or more than one object is selected. """ # `op` is a variable provided by C4D that represents the selected object. # I'm not certain, but I think this is faster than call doc.GetActiveObject() # but it will return `False` if more than one object is selected. if op is not None: return c4d.CMD_ENABLED else: return False def main(): """Open a dialog with the selected object's name. """ if op is None: return active_obj_name = op.GetName() gui.MessageDialog("You selected: " + active_obj_name) if __name__=='__main__': main()
References
- Python API Docs: c4d.plugins.CommandData.GetState
- C++ API Docs: Command Data Class