257 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			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(¤t_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(¤t_time);
 | |
|     getPTimeDiff(&delta_time, ¤t_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, ¤t_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));
 | |
| }
 |