gameui

annotate src/theme.cc @ 5:5a84873185ff

rudimentary theme plugin system and other minor fixes
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 22 Mar 2014 01:50:01 +0200
parents e0916bb20b7f
children
rev   line source
nuclear@3 1 #include <stdio.h>
nuclear@5 2 #include <vector>
nuclear@5 3 #include <algorithm>
nuclear@3 4 #include "theme.h"
nuclear@3 5 #include "widget.h"
nuclear@3 6
nuclear@3 7 #ifdef WIN32
nuclear@3 8 #include <windows.h>
nuclear@5 9
nuclear@5 10 static void *dlopen(const char *name, int flags);
nuclear@5 11 static void dlclose(void *so);
nuclear@5 12 static void dlsym(void *so, const char *symbol);
nuclear@5 13 #else
nuclear@5 14 #include <unistd.h>
nuclear@5 15 #include <dlfcn.h>
nuclear@3 16 #endif
nuclear@5 17
nuclear@3 18 #ifdef __APPLE__
nuclear@3 19 #include <OpenGL/gl.h>
nuclear@3 20 #else
nuclear@3 21 #include <GL/gl.h>
nuclear@3 22 #endif
nuclear@3 23
nuclear@3 24
nuclear@4 25 namespace goatkit {
nuclear@3 26
nuclear@3 27 Theme *theme;
nuclear@5 28 static std::vector<std::string> search_paths;
nuclear@5 29
nuclear@5 30
nuclear@5 31 void add_theme_path(const char *path)
nuclear@5 32 {
nuclear@5 33 if(!path || !*path) return;
nuclear@5 34
nuclear@5 35 std::string s = path;
nuclear@5 36 int last = s.length() - 1;
nuclear@5 37 if(s[last] == '/' || s[last] == '\\') {
nuclear@5 38 s.erase(last);
nuclear@5 39 }
nuclear@5 40
nuclear@5 41 if(std::find(search_paths.begin(), search_paths.end(), s) != search_paths.end()) {
nuclear@5 42 return;
nuclear@5 43 }
nuclear@5 44
nuclear@5 45 search_paths.push_back(s);
nuclear@5 46 }
nuclear@3 47
nuclear@3 48 Theme::Theme()
nuclear@3 49 {
nuclear@3 50 so = 0;
nuclear@3 51 }
nuclear@3 52
nuclear@5 53 Theme::~Theme()
nuclear@5 54 {
nuclear@5 55 unload();
nuclear@5 56 }
nuclear@5 57
nuclear@5 58 typedef WidgetDrawFunc (*LookupFunc)(const char*);
nuclear@5 59
nuclear@3 60 bool Theme::load(const char *name)
nuclear@3 61 {
nuclear@5 62 unload();
nuclear@5 63
nuclear@5 64 if(!(so = dlopen(name, RTLD_LAZY))) {
nuclear@5 65 for(size_t i=0; i<search_paths.size(); i++) {
nuclear@5 66 std::string path = search_paths[i] + std::string(name);
nuclear@5 67
nuclear@5 68 if((so = dlopen(path.c_str(), RTLD_LAZY))) {
nuclear@5 69 break;
nuclear@5 70 }
nuclear@5 71 }
nuclear@5 72
nuclear@5 73 if(!so) {
nuclear@5 74 fprintf(stderr, "%s: failed to load theme plugin: %s\n", __func__, name);
nuclear@5 75 return false;
nuclear@5 76 }
nuclear@5 77 }
nuclear@5 78
nuclear@5 79 // loaded the shared object, now get the lookup function
nuclear@5 80 lookup_theme_draw_func = (LookupFunc)dlsym(so, "get_widget_count");
nuclear@5 81 if(!lookup_theme_draw_func) {
nuclear@5 82 fprintf(stderr, "%s: invalid theme plugin %s\n", __func__, name);
nuclear@5 83 unload();
nuclear@5 84 return false;
nuclear@5 85 }
nuclear@5 86
nuclear@5 87 return true;
nuclear@3 88 }
nuclear@3 89
nuclear@5 90 void Theme::unload()
nuclear@3 91 {
nuclear@5 92 if(so) {
nuclear@5 93 dlclose(so);
nuclear@5 94 so = 0;
nuclear@5 95 }
nuclear@5 96 func_cache.clear();
nuclear@5 97 }
nuclear@5 98
nuclear@5 99 WidgetDrawFunc Theme::get_draw_func(const char *type) const
nuclear@5 100 {
nuclear@5 101 std::map<std::string, WidgetDrawFunc>::const_iterator it = func_cache.find(type);
nuclear@5 102 if(it == func_cache.end()) {
nuclear@5 103 // don't have it cached, try to look it up
nuclear@5 104 WidgetDrawFunc func;
nuclear@5 105 if(lookup_theme_draw_func && (func = lookup_theme_draw_func(type))) {
nuclear@5 106 func_cache[type] = func;
nuclear@5 107 return func;
nuclear@5 108 }
nuclear@5 109
nuclear@5 110 // can't look it up, return the default
nuclear@3 111 return default_draw_func;
nuclear@3 112 }
nuclear@3 113 return it->second;
nuclear@3 114 }
nuclear@3 115
nuclear@3 116 #define LERP(a, b, t) ((a) + ((b) - (a)) * t)
nuclear@3 117 #define DEF_TEX_SZ 32
nuclear@3 118 void default_draw_func(const Widget *w)
nuclear@3 119 {
nuclear@3 120 static unsigned int tex;
nuclear@3 121
nuclear@3 122 if(!tex) {
nuclear@3 123 unsigned char *pixels = new unsigned char[DEF_TEX_SZ * DEF_TEX_SZ * 3];
nuclear@3 124 unsigned char *ptr = pixels;
nuclear@3 125 for(int i=0; i<DEF_TEX_SZ; i++) {
nuclear@3 126 for(int j=0; j<DEF_TEX_SZ; j++) {
nuclear@3 127 bool stripe = (((j + i) / 8) & 1) == 1;
nuclear@3 128 ptr[0] = ptr[1] = ptr[2] = stripe ? 255 : 0;
nuclear@3 129 ptr += 3;
nuclear@3 130 }
nuclear@3 131 }
nuclear@3 132
nuclear@3 133 glGenTextures(1, &tex);
nuclear@3 134 glBindTexture(GL_TEXTURE_2D, tex);
nuclear@3 135 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nuclear@3 136 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@3 137 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, DEF_TEX_SZ, DEF_TEX_SZ, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
nuclear@3 138 delete [] pixels;
nuclear@3 139 }
nuclear@3 140
nuclear@3 141 Vec2 pos = w->get_position();
nuclear@3 142 Vec2 sz = w->get_size();
nuclear@3 143 float aspect = sz.x / sz.y;
nuclear@3 144
nuclear@3 145 glPushAttrib(GL_ENABLE_BIT);
nuclear@3 146 glEnable(GL_TEXTURE_2D);
nuclear@3 147 glBindTexture(GL_TEXTURE_2D, tex);
nuclear@3 148
nuclear@3 149 float offs = w->get_pressed() * 0.1 * sz.y;
nuclear@3 150 glMatrixMode(GL_MODELVIEW);
nuclear@3 151 glPushMatrix();
nuclear@3 152 glTranslatef(offs, -offs, 0);
nuclear@3 153
nuclear@3 154 float active = w->get_active();
nuclear@3 155 float hover = w->get_under_mouse();
nuclear@3 156
nuclear@3 157 float rg = LERP(0.4, 1.0, hover);
nuclear@3 158 float b = LERP(rg, 0, active);
nuclear@3 159 glColor3f(rg, rg, b);
nuclear@3 160
nuclear@3 161 glBegin(GL_QUADS);
nuclear@3 162 glTexCoord2f(0, 1);
nuclear@3 163 glVertex2f(pos.x, pos.y);
nuclear@3 164 glTexCoord2f(aspect, 1);
nuclear@3 165 glVertex2f(pos.x + sz.x, pos.y);
nuclear@3 166 glTexCoord2f(aspect, 0);
nuclear@3 167 glVertex2f(pos.x + sz.x, pos.y + sz.y);
nuclear@3 168 glTexCoord2f(0, 0);
nuclear@3 169 glVertex2f(pos.x, pos.y + sz.y);
nuclear@3 170 glEnd();
nuclear@3 171
nuclear@3 172 glPopMatrix();
nuclear@3 173
nuclear@3 174 glPopAttrib();
nuclear@3 175 }
nuclear@3 176
nuclear@4 177 } // namespace goatkit
nuclear@5 178
nuclear@5 179 #ifdef WIN32
nuclear@5 180 // XXX untested
nuclear@5 181 static void *dlopen(const char *name, int flags)
nuclear@5 182 {
nuclear@5 183 return LoadLibrary(name);
nuclear@5 184 }
nuclear@5 185
nuclear@5 186 static void dlclose(void *so)
nuclear@5 187 {
nuclear@5 188 // TODO
nuclear@5 189 }
nuclear@5 190
nuclear@5 191 static void dlsym(void *so, const char *symbol)
nuclear@5 192 {
nuclear@5 193 return GetProcAddress(so, symbol);
nuclear@5 194 }
nuclear@5 195 #endif