gameui

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