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__);
}