THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 28/01/2009 at 16:39, xxxxxxxx wrote:
User Information:
Cinema 4D Version: 11
Platform: Windows ;
Language(s) : C++ ;
---------
Hey everybody,
I don't want to be one of those people who post code on forums and say "fix this!" as if people were obliged to help out. So instead, I'll ask nicely =P
Seriously though, I'm feeling very uncertain about the code I'm writing for my plugins. The main reason is that there is no "how to start writing plugins for C4D" tutorial that I could find. I'm reading every bit of introductory information I can find on the SDK, but there are still some areas that are vague in my mind.
I'm working on a plugin called MECO (stands for Make-Editable, Connect, Optimize) which boils down all those commands that you need to apply to a NURBS object to get it to a point where it can behave like any other polygonal object. I'm going to release this plugin for free and also open-source. Thus, I'd like it to be as robust as possible.
Would anyone be willing to look at my code and point out the errors of my way? It's commented well so you shouldn't have any problem understanding what I'm doing (especially the experts here).
This is a Command Plugin. Code from the Execute function follows:
> <code>
> //Gotta stop all threads first since we're modifying the active document
> StopAllThreads();
> //Array to hold selected objects
> AtomArray* selectedObjs = AtomArray::Alloc();
> //Fill array with selected objects
> doc->GetActiveObjects(*selectedObjs, TRUE);
>
> //Check if any objects are selected
> if(selectedObjs->GetCount() == 0)
> {
> //If not, free the array and then return
> AtomArray::Free(selectedObjs);
> return FALSE;
> }
>
> //Create Modeling Command Data
> ModelingCommandData cd;
> cd.doc = doc;
> //Set the objects to be changed
> cd.arr = selectedObjs;
>
> if(SendModelingCommand(MCOMMAND_MAKEEDITABLE, cd))
> {
> //Command was successful
> //Insert the resulting objects into the document
> for(int i=0; i<cd.result->GetCount(); i++)
> {
> doc->InsertObject((BaseObject* ) (cd.result->GetIndex(i)), NULL, NULL, FALSE);
> }
> } else {
> //Command failed
> //Free the array and then return
> AtomArray::Free(selectedObjs);
> return FALSE;
> }
>
> //Free the previous array as it's not valid anymore
> AtomArray::Free(selectedObjs);
>
> //Select these objects
> //Select the first one seperately to create a new selection with SELECTION_NEW
> doc->SetSelection((BaseList2D* ) (cd.result->GetIndex(0)), SELECTION_NEW);
> //Now add the others
> for(int i=1; i<cd.result->GetCount(); i++)
> {
> doc->SetSelection((BaseList2D* ) (cd.result->GetIndex(i)), SELECTION_ADD);
> }
>
> //Next step is to Connect these objects
> //Array to hold new selected objects
> AtomArray* selectedObjs_2 = AtomArray::Alloc();
> //Fill array with new selected objects
> doc->GetActiveObjects(*selectedObjs_2, TRUE);
>
> //Create new Modeling Command Data
> ModelingCommandData cd_2;
> cd_2.doc = doc;
> //Set the objects to be changed
> cd_2.arr = selectedObjs_2;
>
> if(SendModelingCommand(MCOMMAND_JOIN, cd_2))
> {
> //Command was successful
> //Insert the resulting objects into the document
> for(int i=0; i<cd_2.result->GetCount(); i++)
> {
> doc->InsertObject((BaseObject* ) (cd_2.result->GetIndex(i)), NULL, NULL, FALSE);
> }
> } else {
> //Command failed
> //Free the new array and then return
> AtomArray::Free(selectedObjs_2);
> return FALSE;
> }
>
> //Free the previous array as it's not valid anymore
> AtomArray::Free(selectedObjs_2);
>
> //Delete the original objects (which are selected) as they are not removed automatically
> //Array to hold new selected objects
> AtomArray* selectedObjs_3 = AtomArray::Alloc();
> //Fill array with new selected objects
> doc->GetActiveObjects(*selectedObjs_3, TRUE);
> for(int i=0; i<selectedObjs_3->GetCount(); i++)
> {
> BaseObject* bobj = (BaseObject* ) selectedObjs_3->GetIndex(i);
> bobj->Remove();
> BaseObject::Free(bobj);
> }
>
> //Free the previous array as it's not valid anymore
> AtomArray::Free(selectedObjs_3);
>
> //Next step is to Optimize points on the objects
> //Create new Modeling Command Data
> ModelingCommandData cd_3;
> cd_3.doc = doc;
> //Also need a Base Container to pass Optimize command data
> BaseContainer bc;
> bc.SetReal(MDATA_OPTIMIZE_TOLERANCE, 0.01);
> bc.SetReal(MDATA_OPTIMIZE_POINTS, TRUE);
> bc.SetReal(MDATA_OPTIMIZE_POLYGONS, TRUE);
> bc.SetReal(MDATA_OPTIMIZE_UNUSEDPOINTS, TRUE);
> //Link the Base Container to the Modeling Command Data
> cd_3.bc = &bc;
> //Set the objects to be changed
> cd_3.arr = cd_2.result;
>
> if(SendModelingCommand(MCOMMAND_OPTIMIZE, cd_3))
> {
> doc->Message(MSG_UPDATE, NULL);
> //Optimize command doesn't return anything.
> } else {
> //Command failed
> return FALSE;
> }
>
> //Force redraw
> EventAdd(EVENT_FORCEREDRAW);
>
> return TRUE;
> </code>
Things I'm aware of:
-There's no UNDO support as of now.
-It actually does what it's supposed to do.
Things I'm worried about:
-Do I need to send UPDATE messages to the active document or the changed/inserted objects after every modeling command?
-I actually don't quite know what messages are for in the first place? Any pointers to useful information regarding messages would be very useful.
-There's a bug with my command that doesn't make any sense to me. If you create a Rectangle spline, put it under an Extrude NURBS, then rotate the Extrude NURBS an arbitrary amount of degrees, then run my command on the Extrude NURBS object, it creates the new object in the original rotation of the Extrude NURBS and not the latest and correct rotation.
Thank you very much for reading this post,
Yilmaz Kiymaz