SDK Question Virtual Cockpit best practices

DecoFox

New member
Joined
Apr 24, 2012
Messages
7
Reaction score
12
Points
3
Location
Anchorage
Hey, very long-time Orbiter player finally getting around to cracking the SDK open, here. I'm posting hoping for some general wisdom on how best to build Virtual Cockpits in a way that doesn't create a ton of technical debt. I come from a Unity/C# background primarily, so you may have to bear with me a little on Orbiter SDK and C++, but I think I'm starting to get it.

About a week ago I got it in my head I wanted to build an Orbiter vessel, which I justified to myself as an excuse to learn C++. I'm a huge virtual cockpit fan and also very bad about not biting off more than I can chew, so I've been going all-out with intent to build an animated VC, custom engine behavior, and whatever system depth I find I have the patience to build. By virtue of the quite-thorough documentation, I've been able to get pretty far:

0008.jpg0016.jpg

I built it off the PB, paying reference to the SDK manual and a few third party guides. It's got the basic necessities: retractable landing gear, animated control surfaces, the beginning of a virtual cockpit, and, as a foray into interactive VCs, a light with a dimmer switch. Digging into switches though, the way forward has started to look less certain. I've been trying to reverse engineer my way through it, but the default vessels seem to handle switches a bit differently between them, and I haven't been able to make total sense of what's going on. The Shuttle-A I mostly follow; I don't totally understand how redraws work just yet, but the Shuttle-A seems to define all its clickable VC elements in the main vessel DLL, and does so more or less the way the documentation describes doing it.

That said, I as I understand the great strength of DLLs is portability and scalability, and it would make sense to organize switches into prototypes that I could re-use to perform similar functions on other vessels. This seems to be what the DeltaGlider is doing, with each switch defined separately and inheriting from a common DGSwitch, which in turn inherits from the common Instrument file. Trouble is, owing probably to my newness to C++, I'm having a hard time determining exactly how the DG switch family actually works. It also seems a little overkill for my applications, since I have no intent of defining a 2D cockpit with matching switches, and the intent to support both seems to be a major function of the DG architecture.

The specific questions I've come up with so far are:
  • Is there some widely agreed on best practice that I'm just not aware of? Does everyone, say, base their interior switches on DGSwitch? Or, at a lower level, on Instrument? Would I be massively reinventing the wheel to handle it any other way?
  • Are there any resources that explain in detail how the DeltaGlider switch family actually works?
  • Are there any resources that explain how to build around subsystems the way the DeltaGlider is, and when one would likely want to?
  • If I go ahead and define my VC in-line the way the Shuttle-A does, am I going to live to regret it? Or does an approach like that make sense sometimes, perhaps on simpler interiors, or on interiors with a lot of bespoke functions not likely to be shared with other vessels.
  • What is the best way to deal with scalability? I don't know what all will be in my virtual cockpit just yet, and intend to add to it as features occur to me or I decide to change how I'm implementing the ones that are there. I can always add new mesh to my heart's content, but every time I introduce a new mesh body (as I probably would for most switches and gauges) I'll be shuffling around the mesh group indices that get used to drive animations. I'd prefer to not have to trawl through the mesh file for which indices I need for every animation I've made every time I make a change. Is there a trick to that? I remember reading some hint that there was a way to access mesh groups by label rather than index, but I haven't found a way to actually do that.
  • What are the difference between the VESSEL base classes? I've been working from 3 and just noticed the Shuttle A works from VESSEL4. Meanwhile, The DeltaGlider works instead from ComponentVessel, which I gather is important to working with subsystems and inheritance, but I'm not clear on the particulars.
Apologies if I'm missing the blindingly obvious; I have been known to do that on occasion.

Edit:
huh, apparently I took a stab at this way back in 2017 but totally forgot about it. Must not have made much progress. This start has been considerably more auspicious.
 
Last edited:

DecoFox

New member
Joined
Apr 24, 2012
Messages
7
Reaction score
12
Points
3
Location
Anchorage
0017.jpg
I went ahead with reference to the Shuttle A (having judged the DG inheritance structure to be a bit overkill for my needs) and have been making alright progress with clickable (Navmode switches) and draggable (light dimmer) VC elements. The sticking point at the moment is MFD displays. The documentation seems to be out of date on those, as it mentions flagging them as "3", and I noticed other spacecraft seem to leave them completely unflagged. Leaving out the flag, I've gotten them to display black, but nothing more than that. Admittedly I have been trying to skirt writing all of the MFD button logic for the time being (I'm a long way away from doing textures), but it doesn't seem like any of the redraws the buttons trigger have to do with the MFDs themselves, so from my understanding of how the code works, I shouldn't strictly need that functionality for the MFDs to display. I'll experiment with doing it all properly tomorrow, but I figured I'd float the question now in case that doesn't prove the solution.
 

Blake

Addon Developer
Addon Developer
Joined
Mar 9, 2009
Messages
238
Reaction score
124
Points
58
Location
Lehi, Utah
I think VC development is a lot of fun, but can be tricky. I'm not aware of any best practices, or ways to make it easier. DG is a good place to look, but that has been structured to generalize a lot of the functionality. If you don't need that it is overkill. Still, it is a working sample, and that is always valuable.

Post your specific questions here and if someone can help, they will. I don't know that the body of active VC developers is very large however.
 

Urwumpe

Not funny anymore
Addon Developer
Donator
Joined
Feb 6, 2008
Messages
37,656
Reaction score
2,376
Points
203
Location
Wolfsburg
Preferred Pronouns
Sire
Essentially, its just software architecture, that you must do there. HOW you do it, is not cast in stone. You have millions of different ways. You can even not use the object-oriented approach at all. In the end, its data words and machine language anyway. But of course, you must pick a format, that you can easily maintain and change, if your spacecraft design is not yet done.

I wish I could be more helpful there, but my experience with it is: Everytime I have a working way how to do a VC, I find a different better one, that learned its lessons from the previous one and fixed many problems I discovered only by actually working with it...
 

DecoFox

New member
Joined
Apr 24, 2012
Messages
7
Reaction score
12
Points
3
Location
Anchorage
Appreciate the advice. I figured the story might be "end up doing it a bit differently and a bit better each time", which is why I went ahead with the Shuttle A example, but it's good to know it probably won't turn around and bite me in a huge way in the immediate future. Now that I better understand what all the animation and active area boilerplate is actually doing, I have a much better idea of how I could split it all if I decide I want to, which helps, too. My original thought was that I could make self-contained DLLs for most buttons and displays and simply place them in the VC environment arbitrarily with a constructor that takes position arguments or something, but that's a bit rich for my blood until I understand the SDK better. As it is, I'm not even totally clear on if I can load entire secondary meshes as opposed to working with groups. Definitely a problem to come back to. Some time after I figure out why I can't get my MFDs to render anything, and probably after I flesh the interior out on whole.
 

n72.75

Move slow and try not to break too much.
Orbiter Contributor
Addon Developer
Tutorial Publisher
Donator
Joined
Mar 21, 2008
Messages
2,699
Reaction score
1,361
Points
128
Location
Saco, ME
Website
mwhume.space
Preferred Pronouns
he/him
The specific questions I've come up with so far are:
  • Is there some widely agreed on best practice that I'm just not aware of? Does everyone, say, base their interior switches on DGSwitch? Or, at a lower level, on Instrument? Would I be massively reinventing the wheel to handle it any other way?

Not really. To be honest there aren't really a huge amount of Orbiter vessels with complicated virtual cockpits.

Generally, keeping things organized is probably best. Perhaps you could make a class for each of the "panels", and then have a std::vector of your switch class to keep track of them.

NASSP and SSV are probably good references to look at. Just be aware that NASSP probably doesn't represent a best practice, just a practice that works pretty well.

  • Are there any resources that explain in detail how the DeltaGlider switch family actually works?

I'm not aware of any other than the code itself. It's possible that there is information here in some older threads, if you search, but I'm not aware of any specific ones.

The API Guide document (\Orbitersdk\doc\API_Guide.pdf) is about as detailed as any offical documentation gets.

  • Are there any resources that explain how to build around subsystems the way the DeltaGlider is, and when one would likely want to?

Same as above unfortunately. This is also highly dependent on how detailed you want to make your simulation: e.g do your lights turn off when if(switch==up), or does the switch control the flow of power to the light.

  • If I go ahead and define my VC in-line the way the Shuttle-A does, am I going to live to regret it? Or does an approach like that make sense sometimes, perhaps on simpler interiors, or on interiors with a lot of bespoke functions not likely to be shared with other vessels.

As long as you don't go too complex, just a big list of definitions in clbkLoadVC shouldn't be too hard to upgrade from later on. I would tend to say that anything more complicated than the Deltaglider is approaching that limit...

  • What is the best way to deal with scalability? I don't know what all will be in my virtual cockpit just yet, and intend to add to it as features occur to me or I decide to change how I'm implementing the ones that are there. I can always add new mesh to my heart's content, but every time I introduce a new mesh body (as I probably would for most switches and gauges) I'll be shuffling around the mesh group indices that get used to drive animations. I'd prefer to not have to trawl through the mesh file for which indices I need for every animation I've made every time I make a change. Is there a trick to that? I remember reading some hint that there was a way to access mesh groups by label rather than index, but I haven't found a way to actually do that.

I don't want to give bad advice, but at some point you'd probably need something that looked like your own API. The SSV base mesh does not include meshes for the switches, which allows the panel configuration to be controlled. NASSP does something similar, but for now, only on the 2D panel.

  • What are the difference between the VESSEL base classes? I've been working from 3 and just noticed the Shuttle A works from VESSEL4. Meanwhile, The DeltaGlider works instead from ComponentVessel, which I gather is important to working with subsystems and inheritance, but I'm not clear on the particulars.

Those are for backward compatibility with the API. VESSEL4 inherits from VESSEL3, etc.

1714961119681.png
 

Matias Saibene

Development hell
Joined
Jul 7, 2012
Messages
1,060
Reaction score
652
Points
128
Location
Monte Hermoso - Argentina
Website
de-todo-un-poco-computacion-e-ideas.blogspot.com.ar
Top