From ea76b6988ccafaa6a4d4ed90f2489d0e49e1f180 Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Sat, 5 Sep 2015 09:32:30 -0400 Subject: Imported Upstream version 0.40.24 --- g_src/enabler.h | 1027 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1027 insertions(+) create mode 100755 g_src/enabler.h (limited to 'g_src/enabler.h') diff --git a/g_src/enabler.h b/g_src/enabler.h new file mode 100755 index 0000000..f524e1d --- /dev/null +++ b/g_src/enabler.h @@ -0,0 +1,1027 @@ +//some of this stuff is based on public domain code from nehe or opengl books over the years +//additions and modifications Copyright (c) 2008, Tarn Adams +//All rights reserved. See game.cpp or license.txt for more information. + +#ifndef ENABLER_H +#define ENABLER_H + +#include "platform.h" +#include +#include +#ifdef __APPLE__ +# include +# include +#else +# include +# include +#endif + +#include "GL/glew.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; +using std::pair; +using std::map; +using std::set; +using std::list; +using std::stack; +using std::queue; + +#include "basics.h" +#include "svector.h" +#include "endian.h" +#include "files.h" +#include "enabler_input.h" +#include "mail.hpp" + +#define ENABLER + +#ifndef BITS + +#define BITS + +#define BIT1 1 +#define BIT2 2 +#define BIT3 4 +#define BIT4 8 +#define BIT5 16 +#define BIT6 32 +#define BIT7 64 +#define BIT8 128 +#define BIT9 256 +#define BIT10 512 +#define BIT11 1024 +#define BIT12 2048 +#define BIT13 4096 +#define BIT14 8192 +#define BIT15 16384 +#define BIT16 32768 +#define BIT17 65536UL +#define BIT18 131072UL +#define BIT19 262144UL +#define BIT20 524288UL +#define BIT21 1048576UL +#define BIT22 2097152UL +#define BIT23 4194304UL +#define BIT24 8388608UL +#define BIT25 16777216UL +#define BIT26 33554432UL +#define BIT27 67108864UL +#define BIT28 134217728UL +#define BIT29 268435456UL +#define BIT30 536870912UL +#define BIT31 1073741824UL +#define BIT32 2147483648UL + +#endif + +#define GAME_TITLE_STRING "Dwarf Fortress" + +class pstringst +{ + public: + string dat; +}; + +class stringvectst +{ + public: + svector str; + + void add_string(const string &st) + { + pstringst *newp=new pstringst; + newp->dat=st; + str.push_back(newp); + } + + long add_unique_string(const string &st) + { + long i; + for(i=(long)str.size()-1;i>=0;i--) + { + if(str[i]->dat==st)return i; + } + add_string(st); + return (long)str.size()-1; + } + + void add_string(const char *st) + { + if(st!=NULL) + { + pstringst *newp=new pstringst; + newp->dat=st; + str.push_back(newp); + } + } + + void insert_string(long k,const string &st) + { + pstringst *newp=new pstringst; + newp->dat=st; + if(str.size()>k)str.insert(k,newp); + else str.push_back(newp); + } + + ~stringvectst() + { + clean(); + } + + void clean() + { + while(str.size()>0) + { + delete str[0]; + str.erase(0); + } + } + + void read_file(file_compressorst &filecomp,long loadversion) + { + long dummy; + filecomp.read_file(dummy); + str.resize(dummy); + + long s; + for(s=0;sdat); + } + } + void write_file(file_compressorst &filecomp) + { + long dummy=str.size(); + filecomp.write_file(dummy); + + long s; + for(s=0;sdat); + } + } + + void copy_from(stringvectst &src) + { + clean(); + + str.resize(src.str.size()); + + long s; + for(s=(long)src.str.size()-1;s>=0;s--) + { + str[s]=new pstringst; + str[s]->dat=src.str[s]->dat; + } + } + + bool has_string(const string &st) + { + long i; + for(i=(long)str.size()-1;i>=0;i--) + { + if(str[i]->dat==st)return true; + } + return false; + } + + void remove_string(const string &st) + { + long i; + for(i=(long)str.size()-1;i>=0;i--) + { + if(str[i]->dat==st) + { + delete str[i]; + str.erase(i); + } + } + } + + void operator=(stringvectst &two); +}; + +class flagarrayst +{ + public: + flagarrayst() + { + slotnum=0; + array=NULL; + } + ~flagarrayst() + { + if(array!=NULL)delete[] array; + array=NULL; + slotnum=0; + } + + void set_size_on_flag_num(long flagnum) + { + if(flagnum<=0)return; + + set_size(((flagnum-1)>>3)+1); + } + + void set_size(long newsize) + { + if(newsize<=0)return; + + if(array!=NULL)delete[] array; + array=new unsigned char[newsize]; + memset(array,0,sizeof(unsigned char)*newsize); + + slotnum=newsize; + } + + void clear_all() + { + if(slotnum<=0)return; + + if(array!=NULL)memset(array,0,sizeof(unsigned char)*slotnum); + } + + void copy_from(flagarrayst &src) + { + clear_all(); + + if(src.slotnum>0) + { + set_size(src.slotnum); + memmove(array,src.array,sizeof(unsigned char)*slotnum); + } + } + + bool has_flag(long checkflag) + { + if(checkflag<0)return false; + long slot=checkflag>>3; + return (slot>=0&&slot>3; + if(slot>=0&&slot>3; + if(slot>=0&&slot>3; + if(slot>=0&&slot0) + { + long ind; + for(ind=0;ind0) + { + //AVOID UNNECESSARY DELETE/NEW + if(array!=NULL&&slotnum!=newsl) + { + delete[] array; + array=new unsigned char[newsl]; + } + if(array==NULL)array=new unsigned char[newsl]; + + long ind; + for(ind=0;indfilename = filename; + std::ifstream file(filename.c_str()); + string version; + getline(file, version); + header << version << std::endl; + while (file.good()) { + string line; + getline(file, line); + lines << line << std::endl; + } + file.close(); + } + GLuint upload(GLenum type) { + GLuint shader = glCreateShader(type); + string lines_done = lines.str(), header_done = header.str(); + const char *ptrs[3]; + ptrs[0] = header_done.c_str(); + ptrs[1] = "#line 1 0\n"; + ptrs[2] = lines_done.c_str(); + glShaderSource(shader, 3, ptrs, NULL); + glCompileShader(shader); + // Let's see if this compiled correctly.. + GLint status; + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) { // ..no. Check the compilation log. + GLint log_size; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_size); + //errorlog << filename << " preprocessed source:" << std::endl; + std::cerr << filename << " preprocessed source:" << std::endl; + //errorlog << header_done << "#line 1 0\n" << lines_done; + std::cerr << header_done << "#line 1 0\n" << lines_done; + //errorlog << filename << " shader compilation log (" << log_size << "):" << std::endl; + std::cerr << filename << " shader compilation log (" << log_size << "):" << std::endl; + char *buf = new char[log_size]; + glGetShaderInfoLog(shader, log_size, NULL, buf); + //errorlog << buf << std::endl; + std::cerr << buf << std::endl; + //errorlog.flush(); + delete[] buf; + MessageBox(NULL, "Shader compilation failed; details in errorlog.txt", "Critical error", MB_OK); + abort(); + } + printGLError(); + return shader; + } +}; + + +class text_info_elementst +{ + public: + virtual string get_string() + { + string empty; + return empty; + } + virtual long get_long() + { + return 0; + } + + virtual ~text_info_elementst(){} +}; + +class text_info_element_stringst : public text_info_elementst +{ + public: + virtual string get_string() + { + return str; + } + text_info_element_stringst(const string &newstr) + { + str=newstr; + } + + protected: + string str; +}; + +class text_info_element_longst : public text_info_elementst +{ + public: + virtual long get_long() + { + return val; + } + text_info_element_longst(long nval) + { + val=nval; + } + + protected: + long val; +}; + +class text_infost +{ + public: + svector element; + + void clean() + { + while(element.size()>0) + { + delete element[0]; + element.erase(0); + } + } + + string get_string(int e) + { + if(e<0||e>=element.size()) + { + string empty; + return empty; + } + if(element[e]==NULL) + { + string empty; + return empty; + } + return element[e]->get_string(); + } + + long get_long(int e) + { + if(e<0||e>=element.size()) + { + return 0; + } + if(element[e]==NULL) + { + return 0; + } + return element[e]->get_long(); + } + + ~text_infost() + { + clean(); + } +}; + +class text_system_file_infost +{ + public: + long index; + string filename; + + static text_system_file_infost *add_file_info(const string &newf,long newi,char newft) + { + return new text_system_file_infost(newf,newi,newft); + } + + void initialize_info(); + void get_text(text_infost &text); + void get_specific_text(text_infost &text,long num); + + protected: + char file_token; + long number; + + text_system_file_infost(const string &newf,long newi,char newft) + { + filename=newf; + file_token=newft; + index=newi; + number=0; + } +}; + +class text_systemst +{ + public: + void register_file_fixed(const string &file_name,int32_t index,char token,char initialize) + { + text_system_file_infost *tsfi=text_system_file_infost::add_file_info(file_name,index,token); + if(initialize)tsfi->initialize_info(); + file_info.push_back(tsfi); + } + void register_file(const string &file_name,int32_t &index,char token,char initialize) + { + int32_t t; + for(t=(int32_t)file_info.size()-1;t>=0;t--) + { + if(file_info[t]->filename==file_name) + { + //RESET CALLING INDEX AND BAIL IF THIS FILE IS ALREADY IN THE SYSTEM + index=file_info[t]->index; + return; + } + } + + text_system_file_infost *tsfi=text_system_file_infost::add_file_info(file_name,index,token); + if(initialize)tsfi->initialize_info(); + file_info.push_back(tsfi); + } + void initialize_system() + { + int32_t t; + for(t=(int32_t)file_info.size()-1;t>=0;t--)file_info[t]->initialize_info(); + } + void get_text(int32_t index,text_infost &text) + { + int32_t t; + for(t=(int32_t)file_info.size()-1;t>=0;t--) + { + if(file_info[t]->index==index) + { + file_info[t]->get_text(text); + return; + } + } + } + void get_text(const string &file_name,text_infost &text) + { + int32_t t; + for(t=(int32_t)file_info.size()-1;t>=0;t--) + { + if(file_info[t]->filename==file_name) + { + file_info[t]->get_text(text); + return; + } + } + } + void get_specific_text(int32_t index,text_infost &text,int32_t num) + { + int32_t t; + for(t=(int32_t)file_info.size()-1;t>=0;t--) + { + if(file_info[t]->index==index) + { + file_info[t]->get_specific_text(text,num); + return; + } + } + } + + ~text_systemst() + { + while(file_info.size()>0) + { + delete file_info[0]; + file_info.erase(0); + } + } + + protected: + svector file_info; +}; + +class curses_text_boxst +{ + public: + stringvectst text; + + void add_paragraph(stringvectst &src,int32_t para_width); + void add_paragraph(const string &src,int32_t para_width); + + void read_file(file_compressorst &filecomp,int32_t loadversion) + { + text.read_file(filecomp,loadversion); + } + void write_file(file_compressorst &filecomp) + { + text.write_file(filecomp); + } + void clean() + { + text.clean(); + } +}; + +#define COPYTEXTUREFLAG_HORFLIP BIT1 +#define COPYTEXTUREFLAG_VERFLIP BIT2 + +#define ENABLERFLAG_RENDER BIT1 +#define ENABLERFLAG_MAXFPS BIT2 + +// GL texture positions +struct gl_texpos { + GLfloat left, right, top, bottom; +}; + +// Covers every allowed permutation of text +struct ttf_id { + std::string text; + unsigned char fg, bg, bold; + + bool operator< (const ttf_id &other) const { + if (fg != other.fg) return fg < other.fg; + if (bg != other.bg) return bg < other.bg; + if (bold != other.bold) return bold < other.bold; + return text < other.text; + } + + bool operator== (const ttf_id &other) const { + return fg == other.fg && bg == other.bg && bold == other.bold && text == other.text; + } +}; + +namespace std { + template<> struct hash { + size_t operator()(ttf_id val) const { + // Not the ideal hash function, but it'll do. And it's better than GCC's. id? Seriously? + return hash()(val.text) + val.fg + (val.bg << 4) + (val.bold << 8); + } + }; +}; + +// Being a texture catalog interface, with opengl, sdl and truetype capability +class textures +{ + friend class enablerst; + friend class renderer_opengl; + private: + vector raws; + bool uploaded; + long add_texture(SDL_Surface*); + protected: + GLuint gl_catalog; // texture catalog gennum + struct gl_texpos *gl_texpos; // Texture positions in the GL catalog, if any + public: + // Initialize state variables + textures() { + uploaded = false; + gl_texpos = NULL; + } + ~textures() { + for (auto it = raws.cbegin(); it != raws.cend(); ++it) + SDL_FreeSurface(*it); +} + int textureCount() { + return raws.size(); + } + // Upload in-memory textures to the GPU + // When textures are uploaded, any alteration to a texture + // is automatically reflected in the uploaded copy - eg. it's replaced. + // This is very expensive in opengl mode. Don't do it often. + void upload_textures(); + // Also, you really should try to remove uploaded textures before + // deleting a window, in case of driver memory leaks. + void remove_uploaded_textures(); + // Returns the most recent texture data + SDL_Surface *get_texture_data(long pos); + // Clone a texture + long clone_texture(long src); + // Remove all color, but not transparency + void grayscale_texture(long pos); + // Loads dimx*dimy textures from a file, assuming all tiles + // are equally large and arranged in a grid + // Texture positions are saved in row-major order to tex_pos + // If convert_magenta is true and the file does not have built-in transparency, + // any magenta (255,0,255 RGB) is converted to full transparency + // The calculated size of individual tiles is saved to disp_x, disp_y + void load_multi_pdim(const string &filename,long *tex_pos,long dimx,long dimy, + bool convert_magenta, + long *disp_x, long *disp_y); + // Loads a single texture from a file, returning the handle + long load(const string &filename, bool convert_magenta); + // To delete a texture.. + void delete_texture(long pos); +}; + +struct tile { + int x, y; + long tex; +}; + +typedef struct { // Window Creation Info + char* title; // Window Title + int width; // Width + int height; // Height + int bitsPerPixel; // Bits Per Pixel + BOOL isFullScreen; // FullScreen? +} GL_WindowInit; // GL_WindowInit + +typedef struct { // Contains Information Vital To A Window + GL_WindowInit init; // Window Init + BOOL isVisible; // Window Visible? +} GL_Window; // GL_Window + +enum zoom_commands { zoom_in, zoom_out, zoom_reset, zoom_fullscreen, zoom_resetgrid }; + + +struct texture_fullid { + int texpos; + float r, g, b; + float br, bg, bb; + + bool operator< (const struct texture_fullid &other) const { + if (texpos != other.texpos) return texpos < other.texpos; + if (r != other.r) return r < other.r; + if (g != other.g) return g < other.g; + if (b != other.b) return b < other.b; + if (br != other.br) return br < other.br; + if (bg != other.bg) return bg < other.bg; + return bb < other.bb; + } +}; + +typedef int texture_ttfid; // Just the texpos + +class renderer { + void cleanup_arrays(); + protected: + unsigned char *screen; + long *screentexpos; + char *screentexpos_addcolor; + unsigned char *screentexpos_grayscale; + unsigned char *screentexpos_cf; + unsigned char *screentexpos_cbr; + // For partial printing: + unsigned char *screen_old; + long *screentexpos_old; + char *screentexpos_addcolor_old; + unsigned char *screentexpos_grayscale_old; + unsigned char *screentexpos_cf_old; + unsigned char *screentexpos_cbr_old; + + void gps_allocate(int x, int y); + Either screen_to_texid(int x, int y); + public: + void display(); + virtual void update_tile(int x, int y) = 0; + virtual void update_all() = 0; + virtual void render() = 0; + virtual void set_fullscreen() {} // Should read from enabler.is_fullscreen() + virtual void zoom(zoom_commands cmd) {}; + virtual void resize(int w, int h) = 0; + virtual void grid_resize(int w, int h) = 0; + void swap_arrays(); + renderer() { + screen = NULL; + screentexpos = NULL; + screentexpos_addcolor = NULL; + screentexpos_grayscale = NULL; + screentexpos_cf = NULL; + screentexpos_cbr = NULL; + screen_old = NULL; + screentexpos_old = NULL; + screentexpos_addcolor_old = NULL; + screentexpos_grayscale_old = NULL; + screentexpos_cf_old = NULL; + screentexpos_cbr_old = NULL; + } + virtual ~renderer() { + cleanup_arrays(); + } + virtual bool get_mouse_coords(int &x, int &y) = 0; + virtual bool uses_opengl() { return false; }; +}; + +class enablerst : public enabler_inputst +{ + friend class initst; + friend class renderer_2d_base; + friend class renderer_2d; + friend class renderer_opengl; + friend class renderer_curses; + + bool fullscreen; + stack > overridden_grid_sizes; + + class renderer *renderer; + void eventLoop_SDL(); +#ifdef CURSES + void eventLoop_ncurses(); +#endif + + // Framerate calculations + int calculated_fps, calculated_gfps; + queue frame_timings, gframe_timings; // Milisecond lengths of the last few frames + int frame_sum, gframe_sum; + int frame_last, gframe_last; // SDL_GetTick returns + void do_update_fps(queue &q, int &sum, int &last, int &calc); + + public: + void clear_fps(); + private: + void update_fps(); + void update_gfps(); + + // Frame timing calculations + float fps, gfps; + float fps_per_gfps; + Uint32 last_tick; + float outstanding_frames, outstanding_gframes; + + // Async rendering + struct async_cmd { + enum cmd_t { pause, start, render, inc, set_fps } cmd; + int val; // If async_inc, number of extra frames to run. If set_fps, current value of fps. + async_cmd() {} + async_cmd(cmd_t c) { cmd = c; } + }; + + struct async_msg { + enum msg_t { quit, complete, set_fps, set_gfps, push_resize, pop_resize, reset_textures } msg; + union { + int fps; // set_fps, set_gfps + struct { // push_resize + int x, y; + }; + }; + async_msg() {} + async_msg(msg_t m) { msg = m; } + }; + + unsigned int async_frames; // Number of frames the async thread has been asked to run + bool async_paused; + Chan async_tobox; // Messages to the simulation thread + Chan async_frombox; // Messages from the simulation thread, and acknowledgements of those to + Chan async_zoom; // Zoom commands (from the simulation thread) + Chan async_fromcomplete; // Barrier for async_msg requests that require acknowledgement + public: + Uint32 renderer_threadid; + private: + + void pause_async_loop(); + void async_wait(); + void unpause_async_loop() { + struct async_cmd cmd; + cmd.cmd = async_cmd::start; + async_tobox.write(cmd); + } + + public: + + string command_line; + + float ccolor[16][3]; // The curses-RGB mapping used for non-curses display modes + + enablerst(); + unsigned long flag; // ENABLERFLAG_RENDER, ENABLERFLAG_MAXFPS + + int loop(string cmdline); + void async_loop(); + void do_frame(); + + // Framerate interface + void set_fps(int fps); + void set_gfps(int gfps); + int get_fps() { return (int)fps; } + int get_gfps() { return (int)gfps; } + int calculate_fps(); // Calculate the actual provided (G)FPS + int calculate_gfps(); + + // Mouse interface, such as it is + char mouse_lbut,mouse_rbut,mouse_lbut_down,mouse_rbut_down,mouse_lbut_lift,mouse_rbut_lift; + char tracking_on; // Whether we're tracking the mouse or not + + // OpenGL state (wrappers) + class textures textures; // Font/graphics texture catalog + GLsync sync; // Rendering barrier + void reset_textures() { + async_frombox.write(async_msg(async_msg::reset_textures)); + } + bool uses_opengl() { + if (!renderer) return false; + return renderer->uses_opengl(); + } + + // Grid-size interface + void override_grid_size(int w, int h); // Pick a /particular/ grid-size + void release_grid_size(); // Undoes override_grid_size + void zoom_display(zoom_commands command); + + + // Window management + bool is_fullscreen() { return fullscreen; } + void toggle_fullscreen() { + fullscreen = !fullscreen; + async_zoom.write(zoom_fullscreen); + } + + // Conversations + text_systemst text_system; + + // TOADY: MOVE THESE TO "FRAMERATE INTERFACE" + MVar simticks, gputicks; + Uint32 clock; // An *approximation* of the current time for use in garbage collection thingies, updated every frame or so. +}; +#endif + +// Function prototypes for deep-DF calls +char beginroutine(); +char mainloop(); +void endroutine(); + +extern enablerst enabler; + +#endif //ENABLER_H -- cgit v1.2.3