gameui
diff src/widget.cc @ 3:f1014234dece
transitions in gui elements are awesome :)
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 21 Mar 2014 03:37:16 +0200 |
parents | e5b1525084f7 |
children | e0916bb20b7f |
line diff
1.1 --- a/src/widget.cc Thu Mar 20 07:03:58 2014 +0200 1.2 +++ b/src/widget.cc Fri Mar 21 03:37:16 2014 +0200 1.3 @@ -1,12 +1,15 @@ 1.4 +#include <stdio.h> 1.5 +#include <math.h> 1.6 #include <string> 1.7 #include <sstream> 1.8 #include "widget.h" 1.9 #include "boolanm.h" 1.10 +#include "theme.h" 1.11 1.12 -using namespace gameui; 1.13 +namespace gameui { 1.14 1.15 struct WidgetImpl { 1.16 - std::string name_prefix; 1.17 + std::string type_str; 1.18 std::string name; 1.19 BBox box; 1.20 1.21 @@ -15,96 +18,249 @@ 1.22 1.23 1.24 Widget::Widget() 1.25 - : name_prefix("widget") 1.26 { 1.27 static int widget_count; 1.28 1.29 + widget = new WidgetImpl; 1.30 + set_type_string("widget"); 1.31 + 1.32 std::stringstream sstr; 1.33 - sstr << name_prefix << widget_count++; 1.34 - name = sstr.str(); 1.35 + sstr << widget->type_str << widget_count++; 1.36 + widget->name = sstr.str(); 1.37 1.38 - box.bmin = Vec2(0, 0); 1.39 - box.bmax = Vec2(1, 1); 1.40 + widget->box.bmin = Vec2(0, 0); 1.41 + widget->box.bmax = Vec2(1, 1); 1.42 1.43 - vis_st = VST_VISIBLE; 1.44 - act_st = AST_ACTIVE; 1.45 + widget->visible.set(true); 1.46 + widget->active.set(true); 1.47 1.48 - vis = act = 1.0; 1.49 + widget->hover.set_transition_duration(250); 1.50 + widget->press.set_transition_duration(50); 1.51 } 1.52 1.53 Widget::~Widget() 1.54 { 1.55 + delete widget; 1.56 } 1.57 1.58 void Widget::show() 1.59 { 1.60 - if(vis_st == VST_EASEVISIBLE || vis_st == VST_EASEIN) { 1.61 - return; 1.62 - } 1.63 - 1.64 - vis_st = VST_EASEIN; 1.65 - vis_start_time = get_cur_time(); 1.66 + widget->visible.change(true); 1.67 } 1.68 1.69 void Widget::hide() 1.70 { 1.71 - if(vis_st == VST_EASEHIDDEN || vis_st == VST_EASEOUT) { 1.72 - return; 1.73 - } 1.74 - 1.75 - vis_st = VST_EASEOUT; 1.76 - vis_start_time = get_cur_time(); 1.77 + widget->visible.change(false); 1.78 } 1.79 1.80 float Widget::get_visibility() const 1.81 { 1.82 - switch(vis_st) { 1.83 - case VST_EASEIN: 1.84 - vis = (get_cur_time() - vis_start_time) / gameui::ease_time; 1.85 - if(vis < 0.0) vis = 0.0; 1.86 - if(vis > 1.0) vis = 1.0; 1.87 - break; 1.88 + return widget->visible.get_value(); 1.89 +} 1.90 1.91 - case VST_EASEOUT: 1.92 - vis = 1.0 - (get_cur_time() - vis_start_time) / gameui::ease_time; 1.93 - if(vis < 0.0) vis = 0.0; 1.94 - if(vis > 1.0) vis = 1.0; 1.95 - break; 1.96 - 1.97 - case VST_HIDDEN: 1.98 - vis = 0.0; 1.99 - break; 1.100 - 1.101 - case VST_VISIBLE: 1.102 - vis = 1.0; 1.103 - break; 1.104 - } 1.105 - 1.106 - return vis; 1.107 +bool Widget::is_visible() const 1.108 +{ 1.109 + return widget->visible.get_state(); 1.110 } 1.111 1.112 void Widget::activate() 1.113 { 1.114 + widget->active.change(true); 1.115 } 1.116 1.117 -#ifdef WIN32 1.118 -long gameui::get_cur_time() 1.119 +void Widget::deactivate() 1.120 { 1.121 - return GetTickCount(); 1.122 + widget->active.change(false); 1.123 } 1.124 -#endif 1.125 1.126 -#if defined(__unix__) || defined(__APPLE__) 1.127 -long gameui::get_cur_time() 1.128 +float Widget::get_active() const 1.129 { 1.130 - struct timeval tv; 1.131 - static struct timeval tv0; 1.132 + return widget->active.get_value(); 1.133 +} 1.134 1.135 - gettimeofday(&tv, 0); 1.136 - if(tv0.tv_sec == 0 && tv0.tv_msec == 0) { 1.137 - tv0 = tv; 1.138 - return 0; 1.139 +bool Widget::is_active() const 1.140 +{ 1.141 + return widget->active.get_state(); 1.142 +} 1.143 + 1.144 +void Widget::press() 1.145 +{ 1.146 + widget->press.change(true); 1.147 +} 1.148 + 1.149 +void Widget::release() 1.150 +{ 1.151 + widget->press.change(false); 1.152 +} 1.153 + 1.154 +float Widget::get_pressed() const 1.155 +{ 1.156 + return widget->press.get_value(); 1.157 +} 1.158 + 1.159 +bool Widget::is_pressed() const 1.160 +{ 1.161 + return widget->press.get_state(); 1.162 +} 1.163 + 1.164 +void Widget::mousein() 1.165 +{ 1.166 + widget->hover.change(true); 1.167 +} 1.168 + 1.169 +void Widget::mouseout() 1.170 +{ 1.171 + widget->hover.change(false); 1.172 +} 1.173 + 1.174 +float Widget::get_under_mouse() const 1.175 +{ 1.176 + return widget->hover.get_value(); 1.177 +} 1.178 + 1.179 +bool Widget::is_under_mouse() const 1.180 +{ 1.181 + return widget->hover.get_state(); 1.182 +} 1.183 + 1.184 +void Widget::set_position(float x, float y) 1.185 +{ 1.186 + set_position(Vec2(x, y)); 1.187 +} 1.188 + 1.189 +void Widget::set_position(const Vec2 &pos) 1.190 +{ 1.191 + Vec2 sz = get_size(); 1.192 + 1.193 + widget->box.bmin = pos; 1.194 + widget->box.bmax.x = pos.x + sz.x; 1.195 + widget->box.bmax.y = pos.y + sz.y; 1.196 +} 1.197 + 1.198 +const Vec2 &Widget::get_position() const 1.199 +{ 1.200 + return widget->box.bmin; 1.201 +} 1.202 + 1.203 +void Widget::set_size(float x, float y) 1.204 +{ 1.205 + set_size(Vec2(x, y)); 1.206 +} 1.207 + 1.208 +void Widget::set_size(const Vec2 &sz) 1.209 +{ 1.210 + widget->box.bmax.x = widget->box.bmin.x + sz.x; 1.211 + widget->box.bmax.y = widget->box.bmin.y + sz.y; 1.212 +} 1.213 + 1.214 +const Vec2 Widget::get_size() const 1.215 +{ 1.216 + return Vec2(widget->box.bmax.x - widget->box.bmin.x, 1.217 + widget->box.bmax.y - widget->box.bmin.y); 1.218 +} 1.219 + 1.220 + 1.221 +const BBox &Widget::get_box() const 1.222 +{ 1.223 + return widget->box; 1.224 +} 1.225 + 1.226 +bool Widget::hit_test(const Vec2 &pt) const 1.227 +{ 1.228 + return pt.x >= widget->box.bmin.x && pt.x < widget->box.bmax.x && 1.229 + pt.y >= widget->box.bmin.y && pt.y < widget->box.bmax.y; 1.230 +} 1.231 + 1.232 +void Widget::draw() const 1.233 +{ 1.234 + widget_draw_func draw_func = default_draw_func; 1.235 + 1.236 + if(theme) { 1.237 + draw_func = theme->get_draw_func(widget->type_str.c_str()); 1.238 } 1.239 - return (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000; 1.240 + 1.241 + draw_func(this); 1.242 } 1.243 -#endif 1.244 + 1.245 +// dummy event handlers 1.246 +void Widget::on_mouse_button(const ButtonEvent &ev) 1.247 +{ 1.248 +} 1.249 + 1.250 +void Widget::on_mouse_motion(const MotionEvent &ev) 1.251 +{ 1.252 +} 1.253 + 1.254 +void Widget::on_mouse_focus(const FocusEvent &ev) 1.255 +{ 1.256 +} 1.257 + 1.258 +void Widget::on_key(const KeyEvent &ev) 1.259 +{ 1.260 +} 1.261 + 1.262 +void Widget::on_click() 1.263 +{ 1.264 +} 1.265 + 1.266 +void Widget::on_double_click() 1.267 +{ 1.268 +} 1.269 + 1.270 +void Widget::on_change() 1.271 +{ 1.272 +} 1.273 + 1.274 + 1.275 +void Widget::set_type_string(const char *type_str) 1.276 +{ 1.277 + widget->type_str = type_str; 1.278 +} 1.279 + 1.280 +/* the event dispatcher generates high-level events (click, etc) 1.281 + * and calls the on_whatever() functions for both low and high-level 1.282 + * events. 1.283 + * The on_whatever functions are called *after* any other actions performed 1.284 + * here, to give subclasses the opportunity to override them easily, by 1.285 + * overriding the on_ functions, without having to override handle_event itself 1.286 + */ 1.287 +// TODO also call callbacks here I guess... 1.288 +void Widget::handle_event(const Event &ev) 1.289 +{ 1.290 + switch(ev.type) { 1.291 + case EV_MOUSE_BUTTON: 1.292 + if(ev.button.press) { 1.293 + press(); 1.294 + } else { 1.295 + if(is_pressed()) { 1.296 + on_click(); 1.297 + } 1.298 + release(); 1.299 + } 1.300 + on_mouse_button(ev.button); 1.301 + break; 1.302 + 1.303 + case EV_MOUSE_MOTION: 1.304 + on_mouse_motion(ev.motion); 1.305 + break; 1.306 + 1.307 + case EV_MOUSE_FOCUS: 1.308 + if(ev.focus.enter) { 1.309 + mousein(); 1.310 + } else { 1.311 + mouseout(); 1.312 + } 1.313 + on_mouse_focus(ev.focus); 1.314 + break; 1.315 + 1.316 + case EV_KEY: 1.317 + on_key(ev.key); 1.318 + break; 1.319 + 1.320 + default: 1.321 + fprintf(stderr, "%s: unknown event id: %d\n", __func__, ev.type); 1.322 + } 1.323 +} 1.324 + 1.325 + 1.326 +} // namespace gameui