On 02/07/2013 at 00:49, xxxxxxxx wrote:
Originally posted by xxxxxxxx
Originally posted by xxxxxxxx
tag->GetNodeData() sounds like what you're looking for.
It sounds like that, but I can't get it to work.
BaseTag* tagFound = someObject->GetNext();
MySpecialTag* msp = (MySpecialTag)tagFound->GetNodeData();
Line two gives error: C2440: 'type cast' : cannot convert from 'NodeData *' to 'MySpecialTag'
There are some fundamental aspects of the C4D way of doing things that I still have not understood. I program all day, because that is my profession, but so far C4D and C++ is still a hobby.
What I am used to, is full object oriented programming. So in my head, tags in C4D sit on their object, and are fully living classes with properties and methods. So when someObject->GetNext() returns a BaseTag, I expect to have access to all the tag's props and methods, in this case stuff I wrote myself.
I also expect to be able to typecast, and furthermore to check availability by using keywords like is or as.
What I have to do now, is to write special methods (functions) and call them using the 'tag' as parameter, like this:
Bool MySpecialTag::DoSomeStuff(BaseTag* tag)
and these functions can as well be static , since they "do not know of" the tag itself in any case.
And then I have to use tag->GetParameter() or tag->SetParameter(), whereas I elsewhere (in C#) only have to call a Getter or Setter I wrote myself, in MySpecialTag.
You are missing an asterisk in the cast.
From what context do you want to call a method on the tag? If you are in a method of the TagData
itself, you can call it they way you are used to it..
> class MyTagData : public TagData {
>
>
>
>
> void FooBar() {
>
> // ...
>
> }
>
>
>
>
> public:
>
>
>
>
> Bool Execute(/* .. */) {
>
> FooBar();
>
> // ...
>
> }
>
>
>
>
> };
Remember you are in C++, not C#. It's different. Languages like C#, Java, Python, Ruby, COFFEE,
PHP, JavaScript, they all *know* what type an object is because they store this information in the
object itself. C++ doesn't do that.
> So when someObject->GetNext() returns a BaseTag, I expect to have access to all the tag's props and methods, in this case stuff I wrote myself.
Get rid of this illusion. It is not this way. I think to understand this, you must dive deep into the
Cinema API, but to give you the two the number one reasons why NodeData plugins are wrapped
by the GeListNode class: Abstraction and Memory. The undo-system for example makes use of the
fact that each GeListNode is just a proxy for a plugin implementation. When an object is moved on
the undo-stack, it's GeListNode is copied, but it is still connected to the exactly same NodeData
implementation.
Btw, it is easier to make use of the Message() system instead of your own boilerplated methods,
because it is quite a work to invoke them: See the "Stability and Testing" section in the docs, under
"Virtual Function Calls".
FYI, you can write wrapper classes (that could also serve as an API to your plugin) by subclassing
BaseTag. Just make sure you are only using methods, no attributes! If you want to use it
cross-over plugins (eg. as an API for extensions for your plugin), you even need to save a pointer
to the methods.
class MyTag : public BaseTag {
MyTag();
~MyTag();
public:
Bool IsEnabled() {
BaseContainer* data = GetDataInstance();
if (data) {
return data->GetBool(MYTAG_ENABLED);
}
return FALSE;
}
const Vector* GetSomeInternalData() {
MyTagData* data = (MyTagData* ) GetNodeData();
if (!data) return NULL;
return data->GetSomeInternalData();
}
const Vector* AnotherWayOfGettingInternalData() {
const Vector* ptr = NULL;
if (!Message(MSG_MY_PRIVATE_MESSAGE_ID_FROM_THE_PLUGINCAFE, &ptr)) {
return FALSE;
}
return ptr;
}
};
"IsEnabled()" and "AnotherWayOfGettingInternalData()" could be used from another plugin too
because they are doing safe operations on the virtual method table, unlike the
"GetSomeInternalData()" method.