API Question oapiGetVesselInterface and custom vessel classes.

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,868
Reaction score
4
Points
0
Location
San Diego
I know how to use oapiGetVesselInterface() to get a generic vessel class interface but how do I go about achieving the same effect with a custom vessel class so that I can access my vessel specific functions and handles?

When I trey to declare my custom vessel interface and assign it I get an error that says "can not convert ____ to VESSEL"

Example...

Code:
		// Create service module as seperate vessel
		strcpy (name, GetName()); 
		strcat (name, "_ServiceMod");
		oapiCreateVessel (name, "AAPO/CSM_ServiceMod", vs);	// create service module vessel

		OBJHANDLE oh_servicemod = oapiGetObjectByName (name);		// get handle of service module vessel 
		VESSEL *v = oapiGetVesselInterface (oh_servicemod);			// get interface for service module
		CSM_ServiceMod *sm = v; // **Problem Line**

It's that last line that's the problem.

I want the CSM_ServiceMod interface so that I can assign class specific variable (animation states and the like) but Orbiter wont let me.
 
You can't do it like that, you're trying to assign a pointer of type VESSEL to a type CSM_ServiceMod. That is an implicit conversion, but the two types do not have instructions that would let them convert implicitly between each other. You have to cast the pointer

In IMS, I'm doing a dynamic_cast. It returns NULL if the object is not of the type you're trying to cast to, and allows my program to not crash if I try to cast the wrong VESSEL instance for some reason...
 
Last edited:
In IMS, I'm doing a dynamic_cast. It returns NULL if the object is not of the type you're trying to cast to, and allows my program to not crash if I try to cast the wrong VESSEL instance for some reason...
If I remember correctly, dynamic casting to your vessel class first requires C casting of the VESSEL you get from oapiGetVesselInterface to VESSEL2 or VESSEL3 type, because VESSEL isn't polymorphic, but VESSEL2 or VESSEL3 are.

If that's the case, then you can get the version of the VESSEL class it was inherited from with VESSEL::Version() method.
 
You can't do it like that, you're trying to assign a pointer of type VESSEL to a type CSM_ServiceMod. That is an implicit conversion, but the two types do not have instructions that would let them convert implicitly between each other. You have to cast the pointer

In IMS, I'm doing a dynamic_cast. It returns NULL if the object is not of the type you're trying to cast to, and allows my program to not crash if I try to cast the wrong VESSEL instance for some reason...

How would I go about doing that?
 
If I remember correctly, dynamic casting to your vessel class first requires C casting of the VESSEL you get from oapiGetVesselInterface to VESSEL2 or VESSEL3 type, because VESSEL isn't polymorphic, but VESSEL2 or VESSEL3 are.

Right, forgot about that part. Thanks! (what a memory some people have :lol:)

How would I go about doing that?

Don't have the IMS source code handy right now. Will post tomorrow.
 
Right, here is the snippet from IMS:

Code:
int IMS::CheckClass(VESSEL *mvessel)
{
	//check if docked mvessel is an IMS mvessel, an IMS module or something else

	/*----------------------------
	IMPORTANT!!!!!
	line "if (mvessel->Version() >= 2)" causes unresolved symbol in connection with UMMU when built in debug mode!
	To build in debug mode, comment that line. 
	----------------------------*/
	if (mvessel->Version() >= 2) 
	{
		IMS *testv = dynamic_cast<IMS*>((VESSEL2*)mvessel);
		if (testv != NULL) return 1;
	}
.
.
.
//stuff not interesting for your purposes
}
 
Code:
	/*----------------------------
	IMPORTANT!!!!!
	line "if (mvessel->Version() >= 2)" causes unresolved symbol in connection with UMMU when built in debug mode!
	To build in debug mode, comment that line. 
	----------------------------*/
	if (mvessel->Version() >= 2)
Code:
[color=red][s]// To build in debug mode, comment that line.[/s][/color]
[color=green]#ifndef _DEBUG[/color]
	if (mvessel->Version() >= 2) 
[color=green]#endif[/color]
:P
 
Right, here is the snippet from IMS:

Code:
int IMS::CheckClass(VESSEL *mvessel)
{
	//check if docked mvessel is an IMS mvessel, an IMS module or something else

	/*----------------------------
	IMPORTANT!!!!!
	line "if (mvessel->Version() >= 2)" causes unresolved symbol in connection with UMMU when built in debug mode!
	To build in debug mode, comment that line. 
	----------------------------*/
	if (mvessel->Version() >= 2) 
	{
		IMS *testv = dynamic_cast<IMS*>((VESSEL2*)mvessel);
		if (testv != NULL) return 1;
	}
.
.
.
//stuff not interesting for your purposes
}


How do you get a class interface from that?
 
But what are you trying to do? Specific vessel functionalities should be invoked passively through callbacks.

If it's just about doing something in the moment of creation, then this code should be written in the vessel construction method, which returns VESSEL - no casting would be needed there.
 
Last edited:
Sure but where are they coming from? Why can't they be defined in the creation callback or simply in the vessel's constructor as its paameters?

Edit
You'll soon have to deal with a similar problem when reloading a scenario, so a common handling function will be required, that should be called in the vessels constructor and scenario reload.
 
Last edited:
Sure but where are they coming from? Why can't they be defined in the creation callback or simply in the vessel's constructor as its paameters?

Because on creation the correct values still reside within the parent vessel (the Command Module), the child (Service Module) has no way of knowing what they are.

You'll soon have to deal with a similar problem when reloading a scenario, so a common handling function will be required, that should be called in the vessels constructor and scenario reload.

No I wont. Any values I manipulate will be stored by the service module's own clbkSaveState function.
 
How do you get a class interface from that?

Why, it's right there:

Code:
IMS *testv = dynamic_cast<IMS*>((VESSEL2*)mvessel);

IMS is my class, testv is a pointer to the instance of that class that vas hidden behind VESSEL *mvessel.
Just replace IMS * with CSM_ServiceMod *.

The pointer isn't kept in my function, because it only serves to create a list of the types of vessels that are currently docked. But at this point, you can also keep it and do pretty much anything with it (i.e. call all public members).
 
Why, it's right there:

Code:
IMS *testv = dynamic_cast<IMS*>((VESSEL2*)mvessel);

IMS is my class, testv is a pointer to the instance of that class that vas hidden behind VESSEL *mvessel.
Just replace IMS * with CSM_ServiceMod *.

The pointer isn't kept in my function, because it only serves to create a list of the types of vessels that are currently docked. But at this point, you can also keep it and do pretty much anything with it (i.e. call all public members).

Ahh, missed that on the initial reading
 
Back
Top