1 #ifndef NO_EDITOR
2 #include <boost/bind.hpp>
3 #include <vector>
4
5 #include "asserts.hpp"
6 #include "geometry.hpp"
7 #include "image_widget.hpp"
8 #include "drag_widget.hpp"
9 #include "raster.hpp"
10
11 enum {
12 HOT_X = 16,
13 HOT_Y = 16,
14 };
15 enum {
16 CURSOR_WIDTH = 32,
17 CURSOR_HEIGHT = 32,
18 };
19
20 enum {
21 BORDER_THICKNESS = 14,
22 };
23
24 static const unsigned char horiz_cursor_data[] = {
25 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x60,
28 0x0a, 0x00, 0x00, 0x50, 0x12, 0x00, 0x00, 0x48, 0x23, 0xff, 0xff, 0xc4, 0x40, 0x00, 0x00, 0x02,
29 0x23, 0xff, 0xff, 0xc4, 0x12, 0x00, 0x00, 0x48, 0x0a, 0x00, 0x00, 0x50, 0x06, 0x00, 0x00, 0x60,
30 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33 };
34
35 static const unsigned char horiz_cursor_mask[] = {
36 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x60,
39 0x0e, 0x00, 0x00, 0x70, 0x1e, 0x00, 0x00, 0x78, 0x3f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xfe,
40 0x3f, 0xff, 0xff, 0xfc, 0x1e, 0x00, 0x00, 0x78, 0x0e, 0x00, 0x00, 0x70, 0x06, 0x00, 0x00, 0x60,
41 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 };
45
46 static const unsigned char vert_cursor_data[] = {
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x20, 0x00,
48 0x00, 0x04, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x0f, 0x78, 0x00, 0x00, 0x01, 0x40, 0x00,
49 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00,
50 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00,
51 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00,
52 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00,
53 0x00, 0x01, 0x40, 0x00, 0x00, 0x0f, 0x78, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04, 0x10, 0x00,
54 0x00, 0x02, 0x20, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
55 };
56
57 static const unsigned char vert_cursor_mask[] = {
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x03, 0xe0, 0x00,
59 0x00, 0x07, 0xf0, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x01, 0xc0, 0x00,
60 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x00,
61 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x00,
62 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x00,
63 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x00,
64 0x00, 0x01, 0xc0, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x07, 0xf0, 0x00,
65 0x00, 0x03, 0xe0, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
66 };
67
68 namespace gui {
69
70 namespace {
71 const std::string DraggerImageVert = "drag-widget-vertical";
72 const std::string DraggerImageHoriz = "drag-widget-horizontal";
73 }
74
drag_widget(const int x,const int y,const int w,const int h,const drag_direction dir,boost::function<void (int,int)> drag_start,boost::function<void (int,int)> drag_end,boost::function<void (int,int)> drag_move)75 drag_widget::drag_widget(const int x, const int y, const int w, const int h,
76 const drag_direction dir,
77 boost::function<void(int, int)> drag_start,
78 boost::function<void(int, int)> drag_end,
79 boost::function<void(int, int)> drag_move)
80 : x_(x), y_(y), w_(w), h_(h), dir_(dir),
81 drag_start_(drag_start), drag_end_(drag_end), drag_move_(drag_move),
82
83 old_cursor_(NULL), dragging_handle_(0)
84 {
85 set_environment();
86 init();
87 }
88
drag_widget(const variant & v,game_logic::formula_callable * e)89 drag_widget::drag_widget(const variant& v, game_logic::formula_callable* e)
90 : widget(v,e), old_cursor_(NULL), dragging_handle_(0)
91 {
92 ASSERT_LOG(get_environment() != 0, "You must specify a callable environment");
93 dir_ = v["direction"].as_string_default("horizontal") == "horizontal" ? DRAG_HORIZONTAL : DRAG_VERTICAL;
94 if(v.has_key("on_drag_start")) {
95 drag_start_ = boost::bind(&drag_widget::drag_start, this, _1, _2);
96 drag_start_handler_ = get_environment()->create_formula(v["on_drag_start"]);
97 }
98 if(v.has_key("on_drag_end")) {
99 drag_end_ = boost::bind(&drag_widget::drag_end, this, _1, _2);
100 drag_end_handler_ = get_environment()->create_formula(v["on_drag_end"]);
101 }
102 if(v.has_key("on_drag")) {
103 drag_move_ = boost::bind(&drag_widget::drag, this, _1, _2);
104 drag_handler_ = get_environment()->create_formula(v["on_drag"]);
105 }
106 std::vector<int> r = v["rect"].as_list_int();
107 ASSERT_EQ(r.size(), 4);
108 x_ = r[0];
109 y_ = r[1];
110 w_ = r[2];
111 h_ = r[3];
112 init();
113 }
114
init()115 void drag_widget::init()
116 {
117 SDL_Cursor* curs;
118 if(dir_ == DRAG_HORIZONTAL) {
119 curs = SDL_CreateCursor(const_cast<Uint8*>(horiz_cursor_data), const_cast<Uint8*>(horiz_cursor_mask),
120 CURSOR_WIDTH, CURSOR_HEIGHT, HOT_X, HOT_Y);
121 dragger_ = widget_ptr(new gui_section_widget(DraggerImageHoriz));
122 } else if(dir_ == DRAG_VERTICAL) {
123 curs = SDL_CreateCursor(const_cast<Uint8*>(vert_cursor_data), const_cast<Uint8*>(vert_cursor_mask),
124 CURSOR_WIDTH, CURSOR_HEIGHT, HOT_X, HOT_Y);
125 drag_cursor_ = cursor_ptr(curs, SDL_FreeCursor);
126
127 dragger_ = widget_ptr(new gui_section_widget(DraggerImageVert));
128 } else {
129 ASSERT_LOG(false, "Drag direction not given as horizontal or vertical " << dir_);
130 }
131 drag_cursor_ = cursor_ptr(curs, SDL_FreeCursor);
132
133 dragger_->set_loc(0, h_/2 - dragger_->height()/2);
134 //std::cerr << "DRAGGER LOC: " << dragger_dims_ << std::endl;
135 //std::cerr << "LEFT EDGE BORDER: " << border_ << std::endl;
136 }
137
drag(int dx,int dy)138 void drag_widget::drag(int dx, int dy)
139 {
140 using namespace game_logic;
141 if(get_environment()) {
142 map_formula_callable_ptr callable = map_formula_callable_ptr(new map_formula_callable(get_environment()));
143 callable->add("drag_dx", variant(dx));
144 callable->add("drag_dy", variant(dy));
145 variant value = drag_handler_->execute(*callable);
146 get_environment()->execute_command(value);
147 } else {
148 std::cerr << "drag_widget::drag() called without environment!" << std::endl;
149 }
150 }
151
drag_start(int x,int y)152 void drag_widget::drag_start(int x, int y)
153 {
154 using namespace game_logic;
155 if(get_environment()) {
156 map_formula_callable_ptr callable = map_formula_callable_ptr(new map_formula_callable(get_environment()));
157 callable->add("drag_x", variant(x));
158 callable->add("drag_y", variant(y));
159 variant value = drag_start_handler_->execute(*callable);
160 get_environment()->execute_command(value);
161 } else {
162 std::cerr << "drag_widget::drag_start() called without environment!" << std::endl;
163 }
164 }
165
drag_end(int x,int y)166 void drag_widget::drag_end(int x, int y)
167 {
168 using namespace game_logic;
169 if(get_environment()) {
170 map_formula_callable_ptr callable = map_formula_callable_ptr(new map_formula_callable(get_environment()));
171 callable->add("drag_x", variant(x));
172 callable->add("drag_y", variant(y));
173 variant value = drag_end_handler_->execute(*callable);
174 get_environment()->execute_command(value);
175 } else {
176 std::cerr << "drag_widget::drag_end() called without environment!" << std::endl;
177 }
178 }
179
handle_draw() const180 void drag_widget::handle_draw() const
181 {
182 if(dragger_) {
183 dragger_->draw();
184 }
185 }
186
handle_event(const SDL_Event & event,bool claimed)187 bool drag_widget::handle_event(const SDL_Event& event, bool claimed)
188 {
189 if(claimed) {
190 return claimed;
191 }
192
193 if(event.type == SDL_MOUSEMOTION) {
194 return handle_mousemotion(event.motion, claimed);
195 } else if(event.type == SDL_MOUSEBUTTONDOWN) {
196 return handle_mousedown(event.button, claimed);
197 } else if(event.type == SDL_MOUSEBUTTONUP) {
198 return handle_mouseup(event.button, claimed);
199 }
200
201 return claimed;
202 }
203
get_border_rect() const204 rect drag_widget::get_border_rect() const
205 {
206 if(dir_ == DRAG_HORIZONTAL) {
207 return rect(x_ - BORDER_THICKNESS/2, y_, BORDER_THICKNESS, h_);
208 }
209 return rect(x_, y_ - BORDER_THICKNESS/2, w_, BORDER_THICKNESS);
210 }
211
get_dragger_rect() const212 rect drag_widget::get_dragger_rect() const
213 {
214 return rect(x_, y_ + h_/2 - dragger_->height()/2, dragger_->width(), dragger_->height() );
215 }
216
handle_mousedown(const SDL_MouseButtonEvent & event,bool claimed)217 bool drag_widget::handle_mousedown(const SDL_MouseButtonEvent& event, bool claimed)
218 {
219 point p;
220 int button_state = SDL_GetMouseState(&p.x, &p.y);
221 if(point_in_rect(p, get_border_rect()) || point_in_rect(p, get_dragger_rect())) {
222 if(dragging_handle_ == 0) {
223 dragging_handle_ = event.button;
224 start_pos_ = p;
225 if(drag_start_) {
226 drag_start_(p.x, p.y);
227 }
228 claimed = true;
229 }
230 }
231 return claimed;
232 }
233
handle_mouseup(const SDL_MouseButtonEvent & event,bool claimed)234 bool drag_widget::handle_mouseup(const SDL_MouseButtonEvent& event, bool claimed)
235 {
236 int mousex, mousey;
237 int button_state = SDL_GetMouseState(&mousex, &mousey);
238 if(dragging_handle_ == event.button) {
239 dragging_handle_ = 0;
240 if(drag_end_) {
241 drag_end_(mousex, mousey);
242 }
243 claimed = true;
244 }
245 return claimed;
246 }
247
handle_mousemotion(const SDL_MouseMotionEvent & event,bool claimed)248 bool drag_widget::handle_mousemotion(const SDL_MouseMotionEvent& event, bool claimed)
249 {
250 point p;
251 int button_state = SDL_GetMouseState(&p.x, &p.y);
252 if(dragging_handle_) {
253 int dx = start_pos_.x - p.x;
254 int dy = start_pos_.y - p.y;
255 //std::cerr << "SDL_MOUSEMOTION: " << p.x << ", " << p.y << "; " << dx << "," << dy << std::endl;
256 if(drag_move_) {
257 drag_move_(dx, dy);
258 start_pos_.x = p.x;
259 start_pos_.y = p.y;
260 if(dir_ == DRAG_HORIZONTAL) {
261 x_ += dx;
262 w_ += dx;
263 } else if(dir_ == DRAG_VERTICAL) {
264 y_ += dy;
265 h_ += dy;
266 }
267 }
268 } else {
269 if(point_in_rect(p, get_dragger_rect()) || point_in_rect(p, get_border_rect())) {
270 if(old_cursor_ == NULL) {
271 old_cursor_ = SDL_GetCursor();
272 SDL_SetCursor(drag_cursor_.get());
273 }
274 } else {
275 if(old_cursor_) {
276 SDL_SetCursor(old_cursor_);
277 old_cursor_ = NULL;
278 }
279 }
280 }
281 return claimed;
282 }
283
284 }
285
286 #endif
287