Okay, here's a cut-down version of my UI that illustrates the ortho camera use. I've left out nice button structures and interface loading, and scaling of objects etc. for different resolutions as these'll want to be designed for the end UI. My clunky solutions won't be wanted! But that's what some of the pointer type's fields are for though not used in this example.
Save this code as "_lib_ToodeeGooey.bb"
Here's an example program that uses it, with a mouse pointer and two 'buttons' (just 2D sprites).
You will need textures for the example obviously. Pointer was a 32x32 hand with transparent background. Anyone and their mother can easily create a basic UI from this, by checking for button clicks based on sprite positions. I use a button type with the structure...
Type TG_button
; Individual 'sprites' for controls
Field sprite% ; Pointer to rectangle mesh
Field texture% ; pointer to texture
Field pos_x% ; x position
Field pos_y% ; y position
Field siz_x% ; x size
Field siz_y% ; y size
Field ref_num% ; Reference number
Field state% ; State, relating to anim number
End Type
I use a Create_Button() function that loads a texture into button\texture, followed by "button\sprite=TG_Create_Sprite(button\texture). Changing this design to incorporate 3D meshes as buttons shouldn't be too hard, and maybe add a String field with an animation string, like model movement?
Save this code as "_lib_ToodeeGooey.bb"
; Shifty's New Toodee-Gooey Library basics ; Constucts a UI from rectangular sprites. ; Positions them from an orthogonal camera. ; USE : Call TG_Initialse() to set up UI. Follow with TG_SetPointer() to set mouse pointer ; Use TG_Load_Sprite to create a 2D button sprite from a texture ; Use Scene_cam as your main program camera ; Use TG_Draw_UI() instead of UpdateWorld+RenderWorld ; Placment of UI components is in screen pixel coords ; - Z value determines z order. High values have higer priority (front of interface). Float values ; - add UI_distance to objects to move them in front of UI camera ; - Range of Z defined by TG_Initialise/CameraRange TG_camera\camera,1,xxx ; - default is 100 for a range of 1-100. Mouse placed at 20. Fractional ; eg. PositionEntity button,100,100,UI_distance+5 Const UI_distance=-10000 ; Camera distance for UI camera Global TG_pointer.TG_point Global TG_camera.TG_cam Global Scene_cam Global TG_sprite ; rectangle mesh Type TG_point ; Rectangle for pointer Field sprite% ; Pointer to rectangle mesh Field texture% ; pointer to texture Field pos_x% ; x position Field pos_y% ; y position Field prev_x% ; previous x position Field prev_y% ; previous y position Field siz_x% ; x size Field siz_y% ; y size ; Field buffer% ; Buffer of underlying image to be restored End Type Type TG_cam Field camera% ; Pointer to camera entity Field pos_x% Field pos_y% Field siz_x% Field siz_y% End Type TG_pointer.TG_point = New TG_point TG_camera.TG_cam = New TG_cam ; UI constructors Function TG_Initialise() ; FUNCTION : initialise UI camera and mouse pointer ; loads rectangular mesh that's basis of all UI sprites HidePointer() TG_sprite = CreateMesh() surf = CreateSurface(TG_sprite) v0 = AddVertex (surf, 0,0,0, 0,0) v1 = AddVertex (surf, 10,0,0, 1,0) v2 = AddVertex (surf, 10,-10,0, 1,1) v3 = AddVertex (surf, 0,-10,0, 0,1) AddTriangle (surf,v0,v1,v2) AddTriangle (surf,v0,v2,v3) TG_camera\camera=CreateCamera() PositionEntity TG_camera\camera,0,0,UI_distance CameraProjMode(TG_camera\camera,0) ; 0 to hide, 2 to render CameraClsMode(TG_camera\camera,0,1) CameraRange TG_camera\camera,1,100 End Function Function TG_SetPointer(img$) ; FUNCTION : sets pointer image TG_pointer\texture= LoadTexture(img$,2) TG_pointer\sprite=TG_Create_Sprite(TG_pointer\texture) TG_pointer\pos_x=MouseX() TG_pointer\pos_y=MouseY() TG_pointer\siz_x=TextureWidth(TG_pointer\texture) TG_pointer\siz_y=TextureHeight(TG_pointer\texture) PositionEntity TG_pointer\sprite, TG_pointer\pos_x, TG_pointer\pos_y, UI_distance+20 End Function Function TG_Create_Sprite(texture,x_size#=0,y_size#=0) ; Doctored sprite code from Skidracer ; 'texture' is a pointer to a texture object, in sizes of squared powers of 2. eg. 128x128 or 256x256 ; this is because GPU's work fastest with power of 2 textures ; optional x_size and y_size values crop the sprite to fit ; eg. for a 27x18 button, create a 32x32 source image, load as texture, and call TG_Load_Sprite(texture,27,18) ; No x_size or y_size values uses texture proportions width=TextureWidth(texture) If Not x_size x_size=width EndIf height=TextureHeight(texture) If Not y_size y_size=height EndIf ; change these for viewports viewwidth=GraphicsWidth() viewheight=GraphicsHeight() ; find existing pixiespace parented to camera magic=0 n=CountChildren(TG_camera\camera) For i=1 To n If EntityName(GetChild(TG_camera\camera,i))="pixiespace" magic=GetChild(GetChild(TG_camera\camera,i),1) EndIf Next If magic=0 magic=CreatePivot(TG_camera\camera) NameEntity(magic,"pixiespace") aspect#=Float(viewheight)/viewwidth PositionEntity magic,-1,aspect,1 scale#=2.0/viewwidth ScaleEntity magic,scale,-scale,-scale magic=CreatePivot(magic) PositionEntity magic,-.5,-.5,0 EndIf ; create sprite from texture as child of magic overlay sprite=CopyMesh(TG_sprite) EntityParent sprite,magic ;cludge for blitz bug in createsprite(parent) scale#=0.2/viewwidth ScaleMesh sprite,x_size*scale,y_size*scale,1 ScaleTexture texture,width/x_size, height/y_size EntityTexture sprite,texture EntityFX sprite,1 Return sprite End Function ; UI control Function TG_Draw_UI() ; cam is a pointer to the scene camera UpdateWorld RenderWorld PositionEntity TG_pointer\sprite,MouseX(),MouseY(),UI_distance+20 CameraProjMode (Scene_cam,0) CameraProjMode (TG_camera\camera,2) RenderWorld CameraProjMode (Scene_cam,1) CameraProjMode (TG_camera\camera,0) End Function ; Misc functions Function texture_mask_colour(texture,r1,g1,b1) buf= TextureBuffer(texture) LockBuffer buf For loop=0 To TextureWidth(texture)-1 For loop1=0 To TextureHeight(texture)-1 RGB1=ReadPixelFast(loop,loop1,TextureBuffer(texture)) ; read the RGB value from the texture r=(RGB1 And $FF0000)Shr 16;separate out the red g=(RGB1 And $FF00) Shr 8;green b=RGB1 And $FF;and blue parts of the color a=255 If r=r1 And g=g1 And b=b1; check RGB lies with the tolerance a=0 End If newrgb= (a Shl 24) Or (r Shl 16) Or (g Shl 8) Or b ; combine the ARGB back into one value WritePixelFast(loop,loop1,newrgb,buf); write back to the texture Next Next UnlockBuffer buf End Function
Here's an example program that uses it, with a mouse pointer and two 'buttons' (just 2D sprites).
; Example of using the UI code. Include "_lib_ToodeeGooey.bb" ;Graphics3D 800,600,0,0 Graphics3D 1024,768,0,1 TG_Initialise() TG_SetPointer("textures\pointer.png") ; Add a 'button' to the 2D UI. "texelchallenge.png" is a 128x128 checkered B&W square to prove pixel-perfect textures Button_texture=LoadTexture("textures\texelchallenge.png") Button_sprite=TG_Create_Sprite(Button_texture,40,120) PositionEntity Button_sprite,400,200,UI_distance+2 ; Add another button with alpha blending Button_2_texture=LoadTexture("textures\texelchallenge.png") Button_2_sprite=TG_Create_Sprite(Button_2_texture) PositionEntity Button_2_sprite,500,200,UI_distance+2 EntityAlpha Button_2_sprite,0.75 ;#Region *** Create scene with random 3D junk Scene_cam=CreateCamera() PositionEntity Scene_cam,0,0,0 CameraZoom Scene_cam,2 Scene_light=CreateLight(2,Scene_cam) LightColor Scene_light,64,64,64 PositionEntity Scene_light,100,0,-100 For n=0 To 150 cube=CreateCube() ScaleEntity cube,Rnd(1,10),Rnd(1,10),Rnd(1,10) PositionEntity cube,Rnd(-200,200),Rnd(-200,200),Rnd(-200,200) EntityColor cube,Rnd(0,2)*128,Rnd(0,2)*128,Rnd(0,2)*128 EntityShininess cube,1 Next ;#End Region While Not KeyHit(1) TurnEntity Scene_cam,0.01,0.005,0.02 TG_Draw_UI() Flip False Wend
You will need textures for the example obviously. Pointer was a 32x32 hand with transparent background. Anyone and their mother can easily create a basic UI from this, by checking for button clicks based on sprite positions. I use a button type with the structure...
Type TG_button
; Individual 'sprites' for controls
Field sprite% ; Pointer to rectangle mesh
Field texture% ; pointer to texture
Field pos_x% ; x position
Field pos_y% ; y position
Field siz_x% ; x size
Field siz_y% ; y size
Field ref_num% ; Reference number
Field state% ; State, relating to anim number
End Type
I use a Create_Button() function that loads a texture into button\texture, followed by "button\sprite=TG_Create_Sprite(button\texture). Changing this design to incorporate 3D meshes as buttons shouldn't be too hard, and maybe add a String field with an animation string, like model movement?