API Question SketchPad vs hDC ?

N_Molson

Addon Developer
Addon Developer
Donator
Joined
Mar 5, 2010
Messages
10,002
Reaction score
4,418
Points
203
Location
Toulouse
Hello again,

At first I didn't wanted to start another thread but... my brain will explode !

I try to display data on a HUD, the SurfaceHUD in this case. The "BombMFD" tutorial, pt. 2-3 (yeah, it's my bible those days), explains very well how to do that.

But...

Orbiter seems to use it's own display method, "Sketchpad". I looked at the "DrawingAPI.h" file for more explanations, but, as it says, it's strictly a drawing API, used to display geometric shapes.

I tried Computerex's code sample, but it is based on the Windows API, which can display numerical values. So when I come to the part where the Textout functions asks a pointer for hDC, I'm doomed...

I've managed to display various text strings like "Hail Probe" or "Hello Probe", but I don't manage to display numerical data.

So I searched on the web and I tried what follows, that is my "best guess"... Because what I need is apparently to convert a double value into a char string. "sprintf" is the obvious answer, but how to adapt it to SketchPad ? It's where I get stucked.

Of course I could use a clbkDrawHud with hDC. But then I would have only data and no more fancy shapes like the landing gear or the nosecone indicators. Which would mean than you have to choose between the two (or that I'd make better how to draw shapes with the Windows API) ?

Where I'm surprised is that SketchPad was implemented to avoid the use of the Windows API :

Code:
// This API defines an abstraction layer for providing drawing support
// for surfaces (e.g. lines and text). It is closely modelled on the
// Windows GDI, but provides an overload mechanism to insert different
// drawing systems.
So I'm completely confused... Do I have to choose between the 2 APIs, or is there a mean to have the best of each ?

Code:
bool DeltaGlider::clbkDrawHUD (int mode, const HUDPAINTSPEC *hps, oapi::Sketchpad *skp)
{
    // draw the default HUD

    VESSEL3::clbkDrawHUD (mode, hps, skp);
    int cx = hps->CX, cy = hps->CY;

    // trying to display a double class value on the HUD

    if (oapiGetHUDMode() == HUD_SURFACE) {

            char* buff;
            buff = (char*) malloc(15);
            double data = 1234.5678;

            sprintf(buff, "%f", data);

            skp->Text (0, hps->H-20,"??", ?);
            
    }
    
    return true;
}
Sorry for the disturbance. I know I'm probably looking at the problem from a wrong angle... but well I really don't see...

:compbash: :hail::probe: :compbash2:
 
Sketchpad was brought into Orbiter 2010 to move away from the Windows GDI functions, which will allow better portability between platforms.

It's generally a good plan to use Sketchpad for new projects.

To write text out, I use a string:

Code:
	int linespacing = mHeight/MFD_LINE_NR;
	int lineNo = 1;
	int charwidth = mWidth/MFD_CHAR_LEN;
	std::string txt;

	// Draws the MFD title
	Title (skp, mfd_name);
	lineNo = lineNo + 2;	// Use Green for the rest of the MFD text

	GetDefaultFont(0);

	skp->SetTextColor(MFD_RED);
	txt = "Now Playing: ";
	skp->Text(3, linespacing*lineNo, txt.c_str(), (int)txt.length());
	lineNo++;

For printing variables, I use sprintf almost like you have it there:

Code:
char buffer[256];

sprintf_s(buffer, "%s [%s]", pVessel->GetName(), pClassName);
txt = buffer;

skp->Text(3, linespacing*lineNo, txt.c_str(), (int)txt.length());
 
Last edited:
the sketchpad isn't really exclusive from the GDI... you CAN, in fact use both.... but it's not reccomendable, as it makes for messy code, and can get very bug-prone :uhh:

you can get a DeviceContext handle (HDC) from any SURFACEHANDLE using oapiGetDC(surfHandle);

just remember to release it later...


*note - this is a shot from the hip... i just might be completely off :hmm:
 
I've got it working ! :speakcool: Added the TAS in knots and the altitude in feet (shuttle fashion), it helps a lot for landings to have those printed in the middle of the screen.

Here I'm stalling beyond any help because my DG version isn't designed to takeoff on it's own (I'll have to remember to make the engines almost inoperative at sea-level, the specs are those of the Shuttle OMS engines) ;)



Well here's the code that worked, if one day someone searchs for the same answer :

Code:
    if (oapiGetHUDMode() == HUD_SURFACE) {

            int linespacing = 2;
            int charwidth = 2;            
            int lineNo = 200;
            std::string txt;

            char buffer[256];
            double TASkts = GetAirspeed()*1.94384449;
            double ALTft = GetAltitude()*3.2808399;

            sprintf_s(buffer, "KTS %.0f", TASkts);
            txt = buffer;
            skp->Text(400, linespacing*lineNo, txt.c_str(),  (int)txt.length());

            sprintf_s(buffer, "FT %.0f", ALTft);
            txt = buffer;
            skp->Text(825, linespacing*lineNo, txt.c_str(),  (int)txt.length());
            
    }

Of course, it would be better to make the data "screen resolution-independent", but that will come later :P

Cool, thanks everyone :cheers:
 
Beware - you're not freeing the memory.
And I don't understand why there's "malloc" in first place. It's C++ so "new" and "delete" operators seems to fit better, or since it's only 15 bytes, and it's only used inside this function, an allocation of "buff" on stack, which would be the best here (like "cx" and "cy" - "[highlight]char buff[16];[/highlight]" - 16 because of alignment, however it should be aligned to 4 bytes boundary by compiler if you set it to 15), and it doesn't need to be unallocated manually.

EDIT: Like in the new code.

---------- Post added at 13:18 ---------- Previous post was at 12:46 ----------

One note though:
Code:
            txt = buffer;
            skp->Text(400, linespacing*lineNo, txt.c_str(),  (int)txt.length());
If you only converted char buffer to string to get the length of string, you could use "strlen" function with "char *" parameter instead. There are too many string conversions in the above code.
 
Heh, yes orb, there are. It's actually pretty much the same as my code, and I wrote it like that because I was being lazy and copy-pasting stuff :P.

Works though. ;)
 
Code:
if (oapiGetHUDMode() == HUD_SURFACE) {

            int linespacing = 2, charwidth = 2, lineNo = 200, len;
           
            char buffer[256];
            memset(buffer, 0, sizeof(buffer));

            double TASkts = GetAirspeed()*1.94384449;
            double ALTft = GetAltitude()*3.2808399;

            len = sprintf_s(buffer, "KTS %.0f", TASkts);
            skp->Text(400, linespacing*lineNo, buffer,  len);

            len = sprintf_s(buffer, "FT %.0f", ALTft);
            skp->Text(825, linespacing*lineNo, buffer,  len);
            
    }
 
Back
Top