lots of improvements to the rocket integration

This commit is contained in:
rdb 2012-01-28 11:49:41 +00:00
parent 3c65b5171b
commit 1168011850
12 changed files with 219 additions and 150 deletions

View File

@ -512,17 +512,6 @@ get_draw_region_pcollector() {
return _draw_region_pcollector;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayRegion::pixel_size_changed
// Access: Private, Virtual
// Description: Called when the size in pixels of this region
// has changed. Also called the first time the
// pixel size is known.
////////////////////////////////////////////////////////////////////
INLINE void DisplayRegion::
pixel_size_changed(int x_size, int y_size) {
}
////////////////////////////////////////////////////////////////////
// Function: DisplayRegion::CDataCull::Constructor
// Access: Public

View File

@ -762,12 +762,6 @@ do_compute_pixels(int x_size, int y_size, CData *cdata) {
cdata->_pbi = int(((1.0f - cdata->_dimensions[2]) * y_size) + 0.5);
cdata->_pti = int(((1.0f - cdata->_dimensions[3]) * y_size) + 0.5);
}
int w = cdata->_pr - cdata->_pl;
int h = cdata->_pt - cdata->_pb;
if (old_w != w || old_h != h) {
pixel_size_changed(w, h);
}
}
////////////////////////////////////////////////////////////////////

View File

@ -162,7 +162,6 @@ private:
void win_display_regions_changed();
void do_compute_pixels(int x_size, int y_size, CData *cdata);
void set_active_index(int index);
INLINE virtual void pixel_size_changed(int x_size, int y_size);
protected:
virtual void do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,

View File

@ -35,6 +35,8 @@ RocketFileInterface(VirtualFileSystem *vfs) : _vfs(vfs) {
////////////////////////////////////////////////////////////////////
Rocket::Core::FileHandle RocketFileInterface::
Open(const Rocket::Core::String& path) {
rocket_cat.debug() << "Opening " << path.CString() << "\n";
// A FileHandle is actually just a void pointer
return (Rocket::Core::FileHandle)
_vfs->open_read_file(Filename::from_os_specific(path.CString()), true);

View File

@ -50,6 +50,83 @@ RocketInputHandler::
~RocketInputHandler() {
}
////////////////////////////////////////////////////////////////////
// Function: RocketInputHandler::get_rocket_key
// Access: Published
// Description: Returns the libRocket KeyIdentifier for the given
// ButtonHandle, or KI_UNKNOWN (0) if it wasn't known.
////////////////////////////////////////////////////////////////////
int RocketInputHandler::
get_rocket_key(const ButtonHandle handle) {
static pmap<int, int> keymap;
pmap<int, int>::const_iterator it;
if (keymap.size() > 0) {
it = keymap.find(handle.get_index());
if (it == keymap.end()) {
return 0;
} else {
return it->second;
}
}
keymap[KeyboardButton::space().get_index()] = KI_SPACE;
keymap[KeyboardButton::backspace().get_index()] = KI_BACK;
keymap[KeyboardButton::tab().get_index()] = KI_TAB;
keymap[KeyboardButton::enter().get_index()] = KI_RETURN;
keymap[KeyboardButton::escape().get_index()] = KI_ESCAPE;
keymap[KeyboardButton::end().get_index()] = KI_END;
keymap[KeyboardButton::home().get_index()] = KI_HOME;
keymap[KeyboardButton::left().get_index()] = KI_LEFT;
keymap[KeyboardButton::up().get_index()] = KI_UP;
keymap[KeyboardButton::right().get_index()] = KI_RIGHT;
keymap[KeyboardButton::down().get_index()] = KI_DOWN;
keymap[KeyboardButton::insert().get_index()] = KI_INSERT;
keymap[KeyboardButton::del().get_index()] = KI_DELETE;
keymap[KeyboardButton::caps_lock().get_index()] = KI_CAPITAL;
keymap[KeyboardButton::f1().get_index()] = KI_F1;
keymap[KeyboardButton::f10().get_index()] = KI_F10;
keymap[KeyboardButton::f11().get_index()] = KI_F11;
keymap[KeyboardButton::f12().get_index()] = KI_F12;
keymap[KeyboardButton::f13().get_index()] = KI_F13;
keymap[KeyboardButton::f14().get_index()] = KI_F14;
keymap[KeyboardButton::f15().get_index()] = KI_F15;
keymap[KeyboardButton::f16().get_index()] = KI_F16;
keymap[KeyboardButton::f2().get_index()] = KI_F2;
keymap[KeyboardButton::f3().get_index()] = KI_F3;
keymap[KeyboardButton::f4().get_index()] = KI_F4;
keymap[KeyboardButton::f5().get_index()] = KI_F5;
keymap[KeyboardButton::f6().get_index()] = KI_F6;
keymap[KeyboardButton::f7().get_index()] = KI_F7;
keymap[KeyboardButton::f8().get_index()] = KI_F8;
keymap[KeyboardButton::f9().get_index()] = KI_F9;
keymap[KeyboardButton::help().get_index()] = KI_HELP;
keymap[KeyboardButton::lcontrol().get_index()] = KI_LCONTROL;
keymap[KeyboardButton::lshift().get_index()] = KI_LSHIFT;
keymap[KeyboardButton::num_lock().get_index()] = KI_NUMLOCK;
keymap[KeyboardButton::page_down().get_index()] = KI_NEXT;
keymap[KeyboardButton::page_up().get_index()] = KI_PRIOR;
keymap[KeyboardButton::pause().get_index()] = KI_PAUSE;
keymap[KeyboardButton::print_screen().get_index()] = KI_SNAPSHOT;
keymap[KeyboardButton::rcontrol().get_index()] = KI_RCONTROL;
keymap[KeyboardButton::rshift().get_index()] = KI_RSHIFT;
keymap[KeyboardButton::scroll_lock().get_index()] = KI_SCROLL;
for (char c = 'a'; c <= 'z'; ++c) {
keymap[KeyboardButton::ascii_key(c).get_index()] = (c - 'a') + KI_A;
}
for (char c = '0'; c <= '9'; ++c) {
keymap[KeyboardButton::ascii_key(c).get_index()] = (c - '0') + KI_0;
}
it = keymap.find(handle.get_index());
if (it != keymap.end()) {
return it->second;
}
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: RocketInputHandler::do_transmit_data
// Access: Protected, Virtual
@ -92,6 +169,8 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
for (int i = 0; i < num_events; i++) {
const ButtonEvent &be = this_button_events->get_event(i);
int rocket_key = KI_UNKNOWN;
switch (be._type) {
case ButtonEvent::T_down:
if (be._button == KeyboardButton::control()) {
@ -107,10 +186,30 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
_wheel_delta -= 1;
} else if (be._button == MouseButton::wheel_down()) {
_wheel_delta += 1;
} else if (be._button == MouseButton::one()) {
_mouse_buttons[0] = true;
} else if (be._button == MouseButton::two()) {
_mouse_buttons[1] = true;
} else if (be._button == MouseButton::three()) {
_mouse_buttons[2] = true;
} else if (be._button == MouseButton::four()) {
_mouse_buttons[3] = true;
} else if (be._button == MouseButton::five()) {
_mouse_buttons[4] = true;
}
rocket_key = get_rocket_key(be._button);
if (rocket_key != KI_UNKNOWN) {
_keys[rocket_key] = true;
}
break;
case ButtonEvent::T_repeat:
rocket_key = get_rocket_key(be._button);
if (rocket_key != KI_UNKNOWN) {
_repeated_keys.push_back(rocket_key);
}
break;
case ButtonEvent::T_up:
@ -122,11 +221,30 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
_modifiers &= ~KM_ALT;
} else if (be._button == KeyboardButton::meta()) {
_modifiers &= ~KM_META;
} else if (be._button == MouseButton::one()) {
_mouse_buttons[0] = false;
} else if (be._button == MouseButton::two()) {
_mouse_buttons[1] = false;
} else if (be._button == MouseButton::three()) {
_mouse_buttons[2] = false;
} else if (be._button == MouseButton::four()) {
_mouse_buttons[3] = false;
} else if (be._button == MouseButton::five()) {
_mouse_buttons[4] = false;
}
rocket_key = get_rocket_key(be._button);
if (rocket_key != KI_UNKNOWN) {
_keys[rocket_key] = false;
}
break;
case ButtonEvent::T_keystroke:
_text_input.push_back(be._keycode);
// Ignore control characters; otherwise, they actually get added to strings in the UI.
if (be._keycode > 0x1F and (be._keycode < 0x7F or be._keycode > 0x9F)) {
_text_input.push_back(be._keycode);
}
break;
case ButtonEvent::T_resume_down:
@ -135,49 +253,6 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
case ButtonEvent::T_move:
break;
}
bool down = (be._type == ButtonEvent::T_down);
if (down || be._type == ButtonEvent::T_up) {
if (be._button == MouseButton::one()) {
_mouse_buttons[1] = down;
} else if (be._button == MouseButton::two()) {
_mouse_buttons[2] = down;
} else if (be._button == MouseButton::three()) {
_mouse_buttons[3] = down;
} else if (be._button == MouseButton::four()) {
_mouse_buttons[4] = down;
} else if (be._button == MouseButton::five()) {
_mouse_buttons[5] = down;
// In the order they are specified in Rocket/Core/Input.h
} else if (be._button == KeyboardButton::space()) {
_keys[KI_SPACE] = down;
} else if (be._button == KeyboardButton::backspace()) {
_keys[KI_BACK] = down;
} else if (be._button == KeyboardButton::tab()) {
_keys[KI_TAB] = down;
} else if (be._button == KeyboardButton::enter()) {
_keys[KI_RETURN] = down;
} else if (be._button == KeyboardButton::escape()) {
_keys[KI_ESCAPE] = down;
} else if (be._button == KeyboardButton::end()) {
_keys[KI_END] = down;
} else if (be._button == KeyboardButton::home()) {
_keys[KI_HOME] = down;
} else if (be._button == KeyboardButton::left()) {
_keys[KI_LEFT] = down;
} else if (be._button == KeyboardButton::up()) {
_keys[KI_UP] = down;
} else if (be._button == KeyboardButton::right()) {
_keys[KI_RIGHT] = down;
} else if (be._button == KeyboardButton::down()) {
_keys[KI_DOWN] = down;
} else if (be._button == KeyboardButton::insert()) {
_keys[KI_INSERT] = down;
} else if (be._button == KeyboardButton::del()) {
_keys[KI_DELETE] = down;
}
}
}
}
}
@ -226,7 +301,17 @@ update_context(Rocket::Core::Context *context, int xoffs, int yoffs) {
context->ProcessKeyUp((KeyIdentifier) it->first, _modifiers);
}
}
_mouse_buttons.clear();
_keys.clear();
}
if (_repeated_keys.size() > 0) {
pvector<int>::const_iterator it;
for (it = _repeated_keys.begin(); it != _repeated_keys.end(); ++it) {
context->ProcessKeyUp((KeyIdentifier) *it, _modifiers);
context->ProcessKeyDown((KeyIdentifier) *it, _modifiers);
}
_repeated_keys.clear();
}
if (_text_input.size() > 0) {

View File

@ -17,12 +17,13 @@
#include "config_rocket.h"
#include "dataNode.h"
#include "buttonHandle.h"
namespace Rocket {
namespace Core {
class Context;
}
};
}
////////////////////////////////////////////////////////////////////
// Class : RocketInputHandler
@ -34,6 +35,8 @@ PUBLISHED:
RocketInputHandler(const string &name = string());
virtual ~RocketInputHandler();
static int get_rocket_key(const ButtonHandle handle);
public:
void update_context(Rocket::Core::Context *context, int xoffs, int yoffs);
@ -57,6 +60,7 @@ private:
typedef pmap<int, bool> ButtonActivityMap;
ButtonActivityMap _mouse_buttons;
ButtonActivityMap _keys;
pvector<int> _repeated_keys;
pvector<short> _text_input;
public:

View File

@ -48,9 +48,10 @@ make(const string &context_name, GraphicsOutput *window,
// Function: RocketRegion::get_context
// Access: Published
// Description: Returns a pointer to the Rocket context associated
// with this region. Will only be valid as long as
// this region still exists, so be sure to toss it
// when you toss the region itself.
// with this region. Does not increase the reference
// count, so if you want to preserve it for longer
// than this region exists, be sure to call
// AddReference() and RemoveReference() yourself.
////////////////////////////////////////////////////////////////////
Rocket::Core::Context* RocketRegion::
get_context() const {

View File

@ -25,29 +25,25 @@ TypeHandle RocketRegion::_type_handle;
// Description: Make sure that context_name is unique.
////////////////////////////////////////////////////////////////////
RocketRegion::
RocketRegion(GraphicsOutput *window, const LVecBase4 &dimensions,
RocketRegion(GraphicsOutput *window, const LVecBase4 &dr_dimensions,
const string &context_name) :
DisplayRegion(window, dimensions),
_dimensions(0, 0) {
DisplayRegion(window, dr_dimensions) {
cerr << "rocket " << this << "\n";
if (window != (GraphicsOutput *)NULL && window->has_size()) {
_dimensions.x = (dimensions[1] - dimensions[0]) * window->get_fb_x_size();
_dimensions.y = (dimensions[3] - dimensions[2]) * window->get_fb_y_size();
}
int pl, pr, pb, pt;
get_pixels(pl, pr, pb, pt);
Rocket::Core::Vector2i dimensions (pr - pl, pt - pb);
rocket_cat.debug()
<< "Setting initial context dimensions to ("
<< _dimensions.x << ", " << _dimensions.y << ")\n";
<< dimensions.x << ", " << dimensions.y << ")\n";
_context = Rocket::Core::CreateContext(context_name.c_str(),
_dimensions, &_interface);
dimensions, &_interface);
nassertv(_context != NULL);
_lens = new OrthographicLens;
_lens->set_film_size(_dimensions.x, -_dimensions.y);
_lens->set_film_offset(_dimensions.x * 0.5, _dimensions.y * 0.5);
_lens->set_film_size(dimensions.x, -dimensions.y);
_lens->set_film_offset(dimensions.x * 0.5, dimensions.y * 0.5);
_lens->set_near_far(-1, 1);
set_camera(new Camera(context_name, _lens));
}
@ -66,7 +62,7 @@ RocketRegion::
}
// We need to do this because libRocket may call into Python
// code to throw events.
// code to throw destruction events.
#ifdef HAVE_ROCKET_PYTHON
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
@ -80,41 +76,6 @@ RocketRegion::
}
}
////////////////////////////////////////////////////////////////////
// Function: RocketRegion::pixel_size_changed
// Access: Private, Virtual
// Description: Called when the size in pixels of this region
// has changed.
////////////////////////////////////////////////////////////////////
void RocketRegion::
pixel_size_changed(int x_size, int y_size) {
if (x_size == _dimensions.x && y_size == _dimensions.y) {
return;
}
// We need to do this because libRocket may call into Python
// code to throw events.
#ifdef HAVE_ROCKET_PYTHON
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
#endif
rocket_cat.debug() << "Setting context dimensions to ("
<< x_size << ", " << y_size << ")\n";
_dimensions.x = x_size;
_dimensions.y = y_size;
_context->SetDimensions(_dimensions);
#ifdef HAVE_ROCKET_PYTHON
PyGILState_Release(gstate);
#endif
_lens->set_film_size(_dimensions.x, -_dimensions.y);
_lens->set_film_offset(_dimensions.x * 0.5, _dimensions.y * 0.5);
}
////////////////////////////////////////////////////////////////////
// Function: RocketRegion::do_cull
// Access: Protected, Virtual
@ -126,31 +87,43 @@ do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
PStatTimer timer(get_cull_region_pcollector(), current_thread);
CullTraverser *trav = get_cull_traverser();
trav->set_cull_handler(cull_handler);
trav->set_scene(scene_setup, gsg, get_incomplete_render());
trav->set_view_frustum(NULL);
// We need to do this because libRocket may call into Python
// code to throw events.
// We (unfortunately) need to do this because libRocket
// may call into Python code to throw events.
#ifdef HAVE_ROCKET_PYTHON
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
#endif
int pl, pr, pb, pt;
get_pixels(pl, pr, pb, pt);
Rocket::Core::Vector2i dimensions (pr - pl, pt - pb);
if (_context->GetDimensions() != dimensions) {
rocket_cat.debug() << "Setting context dimensions to ("
<< dimensions.x << ", " << dimensions.y << ")\n";
_context->SetDimensions(dimensions);
_lens->set_film_size(dimensions.x, -dimensions.y);
_lens->set_film_offset(dimensions.x * 0.5, dimensions.y * 0.5);
}
if (_input_handler != NULL) {
int pl, pr, pb, pt;
get_pixels(pl, pr, pb, pt);
_input_handler->update_context(_context, pl, pb);
} else {
_context->Update();
}
CullTraverser *trav = get_cull_traverser();
trav->set_cull_handler(cull_handler);
trav->set_scene(scene_setup, gsg, get_incomplete_render());
trav->set_view_frustum(NULL);
_interface.render(_context, trav);
#ifdef HAVE_ROCKET_PYTHON
PyGILState_Release(gstate);
#endif
_interface.render(_context, trav);
trav->end_traverse();
}

View File

@ -32,14 +32,12 @@ protected:
RocketRegion(GraphicsOutput *window, const LVecBase4 &dimensions,
const string &context_name);
virtual void pixel_size_changed(int x_size, int y_size);
virtual void do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
GraphicsStateGuardian *gsg, Thread *current_thread);
public:
PUBLISHED:
virtual ~RocketRegion();
PUBLISHED:
INLINE static RocketRegion* make(const string &context_name,
GraphicsOutput *window);
INLINE static RocketRegion* make(const string &context_name,
@ -58,8 +56,7 @@ PUBLISHED:
private:
RocketRenderInterface _interface;
Rocket::Core::Context* _context;
Rocket::Core::Vector2i _dimensions;
OrthographicLens* _lens;
PT(OrthographicLens) _lens;
PT(RocketInputHandler) _input_handler;
public:

View File

@ -13,6 +13,7 @@
////////////////////////////////////////////////////////////////////
#include "rocketRegion.h"
#include <Rocket/Core/Context.h>
#ifndef CPPPARSER
#undef this
@ -31,14 +32,18 @@
////////////////////////////////////////////////////////////////////
PyObject* EXT_CONST_METHOD(RocketRegion,
get_context) {
python::object py_context;
try {
Rocket::Core::Context* context = _ext_this->get_context();
py_context = Rocket::Core::Python::Utilities::MakeObject(context);
} catch (const python::error_already_set& e) {
return NULL;
}
python::object py_context = Rocket::Core::Python::Utilities::MakeObject(context);
return py_context.ptr();
// Make sure the context won't be destroyed before both the Python
// references and the C++ references to it are completely gone.
Py_INCREF(py_context.ptr());
context->AddReference();
return py_context.ptr();
} catch (const python::error_already_set& e) {
// Return NULL, which will trigger the exception in Python
}
return NULL;
}

View File

@ -20,13 +20,14 @@
#include "internalName.h"
#include "geomVertexWriter.h"
#include "geomTriangles.h"
#include "texture.h"
#include "textureAttrib.h"
#include "texturePool.h"
#include "colorBlendAttrib.h"
#include "cullBinAttrib.h"
#include "depthTestAttrib.h"
#include "depthWriteAttrib.h"
#include "scissorAttrib.h"
#include "texture.h"
#include "textureAttrib.h"
#include "texturePool.h"
////////////////////////////////////////////////////////////////////
// Function: RocketRenderInterface::render
@ -39,11 +40,6 @@ render(Rocket::Core::Context* context, CullTraverser *trav) {
nassertv(context != NULL);
MutexHolder holder(_lock);
const Rocket::Core::Vector2i &dimensions = context->GetDimensions();
//CPT(TransformState) scale = TransformState::make_scale(
// LVector3::right() * (1.0 / dimensions.x) +
// LVector3::down() * (1.0 / dimensions.y));
_trav = trav;
_net_transform = trav->get_world_transform();
_net_state = RenderState::make(
@ -55,6 +51,7 @@ render(Rocket::Core::Context* context, CullTraverser *trav) {
ColorBlendAttrib::O_one_minus_incoming_alpha
)
);
_dimensions = context->GetDimensions();
context->Render();
@ -114,9 +111,17 @@ void RocketRenderInterface::
render_geom(const Geom* geom, const RenderState* state, const Rocket::Core::Vector2f& translation) {
LVector3 offset = LVector3::right() * translation.x + LVector3::up() * translation.y;
rocket_cat.spam()
<< "Rendering geom " << geom << " with state "
<< *state << " and translation " << offset << "\n";
if (_enable_scissor) {
state = state->add_attrib(ScissorAttrib::make(_scissor));
rocket_cat.spam()
<< "Rendering geom " << geom << " with state "
<< *state << ", translation (" << offset << "), "
<< "scissor region (" << _scissor << ")\n";
} else {
rocket_cat.spam()
<< "Rendering geom " << geom << " with state "
<< *state << ", translation (" << offset << ")\n";
}
CPT(TransformState) net_transform, modelview_transform;
net_transform = _net_transform->compose(TransformState::make_pos(offset));
@ -289,6 +294,7 @@ ReleaseTexture(Rocket::Core::TextureHandle texture_handle) {
////////////////////////////////////////////////////////////////////
void RocketRenderInterface::
EnableScissorRegion(bool enable) {
_enable_scissor = enable;
}
////////////////////////////////////////////////////////////////////
@ -299,4 +305,8 @@ EnableScissorRegion(bool enable) {
////////////////////////////////////////////////////////////////////
void RocketRenderInterface::
SetScissorRegion(int x, int y, int width, int height) {
_scissor[0] = x / (PN_stdfloat) _dimensions.x;
_scissor[1] = (x + width) / (PN_stdfloat) _dimensions.x;
_scissor[2] = 1.0f - ((y + height) / (PN_stdfloat) _dimensions.y);
_scissor[3] = 1.0f - (y / (PN_stdfloat) _dimensions.y);
}

View File

@ -24,6 +24,11 @@
#include <Rocket/Core/RenderInterface.h>
////////////////////////////////////////////////////////////////////
// Class : RocketRenderInterface
// Description : Class that provides the main render interface for
// libRocket integration.
////////////////////////////////////////////////////////////////////
class RocketRenderInterface : public Rocket::Core::RenderInterface {
public:
void render(Rocket::Core::Context* context, CullTraverser *trav);
@ -56,10 +61,15 @@ protected:
private:
Mutex _lock;
// Hold the scissor settings and whether or not to enable scissoring.
bool _enable_scissor;
LVecBase4f _scissor;
// These are temporarily filled in by render().
CullTraverser *_trav;
CPT(TransformState) _net_transform;
CPT(RenderState) _net_state;
Rocket::Core::Vector2i _dimensions;
};
#endif