Starting C++ SDK Tutorial
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 05/02/2003 at 16:48, xxxxxxxx wrote:
Hi,
I've written up a tutorial describing how to go about isolating a single plugin from the SDK, so that you can use it as a base framework for building your own plugins. This also includes some explanation of what various the files are for in a plugin.I was originally going to post it here, but then it got long, so I've put it on my website instead.
Goto www.astrofish.com and pick option 4 (Tutorial).
Anyway, hope it's useful to someone.
Any Mac users who look at it - I'd appreciate it if you'd let me know whether my pre-built 'xdl' file actually works on a Mac, since it was built on a PC...
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 06/02/2003 at 14:45, xxxxxxxx wrote:
Hi Steve,
thanks a lot for your efforts. Your tutorial is great for people looking for a fast entry into SDK programming.
Thumbs up. Ciao,
MarcusPS: I have done some work on describing the API structure, but due to time constraints don't make much progress. At the weekend I hope to find some time for the tutorials.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 06/02/2003 at 23:55, xxxxxxxx wrote:
Hi Marcus,
it's incredible, but you just post the nearly same I wanted to post today.
I'm really busy at the moment and hope to find more time on Sunday to go on with the tutorial.
Steve, it's good to have more ways to get to similar results, and I'm still learning.
cu
Sneaker -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/02/2003 at 02:01, xxxxxxxx wrote:
ok, here is the way to our first real plugin.
Marcus, thanks again to provide me with the code and additional information.
There is one thing I didn't change, but I think it's better to change it in future.
You stored the PluginID in c4d_symbols.h. This file must be distributed to the end user
and therefore every end-user can change it. This might help during development, but I don't
think that anybody should be able to change a unique PluginID given to the author.so, the first thing we need is a plan what we're going to do.
It's an easy plugin so we don't need a big plan:
Plugin to send a Hello World message box and write some info into console
here are the steps to do this:
- create a subfolder Hello2 under "MyPlugins"
- copy our empty project to Hello2 and rename it like describe above
- create necessary subfolders in project and file system
- res
- strings_de
- strings_us
- ..... (whatever strings_lang you want)
- src
good.
now we need some files.create a new file in "res" folder called "c4d_symbols.h" and fill in this code:
enum { IDS_PLUGIN_NAME = 0, IDS_PLUGIN_DESCR, IDS_MESSAGE, IDS_ERR_CONSTR, PLUGIN_ID = 1009173 };
create a new file in "strings_us" folder called "c4d_strings.str" and fill in this code
STRINGTABLE { IDS_PLUGIN_NAME "Hello World Advanced ;)"; IDS_PLUGIN_DESCR "Prints out a Hello World message"; IDS_MESSAGE "Hello World!"; IDS_ERR_CONSTR "Construction of HelloWorld object failed"; }
if you like to you can create additional files in the language folders. example for "strings_de":
create a file called "c4d_strings.str" and fill in:STRINGTABLE { IDS_PLUGIN_NAME "Hallo Welt Erweitert ;)"; IDS_PLUGIN_DESCR "Gibt eine 'Hallo Welt'-Nachricht aus"; IDS_MESSAGE "Hallo Welt!"; IDS_ERR_CONSTR "Es konnte kein HelloWorld-Objekt erzeugt werden"; }
and now the very important plugin code itself. Create a new file in "src" folder called "Hello2.cpp"
and fill in:#include "c4d.h" #include "c4d_symbols.h" /** * */ class HelloWorld : public CommandData { public: virtual Bool Execute(BaseDocument* doc); }; /// Bool HelloWorld::Execute (BaseDocument* doc) { String wind0 = "Windows"; GeOutString (GeLoadString (IDS_MESSAGE), GEMB_OKCANCEL); GePrint ("Hello World Advanced :))))))"); if (GeGetCurrentOS() == GE_WIN){ GePrint ("Hello World "+wind0); } else { GePrint ("Hello World Mac :))))))"); } return (TRUE); } /** * */ Bool PluginStart () { HelloWorld *helloWorld = NULL; // initialize global resource object if (!resource.Init()) return FALSE; // create new instance of HelloWorld class, if not done already if ((helloWorld = new HelloWorld) == NULL) { GePrint (GeLoadString (IDS_PLUGIN_NAME) + ": " + GeLoadString (IDS_ERR_CONSTR)); return (FALSE); } // register hook and return return (RegisterCommandPlugin (PLUGIN_ID, GeLoadString (IDS_PLUGIN_NAME), 0, GeLoadString (IDS_PLUGIN_DESCR), helloWorld)); } /** * */ void PluginEnd () { } /** * */ Bool PluginMessage(LONG id, void* data) { return (FALSE); }
----------------------------
compile it and if error free start cinema. Open Menu/Plugins/Hello World Advanced (or similar depending on your language settings).
A dialog box appears with our "Hello World" message. Open the console window and see the additional info.
The next time we'll try to describe some background information how plugins work. Marcus supplied me with some html pages I'd like to publish.
No this time no download! Do your homework ;o).
good luck,
Sneaker -
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/02/2003 at 02:17, xxxxxxxx wrote:
Well done! Just one comment though...
> Quote: There is one thing I didn't change, but I think it's better to change it in future.
>
> * * *
>
> You stored the PluginID in c4d_symbols.h. This file must be distributed to the end user
> and therefore every end-user can change it. This might help during development, but I don't
> think that anybody should be able to change a unique PluginID given to the author.
>
> * * *I would DEFINATELY change this. If the PluginID is unique already, which it should be, then there is no reason why the end user should need to change it.
The fact that they _can_ change it means that some people will put in arbitrary values, and sooner or later it will conflict with someone else's plugin number.
With more complex plugins that store information in the document, the result of two different plugins sharing an ID number could be severe corruption of scene files, as one plugin modifies data that it thinks is its own, but actually belongs to another plugin.
I don't see any reason to have it in the symbols file, even during development.
I don't mean to sound critical, but this is a very important issue. If end users start changing plugin ID numbers (e.g. 'just to see what it does'), then you can wave goodbye to the stability that we enjoy at the moment.
Always use unique ID numbers assigned by PluginCafe, and NEVER let the end user change them - they don't need to, and it's dangerous!
Cheers - Steve
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/02/2003 at 06:15, xxxxxxxx wrote:
Hi Steve and Sneaker,
yep you both are right. I did this to make the ID easy modifyable for me. But you're right the data issue is very serious - I didn't think about it. I will change it.
Thanks for the comments. As you see, some comments are missing ... the documentation will follow. I swear! The weekend I was installing LINUX and still am, so please be patient
Ciao,
Marcus -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/02/2003 at 08:08, xxxxxxxx wrote:
With more complex plugins that store information in the document, the result of two different plugins sharing an ID number could be severe corruption of scene files, as one plugin modifies data that it thinks is its own, but actually belongs to another plugin.
---------------------------------
That is actually not possible IMO. Any other plugin with a different ID has access to "public" values created by another plugin. And private data can´t be changed (if not specificaly arranged) by any plugin anyway. Changing data isn´t really linked to PluginIDs. The main reason is to prevent collisions between the registration and for dialog IDs. So if you create a key with your plugin, any other plugin can find this key in the timeline and change the data if possible to change it.
Best
Samir -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/02/2003 at 09:23, xxxxxxxx wrote:
Hi,
I'm referring to private plugin data stored within the document.PluginID values can be used to uniquely identify a subcontainer stored within an object's base container, in which the plugin can safely store arbitrary information for its own purposes.
My understanding is that this is the recommended method for storing such private information.
If another plugin uses the same ID value then both plugins would have access to the same subcontainer, but both would believe that it belonged to them only - as a result they could interact with each other in unpredictable ways.
In this way, different plugins _can_ mess up each others private data.
Cheers - Steve
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/02/2003 at 09:33, xxxxxxxx wrote:
I'm referring to private plugin data stored within the document.
PluginID values can be used to uniquely identify a subcontainer stored within an object's base container, in which the plugin can safely store arbitrary information for its own purposes.
--------------------------------------------
1. Could you explain that "subcontainer" method a bit more detailed? I didn´t know this is a prefered method for using "private" data... two or three lines of code explaining what you mean would be appreciated.
2. private data can´t be accessed by other plugins for it is declared as "private". Maybe you are talking something else?
--------------------------------------------My understanding is that this is the recommended method for storing such private information.
--------------------------------------------
I don´t think so. I have a thousand times the same IDs for basecontainer values in my plugins and none of them did ever collide. So I don´t get the point here really. Maybe someone from the dev support could help us find out what´s going on with stored data in basecontainers... But I can´t imagine it is possible.
---------------------------------------------If another plugin uses the same ID value then both plugins would have access to the same subcontainer, but both would believe that it belonged to them only - as a result they could interact with each other in unpredictable ways.
----------------------------------------------
Sorry, I don´t believe that. Then it would be easily possible to exchange data thru a subcontainer but afaik that´s not possible but only over the PluginMessage Port....?!
Best
Samir -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/02/2003 at 10:11, xxxxxxxx wrote:
Two plugins with the same plugin ID can -not- run at the same time.
However, lets say you have PluginA and PluginB, they both share the same ID (for whatever reason), a user creates a document with PluginA, sends this to someone with PluginB. When they open it, CINEMA will try and find the plugin with the matching ID that is of the same type, if say PluginA and pluginB are both plugin objects, then when PluginB tries to access the basecontainer data the values it reads back will make no/little sense to it, at best the plugin will just behave odd, at worst it could lead to serious problems (maybe a freeze or crash). This is the -only- way two plugins with the same ID could interact, plugins with different IDs (so they can run at the same time), can interact in many ways.
Sharing plugin IDs is NOT advised, they -must- be unique, if during development you use a set of fixed IDs or the temporary IDs, then that is your choice, I never do this, I'd rather start off with my real IDs.
BaseContainer data can be accessed by any plugin, there is no such thing as private, you don't even need to know the IDs of the data, you can enum the data elements.
You can use a subcontainer if you wish, but you don't have to, each type of object has its own basecontainer, the data is per object. Storing data in a BaseContainer is recommended simply because CINEMA will handle read/write and clone, if you have the data in your class then you need to handle the read/write/clone of any data the plugin needs.
I think there is some confusion in what you are both talking about, I couldn't really follow either of you -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/02/2003 at 10:17, xxxxxxxx wrote:
BaseContainer data can be accessed by any plugin, there is no such thing as private, you don't even need to know the IDs of the data, you can enum the data elements.
You can use a subcontainer if you wish, but you don't have to, each type of object has its own basecontainer, the data is per object. Storing data in a BaseContainer is recommended simply because CINEMA will handle read/write and clone, if you have the data in your class then you need to handle the read/write/clone of any data the plugin needs.
-------------------------------------------
Ah ok, this makes things clearer. Thanks for clarification.
-------------------------------------------
I think there is some confusion in what you are both talking about, I couldn't really follow either of you
-------------------------------------------
lol, I didn´t even know myself what we were talking.
Best
Samir -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/02/2003 at 12:26, xxxxxxxx wrote:
David: The A/B plugin situation you described was what I meant regarding potential conflict between plugins - but you explained it much more clearly!
3D: Ok, I shouldn't really have referred to it as 'private', because it's not actually private - it's just data that is only _meant_ to be accessed by one particular plugin. There isn't actually anything to stop it though.
From the SDK (R7 and R8), under 'BaseContainer':
"It is recommended that you use the available containers to store your own values as well. That way they will be automatically saved. However, if you want to store values in the top level of for example an object container, you'll have to use a unique id. You can use a plugin id from http://www.plugincafe.com for this. A good way is to store a sub-container with this id. Inside this sub-container you can use whatever ids you want."If you follow this advice, and use the PluginID as a unique ID number to identify 'your' sub-container, then the A/B situation David described means that one plugin could see the sub-container that the other one wrote, and chaos _may_ then ensue...
One final note - the docs say that using a plugin ID number is a good way of getting a unique number. It seems to me that it is the _only_ way of getting a number that you know is unique.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/02/2003 at 12:46, xxxxxxxx wrote:
well, that is a difference to me. Me, I never use already available Object Containers (except of my own plugin)! For example a light container or anything. This is a difference to what I thought we were talking about! But to be honest I never new they were called subcontainers, so in this point you trapped me.
But as Dave said, there won´t probably be a plugin that will be able to use specific data from another plugin. And by the way, how does this topic came up? Did anybody not use a unique ID? Sorry, haven´t read the whole thread...but I agree to your last statement.
But you should concentrate on other things than plugin IDs. Me I have to use it elsewhere than in the registration method only once in a lifetime. And now that we got the AM it is even less necessary. -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/02/2003 at 14:11, xxxxxxxx wrote:
A comment about putting plugin IDs in the c4d_symbols.h header file, and the risk that the user would change them. This is not a problem with C++ plugins, since the value is stored during compilation, like a #define. (C.O.F.F.E.E. plugins are loaded dynamically, though.)
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 11/02/2003 at 13:06, xxxxxxxx wrote:
Hi Mikael,
yep you're right. And now I rememer again, that was the cause, why I put the plugin ID into the symbol file: That way everybody is able to read the ID. -> I will keep his approach.
Ciao and happy hacking,
Marcus -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 12/02/2003 at 02:44, xxxxxxxx wrote:
Ok, good point about the c4d_symbols.h being compiled in to the plugin. So the risk of conflicting plugin IDs being created by the end user (for C++) shouldn't be an issue.
I still don't think that it's a good idea to put the ID in the file, though:
1. No users should need to know the plugin ID.
2. There's no guarantee that the number in the file matches what the plugin ID actually is. I.e. if at some point after the plugin has been built this number is changed, nothing will break but the information will be inconsistent. That is not a good thing.Scenario:
Somehow two plugins with conflicting ID numbers are created, and they both have the ID number listed in the 'c4d_symbols.h' file. Anyone seeing this could reasonably assume that by changing one of them they could resolve the conflict - but it won't (unless it's a Coffee plugin), so they're likely to assume that something else is causing the problem and start looking for other problems that don't exist...I know that this is an unlikely situation, BUT, I've spent enough time programming to become very keen on defensive programming techniques, and this looks like something that is a bad idea. It makes it look like people can change something when they can't.
Cheers - Steve
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 12/02/2003 at 02:58, xxxxxxxx wrote:
1. No users should need to know the plugin ID.
---------------------------------------
Some users will know anyway for i.e. Object or tag plugins.
->Create COFFEE Expression on pluginobject or object with plugintag(expression) ->use println(op->GetType()) or println(op->GetFirstTag()->GetType());
Hello, there is the plugin ID.
The user shouldn´t be able to change the plugin ID but it´s not dangerous if he knows it (except he then creates a plugin with the same ID on purpose
Best
Samir -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 23/02/2003 at 15:42, xxxxxxxx wrote:
Hi Folks,
I've put the stuff Sneaker and I have done together on a web-page - with some additional information. And currently I'm working on a description for a EdgeFlip plugin. For those who can't wait, I've put it's sources online. The documentation will follow this or next week - depending on my spare time.
And I have to excuse my little English skills - but I hope it's understable.
Here is the (preliminary) link to the web-page:
http://home.arcor.de/marcus.spranger/sdk8_pool/Ciao,
Marcus