Rebuild autotool system
[construo.git] / worldview_select_tool.cxx
blob7c6cf3be9968eac7accd3bdc73150b0103acb7b0
1 // $Id: worldview_select_tool.cxx,v 1.22 2003/07/28 22:46:48 grumbel Exp $
2 //
3 // Construo - A wire-frame construction gamee
4 // Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <math.h>
21 #include "math.hxx"
22 #include "world.hxx"
23 #include "colors.hxx"
24 #include "controller.hxx"
25 #include "worldview_component.hxx"
26 #include "particle.hxx"
27 #include "world_gui_manager.hxx"
28 #include "rect.hxx"
29 #include "root_graphic_context.hxx"
30 #include "worldview_select_tool.hxx"
32 WorldViewSelectTool::WorldViewSelectTool ()
34 mode = IDLE_MODE;
35 old_scale_factor = 1.0f;
38 WorldViewSelectTool::~WorldViewSelectTool ()
42 void
43 WorldViewSelectTool::draw_background (ZoomGraphicContext* gc)
45 for (Selection::iterator i = selection.begin (); i != selection.end (); ++i)
47 (*i)->draw_velocity_vector (gc);
48 (*i)->draw_highlight (gc);
52 void
53 WorldViewSelectTool::draw_foreground (ZoomGraphicContext* gc)
55 float x = WorldViewComponent::instance()->get_gc()->screen_to_world_x (input_context->get_mouse_x ());
56 float y = WorldViewComponent::instance()->get_gc()->screen_to_world_y (input_context->get_mouse_y ());
58 if (mode == GETTING_SELECTION_MODE)
60 gc->draw_rect (Math::min(x, click_pos.x),
61 Math::min(y, click_pos.y),
62 Math::max(x, click_pos.x),
63 Math::max(y, click_pos.y),
64 Colors::selection_rect);
67 if (!selection.empty())
69 Particle& p = **selection.begin();
70 Rect<float> selection_box (p.pos.x, p.pos.y, p.pos.x, p.pos.y);
72 for (Selection::iterator i = selection.begin (); i != selection.end (); ++i)
74 selection_box.x1 = Math::min(selection_box.x1, (*i)->pos.x);
75 selection_box.y1 = Math::min(selection_box.y1, (*i)->pos.y);
77 selection_box.x2 = Math::max(selection_box.x2, (*i)->pos.x);
78 selection_box.y2 = Math::max(selection_box.y2, (*i)->pos.y);
81 float border = 20.0f / gc->get_zoom();
82 gc->draw_rect (selection_box.x1 - border, selection_box.y1 - border,
83 selection_box.x2 + border, selection_box.y2 + border,
84 Colors::new_spring);
86 if (0) // draw selection rect
88 float rsize = 5.0f / gc->get_zoom();
89 gc->draw_fill_rect (selection_box.x1 - border - rsize, selection_box.y1 - border - rsize,
90 selection_box.x1 - border + rsize, selection_box.y1 - border + rsize,
91 Colors::selection_resizer);
92 gc->draw_fill_rect (selection_box.x2 + border - rsize, selection_box.y1 - border - rsize,
93 selection_box.x2 + border + rsize, selection_box.y1 - border + rsize,
94 Colors::selection_resizer);
95 gc->draw_fill_rect (selection_box.x1 - border - rsize, selection_box.y2 + border - rsize,
96 selection_box.x1 - border + rsize, selection_box.y2 + border + rsize,
97 Colors::selection_resizer);
98 gc->draw_fill_rect (selection_box.x2 + border - rsize, selection_box.y2 + border - rsize,
99 selection_box.x2 + border + rsize, selection_box.y2 + border + rsize,
100 Colors::selection_resizer);
103 gc->get_parent_gc()->draw_circle(gc->world_to_screen(selection.get_center ()),
104 8.0f, Colors::selection_rect);
105 gc->get_parent_gc()->draw_circle(gc->world_to_screen(selection.get_center ()),
106 16.0f, Colors::selection_rect);
110 void
111 WorldViewSelectTool::activate ()
115 void
116 WorldViewSelectTool::deactivate ()
118 selection.clear ();
121 void
122 WorldViewSelectTool::on_primary_button_press (int screen_x, int screen_y)
124 switch (mode)
126 case IDLE_MODE:
128 float x = WorldViewComponent::instance()->get_gc()->screen_to_world_x (screen_x);
129 float y = WorldViewComponent::instance()->get_gc()->screen_to_world_y (screen_y);
131 World& world = *Controller::instance()->get_world ();
133 WorldGUIManager::instance()->grab_mouse (WorldViewComponent::instance());
135 mode = GETTING_SELECTION_MODE;
137 click_pos.x = x;
138 click_pos.y = y;
140 // If the mouse clicks on a particle from the selection, we move the selection
141 Particle* new_current_particle = world.get_particle (x, y);
142 for (Selection::iterator i = selection.begin (); i != selection.end (); ++i)
144 if (new_current_particle == *i)
146 Controller::instance()->push_undo();
147 mode = MOVING_SELECTION_MODE;
148 move_diff = Vector2d();
149 break;
153 // If mouse clicks into empty space, we make a new selection
154 if (mode == GETTING_SELECTION_MODE)
156 selection.clear ();
159 break;
161 case SCALING_SELECTION_MODE:
163 graphic_context->pop_cursor();
164 WorldGUIManager::instance()->ungrab_mouse (WorldViewComponent::instance());
165 mode = IDLE_MODE;
166 graphic_context->pop_cursor();
167 old_scale_factor = 1.0f;
170 default:
171 // Do nothing, so that we don't mess up other modes
172 break;
176 void
177 WorldViewSelectTool::on_primary_button_release (int x, int y)
179 WorldGUIManager::instance()->ungrab_mouse (WorldViewComponent::instance());
181 switch(mode)
183 case GETTING_SELECTION_MODE:
185 selection.select_particles(click_pos,
186 WorldViewComponent::instance()->get_gc()->screen_to_world (Vector2d(x,y)));
187 mode = IDLE_MODE;
189 break;
191 case MOVING_SELECTION_MODE:
193 mode = IDLE_MODE;
195 break;
199 void
200 WorldViewSelectTool::on_secondary_button_press (int screen_x, int screen_y)
202 switch (mode)
204 case IDLE_MODE:
205 if (!selection.empty())
207 Controller::instance()->push_undo();
208 graphic_context->push_cursor();
209 graphic_context->set_cursor(CURSOR_ROTATE);
211 mode = ROTATING_SELECTION_MODE;
212 WorldGUIManager::instance()->grab_mouse (WorldViewComponent::instance());
214 click_pos = WorldViewComponent::instance()->get_gc()->screen_to_world(Vector2d(screen_x, screen_y));
216 rotate_center = selection.get_center();
218 break;
220 case SCALING_SELECTION_MODE:
222 graphic_context->pop_cursor();
223 WorldGUIManager::instance()->ungrab_mouse (WorldViewComponent::instance());
224 mode = IDLE_MODE;
225 graphic_context->pop_cursor();
226 selection.scale(1.0f/old_scale_factor, scale_center);
227 old_scale_factor = 1.0f;
229 break;
231 default:
232 break;
236 void
237 WorldViewSelectTool::on_secondary_button_release (int x, int y)
239 switch (mode)
241 case ROTATING_SELECTION_MODE:
242 graphic_context->pop_cursor();
243 WorldGUIManager::instance()->ungrab_mouse (WorldViewComponent::instance());
244 mode = IDLE_MODE;
245 break;
247 default:
248 break;
252 void
253 WorldViewSelectTool::on_delete_press (int x, int y)
255 Controller::instance()->push_undo();
257 World& world = *Controller::instance()->get_world ();
258 for (Selection::iterator i = selection.begin (); i != selection.end (); ++i)
260 world.remove_particle(*i);
263 selection.clear ();
266 void
267 WorldViewSelectTool::on_fix_press (int x, int y)
269 bool mark_all = false;
270 for (Selection::iterator i = selection.begin (); i != selection.end (); ++i)
272 if (!(*i)->get_fixed())
274 mark_all = true;
278 if (mark_all)
280 for (Selection::iterator i = selection.begin (); i != selection.end (); ++i)
282 (*i)->set_fixed (true);
285 else
287 for (Selection::iterator i = selection.begin (); i != selection.end (); ++i)
289 (*i)->set_fixed (!(*i)->get_fixed());
294 void
295 WorldViewSelectTool::on_mouse_move (int screen_x, int screen_y, int of_x, int of_y)
297 World& world = *Controller::instance()->get_world ();
299 switch (mode)
301 case MOVING_SELECTION_MODE:
303 Vector2d new_pos(WorldViewComponent::instance()->get_gc()->screen_to_world_x (screen_x),
304 WorldViewComponent::instance()->get_gc()->screen_to_world_y (screen_y));
306 Vector2d diff = new_pos - click_pos;
308 // Undo the last move (FIXME: Potential round errors)
309 for (Selection::iterator i = selection.begin (); i != selection.end (); ++i)
311 (*i)->pos -= move_diff;
314 if (WorldViewComponent::instance()->uses_grid())
316 diff.x = Math::round_to(diff.x, 10);
317 diff.y = Math::round_to(diff.y, 10);
320 move_diff = diff;
322 for (Selection::iterator i = selection.begin (); i != selection.end (); ++i)
324 (*i)->pos += diff;
326 // Recalculate all springs that are attached to the
327 // selection, but not fully in it.
328 std::vector<Spring*>& spring_mgr = world.get_spring_mgr();
329 for (std::vector<Spring*>::iterator j = spring_mgr.begin ();
330 j != spring_mgr.end (); ++j)
332 if ((*j)->particles.first == *i
333 || (*j)->particles.second == *i)
335 (*j)->recalc_length ();
340 break;
342 case SCALING_SELECTION_MODE:
344 Vector2d new_pos = WorldViewComponent::instance()->get_gc()->screen_to_world(Vector2d(screen_x, screen_y));
345 float scale_factor = fabsf((scale_center - new_pos).norm()/(scale_center - click_pos).norm());
346 selection.scale(1.0f/old_scale_factor, scale_center);
347 selection.scale(scale_factor, scale_center);
348 old_scale_factor = scale_factor;
350 break;
351 case ROTATING_SELECTION_MODE:
353 Vector2d new_pos(WorldViewComponent::instance()->get_gc()->screen_to_world_x (screen_x),
354 WorldViewComponent::instance()->get_gc()->screen_to_world_y (screen_y));
356 float new_angle = atan2(new_pos.y - rotate_center.y,
357 new_pos.x - rotate_center.x);
358 float old_angle = atan2(click_pos.y - rotate_center.y,
359 click_pos.x - rotate_center.x);
360 float rot_angle = new_angle - old_angle;
362 selection.rotate (rot_angle, rotate_center);
364 click_pos = new_pos;
366 break;
367 default:
368 break;
372 void
373 WorldViewSelectTool::on_scale_press (int x, int y)
375 if (!selection.empty())
377 rotate_center = selection.get_center();
378 Controller::instance()->push_undo();
379 graphic_context->push_cursor();
380 graphic_context->set_cursor(CURSOR_SCALE);
382 click_pos = WorldViewComponent::instance()->get_gc()->screen_to_world(Vector2d(x, y));
383 WorldGUIManager::instance()->grab_mouse (WorldViewComponent::instance());
385 mode = SCALING_SELECTION_MODE;
387 scale_center = selection.get_center();
391 void
392 WorldViewSelectTool::on_duplicate_press (int x, int y)
394 selection.duplicate ();
397 void
398 WorldViewSelectTool::on_button_press (int button_id, int x, int y)
400 Vector2d pos = WorldViewComponent::instance()->get_gc()->screen_to_world(Vector2d(x, y));
402 switch (button_id)
404 case BUTTON_SETVELOCITY:
405 selection.set_velocity (pos - selection.get_center ());
406 break;
407 case BUTTON_FLIP:
408 selection.flip();
409 break;
410 break;
411 default:
412 break;
416 void
417 WorldViewSelectTool::on_join_press (int x, int y)
419 std::cout << "Join pressed" << std::endl;
420 selection.join_doubles(5.0f);
423 /* EOF */