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
|