Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
If I remember correctly, most strings now need to be of type maxon::String. Can't remember in which version this was introduced (and that doesn't really matter). Since then you could be using suffix _s GePrint("Print this string..."_s);
GePrint("Print this string..."_s);
There are different ways to output to the console, but I am now mainly using ApplicationOutput.
ApplicationOutput
Wasn't this listed in one of the "API Changes in Rxx"?
For a start some of the methods of CommandData have received an additional argument GeDialog *parentManager.
CommandData
GeDialog *parentManager
Apart from that I would suggest to just setup an R21 (and up) environment(s), port your project files to these, and start building the plugins. From the errors you encounter you might find out what needs to be changed.
I know, this sounds quite a lot as "trial and error", but that's the only advice I have right now. Unless you want to dig through all the SDK documentation's "API changes in R21, S22, R23, S24, R25, S26"
Once you have adapted your source files for macOS, you will be able to just take these over in your Windows (updated) projects, and build the plugins for PC.
EDIT: I myself had set up on Windows an "SDK_Rxx" folder per release, and had extracted the SDK into these, together with the specific projecttool per release. Same for macOS, but there I had prepared an external SSD with different OS versions, and XCode installs. (example: Sierra -> R20 + XCode 9, High Sierra -> R21 + XCode 10, Mojave -> R23 + R25 + XCode 11)
No worries. From your reply it seems this is a bug that is being tackled in a future release. I don't mind this being fixed, but was hoping for another solution (or workaround) to be available for current and older versions (I am still on R20).
However, if using the MouseInput is the only way to go for detectig CTRL+RMB (with known limitations) then I guess we can close this topic. Thank you for your time.
Thanks for the link to the updated page on the dev blog.
Can we please get an update on: https://developers.maxon.net/docs/Cinema4DCPPSDK/html/page_maxonapi_dev_windows.html
As I still am mainly in "R20-timezone" I was trying to figure out which versions of Visual Studio are to be used to compile plugins for R23 and R25. (Might be useful to also update the macOS page ... if needed)
Thanks.
@m_magalhaes said in Detect CTRL + RightMouseButton in SceneHook:
popup is not allowed for the tool
I didn't think of that one. This does seems to mean that using SceneHook::MouseInput to detect CTRL+RMB is probably not the right approach.
SceneHook::MouseInput
Is there another way to detect this action, no matter what tool is active?
In fact, scenehook with a priority lower than 2000 will not be called if you are using another tool than move, scale or rotation.
That might be the case for ToolData derived tools, but I can confirm that with a DescriptionToolData derived tool active the scenehook (with priority 1000) does get called.
ToolData
DescriptionToolData
By default pressing the RightMouseButton in an editor view will show a popup menu. I would want to be able to trigger something similar, but without removing the possibility to trigger the default popup menu with RMB. For this reason I came up with the combination of CTRL + RMB, which I detect in my SceneHook::MouseInput (as follows):
if (msg.GetInt32(BFM_INPUT_CHANNEL) == BFM_INPUT_MOUSERIGHT) { BaseContainer keyChannels; if (GetInputEvent(BFM_INPUT_KEYBOARD, keyChannels)) { Bool ctrlModifier = (keyChannels.GetInt32(BFM_INPUT_QUALIFIER) & QCTRL) != 0; if (ctrlModifier) { ApplicationOutput("SceneHook - MouseInput: RMB + CTRL was pressed"); return true; } } }
This is working fine when a move, rotate, scale tool is active. Even when an own custom created DescriptionTool plugin is active.
However, when the Live Selection tool is active, the code is not triggered. At least not with the default "EXECUTIONPRIORITY_INITIAL" (=value 1000) I had provided when registering my scenehook plugin. When I provide "EXECUTIONPRIORITY_ANIMATION (=value 2000) only then does the code get triggered, also when Live Selection tool is active.
return RegisterSceneHookPlugin(MY_SCENEHOOK_PLUGIN_ID, GeLoadString(IDS_MY_SCENEHOOK), 0, MySceneHook::Alloc, EXECUTIONPRIORITY_ANIMATION, 0);
Any value below 2000 just ignores to trigger the code when Live Selection tool is active. Now, I can understand this is probably not a bug, but made on purpose. But why? Why would the Live Selection tool have more "priority" then any other tool?
Note: I am prototyping this with R20 (on Windows). Have not yet tested with later versions. Nor tried on macOS.
I didn't follow this topic in detail when it was originally posted, but I now noticed that in several of my plugins I do also use GetInputState(BFM_INPUT_KEYBOARD, BFM_INPUT_CHANNEL, KB); in order to check for possible qualifiers being pressed.
GetInputState(BFM_INPUT_KEYBOARD, BFM_INPUT_CHANNEL, KB);
I guess this must have been picked up in the old forum, as the code is quite some years old. It may not have been the intended way, but it seems to have been working all those years. At least till R21, as I haven't worked on more recent versions.
In the old forums there were quite some pieces of "example" code scattered around in posts, and back then it was a way to find out how to use some of the available functionality, due to limited documentation.
Speaking of documentation: I just noticed that https://developers.maxon.net/docs/Cinema4DCPPSDK/html/class_scene_hook_data.html lists MouseInput and KeyboardInput both pointing to "Input Events" for their last function argument [in] msg The keyboard message container. See Input Events. But the link just points back to the beginning of the page. Where to find more details about these "Input Events" ???
MouseInput
KeyboardInput
[in] msg The keyboard message container. See Input Events.
If you want to know from within the TagData-derived object the enable state of the tag you can (with a method receiving a GeListNode* node as argument) do:
BaseTag* tag = (BaseTag*)node; Bool enabled = false; if (tag) { GeData d; tag->GetParameter(<your tag's ENABLE-id>, d, DESCFLAGS_GET::NONE); enabled = d.GetBool(); } ...
If you want to get triggered by the change of state then:
Bool YourTagDataDerivedClass::Message(GeListNode* node, Int32 type, void* data) { if (type == MSG_DESCRIPTION_POSTSETPARAMETER) { DescriptionPostSetValue* postsetval = static_cast<DescriptionPostSetValue*>(data); if (postsetval && (*postsetval->descid == DescID(<your tag's ENABLE-id>))) ... and same as above: you get the state of the enable-parameter
Bool YourTagDataDerivedClass::SetDParameter(GeListNode* node, const DescID& id, const GeData& t_data, DESCFLAGS_SET& flags) { if (!node) return false; const Int32& gadgetID = id[0].id; switch (gadgetID) { case <your tag's ENABLE-id>: enabled = t_data.GetBool();
As far as I know there is no possibility to just "hook into" existing commands of Cinema4D. You will have to provide your own command where you perform the "preliminaries" and then call the existing command. In other words, for your example, you will want to create a 'My Render View' command which perform the tasks you want to see executed before 'Render View' and which after that just calls 'Render View'.
As I won't be spending more time on this project there is no need for delving further into the subject. As such I am setting the status of the topic to "solved".
@ferdinand
I had searched the forums earlier and found quite some references to AddEventNotification used over the years. However, using that technique requires a "host" to be available. In my case I don't see a scenario with a mandatory BaseList2D always available, except for the active document. But still worth a shot ...
AddEventNotification
The reason I was experimenting with the Cinema4D resources was because this is for personal use only (exclusively within R20), and not meant as a plugin to be made public. As such, I would be future-safe, since no further development will be released for R20.
@del The V value of the UVs have switched (since R21 if I am remembering correctly). Originally, the V value was 0 (top) to 1 (bottom), putting the origin of the UVs at the top left. Since R21 the origin has been moved to bottom left, and is also visualized as such in the UV editor, and also in the structure manager. The stored data however, probably for compatibility, has remain untouched and still represents coordinates with origin at top left.
This all means that the stored values and the actual values seen in structure manager are complementary to 1 (the V values are "mirrored") You can see that with the values of point 8.b: its V value in structure manager is 0.889, while its stored value actually is 0.111, where 0.889 is the 1 complement of 0.111 (0.889 + 0.111 = 1) Similarly, the V value of 1 in structure manager is actually stored as 0 ... which you see in the vector representation.
Additionally, the UVs are stored as single precision floats (at least, that was how it was upto R20). I don't know the internals of Python enough, but this might be the reason why you get the strange -1.xxx e-16 value when printed out. Note that printing out the c4d.Vector does show it as 0 (which is the mirrored value of the value 1 in the structure manager.
Hi again, I know this is quite a strange request, but is there a way to detect the press of a tool's description button, outside of the Message() of that tool plugin?
Message()
Let's say I am wanting to add a button to the Modeling Axis tab of the Live Selection tool. For this I edited the toolmodelingaxis.h, .res, .str files. Since I cannot add functionality to the original Modeling Axis tool, I am looking for a way to detect the press of the additional button. Can this be detected via a c4d.plugins.MessageData's CoreMessage() ? Or do I need a C++ SceneHook for this?
An alternative solution would be to implement a CommandData, with dialog containing the button, and dock the dialog somewhere in the layout. But I would prefer to have that button inside of the original tool's description, next to the other attributes.
@m_adam Thanks for the reply. I did mark the post as a question. But didn't see any difference.
I also still don't see any notification, (notification bell remains unchanged), even though there are new notifications when I press the bell icon. Using Firefox (94.0.1 = latest version). No big deal, but it might be related to the failed mark-post-as-question.
I encounter a problem when creating a Python script, and docking that script into the layout. I have simplified the script as much as possible, by simple generating a new script from the Script Manager, and enabled the commented out "def state():" function as such
import c4d from c4d import gui # Welcome to the world of Python # Script state in the menu or the command palette # Return True or c4d.CMD_ENABLED to enable, False or 0 to disable # Alternatively return c4d.CMD_ENABLED|c4d.CMD_VALUE to enable and check/mark def state(): return True # Main function def main(): gui.MessageDialog('Hello World!') # Execute main() if __name__=='__main__': main()
When you save this script, and add the script icon into your layout, then rendering to viewport is broken. Sometimes pressing the "render view" button simply does not react (same with shortcut Ctrl-R), sometimes the command reacts but generates a black render.
Open the script, put the "def state():" function in comment, save, and rendering is reacting as should be.
Haven't tried on other version of Cinema4D, but people have responded that this issue is present in R21 and up (at least on Windows, haven't tried on macOS)
I have tried returning True, False, CMD_ENABLED, CMD_ENABLED | CMD_VALUE ... I even have tried without any return at all. Same result: as soon as "def state():" is present in the script, and script's icon is added to a palette in the layout -> render view is broken
You create a custom GUI to display your custom data by deriving a class from iCustomGUI
class iMyCustomGUI : public iCustomGui ...
Then in you CustomGUIData derived class you implement the allocation by providing the derived iCustomGUI
CDialog* ReferencePointCustomGUI::Alloc(const BaseContainer& settings) { iMyCustomGUI* dlg = NewObjClear(iMyCustomGUI, settings, GetPlugin()); ...
you can find more details in the R20 SDK example customdata_customgui.cpp in folder cinema4dsdk\source\gui Works OK for R16 upto at least R21 (I have not used/tested in more recent versions)
@césar-vonc
Yes you can do this with scripts. I have done this in the past with my Dials plugin.
Let's say you have a CommandData. You simply create a script which does perform c4d.CallCommand(pluginID, option) where <pluginID> is the plugin id of the CommandData, and option is the CallCommand::ExecuteSubID to be executed.
You then assign a shortcut / icon to your script ... and you're done. You can create as many scripts / shortcuts as you want, each with a different <option> value