istereo2

view libs/goatkit/theme.cc @ 7:a3c4fcc9f8f3

- started a goatkit UI theme - font rendering with drawtext and shaders - asset manager (only used by drawtext for now, will replace respath eventually)
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 24 Sep 2015 06:49:25 +0300
parents 3bccfc7d10fe
children 64e15874f3bd
line source
1 /*
2 GoatKit - a themable/animated widget toolkit for games
3 Copyright (C) 2014 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "config.h"
19 #include <stdio.h>
20 #include <vector>
21 #include <string>
22 #include <map>
23 #include <algorithm>
24 #include "theme.h"
25 #include "widget.h"
27 #ifdef WIN32
28 #include <windows.h>
30 static void *dlopen(const char *name, int flags);
31 static void dlclose(void *so);
32 static void *dlsym(void *so, const char *symbol);
33 #else
34 #include <unistd.h>
35 #include <dlfcn.h>
36 #endif
38 #ifdef HAVE_OPENGL_H
39 #include "opengl.h"
41 #else
43 #ifdef __APPLE__
44 #include <OpenGL/gl.h>
45 #else
46 #include <GL/gl.h>
47 #endif
49 #endif /* HAVE_OPENGL_H_ */
51 #ifndef PREFIX
52 #define PREFIX "/usr/local"
53 #endif
55 namespace goatkit {
57 struct ThemeImpl {
58 void *so;
59 WidgetDrawFunc (*lookup_theme_draw_func)(const char*);
60 mutable std::map<std::string, WidgetDrawFunc> func_cache;
61 };
63 Theme *theme;
64 static std::vector<std::string> search_paths;
65 static const char *fallback_paths[] = {
66 PREFIX "/share/goatkit",
67 0
68 };
70 void add_theme_path(const char *path)
71 {
72 if(!path || !*path) return;
74 std::string s = path;
75 int last = s.length() - 1;
76 if(s[last] == '/' || s[last] == '\\') {
77 s.erase(last);
78 }
80 if(std::find(search_paths.begin(), search_paths.end(), s) != search_paths.end()) {
81 return;
82 }
84 search_paths.push_back(s);
85 }
87 Theme::Theme()
88 {
89 impl = new ThemeImpl;
90 impl->so = 0;
91 impl->lookup_theme_draw_func = 0;
92 }
94 Theme::~Theme()
95 {
96 unload();
97 delete impl;
98 }
100 typedef WidgetDrawFunc (*LookupFunc)(const char*);
102 bool Theme::load(const char *name)
103 {
104 unload();
106 if(strcmp(name, "GOATKIT_THEME_BUILTIN") == 0) {
107 impl->so = RTLD_DEFAULT;
108 } else {
109 std::string fname = std::string(name) + ".gtheme";
110 if(!(impl->so = dlopen(fname.c_str(), RTLD_LAZY))) {
111 for(size_t i=0; i<search_paths.size(); i++) {
112 std::string path = search_paths[i] + "/" + fname;
114 if((impl->so = dlopen(path.c_str(), RTLD_LAZY))) {
115 break;
116 }
117 }
119 // try the fallback paths
120 if(!impl->so) {
121 for(int i=0; fallback_paths[i]; i++) {
122 std::string path = std::string(fallback_paths[i]) + "/" + fname;
124 if((impl->so = dlopen(path.c_str(), RTLD_LAZY))) {
125 break;
126 }
127 }
128 }
130 if(!impl->so) {
131 fprintf(stderr, "%s: failed to load theme plugin: %s\n", __func__, name);
132 return false;
133 }
134 }
135 }
137 // loaded the shared object, now get the lookup function
138 impl->lookup_theme_draw_func = (LookupFunc)dlsym(impl->so, "get_widget_func");
139 if(!impl->lookup_theme_draw_func) {
140 fprintf(stderr, "%s: invalid theme plugin %s\n", __func__, name);
141 unload();
142 return false;
143 }
145 return true;
146 }
148 void Theme::unload()
149 {
150 if(impl->so) {
151 if(impl->so != RTLD_DEFAULT) {
152 dlclose(impl->so);
153 }
154 impl->so = 0;
155 }
156 impl->func_cache.clear();
157 }
159 WidgetDrawFunc Theme::get_draw_func(const char *type) const
160 {
161 std::map<std::string, WidgetDrawFunc>::const_iterator it = impl->func_cache.find(type);
162 if(it == impl->func_cache.end()) {
163 // don't have it cached, try to look it up
164 WidgetDrawFunc func;
165 if(impl->lookup_theme_draw_func && (func = impl->lookup_theme_draw_func(type))) {
166 impl->func_cache[type] = func;
167 return func;
168 }
170 // can't look it up, return the default
171 return default_draw_func;
172 }
173 return it->second;
174 }
176 #define LERP(a, b, t) ((a) + ((b) - (a)) * t)
177 #define DEF_TEX_SZ 32
178 void default_draw_func(const Widget *w)
179 {
180 static unsigned int tex;
182 if(!tex) {
183 unsigned char *pixels = new unsigned char[DEF_TEX_SZ * DEF_TEX_SZ * 3];
184 unsigned char *ptr = pixels;
185 for(int i=0; i<DEF_TEX_SZ; i++) {
186 for(int j=0; j<DEF_TEX_SZ; j++) {
187 bool stripe = (((j + i) / 8) & 1) == 1;
188 ptr[0] = ptr[1] = ptr[2] = stripe ? 255 : 0;
189 ptr += 3;
190 }
191 }
193 glGenTextures(1, &tex);
194 glBindTexture(GL_TEXTURE_2D, tex);
195 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
196 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
197 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, DEF_TEX_SZ, DEF_TEX_SZ, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
198 delete [] pixels;
199 }
201 Vec2 pos = w->get_position();
202 Vec2 sz = w->get_size();
203 float aspect = sz.x / sz.y;
205 #if !defined(GL_ES_VERSION_2_0)
206 glPushAttrib(GL_ENABLE_BIT);
207 glEnable(GL_TEXTURE_2D);
208 #endif
209 glBindTexture(GL_TEXTURE_2D, tex);
211 float offs = w->get_pressed() * 0.1 * sz.y;
212 glMatrixMode(GL_MODELVIEW);
213 glPushMatrix();
214 glTranslatef(offs, -offs, 0);
216 float active = w->get_active();
217 float hover = w->get_under_mouse();
219 float rg = LERP(0.4, 1.0, hover);
220 float b = LERP(rg, 0, active);
221 glColor3f(rg, rg, b);
223 glBegin(GL_QUADS);
224 glTexCoord2f(0, 1);
225 glVertex2f(pos.x, pos.y);
226 glTexCoord2f(aspect, 1);
227 glVertex2f(pos.x + sz.x, pos.y);
228 glTexCoord2f(aspect, 0);
229 glVertex2f(pos.x + sz.x, pos.y + sz.y);
230 glTexCoord2f(0, 0);
231 glVertex2f(pos.x, pos.y + sz.y);
232 glEnd();
234 glPopMatrix();
236 #ifndef GL_ES_VERSION_2_0
237 glPopAttrib();
238 #endif
239 }
241 } // namespace goatkit
243 #ifdef WIN32
244 // XXX untested
245 static void *dlopen(const char *name, int flags)
246 {
247 return LoadLibrary(name);
248 }
250 static void dlclose(void *so)
251 {
252 FreeLibrary(so);
253 }
255 static void *dlsym(void *so, const char *symbol)
256 {
257 if(so == RTLD_DEFAULT) {
258 so = GetModuleHandle(0);
259 }
260 return (void*)GetProcAddress(so, symbol);
261 }
262 #endif