UniversalPUB / Mit++ Library Infothread 1

Forum Archive - from http://theuniversal.net
Locked
User avatar
morbydvisns
Posts: 1889
Joined: Sun Jan 30, 2005 12:51 am

UniversalPUB / Mit++ Library Infothread 1

Post by morbydvisns »

Here we will dissect and discuss the sample codes provided with the library. The official name is UniversalPUB but I have unofficially dubbed this the Mit++ Library.

We will start, traditionally, with the classic 'Hello World' sample.


Also, please bear with me here. I'm not going to claim to know how this all works, as I'm rather new to this programming stuff. Some stuff is semi-documented within the code. I will do my best to outline most else. Some i just really have no idea yet what the technical function is, but I'm sure Mit could clue us in on some bits =).

Anyway, here we go. I will break this code in to blocks so my comments don't blend in with the code, but if you had the proper library files, you would be able to past in each box in succession and compile.

Code: Select all

//-----------------------------------------------------------------------------------------------------------------------
// main.cpp
//
//  HelloWorld sample for Interface library
//
//-----------------------------------------------------------------------------------------------------------------------

#include <StdWinInclude.h>		// If we need to know about windows stuff like HWNDs, HINSTANCEs etc, then we need to include this first
#include <StandardDef.h>		// This specifies a minimal set of 'standard' defines like BOOL
#include <Interface.h>			// The 2d graphics interface library

//-----------------------------------------------------------------------------------------------------------------------
In this area, we tell the compiler what files will be included with this one.
Public variables and constructors and such will be available that are in the included file names specified.

Code: Select all


//-----------------------------------------------------------------------------------------------------------------------
// ------------------------------------------- Windows specific stuff

HWND	ghwndMain;		// Global window handle

//-------------------------------------------------------------------------
// Function    : WindowsMsgProc
// Description : 
//-------------------------------------------------------------------------
LRESULT WINAPI WindowsMsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
	case WM_KEYDOWN:
		//Handle a key press event
		switch (wParam)
		{
		case VK_ESCAPE:
			PostQuitMessage( 0 );
			return( DefWindowProc( hWnd, msg, wParam, lParam ) );
			break;
		}
		break;
	case WM_DESTROY:
		// Handle close & quit
		PostQuitMessage( 0 );
		return 0;
		break;
	default:
		break;
	}

    return( DefWindowProc( hWnd, msg, wParam, lParam ) );
}
WindowsMsgProc receives messages sent from Windows... There are many. the HWND tells it which window its referring to (i think lol).
the UINT msg is a general windows message. There are many as well here, a google search of either WM_ messages in the example will lead you to more. http://msdn.microsoft.com/en-us/library/ is a big help with info on stuff like that.

WPARAM is like a sub-message i guess. In the case of WM_KEYDOWN, it contains info on which key was pressed. VK_ESCAPE would obviously mean it was the ESCAPE key pressed. the PostQuitMessage( 0 ); tells it to exit that window(application). I believe it also sends a WM_DESTROY message from Windows.

switch( ) is a conditional statement. based upon the variable name you put between the ( )'s
So what it's doing is looking at (msg). whenever (msg) is WM_KEYDOWN, it then in turn does another switch to evaluate wParam. And, when it says the ESC key was pressed, it closes the program.

There must be a break; at the end of each condition of the switch. This tells it the switch is complete. If there is no break; it will just continue down and execute the next condition for some reason. And no, this isn't a drunken Mit coding issue, it's just how it is in the language =).

and default defines what to do if none of the conditions are met.

Code: Select all


//-------------------------------------------------------------------------
// Function    : InitialiseWindow
// Description : 
//-------------------------------------------------------------------------
void		InitialiseWindow( void )
{

WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WindowsMsgProc, 0L, 0L,
                  GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                  "UniversalHelloWorldSample", NULL };

	// Create window
	ghwndMain = InterfaceInitWindow( "Universal - Interface Library - HelloWorld sample", &wc );

}
//-----------------------------------------------------------------------------------------------------------------------

Initializes and creates the window to work within. Details are fuzzy here for now, except the InterfaceInitWindow specifies the title at the top bar of the window.

Code: Select all



//-------------------------------------------------------------------------
// Function    : MainInitialise
// Description : 
//-------------------------------------------------------------------------
void	MainInitialise( void )
{
	// Create the window for viewing things in
	InitialiseWindow();

	// Initialise D3D
	InterfaceInitDisplayDevice( 0 );

	// Initialise the interface 
	InterfaceInit();

}

The MainInitialize section is just that. It initializes anything you may need initializing. It is called from the Main section found below, but that's not important right at the moment.

You may create a procedure that only needs to happen once when the program starts. This is where you would call it from.

Code: Select all


//-------------------------------------------------------------------------
// Function    : MainUpdate
// Description : 
//-------------------------------------------------------------------------
void	MainUpdate( void )
{

	// New frame - clear the back buffer
	InterfaceNewFrame( 0 );

	// Signal start of rendering pass
	InterfaceBeginRender();

	// Draw stuff here
	InterfaceText( 0, 10, 10, "Hello World", 0xFFFFFFFF, 1 );

	// Flush the Interface renderer
	InterfaceDraw();
			
	// Signal end of this pass
	InterfaceEndRender();

	// Present the results to the user
	InterfacePresent();

}
This is executed once per frame. Documented clearly enough =) I'll just go over the text drawing details.

InterfaceText( 0, 10, 10, "Hello World", 0xFFFFFFFF, 1 );

InterfaceText is the name of the procedure to do this.

The first value passed with this is the layer to be rendered on. The lower the number renders first. Higher numbers render on top of lower numbers, covering them.

Second value specifies X coord, third is Y coord to start drawing at.

third value is what its going to print on the screen. After that is the color in hex value, and then the last number is the font to draw in (Havnt messed with changing fonts, or how the font number is determined yet).


Code: Select all



//-------------------------------------------------------------------------
// Function    : MainShutdown
// Description : 
//-------------------------------------------------------------------------
void	MainShutdown( void )
{
	InterfaceFree();
}



//-------------------------------------------------------------------------
// Function    : WinMain
// Description : The application's entry point
//-------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR lpCmdLine, INT )
{
//	ghInstance = hInst;

	MainInitialise();

	MSG msg;
	ZeroMemory( &msg, sizeof(msg) );
		
	// Do the main loop
	while( msg.message != WM_QUIT )
	{
		if ( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
		{
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
		else
		{	
			MainUpdate();
		}
	}

	MainShutdown();

	return 0;
}

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR lpCmdLine, INT ) is the entry point of the application. this is called once, except the WHILE loop that runs continuous. Note here is where MainInitialize is called. It only runs once, t hen it hits the while and keeps that looping until it receives a quit message and shutdown is initalized.


Hope this helps a little bit. Next post we will go a little deeper and I will touch on the interface and how 2d graphics are put into play.
[/url]
theseer
VIP
VIP
Posts: 782
Joined: Sat Dec 04, 2004 9:50 am

Post by theseer »

This may be a tad naive question, but... where is this library that you're dissecting? :D
User avatar
morbydvisns
Posts: 1889
Joined: Sun Jan 30, 2005 12:51 am

Post by morbydvisns »

Right now its not been made public yet, just getting a head start on some infos... Heres the link to its sourceforge registration which is where i assume where it will be available once its public:

http://sourceforge.net/projects/universalpub/
User avatar
morbydvisns
Posts: 1889
Joined: Sun Jan 30, 2005 12:51 am

Loading a graphic to the 2d interface

Post by morbydvisns »

Good evening class.
Now I am going to demonstrate how to display an image file to the 2d interface.

Start with selecting an image. For this basic example, we will just call it "image.jpg" and assume that its just in the Exe folder of the UniversalPub.

Now, let's look at the routines we're going to be using for this.

Code: Select all

int    InterfaceGetTexture( const char* szFilename, int nFlags );

int InterfaceCreateNewTexturedOverlay( int nLayer, int nTextureHandle );

void   InterfaceSprite( int nOverlayNum, int nX, int nY, float fTexGrid, int nTexGridNum, ulong ulCol, float fRotation, float fScale );

void   InterfaceTexturedRect( int nOverlayNum, int nX, int nY, int nWidth, int nHeight, ulong ulCol, float fU, float fV, float fU2, float fV2 );

Ok now. We're going to start with the InterfaceGetTexture. this is an integer constructor. What you will need to do is declare an integer variable for it, and set the variable to the constructor.

Code: Select all

int myImage;

myImage = InterfaceGetTexture('image.jpg",0)  
This loads the texture image, and assigns it a value (textureHandle) for its spot. Im not sure what nFlags are I just use 0.

Next, we have to create the texture overlay for it. Think of this like a layer for that texture.

Same case as the last one.. This is an integer constructor, so a variable must be set to it.

Code: Select all

int myOverlay;
myOverlay = InterfaceCreateNewTexturedOverlay(0, myImage );
This loads the overlay to memory for use later. It says on layer 0, it will display the image defined for the myImage handle.

The 2 above code snips need only be executed once. I created a void function in the OSD code file called OSDInitialize, which contain those 2 functions. OSDInitialize is ran from the main.cpp program during the MainInitialize that i explained in the last post about.


From here there are a couple different ways we can put the image on the screen. First I will demonstrate InterfaceSprite.

Code: Select all

 InterfaceSprite(myOverlay, 100,100,.25f,0,0xFFFFFFFF,0.0f,1.0f );
Now, the switches.. the first, obviously, is which textured overlay your going to put on this sprite. The 2nd and 3rd are coords X and Y to place the upper left corner of the image on the screen.

the 3rd is a float, which basically means it can hold decimals. It tells the program what % of the texture each frame of the animation consume. So, if we have a sprite sheet of 4 rows and 4 columns of frames, we put 0.25f. Float values must always be followed by the 'f'. Next value, where I have '0' is the frame of the sprite sheet to display. This counts along the X axis first. So, 0 would be the first frame on the first row using our example 5 would be the first frame on the 2nd row. 15 would be the very bottom right frame.

Then we have color in hex, rotation, and display scale (scaled based upon actual image size).


Then we have

Code: Select all

InterfaceTexturedRect( myOverlay, 100,100,500,500, 0xFFFFFFFF,.75f,.25f,1.0f,.50f);
This one starts the same as the last as far as the switches go.

overlay variable you want to use,xCoord,yCoord.
the 4th and 5th, where i have 500,500, are x value width and y value height to display it as. Then we have color in hex.

After that we have 4 values to enter. Basically, the first number is X coordinate in % to start, after that is Y the same. The last 2 switches tell it where to stop reading the texture at in X and Y. Manually defining the frame coords. In our example, would start on the 3rd frame across (starting at 75% X), and the 2nd frame down (25% into the Y range). So this example would display frame 7 of the sprite sheet.

The last step (whichever of the above 2 you may decide to use) needs to go into the update so it loads the sprite or textured rectangle every frame.

in order to automatically flip frames of the sprite sheet, giving it a flipbook animation feel, I recommend using the first method, since you can directly specify which frame is drawn each update. To do this you will need to declare a variable and add a little code:

Code: Select all

//THIS PART GOES AT THE TOP OF THE FILE YOUR WORKING WITHIN TO DECLARE THE VARIABLE AND SET IT TO 0.
int spriteFrame = 0;


//AND THIS PART GOES IN YOUR UPDATE AREA.
spriteFrame++;
  if (spriteFrame > 15)
   {   
	 spriteFrame = 0;
   }
  

 InterfaceSprite(myOverlay, 100,100,.25f,spriteFrame,0xFFFFFFFF,0.0f,1.0f );


Ticks up the spriteframe each frame and once it gets past 15 which is the last frame in our 4x4 example (starting at 0, at the top left), it sets itself back to 0 to start over.





That should be about it for that. I put everything in the OSD.CPP file. You have to declare an external void in the OSD.h file for the OSDinitialize

Code: Select all

extern void OSDinitialize ( void );
then create the void in OSD.cpp

Code: Select all

OSDinitialize( void )
{
...gettexture and  newtextureoverlay in this area
}

That is all for now. Any questions, just ask.
Locked