ref: 75fb5f7ad01c46e20cb7cd29b0633a8775fe42cf
dir: /SDL_Examples/menu.c/
/* OPENIMGUI STANDARD DEMO
Demo of Gek's proposed Open Immediate Mode Gui Standard
*/
//#define PLAY_MUSIC
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../include/GL/gl.h"
#include "../include/zbuffer.h"
#define CHAD_API_IMPL
#define CHAD_MATH_IMPL
#include "../include-demo/3dMath.h"
#ifdef PLAY_MUSIC
#include "../include-demo/api_audio.h"
#else
typedef unsigned char uchar;
#endif
#include <SDL/SDL.h>
// Gek's OpenIMGUI standard.
#define OPENIMGUI_IMPL
#include "../include-demo/openimgui.h"
#ifndef M_PI
#define M_PI 3.14159265
#endif
int winSizeX = 640;
int winSizeY = 480;
double tpassed = 0;
int isRunning = 1;
int dirbstates[4] = {0, 0, 0, 0}; // up,down,left,right
int mousepos[2] = {0, 0};
int using_cursorkeys = 0; // Switches to cursor keys upon pressing a key.
int mb = 0; // cursor button
int mb2 = 0; // cursor second button.
#define BEGIN_EVENT_HANDLER \
void events(SDL_Event* e) { \
switch (e->type) {
#define E_KEYSYM e->key.keysym.sym
#define END_EVENT_HANDLER \
} \
}
#define EVENT_HANDLER events
#define E_MOTION e->motion
#define E_BUTTON e->button.button
#define E_WINEVENT e->window.event
#define E_WINW e->window.data1
#define E_WINH e->window.data2
vec3 mouse_to_normal(int mx, int my) {
vec3 r;
r.d[0] = mx / (float)winSizeX;
r.d[1] = my / (float)winSizeY;
return r;
}
void drawBox(GLfloat x, GLfloat y, GLfloat xdim, GLfloat ydim) { // 0,0 is top left, 1,1 is bottom right
x *= 2;
xdim *= 2;
y *= 2;
ydim *= 2;
glBegin(GL_TRIANGLES);
// TRIANGLE 1,
glTexCoord2f(0, 0);
glVertex3f(-1 + x, 1 - y - ydim, 0.5); // Bottom Left Corner
glTexCoord2f(1, -1);
glVertex3f(-1 + x + xdim, 1 - y, 0.5); // Top Right Corner
glTexCoord2f(0, -1);
glVertex3f(-1 + x, 1 - y, 0.5); // Top Left
// TRIANGLE 2
glTexCoord2f(0, 0);
glVertex3f(-1 + x, 1 - y - ydim, 0.5); // Bottom Left Corner
glTexCoord2f(1, 0);
glVertex3f(-1 + x + xdim, 1 - y - ydim, 0.5);
glTexCoord2f(1, -1);
glVertex3f(-1 + x + xdim, 1 - y, 0.5); // Top Right Corner
glEnd();
return;
}
void drawMouse() {
if (!omg_cb)
glColor3f(0.7, 0.7, 0.7);
else
glColor3f(1.0, 0.1, 0.1);
// if(!using_cursorkeys)
drawBox(omg_cursorpos[0], omg_cursorpos[1], 0.03, 0.03);
// else
// drawBox(omg_cursorpos_presuck[0],omg_cursorpos_presuck[1], 0.03, 0.03);
}
void drawTB(const char* text, GLuint textcolor, GLfloat x, GLfloat y, GLint size, float* tw, float* th) {
size = (size > 64) ? 64 : ((size < 8) ? 8 : size);
size >>= 3; // divide by 8 to get the GLTEXTSIZE
if (!size || !text)
return;
int mw = 0, h = 1, cw = 0; // max width, height, current width
for (int i = 0; text[i] != '\0' && (text[i] & 127); i++) {
if (text[i] != '\n')
cw++;
else {
cw = 0;
h++;
}
if (mw < cw)
mw = cw;
}
float w = (size)*8 * (mw) / (float)winSizeX;
float bw = 3 * size / (float)winSizeX;
float h_ = (size)*8 * (h) / (float)winSizeY;
float bh = 3 * size / (float)winSizeY;
drawBox(x, y, w, h_);
*tw = w + bw;
*th = h_ + bh;
glTextSize(size);
glDrawText((unsigned char*)text, x * winSizeX, y * winSizeY, textcolor);
return;
}
int omg_box(float x, float y, float xdim, float ydim, int sucks, float buttonjumpx, float buttonjumpy, int hints) {
// hints is the color of the box.
float r = ((hints & 0xFF0000) >> 16) / 255.0;
float g = ((hints & 0xFF00) >> 8) / 255.0;
float b = ((hints & 0xFF)) / 255.0;
glColor3f(r, g, b);
drawBox(x, y, xdim, ydim);
omg_box_suck(x, y, xdim, ydim, sucks, buttonjumpx, buttonjumpy);
return omg_box_retval(x, y, xdim, ydim);
}
int omg_textbox(float x, float y, const char* text, int textsize, int sucks, float buttonjumpx, float buttonjumpy, int hints, int hintstext) {
float r = ((hints & 0xFF0000) >> 16) / 255.0;
float g = ((hints & 0xFF00) >> 8) / 255.0;
float b = ((hints & 0xFF)) / 255.0;
glColor3f(r, g, b);
float xdim = 0, ydim = 0;
drawTB(text, (GLuint)hintstext, x, y, textsize, &xdim, &ydim);
omg_box_suck(x, y, xdim, ydim, sucks, buttonjumpx, buttonjumpy);
return omg_box_retval(x, y, xdim, ydim);
}
int haveclicked = 0; // For our toggleable movable button.
vec3 tbcoords = (vec3){{0.4, 0.4, 0}};
vec3 slidcoords = (vec3){{0.1, 0.8, 0}};
float slidmoffset = 0;
int slidersliding = 0; // Is the slider being slid?
void draw() {
if (mb2) { // Use an additional input to move gui elements for testing- right click moves the button.
tbcoords.d[0] = omg_cursorpos[0];
tbcoords.d[1] = omg_cursorpos[1];
haveclicked = 0;
}
if (omg_textbox(0.01, 0, "\nEntry 1\n", 24, 1, 0.4, 0.2, 0xFFFFFF, 0) && omg_cb == 2)
puts("Entry 1");
if (omg_textbox(0.01, 0.2, "\nEntry 2\n", 24, 1, 0.4, 0.2, 0xFFFFFF, 0) && omg_cb == 2)
puts("Entry 2");
if (omg_textbox(0.01, 0.4, "\nEntry 3\n", 24, 1, 0.4, 0.2, 0xFFFFFF, 0) && omg_cb == 2)
puts("Entry 3");
if (omg_textbox(0.01, 0.6, "\nQuit\n", 24, 1, 0.4, 0.2, 0xFFFFFF, 0) && omg_cb == 2) {
puts("Quitting...");
isRunning = 0;
}
if (omg_textbox(tbcoords.d[0], tbcoords.d[1], "\nClick me and I toggle color!\n", 16, 1, 0.4, 0.3, 0xFFFFFF, haveclicked ? 0xFF0000 : 0x00) &&
omg_cb == 1) {
puts("Detected click! EVENT FIRED!\n");
haveclicked = !haveclicked;
}
// A slider element
if (omg_textbox(slidcoords.d[0], slidcoords.d[1], "\n Slider \n", 16, 1, 0.4, 0.3, 0xFFFFFF, haveclicked ? 0xFF0000 : 0x00) && omg_cb == 1) {
slidersliding = 1;
slidmoffset = omg_cursorpos[0] - slidcoords.d[0];
}
if (omg_cb == 2)
slidersliding = 0;
// Handle the slider sliding behavior.
if (slidersliding) {
if (using_cursorkeys) {
if (omg_udlr[3]) {
slidcoords.d[0] = clampf(slidcoords.d[0] + 0.05, 0.1, 0.7);
}
if (omg_udlr[2]) {
slidcoords.d[0] = clampf(slidcoords.d[0] - 0.05, 0.1, 0.7);
}
omg_cursorpos[0] = slidcoords.d[0] + slidmoffset;
omg_cursorpos[1] = slidcoords.d[1];
} else {
// Move the element to the cursorposition's x.
slidcoords.d[0] = clampf(omg_cursorpos[0] - slidmoffset, 0.1, 0.7);
}
printf("Slider's value is %f\n", slidcoords.d[0]);
}
drawMouse();
}
void initScene() {
static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
static GLfloat white[4] = {1.0, 1.0, 1.0, 0.0};
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glLightfv(GL_LIGHT0, GL_DIFFUSE, white);
// glLightfv( GL_LIGHT0, GL_AMBIENT, white);
// glLightfv( GL_LIGHT0, GL_SPECULAR, white);
// glEnable(GL_CULL_FACE);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
// glEnable(GL_LIGHTING);
// glEnable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
// glEnable( GL_LIGHT0 );
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glShadeModel(GL_SMOOTH);
glTextSize(GL_TEXT_SIZE24x24);
glEnable(GL_NORMALIZE);
}
BEGIN_EVENT_HANDLER
case SDL_KEYDOWN:
using_cursorkeys = 1;
switch (E_KEYSYM) {
case SDLK_ESCAPE:
case SDLK_q:
isRunning = 0;
break;
case SDLK_UP:
dirbstates[0] = 1;
break;
case SDLK_DOWN:
dirbstates[1] = 1;
break;
case SDLK_LEFT:
dirbstates[2] = 1;
break;
case SDLK_RIGHT:
dirbstates[3] = 1;
break;
case SDLK_SPACE:
case SDLK_RETURN:
mb = 1;
break;
default:
break;
}
break;
case SDL_KEYUP:
using_cursorkeys = 1;
switch (E_KEYSYM) {
case SDLK_SPACE:
case SDLK_RETURN:
mb = 0;
break;
case SDLK_UP:
dirbstates[0] = 0;
break;
case SDLK_DOWN:
dirbstates[1] = 0;
break;
case SDLK_LEFT:
dirbstates[2] = 0;
break;
case SDLK_RIGHT:
dirbstates[3] = 0;
break;
default:
break;
}
break;
case SDL_QUIT:
isRunning = 0;
break;
case SDL_MOUSEBUTTONDOWN:
if (E_BUTTON == SDL_BUTTON_LEFT)
mb = 1;
if (E_BUTTON == SDL_BUTTON_RIGHT) {
mb2 = 1;
}
break;
case SDL_MOUSEBUTTONUP:
if (E_BUTTON == SDL_BUTTON_LEFT)
mb = 0;
if (E_BUTTON == SDL_BUTTON_RIGHT)
mb2 = 0;
break;
case SDL_MOUSEMOTION:
using_cursorkeys = 0;
mousepos[0] = E_MOTION.x;
mousepos[1] = E_MOTION.y;
break;
END_EVENT_HANDLER
int main(int argc, char** argv) {
// initialize SDL video:
unsigned int fps = 0;
char needsRGBAFix = 0;
if (argc > 2) {
char* larg = argv[1];
for (int i = 0; i < argc; i++) {
if (!strcmp(larg, "-w"))
winSizeX = atoi(argv[i]);
if (!strcmp(larg, "-h"))
winSizeY = atoi(argv[i]);
if (!strcmp(larg, "-fps"))
fps = strtoull(argv[i], 0, 10);
larg = argv[i];
}
}
#ifdef PLAY_MUSIC
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
#else
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
#endif
fprintf(stderr, "ERROR: cannot initialize SDL video.\n");
return 1;
}
#ifdef PLAY_MUSIC
ainit(0);
#endif
SDL_Surface* screen = NULL;
if ((screen = SDL_SetVideoMode(winSizeX, winSizeY, TGL_FEATURE_RENDER_BITS, SDL_SWSURFACE)) == 0) {
fprintf(stderr, "ERROR: Video mode set failed.\n");
return 1;
}
printf("\nRMASK IS %u", screen->format->Rmask);
printf("\nGMASK IS %u", screen->format->Gmask);
printf("\nBMASK IS %u", screen->format->Bmask);
printf("\nAMASK IS %u", screen->format->Amask);
#if TGL_FEATURE_RENDER_BITS == 32
if (screen->format->Rmask != 0x00FF0000 || screen->format->Gmask != 0x0000FF00 || screen->format->Bmask != 0x000000FF) {
needsRGBAFix = 1;
printf("\nYour screen is using an RGBA output different than this library expects.");
printf("\nYou should consider using the 16 bit version for optimal performance");
}
#endif
printf("\nRSHIFT IS %u", screen->format->Rshift);
printf("\nGSHIFT IS %u", screen->format->Gshift);
printf("\nBSHIFT IS %u", screen->format->Bshift);
printf("\nASHIFT IS %u\n", screen->format->Ashift);
fflush(stdout);
#ifdef PLAY_MUSIC
track* myTrack = NULL;
myTrack = lmus("WWGW.mp3");
mplay(myTrack, -1, 1000);
#endif
SDL_ShowCursor(SDL_ENABLE);
SDL_WM_SetCaption(argv[0], 0);
// initialize TinyGL:
int mode;
switch (screen->format->BitsPerPixel) {
case 16:
// fprintf(stderr,"\nUnsupported by maintainer!!!");
mode = ZB_MODE_5R6G5B;
// return 1;
break;
case 32:
mode = ZB_MODE_RGBA;
break;
default:
return 1;
break;
}
ZBuffer* frameBuffer = ZB_open(winSizeX, winSizeY, mode, 0);
glInit(frameBuffer);
// initialize GL:
glClearColor(0.0, 0.0, 0.0, 0.0);
glViewport(0, 0, winSizeX, winSizeY);
glEnable(GL_DEPTH_TEST);
// GLfloat h = (GLfloat) winSizeY / (GLfloat) winSizeX;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// glFrustum( -1.0, 1.0, -h, h, 5.0, 60.0 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// glTranslatef( 0.0, 0.0, -45.0 );
initScene();
// variables for timing:
long long unsigned int frames = 0;
unsigned int tNow = SDL_GetTicks();
unsigned int tLastFps = tNow;
// main loop:
while (isRunning) {
++frames;
tpassed += frames * 16.666666 / 1000.0;
tNow = SDL_GetTicks();
// do event handling:
SDL_Event ev;
while (SDL_PollEvent(&ev))
events(&ev);
if (using_cursorkeys)
omg_update_keycursor(dirbstates[0], dirbstates[1], dirbstates[2], dirbstates[3], mb);
else {
vec3 r = mouse_to_normal(mousepos[0], mousepos[1]);
omg_update_mcursor(r.d[0], r.d[1], mb);
}
// draw scene:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// This is where we render our GUI!
draw();
// glDrawText((unsigned char*)"\nBlitting text\nto the screen!", 0, 0, 0x000000FF);
// swap buffers:
if (SDL_MUSTLOCK(screen) && (SDL_LockSurface(screen) < 0)) {
fprintf(stderr, "SDL ERROR: Can't lock screen: %s\n", SDL_GetError());
return 1;
}
// Quickly convert all pixels to the correct format
#if TGL_FEATURE_RENDER_BITS == 32
if (needsRGBAFix)
for (int i = 0; i < frameBuffer->xsize * frameBuffer->ysize; i++) {
#define DATONE (frameBuffer->pbuf[i])
DATONE = ((DATONE & 0x000000FF)) << screen->format->Rshift | ((DATONE & 0x0000FF00) >> 8) << screen->format->Gshift |
((DATONE & 0x00FF0000) >> 16) << screen->format->Bshift;
}
#endif
ZB_copyFrameBuffer(frameBuffer, screen->pixels, screen->pitch);
if (SDL_MUSTLOCK(screen))
SDL_UnlockSurface(screen);
SDL_Flip(screen);
if (fps > 0)
if ((1000 / fps) > (SDL_GetTicks() - tNow)) {
SDL_Delay((1000 / fps) - (SDL_GetTicks() - tNow)); // Yay stable framerate!
}
// check for error conditions:
char* sdl_error = SDL_GetError();
if (sdl_error[0] != '\0') {
fprintf(stderr, "SDL ERROR: \"%s\"\n", sdl_error);
SDL_ClearError();
}
// update fps:
if (tNow >= tLastFps + 5000) {
printf("%llu frames in %f secs, %f frames per second.\n", frames, (float)(tNow - tLastFps) * 0.001f,
(float)frames * 1000.0f / (float)(tNow - tLastFps));
tLastFps = tNow;
frames = 0;
}
}
printf("%llu frames in %f secs, %f frames per second.\n", frames, (float)(tNow - tLastFps) * 0.001f, (float)frames * 1000.0f / (float)(tNow - tLastFps));
// cleanup:
ZB_close(frameBuffer);
glClose();
if (SDL_WasInit(SDL_INIT_VIDEO))
SDL_QuitSubSystem(SDL_INIT_VIDEO);
#ifdef PLAY_MUSIC
mhalt();
Mix_FreeMusic(myTrack);
acleanup();
#endif
SDL_Quit();
return 0;
}