Browse Source

experimental libRocket support

rdb 14 years ago
parent
commit
69fcb76b1a

+ 11 - 0
panda/src/pandabase/pandasymbols.h

@@ -232,6 +232,14 @@
   #define EXPTP_PANDAX11 extern
   #define EXPTP_PANDAX11 extern
 #endif
 #endif
 
 
+#ifdef BUILDING_ROCKET
+  #define EXPCL_ROCKET __declspec(dllexport)
+  #define EXPTP_ROCKET
+#else
+  #define EXPCL_ROCKET __declspec(dllimport)
+  #define EXPTP_ROCKET extern
+#endif
+
 #ifdef BUILDING_SHADER
 #ifdef BUILDING_SHADER
   #define EXPCL_SHADER __declspec(dllexport)
   #define EXPCL_SHADER __declspec(dllexport)
   #define EXPTP_SHADER
   #define EXPTP_SHADER
@@ -339,6 +347,9 @@
 #define EXPCL_PANDAX11
 #define EXPCL_PANDAX11
 #define EXPTP_PANDAX11
 #define EXPTP_PANDAX11
 
 
+#define EXPCL_ROCKET
+#define EXPTP_ROCKET
+
 #define EXPCL_SHADER
 #define EXPCL_SHADER
 #define EXPTP_SHADER
 #define EXPTP_SHADER
 
 

+ 38 - 0
panda/src/rocket/Sources.pp

@@ -0,0 +1,38 @@
+#define OTHER_LIBS p3interrogatedb:c p3dconfig:c p3dtoolconfig:m \
+                   p3dtoolutil:c p3dtoolbase:c p3dtool:m p3prc:c
+
+#define USE_PACKAGES rocket
+
+#define BUILDING_DLL BUILDING_ROCKET
+
+#begin lib_target
+  #define TARGET p3rocket
+  #define LOCAL_LIBS \
+    p3display p3pgraph p3gobj p3linmath p3putil p3dgraph
+
+  #define COMBINED_SOURCES rocket_composite1.cxx
+
+  #define SOURCES \
+    config_rocket.h \
+    rocketFileInterface.h \
+    rocketInputHandler.h \
+    rocketRegion.h $[if $[HAVE_ROCKET_PYTHON],rocketRegion_ext.I] \
+    rocketRenderInterface.h \
+    rocketSystemInterface.h
+
+  #define INCLUDED_SOURCES \
+    config_rocket.cxx \
+    rocketFileInterface.cxx \
+    rocketInputHandler.cxx \
+    rocketRegion.cxx \
+    rocketRenderInterface.cxx \
+    rocketSystemInterface.cxx
+
+  #define INSTALL_HEADERS \
+    config_rocket.h rocketRegion.h
+
+#if $[HAVE_ROCKET_PYTHON]
+  #define IGATESCAN rocketInputHandler.h rocketInputHandler.cxx rocketRegion.h rocketRegion.cxx rocketRegion_ext.I
+#endif
+
+#end lib_target

+ 59 - 0
panda/src/rocket/config_rocket.cxx

@@ -0,0 +1,59 @@
+// Filename: config_rocket.cxx
+// Created by:  rdb (04Nov11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "config_rocket.h"
+#include "rocketFileInterface.h"
+#include "rocketInputHandler.h"
+#include "rocketRegion.h"
+#include "rocketSystemInterface.h"
+
+#include "pandaSystem.h"
+#include "dconfig.h"
+
+#include <Rocket/Core.h>
+
+Configure(config_rocket);
+NotifyCategoryDef(rocket, "");
+
+ConfigureFn(config_rocket) {
+  init_librocket();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: init_librocket
+//  Description: Initializes the library.  This must be called at
+//               least once before any of the functions or classes in
+//               this library can be used.  Normally it will be
+//               called by the static initializers and need not be
+//               called explicitly, but special cases exist.
+////////////////////////////////////////////////////////////////////
+void
+init_librocket() {
+  static bool initialized = false;
+  if (initialized) {
+    return;
+  }
+  initialized = true;
+
+  RocketInputHandler::init_type();
+  RocketRegion::init_type();
+
+  RocketFileInterface* fi = new RocketFileInterface;
+  Rocket::Core::SetFileInterface(fi);
+
+  RocketSystemInterface* si = new RocketSystemInterface;
+  Rocket::Core::SetSystemInterface(si);
+
+  Rocket::Core::Initialise();
+}

+ 25 - 0
panda/src/rocket/config_rocket.h

@@ -0,0 +1,25 @@
+// Filename: config_rocket.h
+// Created by:  rdb (04Nov11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef CONFIG_ROCKET_H
+#define CONFIG_ROCKET_H
+
+#include "pandabase.h"
+#include "notifyCategoryProxy.h"
+
+NotifyCategoryDecl(rocket, EXPCL_ROCKET, EXPTP_ROCKET);
+
+extern EXPCL_ROCKET void init_librocket();
+
+#endif

+ 108 - 0
panda/src/rocket/rocketFileInterface.cxx

@@ -0,0 +1,108 @@
+// Filename: rocketFileInterface.cxx
+// Created by:  rdb (03Nov11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "rocketFileInterface.h"
+#include "virtualFileSystem.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketFileInterface::Constructor
+//       Access: Public
+//  Description: Constructs a RocketFileInterface for the given
+//               VFS, or the default if NULL is given.
+////////////////////////////////////////////////////////////////////
+RocketFileInterface::
+RocketFileInterface(VirtualFileSystem *vfs) : _vfs(vfs) {
+  if (_vfs == NULL) {
+    _vfs = VirtualFileSystem::get_global_ptr();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketFileInterface::Open
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+Rocket::Core::FileHandle RocketFileInterface::
+Open(const Rocket::Core::String& path) {
+  // A FileHandle is actually just a void pointer
+  return (Rocket::Core::FileHandle)
+    _vfs->open_read_file(Filename::from_os_specific(path.CString()), true);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketFileInterface::Close
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void RocketFileInterface::
+Close(Rocket::Core::FileHandle file) {
+  if ((istream*) file != (istream*) NULL) {
+    _vfs->close_read_file((istream*) file);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketFileInterface::Read
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+size_t RocketFileInterface::
+Read(void* buffer, size_t size, Rocket::Core::FileHandle file) {
+  istream* const stream = (istream*) file;
+  if (stream == (istream*) NULL) {
+    return 0;
+  }
+
+  stream->read((char*) buffer, size);
+  return stream->gcount();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketFileInterface::Seek
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool RocketFileInterface::
+Seek(Rocket::Core::FileHandle file, long offset, int origin) {
+  istream* stream = (istream*) file;
+  if (stream == (istream*) NULL) {
+    return false;
+  }
+
+  switch(origin) {
+  case SEEK_SET:
+    stream->seekg(offset, ios::beg);
+    break;
+  case SEEK_CUR:
+    stream->seekg(offset, ios::cur);
+    break;
+  case SEEK_END:
+    stream->seekg(offset, ios::end);
+  };
+
+  return !stream->fail();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketFileInterface::Tell
+//       Access: Public   
+//  Description: 
+////////////////////////////////////////////////////////////////////
+size_t RocketFileInterface::
+Tell(Rocket::Core::FileHandle file) {
+  if ((istream*) file == (istream*) NULL) {
+    return -1;
+  }
+  return ((istream*) file)->tellg();
+}

+ 40 - 0
panda/src/rocket/rocketFileInterface.h

@@ -0,0 +1,40 @@
+// Filename: rocketFileInterface.h
+// Created by:  rdb (03Nov11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ROCKET_FILE_INTERFACE_H
+#define ROCKET_FILE_INTERFACE_H
+
+#include "config_rocket.h"
+
+#include <Rocket/Core/FileInterface.h>
+
+class VirtualFileSystem;
+
+class RocketFileInterface : public Rocket::Core::FileInterface {
+public:
+  RocketFileInterface(VirtualFileSystem *vfs = NULL);
+  virtual ~RocketFileInterface() {};
+
+  Rocket::Core::FileHandle Open(const Rocket::Core::String& path);
+  void Close(Rocket::Core::FileHandle file);
+
+  size_t Read(void* buffer, size_t size, Rocket::Core::FileHandle file);
+  bool Seek(Rocket::Core::FileHandle file, long offset, int origin);
+  size_t Tell(Rocket::Core::FileHandle file);
+
+protected:
+  VirtualFileSystem* _vfs;
+};
+
+#endif

+ 241 - 0
panda/src/rocket/rocketInputHandler.cxx

@@ -0,0 +1,241 @@
+// Filename: rocketInputHandler.cxx
+// Created by:  rdb (20Dec11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "rocketInputHandler.h"
+#include "buttonEventList.h"
+#include "dataGraphTraverser.h"
+#include "linmath_events.h"
+#include "rocketRenderInterface.h"
+#include "keyboardButton.h"
+#include "mouseButton.h"
+
+#include <Rocket/Core/Input.h>
+
+using namespace Rocket::Core::Input;
+
+TypeHandle RocketInputHandler::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketInputHandler::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+RocketInputHandler::
+RocketInputHandler(const string &name) :
+  DataNode(name),
+  _modifiers(0),
+  _wheel_delta(0)
+{
+  _pixel_xy_input = define_input("pixel_xy", EventStoreVec2::get_class_type());
+  _button_events_input = define_input("button_events", ButtonEventList::get_class_type());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketInputHandler::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+RocketInputHandler::
+~RocketInputHandler() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketInputHandler::do_transmit_data
+//       Access: Protected, Virtual
+//  Description: The virtual implementation of transmit_data().  This
+//               function receives an array of input parameters and
+//               should generate an array of output parameters.  The
+//               input parameters may be accessed with the index
+//               numbers returned by the define_input() calls that
+//               were made earlier (presumably in the constructor);
+//               likewise, the output parameters should be set with
+//               the index numbers returned by the define_output()
+//               calls.
+////////////////////////////////////////////////////////////////////
+void RocketInputHandler::
+do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
+                 DataNodeTransmit &output) {
+  Thread *current_thread = trav->get_current_thread();
+  MutexHolder holder(_lock);
+
+  if (input.has_data(_pixel_xy_input)) {
+    // The mouse is within the window.  Get the current mouse position.
+    const EventStoreVec2 *pixel_xy;
+    DCAST_INTO_V(pixel_xy, input.get_data(_pixel_xy_input).get_ptr());
+    LVecBase2 p = pixel_xy->get_value();
+
+    // Determine if mouse moved from last position
+    if (p != _mouse_xy) {
+      _mouse_xy_changed = true;
+      _mouse_xy = p;
+    }
+  }
+
+  ButtonEventList new_button_events;
+
+  // Look for new button events.
+  if (input.has_data(_button_events_input)) {
+    const ButtonEventList *this_button_events;
+    DCAST_INTO_V(this_button_events, input.get_data(_button_events_input).get_ptr());
+    int num_events = this_button_events->get_num_events();
+    for (int i = 0; i < num_events; i++) {
+      const ButtonEvent &be = this_button_events->get_event(i);
+
+      switch (be._type) {
+      case ButtonEvent::T_down:
+        if (be._button == KeyboardButton::control()) {
+          _modifiers |= KM_CTRL;
+        } else if (be._button == KeyboardButton::shift()) {
+          _modifiers |= KM_SHIFT;
+        } else if (be._button == KeyboardButton::alt()) {
+          _modifiers |= KM_ALT;
+        } else if (be._button == KeyboardButton::meta()) {
+          _modifiers |= KM_META;
+
+        } else if (be._button == MouseButton::wheel_up()) {
+          _wheel_delta -= 1;
+        } else if (be._button == MouseButton::wheel_down()) {
+          _wheel_delta += 1;
+        }
+        break;
+
+      case ButtonEvent::T_repeat:
+        break;
+
+      case ButtonEvent::T_up:
+        if (be._button == KeyboardButton::control()) {
+          _modifiers &= ~KM_CTRL;
+        } else if (be._button == KeyboardButton::shift()) {
+          _modifiers &= ~KM_SHIFT;
+        } else if (be._button == KeyboardButton::alt()) {
+          _modifiers &= ~KM_ALT;
+        } else if (be._button == KeyboardButton::meta()) {
+          _modifiers &= ~KM_META;
+        }
+        break;
+
+      case ButtonEvent::T_keystroke:
+        _text_input.push_back(be._keycode);
+        break;
+
+      case ButtonEvent::T_resume_down:
+        break;
+
+      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;
+        }
+      }
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketInputHandler::update_context
+//       Access: Public
+//  Description: Updates the libRocket context with the changes
+//               that we have gathered in do_transmit_data.
+//               Also calls Update() on the context.
+////////////////////////////////////////////////////////////////////
+void RocketInputHandler::
+update_context(Rocket::Core::Context *context, int xoffs, int yoffs) {
+  MutexHolder holder(_lock);
+
+  if (_mouse_xy_changed) {
+    _mouse_xy_changed = false;
+
+    context->ProcessMouseMove(_mouse_xy.get_x() - xoffs,
+                              _mouse_xy.get_y() - yoffs, _modifiers);
+  }
+
+  if (_mouse_buttons.size() > 0) {
+    ButtonActivityMap::const_iterator it;
+    for (it = _mouse_buttons.begin(); it != _mouse_buttons.end(); ++it) {
+      if (it->second) {
+        context->ProcessMouseButtonDown(it->first, _modifiers);
+      } else {
+        context->ProcessMouseButtonUp(it->first, _modifiers);
+      }
+    }
+    _mouse_buttons.clear();
+  }
+
+  if (_wheel_delta != 0) {
+    context->ProcessMouseWheel(_wheel_delta, _modifiers);
+    _wheel_delta = 0;
+  }
+
+  if (_keys.size() > 0) {
+    ButtonActivityMap::const_iterator it;
+    for (it = _keys.begin(); it != _keys.end(); ++it) {
+      if (it->second) {
+        context->ProcessKeyDown((KeyIdentifier) it->first, _modifiers);
+      } else {
+        context->ProcessKeyUp((KeyIdentifier) it->first, _modifiers);
+      }
+    }
+    _mouse_buttons.clear();
+  }
+
+  if (_text_input.size() > 0) {
+    pvector<short>::const_iterator it;
+    for (it = _text_input.begin(); it != _text_input.end(); ++it) {
+      context->ProcessTextInput(*it);
+    }
+    _text_input.clear();
+  }
+
+  context->Update();
+}

+ 80 - 0
panda/src/rocket/rocketInputHandler.h

@@ -0,0 +1,80 @@
+// Filename: rocketInputHandler.h
+// Created by:  rdb (20Dec11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ROCKETINPUTHANDLER_H
+#define ROCKETINPUTHANDLER_H
+
+#include "config_rocket.h"
+#include "dataNode.h"
+
+namespace Rocket {
+  namespace Core {
+    class Context;
+  }
+};
+
+////////////////////////////////////////////////////////////////////
+//       Class : RocketInputHandler
+// Description : DataNode that listens for keyboard and mouse
+//               events and passes them to libRocket.
+////////////////////////////////////////////////////////////////////
+class EXPCL_ROCKET RocketInputHandler : public DataNode {
+PUBLISHED:
+  RocketInputHandler(const string &name = string());
+  virtual ~RocketInputHandler();
+
+public:
+  void update_context(Rocket::Core::Context *context, int xoffs, int yoffs);
+
+protected:
+  // Inherited from DataNode
+  virtual void do_transmit_data(DataGraphTraverser *trav,
+                                const DataNodeTransmit &input,
+                                DataNodeTransmit &output);
+
+private:
+  Mutex _lock;
+
+  // inputs
+  int _pixel_xy_input;
+  int _button_events_input;
+
+  LVecBase2 _mouse_xy;
+  bool _mouse_xy_changed;
+  int _modifiers;
+  int _wheel_delta;
+  typedef pmap<int, bool> ButtonActivityMap;
+  ButtonActivityMap _mouse_buttons;
+  ButtonActivityMap _keys;
+  pvector<short> _text_input;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    DataNode::init_type();
+    register_type(_type_handle, "RocketInputHandler",
+                  DataNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#endif

+ 84 - 0
panda/src/rocket/rocketRegion.I

@@ -0,0 +1,84 @@
+// Filename: rocketRegion.I
+// Created by:  rdb (01Dec11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRegion::make
+//       Access: Published, Static
+//  Description: Creates a libRocket context with the given name
+//               (must be unique) for the given window.  Returns
+//               a new DisplayRegion where the libRocket context
+//               will render to.
+//               This variant of make() creates a region that
+//               fills the entire window.
+////////////////////////////////////////////////////////////////////
+INLINE RocketRegion *RocketRegion::
+make(const string &context_name, GraphicsOutput *window) {
+  return make(context_name, window, LVecBase4(0.0f, 1.0f, 0.0f, 1.0f));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRegion::make
+//       Access: Published, Static
+//  Description: Creates a libRocket context with the given name
+//               (must be unique) for the given window.  Returns
+//               a new DisplayRegion where the libRocket context   
+//               will render to.
+////////////////////////////////////////////////////////////////////
+INLINE RocketRegion *RocketRegion::
+make(const string &context_name, GraphicsOutput *window,
+     const LVecBase4 &dimensions) {
+
+  return new RocketRegion(window, dimensions, context_name);
+}
+
+#ifndef CPPPARSER
+////////////////////////////////////////////////////////////////////
+//     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.
+////////////////////////////////////////////////////////////////////
+Rocket::Core::Context* RocketRegion::
+get_context() const {
+  return _context;
+}
+#endif
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRegion::set_input_handler
+//       Access: Published
+//  Description: Sets the RocketInputHandler object from which to
+//               gather the keyboard and mouse inputs to pass to
+//               the libRocket context before rendering.
+//               You may use one input handler to provide inputs to
+//               any number of RocketRegion objects.
+////////////////////////////////////////////////////////////////////
+INLINE void RocketRegion::
+set_input_handler(RocketInputHandler *handler) {
+  _input_handler = handler;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRegion::get_input_handler
+//       Access: Published
+//  Description: Returns the RocketInputHandler object previously
+//               passed to set_input_handler.
+////////////////////////////////////////////////////////////////////
+INLINE RocketInputHandler *RocketRegion::
+get_input_handler() const {
+  return _input_handler;
+}

+ 156 - 0
panda/src/rocket/rocketRegion.cxx

@@ -0,0 +1,156 @@
+// Filename: rocketRegion.cxx
+// Created by:  rdb (30Nov11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "rocketRegion.h"
+#include "graphicsOutput.h"
+#include "orthographicLens.h"
+#include "pStatTimer.h"
+
+TypeHandle RocketRegion::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRegion::Constructor
+//       Access: Protected
+//  Description: Make sure that context_name is unique.
+////////////////////////////////////////////////////////////////////
+RocketRegion::
+RocketRegion(GraphicsOutput *window, const LVecBase4 &dimensions,
+             const string &context_name) :
+  DisplayRegion(window, dimensions),
+  _dimensions(0, 0) {
+
+  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();
+  }
+
+  rocket_cat.debug()
+    << "Setting initial context dimensions to ("
+    << _dimensions.x << ", " << _dimensions.y << ")\n";
+
+  _context = Rocket::Core::CreateContext(context_name.c_str(),
+                                         _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_near_far(-1, 1);
+  set_camera(new Camera(context_name, _lens));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRegion::Destructor
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+RocketRegion::
+~RocketRegion() {
+  if (_context != NULL) {
+    if (_context->GetReferenceCount() > 1) {
+      _context->RemoveReference();
+      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
+
+    _context->RemoveReference();
+
+#ifdef HAVE_ROCKET_PYTHON
+    PyGILState_Release(gstate);
+#endif
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     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
+//  Description: Performs a cull traversal for this region.
+////////////////////////////////////////////////////////////////////
+void RocketRegion::
+do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
+        GraphicsStateGuardian *gsg, Thread *current_thread) {
+
+  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.
+#ifdef HAVE_ROCKET_PYTHON
+  PyGILState_STATE gstate;
+  gstate = PyGILState_Ensure();
+#endif
+
+  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();
+  }
+
+#ifdef HAVE_ROCKET_PYTHON
+  PyGILState_Release(gstate);
+#endif
+
+  _interface.render(_context, trav);
+
+  trav->end_traverse();
+}

+ 85 - 0
panda/src/rocket/rocketRegion.h

@@ -0,0 +1,85 @@
+// Filename: rocketRegion.h
+// Created by:  rdb (30Nov11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ROCKETREGION_H
+#define ROCKETREGION_H
+
+#include "config_rocket.h"
+#include "displayRegion.h"
+#include "rocketRenderInterface.h"
+#include "rocketInputHandler.h"
+
+class OrthographicLens;
+
+////////////////////////////////////////////////////////////////////
+//       Class : RocketRegion
+// Description : Represents a region in a window or buffer where
+//               the libRocket UI will be rendered to.
+////////////////////////////////////////////////////////////////////
+class EXPCL_ROCKET RocketRegion : public DisplayRegion {
+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:
+  virtual ~RocketRegion();
+
+PUBLISHED:
+  INLINE static RocketRegion* make(const string &context_name,
+                                   GraphicsOutput *window);
+  INLINE static RocketRegion* make(const string &context_name,
+                                   GraphicsOutput *window,
+                                   const LVecBase4 &dimensions);
+#ifndef CPPPARSER
+  INLINE Rocket::Core::Context* get_context() const;
+#endif
+#ifdef HAVE_ROCKET_PYTHON
+  EXTENSION(PyObject *get_context() const);
+#endif
+
+  INLINE void set_input_handler(RocketInputHandler *handler);
+  INLINE RocketInputHandler *get_input_handler() const;
+
+private:
+  RocketRenderInterface _interface;
+  Rocket::Core::Context* _context;
+  Rocket::Core::Vector2i _dimensions;
+  OrthographicLens* _lens;
+  PT(RocketInputHandler) _input_handler;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    DisplayRegion::init_type();
+    register_type(_type_handle, "RocketRegion",
+                  DisplayRegion::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "rocketRegion.I"
+
+#endif /* ROCKETREGION_H */

+ 37 - 0
panda/src/rocket/rocketRegion_ext.I

@@ -0,0 +1,37 @@
+// Filename: rocketRegion_ext.I
+// Created by:  rdb (06Dec11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "rocketRegion.h"
+
+#ifndef CPPPARSER
+#undef this
+#include <Rocket/Core/Python/Utilities.h>
+#endif
+
+////////////////////////////////////////////////////////////////////
+//     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.
+//               It's best to call this method just once and store
+//               the context in a Python variable, to avoid overhead.
+////////////////////////////////////////////////////////////////////
+PyObject* EXT_CONST_METHOD(RocketRegion,
+get_context) {
+  Rocket::Core::Context* context = _ext_this->get_context();
+  python::object py_context = Rocket::Core::Python::Utilities::MakeObject(context);
+  return py_context.ptr();
+}

+ 302 - 0
panda/src/rocket/rocketRenderInterface.cxx

@@ -0,0 +1,302 @@
+// Filename: rocketRenderInterface.cxx
+// Created by:  rdb (04Nov11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "rocketRenderInterface.h"
+#include "cullableObject.h"
+#include "cullHandler.h"
+#include "geomVertexData.h"
+#include "geomVertexArrayData.h"
+#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"
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRenderInterface::render
+//       Access: Public
+//  Description: Called by RocketNode in cull_callback.  Invokes
+//               context->Render() and culls the result.
+////////////////////////////////////////////////////////////////////
+void RocketRenderInterface::
+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(
+    CullBinAttrib::make("unsorted", 0),
+    DepthTestAttrib::make(RenderAttrib::M_none),
+    DepthWriteAttrib::make(DepthWriteAttrib::M_off),
+    ColorBlendAttrib::make(ColorBlendAttrib::M_add,
+      ColorBlendAttrib::O_incoming_alpha,
+      ColorBlendAttrib::O_one_minus_incoming_alpha
+    )
+  );
+
+  context->Render();
+
+  _trav = NULL;
+  _net_transform = NULL;
+  _net_state = NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRenderInterface::make_geom
+//       Access: Protected
+//  Description: Called internally to make a Geom from Rocket data.
+////////////////////////////////////////////////////////////////////
+PT(Geom) RocketRenderInterface::
+make_geom(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, GeomEnums::UsageHint uh) {
+  PT(GeomVertexData) vdata = new GeomVertexData("", GeomVertexFormat::get_v3c4t2(), uh);
+  vdata->unclean_set_num_rows(num_vertices);
+  {
+    GeomVertexWriter vwriter(vdata, InternalName::get_vertex());
+    GeomVertexWriter cwriter(vdata, InternalName::get_color());
+    GeomVertexWriter twriter(vdata, InternalName::get_texcoord());
+
+    // Write the vertex information.
+    for (int i = 0; i < num_vertices; ++i) {
+      const Rocket::Core::Vertex &vertex = vertices[i];
+
+      vwriter.add_data3f(LVector3f::right() * vertex.position.x + LVector3f::up() * vertex.position.y);
+      cwriter.add_data4i(vertex.colour.red, vertex.colour.green,
+                         vertex.colour.blue, vertex.colour.alpha);
+      twriter.add_data2f(vertex.tex_coord.x, 1.0f - vertex.tex_coord.y);
+    }
+  }
+
+  // Create a primitive and write the indices.
+  PT(GeomTriangles) triangles = new GeomTriangles(uh);
+  {
+    PT(GeomVertexArrayData) idata = triangles->modify_vertices();
+    idata->unclean_set_num_rows(num_indices);
+    GeomVertexWriter iwriter(idata, 0);
+
+    for (int i = 0; i < num_indices; ++i) {
+      iwriter.add_data1i(indices[i]);
+    }
+  }
+
+  PT(Geom) geom = new Geom(vdata);
+  geom->add_primitive(triangles);
+  return geom;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRenderInterface::render_geom
+//       Access: Protected
+//  Description: Only call this during render().  Culls a geom.
+////////////////////////////////////////////////////////////////////
+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";
+
+  CPT(TransformState) net_transform, modelview_transform;
+  net_transform = _net_transform->compose(TransformState::make_pos(offset));
+  modelview_transform = _trav->get_world_transform()->compose(net_transform);
+
+  CullableObject *object =
+    new CullableObject(geom, _net_state->compose(state),
+                       net_transform, modelview_transform,
+                       _trav->get_gsg());
+  _trav->get_cull_handler()->record_object(object, _trav);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRenderInterface::RenderGeometry
+//       Access: Protected
+//  Description: Called by Rocket when it wants to render geometry
+//               that the application does not wish to optimize.
+////////////////////////////////////////////////////////////////////
+void RocketRenderInterface::
+RenderGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture, const Rocket::Core::Vector2f& translation) {
+  PT(Geom) geom = make_geom(vertices, num_vertices, indices, num_indices, GeomEnums::UH_stream);
+
+  CPT(RenderState) state;
+  if ((Texture*) texture != (Texture*) NULL) {
+    state = RenderState::make(TextureAttrib::make((Texture*) texture));
+  } else {
+    state = RenderState::make_empty();
+  }
+
+  render_geom(geom, state, translation);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRenderInterface::CompileGeometry
+//       Access: Protected      
+//  Description: Called by Rocket when it wants to compile geometry
+//               it believes will be static for the forseeable future.
+////////////////////////////////////////////////////////////////////
+Rocket::Core::CompiledGeometryHandle RocketRenderInterface::
+CompileGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture) {
+
+  CompiledGeometry *c = new CompiledGeometry;
+  c->_geom = make_geom(vertices, num_vertices, indices, num_indices, GeomEnums::UH_static);
+
+  if ((Texture*) texture != (Texture*) NULL) {
+    PT(TextureStage) stage = new TextureStage("");
+    stage->set_mode(TextureStage::M_replace);
+
+    CPT(TextureAttrib) attr = DCAST(TextureAttrib, TextureAttrib::make());
+    attr = DCAST(TextureAttrib, attr->add_on_stage(stage, (Texture*) texture));
+
+    c->_state = RenderState::make(attr);
+
+    rocket_cat.debug()
+      << "Compiled geom " << c->_geom << " with texture '"
+      << ((Texture*) texture)->get_name() << "'\n";
+  } else {
+    c->_state = RenderState::make_empty();
+
+    rocket_cat.debug()
+      << "Compiled geom " << c->_geom << " without texture\n";
+  }
+
+  return (Rocket::Core::CompiledGeometryHandle) c;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRenderInterface::RenderCompiledGeometry
+//       Access: Protected
+//  Description: Called by Rocket when it wants to render
+//               application-compiled geometry.
+////////////////////////////////////////////////////////////////////
+void RocketRenderInterface::
+RenderCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry, const Rocket::Core::Vector2f& translation) {
+
+  CompiledGeometry *c = (CompiledGeometry*) geometry;
+  render_geom(c->_geom, c->_state, translation);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRenderInterface::ReleaseCompiledGeometry
+//       Access: Protected
+//  Description: Called by Rocket when it wants to release
+//               application-compiled geometry.
+////////////////////////////////////////////////////////////////////
+void RocketRenderInterface::
+ReleaseCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry) {
+  delete (CompiledGeometry*) geometry;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRenderInterface::LoadTexture
+//       Access: Protected
+//  Description: Called by Rocket when a texture is required by the
+//               library.
+////////////////////////////////////////////////////////////////////
+bool RocketRenderInterface::
+LoadTexture(Rocket::Core::TextureHandle& texture_handle,
+            Rocket::Core::Vector2i& texture_dimensions,
+            const Rocket::Core::String& source) {
+
+  PT(Texture) tex = TexturePool::load_texture(Filename::from_os_specific(source.CString()));
+  if (tex == NULL) {
+    texture_handle = 0;
+    texture_dimensions.x = 0;
+    texture_dimensions.y = 0;
+    return false;
+  }
+
+  texture_dimensions.x = tex->get_x_size();
+  texture_dimensions.y = tex->get_y_size();
+  tex->ref();
+  texture_handle = (Rocket::Core::TextureHandle) tex.p();
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRenderInterface::GenerateTexture
+//       Access: Protected
+//  Description: Called by Rocket when a texture is required to be
+//               built from an internally-generated sequence of pixels.
+////////////////////////////////////////////////////////////////////
+bool RocketRenderInterface::
+GenerateTexture(Rocket::Core::TextureHandle& texture_handle,
+                const Rocket::Core::byte* source,
+                const Rocket::Core::Vector2i& source_dimensions) {
+
+  PT(Texture) tex = new Texture;
+  tex->setup_2d_texture(source_dimensions.x, source_dimensions.y,
+                        Texture::T_unsigned_byte, Texture::F_rgba);
+  PTA_uchar image = tex->modify_ram_image();
+
+  // Convert RGBA to BGRA
+  for (size_t i = 0; i < image.size(); i += 4) {
+    image[i] = source[i + 2];
+    image[i + 1] = source[i + 1];
+    image[i + 2] = source[i];
+    image[i + 3] = source[i + 3];
+  }
+
+  tex->set_wrap_u(Texture::WM_clamp);
+  tex->set_wrap_v(Texture::WM_clamp);
+
+  tex->ref();
+  texture_handle = (Rocket::Core::TextureHandle) tex.p();
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRenderInterface::ReleaseTexture
+//       Access: Protected
+//  Description: Called by Rocket when a loaded texture is no longer
+//               required.
+////////////////////////////////////////////////////////////////////
+void RocketRenderInterface::
+ReleaseTexture(Rocket::Core::TextureHandle texture_handle) {
+  Texture* tex = (Texture*) texture_handle;
+  if (tex != (Texture*) NULL) {
+    tex->unref();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRenderInterface::EnableScissorRegion
+//       Access: Protected
+//  Description: Called by Rocket when it wants to enable or disable
+//               scissoring to clip content.
+////////////////////////////////////////////////////////////////////
+void RocketRenderInterface::
+EnableScissorRegion(bool enable) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketRenderInterface::SetScissorRegion
+//       Access: Protected
+//  Description: Called by Rocket when it wants to change the
+//               scissor region.
+////////////////////////////////////////////////////////////////////
+void RocketRenderInterface::
+SetScissorRegion(int x, int y, int width, int height) {
+}

+ 65 - 0
panda/src/rocket/rocketRenderInterface.h

@@ -0,0 +1,65 @@
+// Filename: rocketRenderInterface.h
+// Created by:  rdb (04Nov11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ROCKET_RENDER_INTERFACE_H
+#define ROCKET_RENDER_INTERFACE_H
+
+#include "config_rocket.h"
+#include "cullTraverser.h"
+#include "cullTraverserData.h"
+#include "geom.h"
+#include "renderState.h"
+#include "transformState.h"
+
+#include <Rocket/Core/RenderInterface.h>
+
+class RocketRenderInterface : public Rocket::Core::RenderInterface {
+public:
+  void render(Rocket::Core::Context* context, CullTraverser *trav);
+
+protected:
+  struct CompiledGeometry {
+    CPT(Geom) _geom;
+    CPT(RenderState) _state;
+  };
+
+  PT(Geom) make_geom(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, GeomEnums::UsageHint uh);
+  void render_geom(const Geom* geom, const RenderState* state, const Rocket::Core::Vector2f& translation);
+
+  void RenderGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture, const Rocket::Core::Vector2f& translation);
+  Rocket::Core::CompiledGeometryHandle CompileGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture);
+  void RenderCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry, const Rocket::Core::Vector2f& translation);
+  void ReleaseCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry);
+
+  bool LoadTexture(Rocket::Core::TextureHandle& texture_handle,
+                   Rocket::Core::Vector2i& texture_dimensions,
+                   const Rocket::Core::String& source);
+  bool GenerateTexture(Rocket::Core::TextureHandle& texture_handle,
+                       const Rocket::Core::byte* source,
+                       const Rocket::Core::Vector2i& source_dimensions);
+  void ReleaseTexture(Rocket::Core::TextureHandle texture_handle);
+
+  void EnableScissorRegion(bool enable);
+  void SetScissorRegion(int x, int y, int width, int height);
+
+private:
+  Mutex _lock;
+
+  // These are temporarily filled in by render().
+  CullTraverser *_trav;
+  CPT(TransformState) _net_transform;
+  CPT(RenderState) _net_state;
+};
+
+#endif

+ 56 - 0
panda/src/rocket/rocketSystemInterface.cxx

@@ -0,0 +1,56 @@
+// Filename: rocketSystemInterface.h
+// Created by:  rdb (03Nov11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "rocketSystemInterface.h"
+#include "clockObject.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketSystemInterface::GetElapsedTime
+//       Access: Public
+//  Description: Get the number of seconds elapsed since the start
+//               of the application.
+////////////////////////////////////////////////////////////////////
+float RocketSystemInterface::
+GetElapsedTime() {
+  ClockObject *clock = ClockObject::get_global_clock();
+  //XXX not sure exactly how Rocket uses uses it, maybe get_frame_time is better?
+  return clock->get_real_time();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RocketSystemInterface::LogMessage
+//       Access: Public
+//  Description: Log the specified message.  Returns true to
+//               continue execution, false to break into the
+//               debugger.
+////////////////////////////////////////////////////////////////////
+bool RocketSystemInterface::
+LogMessage(Rocket::Core::Log::Type type, const Rocket::Core::String& message) {
+  switch(type) {
+  case Rocket::Core::Log::LT_ALWAYS:
+  case Rocket::Core::Log::LT_ERROR:
+  case Rocket::Core::Log::LT_ASSERT:
+    rocket_cat.error() << message.CString() << "\n";
+    return true;
+  case Rocket::Core::Log::LT_WARNING:
+    rocket_cat.warning() << message.CString() << "\n";
+    return true;
+  case Rocket::Core::Log::LT_INFO:
+    rocket_cat.info() << message.CString() << "\n";
+    return true;
+  case Rocket::Core::Log::LT_DEBUG:
+    rocket_cat.debug() << message.CString() << "\n";
+  }
+  return true;
+}

+ 29 - 0
panda/src/rocket/rocketSystemInterface.h

@@ -0,0 +1,29 @@
+// Filename: rocketSystemInterface.h
+// Created by:  rdb (03Nov11)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ROCKET_SYSTEM_INTERFACE_H
+#define ROCKET_SYSTEM_INTERFACE_H
+
+#include "config_rocket.h"
+
+#include <Rocket/Core/SystemInterface.h>
+#include <Rocket/Core/Log.h>
+
+class RocketSystemInterface : public Rocket::Core::SystemInterface {
+public:
+  float GetElapsedTime();
+  bool LogMessage(Rocket::Core::Log::Type type, const Rocket::Core::String& message);
+};
+
+#endif

+ 6 - 0
panda/src/rocket/rocket_composite1.cxx

@@ -0,0 +1,6 @@
+#include "config_rocket.cxx"
+#include "rocketFileInterface.cxx"
+#include "rocketInputHandler.cxx"
+#include "rocketRegion.cxx"
+#include "rocketRenderInterface.cxx"
+#include "rocketSystemInterface.cxx"