Could you post an example?
Sure.
Here's what the registering of my "MFC" class looks like in clbkLoadPanel (well, one of the instances, anyways):
Code:
RegisterPanelArea(hPanel, AID_MFC1, _R(8,8,258,238), PANEL_REDRAW_USER, PANEL_MOUSE_LBDOWN|PANEL_MOUSE_LBPRESSED|PANEL_MOUSE_LBUP|PANEL_MOUSE_ONREPLAY, panel2dtex, mfc[0]);
As you can see, I'm registering all mouse events, but only the USER redraw event, because I want total control over when a redraw occurs and when not.
The class has a function for triggering its own redraw:
Code:
void IMS_MFC::TriggerRedraw()
{
if (vessel->GetActivePanel() == Panelid && oapiCameraInternal() && vessel == oapiGetFocusInterface())
oapiTriggerPanelRedrawArea(Panelid, MYid);
}
The class has to know three things: the vessel it is a part of, its panel id (not relevant for VC) and its own id (to tell Orbiter that it wants to be redrawn).
The first line checks if it is even located on the currently active panel of the vessel (as this function is also used for timed redraws, not just for input triggered redraws. Also, this isn't an API function, but it's irrelevant for VC anyways), if Orbiter is even in cockpitmode and wheather or not the current focus vessel is the vessel that contains this panel elements (otherwise, redrawing would not just be futile, but ctd-ishly dangerous, as I noticed).
If all these conditions are fulfilled, the function triggers the redraw of its panel element. Otherwise there won't be a redraw (as none is necessary).
In the event processing function of the class, it determines what exactly has been modified, and if the event warrants a re-write (that is, the apearance of the element changes by the event), it simply callsTriggerRedraw, like for example (mostly pseudocode):
Code:
bool IMS_MFC::ProcessMouse2D(int event, int mx, int my)
{
if (ThisImportantButtonPressed)
{
Do;
Stuff;
This;
Button;
Should;
Do;
TriggerRedraw();
return true;
}
return false;
}
and that's that. When the user clicks on an inactive area of the panel, the redraw won't occur (as it would if I simply told orbiter to redraw everytime the element has been clicked). This can make sense or not, depending on wheather you have inactive areas inside a panel element (and I have lots of them, as this is a dynamic "touchscreen" interface, that means the same element can execute various functions and display various information).
Then there's the timer function of the class, which is pretty straightforward too:
Code:
bool IMS_MFC::CheckRedrawTimer(double simdt)
{
if (RedrawTimer == 0 || !active || mnu) return false; //if timer set to zero, not active or in menu mode, don't even bother
ElapsedTime += simdt / oapiGetTimeAcceleration(); //adjust for time acceleration. mor fps friendly.
if (ElapsedTime > RedrawTimer)
{
ElapsedTime = 0;
timerInterval = !timerInterval; //just a variable tat changes state every time. Usually used for blinkenlights
TriggerRedraw();
}
return true;
}
This function gets called for every instance of the class in every frame (from clbkPreStep). It updates the elapsed time since the last timer, and if the time is larger than the interval set (can be different for every instance, deending on what the instance is displaying) it resets the elapsed time and calls TriggerRedraw(). So every time the timer of an element elapses, Orbiter will get a RedrawEvent from that instance, if the conditions in TriggerRedraw are met. Note that this function automatically compensates for time acceleration, meaning, the redraw intervall will always be in real time. This can make sense or not, depending on the display. For a clock it might make sense to update it in sim time, for a life support display usually not so much.
Is animation and (the additional vertices required) really that much more efficient than blitting?
Ohhhhh yes. Our Graphics Hardware is heavily optimised for that kind of stuff. Blitting is more of an afterthought in the design, really (As far as I know, the good old Supernintendo can rival a modern low to mid-end GPU in blitting performance under certain circumstances (very narrow circumstances, admittedly), because blitting speed was pretty much the only thing that stuff was designed for).
I had already been considering doing the ADI ball as an actual mesh because I thought the code might be simpler, should I just go a head and do it?
If it's even simpler to code, there's no reason whatsoever not to.
EDIT:
If I'm not going to have a scrolling scale should I do the gauges seperately?
Not sure what you mean, you'll need to be a bit more specific.
Of course if I really wanted to go overboard I'd do the whole cockpit as mesh animations but I've been trying to keep the vert count to an absolutminimum because I was under the impression that animations/mesh rendering were a much bigger drain on system resources than textures.
More taxing than
textures, yes. More taxing than blitting stuff around in memory? Hell no!!