THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 09/03/2005 at 23:29, xxxxxxxx wrote:
Cinema 4D Version: 8.012
Platform: Windows ; Mac ; Mac OSX ;
Language(s) : C++ ;
Before you mention using 'messaging', this isn't about passing communicative information. It's about, let's say, doing a Copy of some data in one instance of my PluginShader and having that for Paste action in another instance of my PluginShader.
Any bright ideas on how to go about this? A Cinema4D Clipboard starts sounding like a nice feature.
On 10/03/2005 at 04:27, xxxxxxxx wrote:
What do you exactly mean by "Paste Action"? Is this done by the user? Otherwise you could provide a linkfield to drop your shader into, then you can retrieve it in your other shader easily and you can access it´s data.
On 10/03/2005 at 13:49, xxxxxxxx wrote:
More details will help, I guess. Realize that I'm working on an alternative approach, but it is still a long, twisted, maniacal experiment at this stage.
There is my PluginShader which gets plugged into Materials' Channels. Simple enough. Each instance contains its own set of shadertree nodes (my own class). These 'nodes' are edited in a dialog (try doing a GeUserArea in the AM - yeah, right) - nodes are created, deleted, connected, properties set. There is also the ability to cut/paste and copy/paste either nodes or data from one node to another. Again, this is all easy from within the same PluginShader. And, yes, this is done by the user.
But I want cross-Document cut/paste and copy/paste. Thus, the user can copy node-data or a group of nodes and paste them into another PluginShader's node set. The only way to do that is with another plugin that works across Documents. So far, the only viable choice is a Command plugin. Command plugins have the nasty attribute of having nothing. There is an Execute() and done. No way to get to the CommandData (this was verified by Mikael some time ago), no communications (show me the Message/Command/CoreMessage methods in a CommandData).
There are other approaches wherein the nodes themselves would need to become Cinema4D somethings (e.g.: CustomDataType or PluginNode). I just don't have the man-power (me) or the time (looking at 1-2 months, not 1-2 years) to construct an elaborate system to do this.
The experiment mentioned above involves a Command plugin, but it requires that it be launched before editing can occur. The editor dialog is opened on Execute (et Voila! I have something with which to send/receive messages). The dialog then announces itself to all of the existing PluginShaders. Well, that's the simplistic idea anyway.
Maybe there's an area or fifty of the SDK that I don't comprehend completely, but this seems like the only way to accomplish this task (again, without building my own GV system - not worth the time and effort).
On 10/03/2005 at 13:58, xxxxxxxx wrote:
Getting to the CommandData should be possible. Just use GeRegistryFind(C4DPL_COMMAND, id) and then Registry::GetData(). This will get you the CommandData pointer. What I said was probably that it's not allowed to use this structure in two different plugins. As long as you put the plugins in the same cdl/xdl file it should be fine. (This has to do with the memory position of the vtable for the virtual functions.)
If the plugins are not in the same file you could use a MessageData plugin and SpecialEventAdd() to communicate.
On 10/03/2005 at 14:46, xxxxxxxx wrote:
They are in the same file. This is what I was looking for. Some while back, you had mentioned using FindPlugin() and GetPluginStructure(), but this turned out to be a blind path since GetPluginStructure() always returns NULL (being private and internal, I guess).
Actually, I was working towards the second option (despite them being in the same file). One question about this for future reference: After sending the SpecialEventAdd() message, what is the 'id' and what are the 'msg' contents? Does msg.GetId() return the id used in SpecialEventAdd() and the two ULONGs are stored where (under what container IDs)?
Okay, that was two questions! ;0)
On 10/03/2005 at 14:50, xxxxxxxx wrote:
On 10/03/2005 at 14:53, xxxxxxxx wrote:
Well, whenever you are dealing with none document specific data that each document may need to reference a global clipboard is always helpful.? Global pointer in your main source that is referenced as an external variable from the other sources ( in the same project ). If you are going to write your nodes as separate plugins you could just use messaging to request the global clipboard pointer from the shader hub.
On 10/03/2005 at 15:04, xxxxxxxx wrote:
Mikael - received and understood!
darf - I had considered using the Global CommandData pointer stored in main.cpp. Used an 'extern' in the PluginShader source. Instant crashola. Don't know why though since it is gNew'd before either the Command or Shader plugins are registered. In this case, the 'global clipboard' is the Command plugin.
On 10/03/2005 at 15:34, xxxxxxxx wrote:
No offense intended, but I would double check your code.
On 10/03/2005 at 16:00, xxxxxxxx wrote:
None taken, but I mainly know what I'm doing. This is somewhat simple. I don't think that I could release a commercial plugin for both Windows and MacOS (with 50 reg. users and probably twice that using the demo) which received comments like "one of the most stable Cinema4D plugins I've ever used" and be a hack programmer.
interShader *intershader = NULL;
// Plugin Functions
// create new instance of interShader class
if (!(intershader = gNew interShader))
// register hook and return
return RegisterInterShader(intershader) && RegisterIShader();
extern interShader *intershader;
Bool iShader::Init(GeListNode *node)
is = intershader;
// BOOM - CRASH ;)
* All nonrelevant code removed.
Now, of course, this could be the incorrect approach. I don't use globals anymore except as static or const data (like CHAR* arrays) since starting Java and C++.
If this is incorrect, correct it!
On 10/03/2005 at 16:56, xxxxxxxx wrote:
Nonetheless, I don't like using and depending upon global data. I've gone the SpecialEventAdd() direction and it's working like a charm. Heck, I'm an old Amiga programmer, so I know the idea of 'interprocess communications" and like the elegance of the method - as long as there is a way to do it!
On 10/03/2005 at 17:48, xxxxxxxx wrote:
I'm having no luck with GeRegistryFind(). It always returns NULL. The Command and Shader plugins are in the same cdl/xdl and registered. GeRegistryFind() is being called in the ShaderData's Init().
On 10/03/2005 at 19:03, xxxxxxxx wrote:
Some of the relevant code is missing. 9-)
On 10/03/2005 at 19:31, xxxxxxxx wrote:
Any clues agout GeRegistryFind()? I tried the plugin for the CommandPlugin, for another of my plugins, and one of the Cinema4D SDK plugins. All NULL!
Don't tell me that all avenues to get the CommandData have been cut off by devious programmers?
On 10/03/2005 at 20:27, xxxxxxxx wrote:
All you smarty-pants, huh? Try this:
In PluginStart() after gNew of CommandData:
Bool success = GeRegistryAdd(PLUGIN_ID, C4DPL_COMMAND, intershader);
In ShaderPlugin.Init() :
if (!(registry = GeRegistryFind(PLUGIN_ID, C4DPL_COMMAND)))
if (!(intershader = (interShader* )(registry->GetData())))
Note that sub_id refers to Plugin ID and main_id refers to type, not vice versa!
Thank you, Mikael. This at least gave me a direction to go. Make a note of this for future documention, please.