Making Spline GUI's
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/06/2011 at 06:24, xxxxxxxx wrote:
If you write the Spline GUI yourself, you will have to write the Spline and its interpolation, too.
Here's a starter:
Spline article on Wikipedia -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/06/2011 at 06:43, xxxxxxxx wrote:
Interesting article, jack. Thanks !
Here's my approach yet. Unfortunately drawing a circle is not very easy.
I wrote a DrawCircle method, but it's not very satisfying.Yet, you can move around a rectangle on the userarea.
Cheers,
Niklas -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/06/2011 at 10:58, xxxxxxxx wrote:
Sorry about not being clear.
I'm interested in learning more about custom GUI's like what Nux posted. But the spline GUI I'm talking about is the built in one(graph view) that comes with C4D.I'm having problems creating my own simple spline control on my own tag.
-The first problem is I can't get the spline graph to show up.
-The second problem is because the number of knots is dynamic. I don't know how to get the values of the spline's knots. So I can use that information to control something in the scene.Here's my tag plugin's .cpp code:
#include "c4d.h" #include "c4d_symbols.h" #include "tmyspline_GUI.h" #include "c4d_graphview_enum.h" #include "c4d_graphview.h" #include "c4d_graphview_def.h" #include "customgui_splinecontrol.h" class MySplineTag : public TagData { INSTANCEOF(MySplineTag,TagData) public: virtual Bool Init(GeListNode *node); virtual EXECUTIONRESULT Execute(BaseTag *tag, BaseDocument *doc, BaseObject *op, BaseThread *bt, LONG priority, EXECUTIONFLAGS flags); virtual void Free(GeListNode *node); virtual Bool Message(GeListNode *node, LONG type, void *data); static NodeData *Alloc(void) { return gNew MySplineTag; } }; Bool MySplineTag::Init(GeListNode *node) { BaseContainer *bc=((BaseList2D* )node)->GetDataInstance(); bc->SetReal(MAX_VALUE, 10.0); GeData d(CUSTOMDATATYPE_SPLINE, DEFAULTVALUE); SplineData* p = (SplineData* )d.GetCustomDataType(CUSTOMDATATYPE_SPLINE); if (p) { p->MakeLinearSpline(2); p->SetRound(1.0); } bc->SetData(MYSPLINE, d); return TRUE; } EXECUTIONRESULT MySplineTag::Execute(BaseTag *tag, BaseDocument *doc, BaseObject *op, BaseThread *bt, LONG priority, EXECUTIONFLAGS flags) { BaseContainer *bc = op->GetDataInstance(); SplineData *myspline = (SplineData* )bc->GetCustomDataType(MYSPLINE, CUSTOMDATATYPE_SPLINE); Real displace = bc->GetReal(MAX_VALUE); if (myspline) GePrint("True"); return EXECUTIONRESULT_OK; } void MySplineTag::Free(GeListNode *node) { } Bool MySplineTag::Message(GeListNode *node, LONG type, void *data) { return SUPER::Message(node,type,data); } ////////////////////////////////////////////////////////////////////////// #define PLUGIN_ID 10000011 // Testing ID ONLY!!! Bool RegisterMySplineTag() { return RegisterTagPlugin(PLUGIN_ID, GeLoadString(IDS_MYSPLINE_GUI), TAG_MULTIPLE|TAG_VISIBLE, MySplineTag::Alloc,"tmyspline_GUI", AutoBitmap("myicon.tif"),0); }
Here's the .h file:
#ifndef _Tmyspline_GUI_H_ #define _Tmyspline_GUI_H_ enum { MAX_VALUE = 2000, MYSPLINE = 2001, }; #endif
Here's the .res file
CONTAINER Tmyspline_GUI { NAME Tmyspline_GUI; INCLUDE Texpression; GROUP ID_TAGPROPERTIES { REAL MAX_VALUE { UNIT METER; MIN 0.0; } SPLINE MYSPLINE { SHOWGRID_H; SHOWGRID_V; GRIDSIZE_H 8; GRIDSIZE_V 8; HAS_PRESET_BTN; MINSIZE_H 120; MINSIZE_V 90; EDIT_H; EDIT_V; LABELS_H; LABELS_V; HAS_ROUND_SLIDER; X_MIN 0; X_MAX 100; Y_MIN 0; Y_MAX 100; X_STEPS 1; Y_STEPS 1; } } }
Here's the .str file:
STRINGTABLE Tmyspline_GUI { Tmyspline_GUI "My spline GUI test"; MAX_VALUE "Max Spline Value"; MYSPLINE "My Spline's Shape"; }
Here's the strange part.
If I use this same code to edit one of the hair tag examples in the SDK. It's works and The graph and spline shows up. But when I try to build my own tag, without doing it inside of the cinema4dsdk. It doesn't show up.
So I'm thinking that maybe I'm missing an include?
But I can't find it.After I get the stupid thing to show up.
Then I have to tackle how to get the values of the spline's knots.-ScottA
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/06/2011 at 11:23, xxxxxxxx wrote:
But in your .res fil you are using the BuiltIn Spline Datatype ?! :nerd:
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/06/2011 at 11:43, xxxxxxxx wrote:
Yeah. Sorry about the confusion Nux.
I am interested in learning more about the actual hand made(UserArea) custom GUI stuff too.
But for now. I'm just trying to understand how to use the built-in spline graph GUI.-ScottA
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/06/2011 at 12:00, xxxxxxxx wrote:
Ah, ok. I can't help you there, because I do only code in Python, yet.
So I hope my Python Code above helps you about how to create knots and being able to drag them around with the mouse. The only thing missing in this UserArea is the interpolated Spline.Cheers,
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/06/2011 at 13:22, xxxxxxxx wrote:
I can't figure out why my stupid spline isn't showing up in my own non SDK plugin.
So I'm going to keep working on the one I converted from a hair tag in the sdk project for now.
Hopefully Matthias will know why my spline isn't showing up.Here's the code so far:
Bool MySplineTag::Message(GeListNode *node, LONG type, void *data) { BaseContainer *bc=((BaseList2D* )node)->GetDataInstance(); // Assign the container for node(that holds the spline data) to a variable("bc") Real maxvalue = bc->GetReal(MAX_VALUE); // The max value setting SplineData *myspline=(SplineData* )bc->GetCustomDataType(MYSPLINE, CUSTOMDATATYPE_SPLINE); // Get the spline from the container and assign it to a variable("myspline") Real knotcount = 0; if(myspline) // if there is a spline drawn { knotcount = myspline->GetKnotCount(); CustomSplineKnot *first = myspline->GetKnot(0); myspline->SetRange(0, maxvalue, 1, 0, maxvalue, 1); //Set the spline's range //Real xmin, Real xmax, Real xsteps, Real ymin, Real ymax, Real ysteps } GePrint(RealToString(knotcount)); //Now I need to Get the value for each point in the spline. How? return true; }
I'm slowly getting there. But now I'm stuck on getting the values for each of the spline's knots.
-ScottA
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/06/2011 at 21:12, xxxxxxxx wrote:
You just get the vPos member from the CustomSplineKnot struct:
Vector knotPos = first->vPos;
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 27/06/2011 at 09:32, xxxxxxxx wrote:
Thanks David.
Getting there. Slow but sure.
Now that I've got what I need to create a spline GUI and retrieve the knot's data in my message method. I have to figure out how to make it control something in my Execute method.Plus. I still have to figure out what #include file to add so I can use this as a stand alone plugin.
-ScottA
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 28/06/2011 at 01:06, xxxxxxxx wrote:
Ok, here is a very simple but complete example of a tag with a spline gui element in its description.
I hope this helps because I honestly don't know why it's not working for you.
splintag.cpp
///////////////////////////////////////////////////////////// // CINEMA 4D SDK // ///////////////////////////////////////////////////////////// // (c) 1989-2004 MAXON Computer GmbH, all rights reserved // ///////////////////////////////////////////////////////////// // "look at editor camera" expression example #include "c4d.h" #include "c4d_symbols.h" #include "tsplinetag.h" class SplineTag : public TagData { public: virtual Bool Init(GeListNode *node); virtual EXECUTIONRESULT Execute(BaseTag *tag, BaseDocument *doc, BaseObject *op, BaseThread *bt, LONG priority, EXECUTIONFLAGS flags); static NodeData *Alloc(void) { return gNew SplineTag; } }; Bool SplineTag::Init(GeListNode *node) { BaseTag *tag = (BaseTag* )node; BaseContainer *data = tag->GetDataInstance(); GeData d(CUSTOMDATATYPE_SPLINE, DEFAULTVALUE); SplineData *p = (SplineData* )d.GetCustomDataType(CUSTOMDATATYPE_SPLINE); if (!p) return FALSE; p->MakeLinearSpline(2); p->SetRound(1.0); data->SetData(MY_SPLINE, d); return TRUE; } EXECUTIONRESULT SplineTag::Execute(BaseTag *tag, BaseDocument *doc, BaseObject *op, BaseThread *bt, LONG priority, EXECUTIONFLAGS flags) { GeData d; if (tag->GetParameter(DescLevel(MY_SPLINE), d, DESCFLAGS_GET_0)) { SplineData *sd = (SplineData* )d.GetCustomDataType(CUSTOMDATATYPE_SPLINE); if (sd) { // access the SplineData LONG kcnt = sd->GetKnotCount(); LONG i; for (i=0; i<kcnt; i++) { CustomSplineKnot *knot = sd->GetKnot(i); if (knot) { // the spline knot position Vector p = knot->vPos; } } } } return EXECUTIONRESULT_OK; } // be sure to use a unique ID obtained from www.plugincafe.com #define ID_SPLINETAG 1001165 Bool RegisterSplineTag(void) { return RegisterTagPlugin(ID_SPLINETAG, GeLoadString(IDS_SPLINETAG),TAG_EXPRESSION|TAG_VISIBLE,SplineTag::Alloc,"Tsplinetag",AutoBitmap("icon.tif"),0); }
main.cpp
///////////////////////////////////////////////////////////// // CINEMA 4D SDK // ///////////////////////////////////////////////////////////// // (c) 1989-2004 MAXON Computer GmbH, all rights reserved // ///////////////////////////////////////////////////////////// // Starts the plugin registration #include "c4d.h" // forward declarations Bool RegisterSplineTag(void); Bool PluginStart(void) { if (!RegisterSplineTag()) return FALSE; return TRUE; } void PluginEnd(void) { } Bool PluginMessage(LONG id, void *data) { //use the following lines to set a plugin priority // switch (id) { case C4DPL_INIT_SYS: if (!resource.Init()) return FALSE; // don't start plugin without resource // important, the serial hook must be registered before PluginStart(), best in C4DPL_INIT_SYS //if (!RegisterExampleSNHook()) return FALSE; return TRUE; case C4DMSG_PRIORITY: return TRUE; } return FALSE; }
tsplinetag.res
CONTAINER Tsplinetag { NAME Tsplinetag; INCLUDE Texpression; GROUP ID_TAGPROPERTIES { SPLINE MY_SPLINE { } } }
tsplinetag.h
#ifndef _Tsplinetag_H_ #define _Tsplinetag_H_ enum { MY_SPLINE = 1000 }; #endif
tsplinetag.str
STRINGTABLE Tsplinetag { Tsplinetag "Spline Tag"; MY_SPLINE "My Spline"; }
c4d_symbols.h
enum { // string table definitions IDS_SPLINETAG = 10000, // End of symbol definition _DUMMY_ELEMENT_ };
c4d_string.str
// C4D-StringResource // Identifier Text STRINGTABLE { IDS_SPLINETAG "Spline Tag"; }
cheers,
Matthias -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 28/06/2011 at 07:52, xxxxxxxx wrote:
Thanks a lot Matthias.
Since I wasn't able to figure out why my STD alone version wouldn't show up. While my SDK version did. I ended up deleting everything from the SDK. And created my STD alone version that way.
Looking at your example. Now I'm even more confused about how the whole Message() & Execute() functions work.
Since most people put their button (clicked/not clicked) actions inside of the Message() function. My understanding of this was that the Message() function was used to communicate to C4D about the GUI states.
And The Execute() function is only used to do the actual execution of something.
But in your example. You have everything in the Execute() function. And no Message() function at all.I'm confused.
-ScottA
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 05/07/2011 at 01:49, xxxxxxxx wrote:
It's actually not that difficult. You access the GUI elements whenever you need the state or value of an GUI element. GUI elements that have no state, like a button, are an exception and are handled through the Message method by waiting for the MSG_DESCRIPTION_COMMAND message. One thing to keep in mind is to avoid unnecessary GUI calls. For instance in a shader you would access the GUI outside of the shader Output() method because otherwise GUI access would be done for every rendered pixel, making things really slow and unsafe.
cheers,
Matthias