SDK Question Redrawing MFD Buttons

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
I had to take a break from Orbiter due to real life but I'm back now and working getting my Lunar Module's VC up and running.

As the title says, the topic of this thread is MFD buttons. I already have them registered and responding to mouse events, the only thing left is to display the labels.

As with much of this project I started by copy/pasting from OrbiterSDK sample but I need help with parsing and trouble-shooting.

here's the function as copied from the stock DG, at first glance it seemed pretty straight-forward. I simply commented out the "isVC" boolean as it was un-needed (no 2D panel) and matched the x/y values my button texture.

Code:
void LEM::RedrawMFDButtons (SURFHANDLE surf, int mfd, int side) // (Copied from stock DG)
{
  HDC hDC = oapiGetDC (surf);
  HFONT pFont = (HFONT)SelectObject (hDC, g_Param.font[1]);
  SetTextColor (hDC, RGB(196, 196, 196));
  SetTextAlign (hDC, TA_CENTER);
  SetBkMode (hDC, TRANSPARENT);

  const char *label;
  //bool isVC = (oapiCockpitMode() == COCKPIT_VIRTUAL);
  //int x = (isVC ? 12:13);
  //int y = (isVC ? 0:3);

  int x = 16;
  int y = 4;

  for (int bt = 0; bt < 6; bt++) 
  {
    if (label = oapiMFDButtonLabel(mfd, bt + side*6)) 
    {
    TextOut (hDC, x, y, label, strlen (label));
    //if (isVC) x += 24;
    //else      y += 41;
    y += 40;
    } 
    else break;
  }

SelectObject (hDC, pFont);
oapiReleaseDC (surf, hDC);
}

When I went to compile I got the following errors

Code:
1>c:\users\hlynkacg\documents\visual studio 2010\projects\lunarlanders\lemcockpit.cpp(280): error C2065: 'g_Param' : undeclared identifier
1>c:\users\hlynkacg\documents\visual studio 2010\projects\lunarlanders\lemcockpit.cpp(280): error C2228: left of '.font' must have class/struct/union

Now 'g_Param' has already been declared as a global in my vessel's primary cpp file (I split everything associated with the cockpit into it's own file just for the sake of readability but VS finds it just fine when i click "go to def" so I don't know why it's complaining.

Here's the definition as it appears in my header
Code:
// I don't know what exactly this does but it's associated with graphics in some way and apperently it is important. I copied it from the stock DG's header file
typedef struct 
  {
  HINSTANCE hDLL;
  HFONT font[2];   
  DWORD col[4];      
  HBRUSH brush[4];
  HPEN pen[2];
  } GDIParams;

and here's the global declaration in my primary cpp file
Code:
//==============================================================
//	ORBITER MODULE: HlynkaCG's 'SPIDER' LUNAR EXCURSION MODULE
//				A custom Vessel For Orbiter 2010/11
//  
//	SpiderLEM.cpp
//	Implementation of Lunar Excursion Module vessel class
//==============================================================

#define STRICT
#define ORBITER_MODULE
#include "Orbitersdk.h"
#include "SpiderLEM.h"
#include "LEMcockpit.h"

GDIParams g_Param; // this does something

The '.font' however was a new one to me so I went digging through the Delta Glider's source to find it.

this is what I found...

Code:
// --------------------------------------------------------------
// Module initialisation
// --------------------------------------------------------------
DLLCLBK void InitModule (HINSTANCE hModule)
{
	g_Param.hDLL = hModule;
	oapiRegisterCustomControls (hModule);

	// allocate GDI resources
	g_Param.font[0]  = CreateFont (-13, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 0, "Arial");
	g_Param.font[1]  = CreateFont (-10, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, "Arial");
	g_Param.brush[0] = CreateSolidBrush (RGB(0,255,0));    // green
	g_Param.brush[1] = CreateSolidBrush (RGB(255,0,0));    // red
	g_Param.brush[2] = CreateSolidBrush (RGB(80,80,224));  // blue
	g_Param.brush[3] = CreateSolidBrush (RGB(160,120,64)); // brown
	g_Param.pen[0] = CreatePen (PS_SOLID, 1, RGB(224,224,224));
	g_Param.pen[1] = CreatePen (PS_SOLID, 3, RGB(164,164,164));

	// allocate textures
	DeltaGlider::panel2dtex = oapiLoadTexture ("DG\\dg_panel.dds");
}

// --------------------------------------------------------------
// Module cleanup
// --------------------------------------------------------------
DLLCLBK void ExitModule (HINSTANCE hModule)
{
	oapiUnregisterCustomControls (hModule);

	int i;

	// deallocate GDI resources
	for (i = 0; i < 2; i++) DeleteObject (g_Param.font[i]);
	for (i = 0; i < 4; i++) DeleteObject (g_Param.brush[i]);
	for (i = 0; i < 2; i++) DeleteObject (g_Param.pen[i]);

	// deallocate textures
	oapiDestroySurface (DeltaGlider::panel2dtex);
}

I recognize the DLLCLBK init/exit functions and thier purpose but what exactly is goining on and how do I make it do what I want?

I tried simply copy/pasting into my own API callback interface and commenting out the DG reference but that didn't work.

As always any insight would be greatly appreciated. :hailprobe:
 
Last edited:

jedidia

shoemaker without legs
Addon Developer
Joined
Mar 19, 2008
Messages
10,882
Reaction score
2,133
Points
203
Location
between the planets
ouh, outdated tutorial. You really shouldn't use the win GDI anymore. If you follow the code in the DG, you will see that it actually draws its MFD buttns with a bitmap font as we did for your clock (in fact, the print function I gave you was an adaptation of the MFD buttons drawing from the DG). alternatively, you can think about using sketchpad, but not windows. Those definitions are still there in the DG code, it hasn't been cleaned up very well, but you'll find that they're actually not used anymore.
 
Last edited:

orb

New member
News Reporter
Joined
Oct 30, 2009
Messages
14,020
Reaction score
4
Points
0
Code:
1>c:\users\hlynkacg\documents\visual studio 2010\projects\lunarlanders\lemcockpit.cpp(280): error C2065: 'g_Param' : undeclared identifier
1>c:\users\hlynkacg\documents\visual studio 2010\projects\lunarlanders\lemcockpit.cpp(280): error C2228: left of '.font' must have class/struct/union
Now 'g_Param' has already been declared as a global in my vessel's primary cpp file (I split everything associated with the cockpit into it's own file just for the sake of readability but VS finds it just fine when i click "go to def" so I don't know why it's complaining.
Was it declared in lemcockpit.cpp (or included in its header file)?

If it was declared in one of the cpp file and you want to use it in another cpp file, you need to declare it in that another cpp file as 'extern', like:
Code:
extern GDIParams g_Param;
 

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
ouh, outdated tutorial. You really shouldn't use the win GDI anymore. If you follow the code in the DG, you will see that it actually draws its MFD buttns with a bitmap font as we did for your clock (in fact, the print function I gave you was an adaptation of the MFD buttons drawing from the DG). alternatively, you can think about using sketchpad, but not windows. Those definitions are still there in the DG code, it hasn't been cleaned up very well, but you'll find that they're actually not used anymore.

I don't understand, looking at the DG resource files there's no "Arial" bitmap so where is it bliting from? Likewise the dg's TextOutput functions appear to allow transperancy and changing the size/color of the text, I didn't think that this was possible with bliting.

Do I really need to generate a seperate bitmap for every possible font/size/color/background combinatation?

Was it declared in lemcockpit.cpp (or included in its header file)?

If it was declared in one of the cpp file and you want to use it in another cpp file, you need to declare it in that another cpp file as 'extern', like:
Code:
extern GDIParams g_Param;

It was declared outside of LEMcockpit.cpp, that fixed part of it, thank you.

---------- Post added at 11:35 PM ---------- Previous post was at 11:27 PM ----------

Ok new error.

Code:
1>c:\users\hlynkacg\documents\visual studio 2010\projects\lunarlanders\spiderlem.cpp(927): error C3861: 'oapiRegisterCustomControls': identifier not found
1>c:\users\hlynkacg\documents\visual studio 2010\projects\lunarlanders\spiderlem.cpp(946): error C3861: 'oapiUnregisterCustomControls': identifier not found

in association with...

Code:
// Module initialisation
DLLCLBK void InitModule (HINSTANCE hModule)
{
	g_Param.hDLL = hModule;
	[COLOR="red"]oapiRegisterCustomControls (hModule);[/COLOR]

	// allocate GDI resources
	g_Param.font[0]  = CreateFont (-13, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 0, "Arial");
	g_Param.font[1]  = CreateFont (-10, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, "Arial");
	g_Param.brush[0] = CreateSolidBrush (RGB(0,255,0));    // green
	g_Param.brush[1] = CreateSolidBrush (RGB(255,0,0));    // red
	g_Param.brush[2] = CreateSolidBrush (RGB(80,80,224));  // blue
	g_Param.brush[3] = CreateSolidBrush (RGB(160,120,64)); // brown
	g_Param.pen[0] = CreatePen (PS_SOLID, 1, RGB(224,224,224));
	g_Param.pen[1] = CreatePen (PS_SOLID, 3, RGB(164,164,164));

	//// allocate textures
	//DeltaGlider::panel2dtex = oapiLoadTexture ("DG\\dg_panel.dds");
}

// Module cleanup
DLLCLBK void ExitModule (HINSTANCE hModule)
{
	[COLOR="Red"]oapiUnregisterCustomControls (hModule);[/COLOR]

	int i;

	// deallocate GDI resources
	for (i = 0; i < 2; i++) DeleteObject (g_Param.font[i]);
	for (i = 0; i < 4; i++) DeleteObject (g_Param.brush[i]);
	for (i = 0; i < 2; i++) DeleteObject (g_Param.pen[i]);

	//// deallocate textures
	//oapiDestroySurface (DeltaGlider::panel2dtex);
}
 

jedidia

shoemaker without legs
Addon Developer
Joined
Mar 19, 2008
Messages
10,882
Reaction score
2,133
Points
203
Location
between the planets
I don't understand, looking at the DG resource files there's no "Arial" bitmap so where is it bliting from?

Don't look at the resource files. Those are outdated too. Look at the texture files, the font is stored directly in the panel texture ;)

Likewise the dg's TextOutput functions appear to allow transperancy and changing the size/color of the text, I didn't think that this was possible with bliting.

I never got transparency to work, doesn't mean it must be impossible. Varying font-sizes are certainly possible, you just need a bitmap font for every size. Again, that's actually how practicaly all games do it. You have a managable number of different fonts and sizes in any GUI, and blitting them from video memory is just that much faster than employing truetype fonts. Although the inability to change color in Orbiter, which is relatively easy if you have direct memory access, is somewhat of a drawback.

Also, I haven't seen the DG employ transparency anywhere, nor different font sizes. All backgrounds it prints on are black.

Do I really need to generate a seperate bitmap for every possible font/size/color/background combinatation?

I would recommend it. A positive side effect of it is that you think really hard what fonts in what size you actually need in a GUI, because as a rule of thumb, you should always have the least variety possible that still conveys what you want to convey. However, if even that lowest number of fonts and sizes is too large, you can still use sketchpad. Whatever you do, don't use those Win-GDI drawing functions anymore. It's like cleaning a road with a large hose, and then go over it again with a toothbrush...
 

csanders

Addon Developer
Addon Developer
Joined
Jan 18, 2012
Messages
219
Reaction score
0
Points
0
Location
Plymouth
[/COLOR]Ok new error.

Code:
1>c:\users\hlynkacg\documents\visual studio 2010\projects\lunarlanders\spiderlem.cpp(927): error C3861: 'oapiRegisterCustomControls': identifier not found
1>c:\users\hlynkacg\documents\visual studio 2010\projects\lunarlanders\spiderlem.cpp(946): error C3861: 'oapiUnregisterCustomControls': identifier not found

in association with...

Is this line in your spiderlem.cpp?
#include "OrbiterAPI.h"

EDIT: on second glance "oapiRegisterCustomControls" isn't in my OrbiterAPI.h header...
 

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
Don't look at the resource files. Those are outdated too. Look at the texture files, the font is stored directly in the panel texture ;)

Well Sh*t...

That explains half of my problems right there.

Ok where are the DG's REAL redraw functions, the ones I should be looking at?
 

csanders

Addon Developer
Addon Developer
Joined
Jan 18, 2012
Messages
219
Reaction score
0
Points
0
Location
Plymouth
FYI, this is a slightly better way to handle global variables, because you don't have to manually add an "extern type variableName" to every cpp file that uses the variable. You just have to include the header file, which you have to do anyway for the file to recognize the type to begin with:

Code:
// I don't know what exactly this does but it's associated with graphics in some way and apperently it is important. I copied it from the stock DG's header file
typedef struct 
  {
  HINSTANCE hDLL;
  HFONT font[2];   
  DWORD col[4];      
  HBRUSH brush[4];
  HPEN pen[2];
  } GDIParams;

GDIParams &GetGDIParams();//Note the &

in the .cpp file that has your g_Param:
Code:
GDIParams g_Param;
GDIParams &GetGDIParams()
{
    return g_Param;
}

Since it returns the variable as a reference:
GetGDIParams().pen[0] = somePen;
Does the same thing as:
g_Param.pen[0]; = somePen;
 

martins

Orbiter Founder
Orbiter Founder
Joined
Mar 31, 2008
Messages
2,448
Reaction score
462
Points
83
Website
orbit.medphys.ucl.ac.uk
To be honest, the redraw functions in the DG are in a slightly messy state at the moment. Maybe I can clean them up a bit for the next beta.

Currently, the 2-D panel mouse and redraw event functionality has been implemented in the PanelElement-derived classes. For example, the MFD button redraws are in MFDButtonCol::Redraw2D (file MFDButton.cpp).

However, the VC redraw functions are still part of the DeltaGlider class (DeltaGlider::RedrawPanel_MFDButton). This should really be moved to MFDButtonCol::Redraw3D

For now, it may be better to look at the DeltaGlider's 2D redraw mechanism for inspiration, even if you are implementing a virtual cockpit. The DG's 2D panel is in effect a flat VC, so the methods should translate to a real VC without too much change.
 

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
Ok this is wierd...

mainpanel.dds is not a dynamic texture and is referenced nowhere in the dll (only the mesh) and yet...

picture.php


here's the pertinent section of clbkloadvc

Code:
// Define MFD Buttons
	sh_MFD = oapiGetTextureHandle (mh_cockpit, 5); // (mh_cockpit, Cmd_MFDbuttons);
	
	oapiVCRegisterArea (AID_MFD0_LBUTTONS,  _R( 0, 0, MFDtexW, MFDtexH), PANEL_REDRAW_MOUSE, PANEL_MOUSE_LBDOWN, PANEL_MAP_BACKGROUND, sh_MFD); // Left soft-keys
		oapiVCSetAreaClickmode_Quadrilateral (AID_MFD0_LBUTTONS, (MFD_POS + MFD_BUTTON_OFFSET[ 0]), (MFD_POS + MFD_BUTTON_OFFSET[ 1]), (MFD_POS + MFD_BUTTON_OFFSET[ 2]), (MFD_POS + MFD_BUTTON_OFFSET[ 3]) );
	
	oapiVCRegisterArea (AID_MFD0_RBUTTONS,  _R( 0, 0, MFDtexW, MFDtexH), PANEL_REDRAW_MOUSE, PANEL_MOUSE_LBDOWN, PANEL_MAP_BACKGROUND, sh_MFD); // Right soft-keys
		oapiVCSetAreaClickmode_Quadrilateral (AID_MFD0_RBUTTONS, (MFD_POS + MFD_BUTTON_OFFSET[ 4]), (MFD_POS + MFD_BUTTON_OFFSET[ 5]), (MFD_POS + MFD_BUTTON_OFFSET[ 6]), (MFD_POS + MFD_BUTTON_OFFSET[ 7]));
	
	oapiVCRegisterArea ((AID_MFD0_PWR), _R(0,0,0,0), PANEL_REDRAW_NEVER, PANEL_MOUSE_LBDOWN, PANEL_MAP_NONE, NULL); // Power Button
		oapiVCSetAreaClickmode_Spherical	((AID_MFD0_PWR), (MFD_POS + MFD_BUTTON_OFFSET[ 8]), 0.01);
	
	oapiVCRegisterArea ((AID_MFD0_SEL), _R(0,0,0,0), PANEL_REDRAW_NEVER, PANEL_MOUSE_LBDOWN, PANEL_MAP_NONE, NULL); // Select Button
		oapiVCSetAreaClickmode_Spherical	((AID_MFD0_SEL), (MFD_POS + MFD_BUTTON_OFFSET[ 9]), 0.01);
	
	oapiVCRegisterArea ((AID_MFD0_MNU), _R(0,0,0,0), PANEL_REDRAW_NEVER, PANEL_MOUSE_LBDOWN, PANEL_MAP_NONE, NULL); // Menu Button
		oapiVCSetAreaClickmode_Spherical	((AID_MFD0_MNU), (MFD_POS + MFD_BUTTON_OFFSET[10]), 0.01);

Yes I have confirmed that 'mgroup 5' is in fact 'Cmd_MFDbuttons' not the main panel.

Here's the MFD button redraw function as adapted from the DG...

Code:
void LEM::RedrawMFDButtons (SURFHANDLE surf, int mfd, int side) // write MFD button labels
{
	int i, btn, len, w;
	const char *label;

	int tgtX; 
	int	tgtY;

	//x = tx_w/2;
	//y = 4;
	
	//for (btn = 0; btn < 6; btn++) oapiBlt(surf, surf, tgtX, tgtY, CHY, 28, CHH); // print blank label

	for (btn = 0; btn < 6; btn++)
	{
		if( label = oapiMFDButtonLabel(mfd, btn+side*6)) // get MFD button label as a string
		{
			len = strlen(label); // get label string length
			for (w = i = 0; i < len; i++) w += CHW[label[i]]; // Calculate width of printed string in pixles 
			for (i = 0, tgtX = btncol[side]-w/2; i < len; i++) 
			{
				w = CHW[label[i]]; 
				if (w) 
				{
					oapiBlt (surf, sh_Inst, tgtX, btnrow[btn], CHX[label[i]], CHY, w, CHH);
					tgtX += w;
				}
			}
		}
		else break;
	}
    //return false;
}

sh_Inst is a texture I created to save fonts and other intrument display elements. Clearly that ref is working because the font is printing just not to the right place.

aside from the initial surf definition does anyone have any ideas of where I might have gotten my wires crossed because I am very confused.
 
Top