src/view.cpp in reflexion-0.1.8 vs src/view.cpp in reflexion-0.1.9

- old
+ new

@@ -2,10 +2,11 @@ #include <assert.h> #include <algorithm> #include <boost/scoped_ptr.hpp> +#include "xot/util.h" #include "reflex/window.h" #include "reflex/body.h" #include "reflex/exception.h" #include "world.h" @@ -28,10 +29,12 @@ View* parent; Bounds frame; + float angle, scale; + boost::scoped_ptr<Selector> pselector; boost::scoped_ptr<Point> pscroll; boost::scoped_ptr<ChildList> pchildren; @@ -49,11 +52,11 @@ short hide_count; uint flags; Data () - : window(NULL), parent(NULL), + : window(NULL), parent(NULL), angle(0), scale(1), capture(CAPTURE_NONE), hide_count(0), flags(0) { } ~Data () @@ -82,34 +85,62 @@ { if (!pstyles) pstyles.reset(new StyleList); return *pstyles; } - World* world () + World* world (View* this_) { - if (!pworld) pworld.reset(new World()); + assert(this_); + + if (!pworld) + { + pworld.reset(new World(this_)); + resize_world(this_); + } return pworld.get(); } World* parent_world () { if (!parent) return NULL; - return parent->self->world(); + return parent->self->world(parent); } Body* body (View* this_) { if (!pbody) { World* world = parent_world(); if (!world) return NULL; - pbody.reset(world->create_body(frame.position())); + pbody.reset(world->create_body(this_, frame.position())); this_->make_body(); } return pbody.get(); } + void resize_world (View* this_) + { + assert(this_); + + World* w = pworld.get(); + if (!w) return; + + w->resize(frame.width, frame.height); + this_->redraw(); + } + + void update_body (View* this_) + { + assert(this_); + + Body* b = pbody.get(); + if (!b) return; + + b->set_transform(frame.x, frame.y, angle); + this_->redraw(); + } + };// View::Data void set_window (View* this_, Window* window_) @@ -160,22 +191,59 @@ this_->self->parent = parent_; set_window(this_, parent_ ? parent_->window() : NULL); } + static void reflow_children (View* parent, const FrameEvent* event = NULL); + static void + update_view_frame (View* view, const Bounds& frame, float angle, bool update_body) + { + if (!view) + argument_error(__FILE__, __LINE__); + + if (!*view) + invalid_state_error(__FILE__, __LINE__); + + View::Data* self = view->self.get(); + if (frame == self->frame && angle == self->angle) return; + + FrameEvent event(frame, self->frame, angle, self->angle); + self->frame = frame; + self->angle = angle; + + bool move = event.is_move(), rotate = event.is_rotate(); + + if (move) view->on_move(&event); + if (rotate) view->on_rotate(&event); + + if (update_body && (move || rotate)) + self->update_body(view); + + if (event.is_resize()) + { + self->resize_world(view); + view->on_resize(&event); + + reflow_children(view, &event); + } + + view->redraw(); + } + + static void update_world (View* view, float dt) { World* world = view->self->pworld.get(); if (world) world->step(dt); Body* body = view->self->pbody.get(); if (body) { Bounds b = view->frame(); b.move_to(body->position()); - view->set_frame(b); + update_view_frame(view, b, body->angle(), false); } } void update_view_tree (View* view, const UpdateEvent& event) @@ -207,33 +275,45 @@ argument_error(__FILE__, __LINE__); if (view->hidden()) return; DrawEvent e = event; - e.painter->push_matrix(); - e.painter->push_attr(); + Painter* p = e.painter; + Body* b = view->self->pbody.get(); - Bounds b = view->frame(); - Point p = b.position() - view->scroll(); - e.painter->translate(p); + p->push_matrix(); + p->push_attr(); - p += offset; - Bounds c = clip & b.move_to(p); - e.painter->set_clip(c); + Bounds frame = view->frame(); + Point pos = frame.position() - view->scroll(); + p->translate(pos); + float angle = view->self->angle; + if (angle != 0) p->rotate(angle); + + float scale = view->self->scale; + if (scale != 1) p->scale(scale); + + pos += offset; + Bounds clip2 = clip & frame.move_to(pos); + if (b) + p->no_clip(); + else + p->set_clip(clip2); + e.view = view; - e.bounds = b.move_to(0, 0, b.z); + e.bounds = frame.move_to(0, 0, frame.z); view->on_draw(&e); View::child_iterator end = view->child_end(); for (View::child_iterator it = view->child_begin(); it != end; ++it) - draw_view_tree(it->get(), e, p, c); + draw_view_tree(it->get(), e, pos, clip2); - draw_world(view, e.painter); + draw_world(view, p); - e.painter->pop_attr(); - e.painter->pop_matrix(); + p->pop_attr(); + p->pop_matrix(); } #if 0 void get_all_margins (MarginList* margins, View* view) { @@ -552,11 +632,11 @@ if (margin.bottom.get_pixel(&m, parent_size.y)) size->y += m; } } #endif static void - reflow_children (View* parent, const FrameEvent* event = NULL) + reflow_children (View* parent, const FrameEvent* event) { if (!parent) argument_error(__FILE__, __LINE__); if (!parent->self->pchildren) return; @@ -795,10 +875,12 @@ if (it == child_end()) return; if (child->parent() != this) invalid_state_error(__FILE__, __LINE__); + child->clear_body(); + set_parent(child, NULL); self->pchildren->erase(it); } static void @@ -1198,43 +1280,47 @@ } void View::set_frame (const Bounds& frame) { + update_view_frame(this, frame, self->angle, true); + } + + const Bounds& + View::frame () const + { if (!*this) invalid_state_error(__FILE__, __LINE__); - const Bounds& current = self->frame; - if (frame == current) return; + return self->frame; + } - self->frame = frame; - - FrameEvent event( - self->frame, - frame.x - current.x, frame.y - current.y, - frame.w - current.w, frame.h - current.h); - if (event.is_move()) on_move(&event); - if (event.is_resize()) on_resize(&event); - - reflow_children(this, &event); - redraw(); +#if 0 + void + View::set_angle (float degree) + { + update_view_frame(this, self->frame, degree, true); } +#endif - const Bounds& - View::frame () const + float + View::angle () const { if (!*this) invalid_state_error(__FILE__, __LINE__); - return self->frame; + return self->angle; } static const Point ZERO_SCROLL; void View::scroll_to (coord x, coord y, coord z) { + if (!*this) + invalid_state_error(__FILE__, __LINE__); + Point old = self->scroll(); self->scroll().reset(x, y, z); ScrollEvent e(x, y, z, x - old.x, y - old.y, z - old.z); on_scroll(&e); redraw(); @@ -1260,19 +1346,25 @@ } const Point& View::scroll () const { + if (!*this) + invalid_state_error(__FILE__, __LINE__); + if (self->pscroll) return self->scroll(); else return ZERO_SCROLL; } void View::set_capture (uint types) { + if (!*this) + invalid_state_error(__FILE__, __LINE__); + if (types == self->capture) return; uint old = self->capture; self->capture = types; @@ -1289,10 +1381,13 @@ } uint View::capture () const { + if (!*this) + invalid_state_error(__FILE__, __LINE__); + return self->capture; } View* View::parent () @@ -1337,38 +1432,47 @@ View::body () const { return const_cast<View*>(this)->body(); } - void - View::set_density (float density) + float + View::meter2pixel (float meter, bool create_world) { - Body* b = body(); - if (!b) + if (!*this) invalid_state_error(__FILE__, __LINE__); - b->set_density(density); - } + Body* body = self->pbody.get(); + if (body) + return body->meter2pixel(meter); - void - View::set_friction (float friction) - { - Body* b = body(); - if (!b) + World* world = self->pworld.get(); + if (world) + return world->meter2pixel(meter); + + View* parent_ = NULL; + World* parent_world = NULL; + if ( + (parent_ = parent()) && + (parent_world = parent_->self->pworld.get())) + { + return parent_world->meter2pixel(meter); + } + + if (!create_world) invalid_state_error(__FILE__, __LINE__); - b->set_friction(friction); + World* new_world = self->world(this); + if (!new_world) + invalid_state_error(__FILE__, __LINE__); + + return new_world->meter2pixel(meter); } - void - View::set_restitution (float restitution) + float + View::meter2pixel (float meter) const { - Body* b = body(); - if (!b) - invalid_state_error(__FILE__, __LINE__); - - b->set_restitution(restitution); + return const_cast<View*>(this)->meter2pixel(meter, false); } void View::set_gravity (float x, float y) { @@ -1376,39 +1480,66 @@ } void View::set_gravity (const Point& vector) { - World* world = self->world(); - if (!world) + if (!*this) invalid_state_error(__FILE__, __LINE__); - world->set_gravity(vector); + World* w = self->world(this); + if (!w) + invalid_state_error(__FILE__, __LINE__); + + w->set_gravity(vector); } Point View::gravity () const { - World* world = self->pworld.get(); - return world ? world->gravity() : 0; + if (!*this) + invalid_state_error(__FILE__, __LINE__); + + World* w = self->pworld.get(); + return w ? w->gravity() : 0; } + Body* + View::wall () + { + if (!*this) + invalid_state_error(__FILE__, __LINE__); + + return self->world(this)->wall(); + } + + const Body* + View::wall () const + { + return const_cast<View*>(this)->wall(); + } + void View::set_debug (bool state) { - World* world = self->world(); - if (!world) + if (!*this) invalid_state_error(__FILE__, __LINE__); - world->set_debug(state); + World* w = self->world(this); + if (!w) + invalid_state_error(__FILE__, __LINE__); + + w->set_debug(state); } bool - View::is_debug () const + View::debugging () const { - World* world = self->pworld.get(); - return world ? world->is_debug() : false; + if (!*this) + invalid_state_error(__FILE__, __LINE__); + + World* w = self->pworld.get(); + return w ? w->debugging() : false; } Point View::from_parent (const Point& point) const { @@ -1508,10 +1639,17 @@ if (!e) argument_error(__FILE__, __LINE__); } void + View::on_rotate (FrameEvent* e) + { + if (!e) + argument_error(__FILE__, __LINE__); + } + + void View::on_scroll (ScrollEvent* e) { if (!e) argument_error(__FILE__, __LINE__); } @@ -1603,9 +1741,37 @@ //scroll_by(e->dx, e->dy, e->dz); } void View::on_capture (CaptureEvent* e) + { + if (!e) + argument_error(__FILE__, __LINE__); + } + + void + View::on_contact (ContactEvent* e) + { + if (!e) + argument_error(__FILE__, __LINE__); + + switch (e->type) + { + case ContactEvent::BEGIN: on_contact_begin(e); break; + case ContactEvent::END: on_contact_end(e); break; + case ContactEvent::NONE: break; + } + } + + void + View::on_contact_begin (ContactEvent* e) + { + if (!e) + argument_error(__FILE__, __LINE__); + } + + void + View::on_contact_end (ContactEvent* e) { if (!e) argument_error(__FILE__, __LINE__); }