timesynk/engine/sdl/interface.c

257 lines
8.3 KiB
C

/******
******/
#include "../globals.h"
#include "interface.h"
#include "r_gl.h"
#include "r_soft.h"
int interfaceInit() {
g_video_width = getTablePairValueInt(g_settings, "v_width");
g_video_height = getTablePairValueInt(g_settings, "v_height");
g_video_fullscreen = getTablePairValueInt(g_settings, "v_fullscreen");
#if _WIN32 | _WIN64 | __APPLE__
SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER);
#else
SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTTHREAD);
#endif
interfaceSetRenderer(getTablePairValueInt(g_settings, "v_renderer"));
/* load our global fonts */
g_font_large = newFont();
loadFontFromMemory(g_font_large, badfont_large_png, badfont_large_png_length, 16, 32);
setFontScale(g_font_large, 2.0f, 2.0f);
g_font_medium = newFont();
loadFontFromMemory(g_font_medium, badfont_medium_png, badfont_medium_png_length, 16, 32);
setFontScale(g_font_medium, 2.0f, 2.0f);
/* load our ui sprites */
spritesheet_ui = newSpritesheet();
loadSpritesheetFromMemory(spritesheet_ui, ui_png, ui_png_length, 64, 64, 8);
setSpritesheetScale(spritesheet_ui, 2.0f, 2.0f);
/* load menu bg */
menu_bg = newSpritesheet();
loadSpritesheetFromMemory(menu_bg, menu_bg_png, menu_bg_png_length, 1280, 480, 1);
setSpritesheetScale(menu_bg, 2.0f, 2.0f);
/* set up our display */
g_r_Init();
g_screen = screen; // for state(s) to access 'em
SDL_Delay(100);
g_video_width = (SDL_GetVideoSurface())->w;
g_video_height = (SDL_GetVideoSurface())->h;
/* reinit to deal with some window managers on X */
g_r_Reinit();
SDL_WM_SetCaption("timesynk", NULL);
/* set our video tickrate/refresh vars */
vid_tickrate = (1000.0f / getTablePairValueFloat(g_settings, "v_fps")); // target 60 tickrate
g_cap_framerate = getTablePairValueInt(g_settings, "v_framecap");
setPTime(&g_tick_time, 0, 0, getTablePairValueInt(g_settings, "tickrate"));
vid_frames = 0;
/* */
/* set up our tickrate into a PTime structure */
sleep_time.n = (1000000000/53);
sleep_time.m = sleep_time.n/1000000;
printf("tickrate: %ld\n", sleep_time.n);
/* set up unicode, important to TSEvent */
SDL_EnableUNICODE(SDL_ENABLE);
/* load global elements, i.e., fps counter */
g_elements = newElementList();
struct Dimension dimen = { 0, 0, 128, 32 };
g_element_fps = newElement(E_TYPE_TEXT, 0, g_r_setupElement, dimen);
setElementValue(g_element_fps, 0);
setElementFont(g_element_fps, g_font_medium);
g_element_fps->target = g_screen;
addElementToList(g_elements, g_element_fps);
/* is it wrong to use function pointers to (vaguely) mimic Object oriented states? */
g_initState = initModulesState;
g_freeState = freeModulesState;
g_handleState = handleModulesState;
g_processState = processModulesState;
g_renderState = renderModulesState;
g_switch_state = 0;
return 0;
}
int interfaceRun() {
struct PTime current_time; // time at start of loop
struct PTime last_time; // time at end of last loop
struct PTime delta_time; // difference between current_time and last_time
getPTime(&current_time);
SDL_Event event;
struct TSEvent ts_event; // SDL->TS event structure
/* begin our main loop */
g_initState();
while(g_running) {
last_time = current_time;
getPTime(&current_time);
getPTimeDiff(&delta_time, &current_time, &last_time);
// handle input and pass to state
while(SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_KEYDOWN:
ts_event.type = TS_KEYBOARD;
ts_event.keyboard.key.scancode = event.key.keysym.scancode;
ts_event.keyboard.key.mod = event.key.keysym.mod;
ts_event.keyboard.key.sym = event.key.keysym.sym;
ts_event.keyboard.key.unicode = event.key.keysym.unicode;
ts_event.keyboard.state = TS_KEYDOWN;
g_handleState(ts_event);
break;
case SDL_KEYUP:
ts_event.type = TS_KEYBOARD;
ts_event.keyboard.key.scancode = event.key.keysym.scancode;
ts_event.keyboard.key.mod = event.key.keysym.mod;
ts_event.keyboard.key.sym = event.key.keysym.sym;
ts_event.keyboard.key.unicode = event.key.keysym.unicode;
ts_event.keyboard.state = TS_KEYUP;
g_handleState(ts_event);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
ts_event.type = TS_MOUSECLICK;
ts_event.mouseclick.button = event.button.button;
ts_event.mouseclick.state = event.button.state;
ts_event.mouseclick.x = event.button.x;
ts_event.mouseclick.y = event.button.y;
g_handleState(ts_event);
break;
// TODO: USER_EVENT will call here, with a subtype of GAME_TICK as called by subtype of NET_RECEIVE. Within GAME_TICK, we will run game logic (gameTick() or some such) if a game is indeed running.
case SDL_QUIT:
g_running = 0;
break;
default:
break;
}
}
// do state processing
g_processState(delta_time.n);
// now we move on to rendering
// clear out the screen :)
g_clearScreen();
// draw state
g_renderState();
// draw global elements
g_renderElements(g_elements);
// update fps counter
vid_frames++;
if (current_time.s - count_time.s >= 1) {
struct PTime delta_fps_time;
getPTimeDiff(&delta_fps_time, &current_time, &count_time);
int fps = vid_frames / delta_fps_time.s;
count_time = current_time;
vid_frames = 0;
setElementValue(g_element_fps, fps);
}
// render updates to screen
g_renderScreen();
// cap framerate if bool is set!
if (g_cap_framerate) {
int64_t delay_ns = sleep_time.n - delta_time.n;
if (delay_ns < 0) {
printf("uhoh, delay took %ld, so we wait for %ld\n", delta_time.n, delay_ns);
delay_ns = 0;
}
doNanoSleep(delay_ns);
}
// switch states if running state requested it.
if (g_switch_state == 1) {
g_freeState(); // free old state
g_initState(); // init new state, setting up state pointers
g_switch_state = 0;
}
}
return 0;
}
int interfaceClose() {
g_freeState();
g_r_Close();
SDL_FreeSurface(screen);
SDL_Quit();
return 0;
}
int interfaceSetVideo() {
if ((screen = SDL_SetVideoMode(g_video_width, g_video_height, 32, SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE|g_video_fullscreen)) == NULL){
return 1;
}
return 0;
}
int interfaceSetRenderer(int render_id) {
switch(render_id) {
case R_OPENGL:
g_loadSpritesheet = &r_gl_loadSpritesheet;
g_renderElements = &r_gl_renderElements;
g_renderElement = &r_gl_renderElement;
g_renderSprite = &r_gl_renderSprite;
g_r_Init = &r_gl_Init;
g_r_Reinit = &r_gl_Init;
g_r_Close = &r_gl_Close;
g_renderScreen = &r_gl_renderScreen;
g_clearScreen = &r_gl_clearScreen;
g_r_setupElement = &r_gl_setupElement;
g_r_cleanElement = &r_gl_cleanElement;
return R_OPENGL;
break;
case R_SOFTWARE:
g_loadSpritesheet = &loadSpritesheetFromFile;
g_renderElements = &r_soft_renderElements;
g_renderElement = &r_soft_renderElement;
g_renderSprite = &r_soft_drawSprite;
g_r_Init = &r_soft_Init;
g_r_Reinit = &r_soft_Init;
g_r_Close = &r_soft_Close;
g_renderScreen = &r_soft_renderScreen;
g_clearScreen = &r_soft_clearScreen;
g_r_setupElement = &r_soft_setupElement;
g_r_cleanElement = &r_soft_cleanElement;
return R_SOFTWARE;
break;
default:
return -1;
break;
}
return -2;
}
void genElementDimensions(struct Element *element) {
if (element == NULL) return;
int width;
//int height;
int temp = 0;
switch(element->type) {
case E_TYPE_TEXT:
element->dimen.w = ((struct TextElement *)element->data)->length * ((struct Font*)element->font)->s_width;
element->dimen.h = ((struct Font*)element->font)->s_height;
break;
case E_TYPE_BUTTON:
width = ((struct TextElement *)element->data)->length * ((struct Font*)element->font)->s_width + (6*spritesheet_ui->scale_x);
temp = spritesheet_ui->s_width*2; // minimum width
element->dimen.w = ( temp > width ? temp : width );
element->dimen.h = spritesheet_ui->s_height;
break;
}
}
int getElementX(struct Element *element) {
return element->dimen.x+(element->sx*(g_video_width/3));
}
int getElementY(struct Element *element) {
return element->dimen.y+(element->sy*(g_video_height/3));
}