mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -04:00
Fix MouseRecorder & let PandaNode inherit from TypedWritableReferenceCount
This commit is contained in:
parent
0dc0bbdf0c
commit
0a64bdb33b
@ -35,6 +35,8 @@ using namespace std;
|
|||||||
#define TYPENAME typename
|
#define TYPENAME typename
|
||||||
#define CONSTEXPR
|
#define CONSTEXPR
|
||||||
#define NOEXCEPT noexcept
|
#define NOEXCEPT noexcept
|
||||||
|
#define FINAL
|
||||||
|
#define OVERRIDE
|
||||||
|
|
||||||
#define EXPORT_TEMPLATE_CLASS(expcl, exptp, classname)
|
#define EXPORT_TEMPLATE_CLASS(expcl, exptp, classname)
|
||||||
|
|
||||||
@ -121,6 +123,7 @@ typedef ios::seekdir ios_seekdir;
|
|||||||
#define INLINE inline
|
#define INLINE inline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Determine the availability of C++11 features.
|
||||||
#if defined(__has_extension) // Clang magic.
|
#if defined(__has_extension) // Clang magic.
|
||||||
# if __has_extension(cxx_constexpr)
|
# if __has_extension(cxx_constexpr)
|
||||||
# define CONSTEXPR constexpr
|
# define CONSTEXPR constexpr
|
||||||
@ -135,20 +138,30 @@ typedef ios::seekdir ios_seekdir;
|
|||||||
# if __has_extension(cxx_rvalue_references) && (__cplusplus >= 201103L)
|
# if __has_extension(cxx_rvalue_references) && (__cplusplus >= 201103L)
|
||||||
# define USE_MOVE_SEMANTICS
|
# define USE_MOVE_SEMANTICS
|
||||||
# endif
|
# endif
|
||||||
|
# if __has_extension(cxx_override_control)
|
||||||
|
# define FINAL final
|
||||||
|
# define OVERRIDE override
|
||||||
|
# endif
|
||||||
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && (__cplusplus >= 201103L)
|
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && (__cplusplus >= 201103L)
|
||||||
// noexcept was introduced in GCC 4.6, constexpr in GCC 4.7, rvalue refs in
|
// noexcept was introduced in GCC 4.6, constexpr in GCC 4.7, rvalue refs in
|
||||||
// GCC 4.3. However, GCC only started defining __cplusplus properly in 4.7.
|
// GCC 4.3. However, GCC only started defining __cplusplus properly in 4.7.
|
||||||
# define CONSTEXPR constexpr
|
# define CONSTEXPR constexpr
|
||||||
# define NOEXCEPT noexcept
|
# define NOEXCEPT noexcept
|
||||||
# define USE_MOVE_SEMANTICS
|
# define USE_MOVE_SEMANTICS
|
||||||
|
# define FINAL final
|
||||||
|
# define OVERRIDE override
|
||||||
#elif defined(_MSC_VER) && _MSC_VER >= 1600
|
#elif defined(_MSC_VER) && _MSC_VER >= 1600
|
||||||
// MSVC 2010 has move semantics.
|
// MSVC 2010 has move semantics. Not much else.
|
||||||
# define CONSTEXPR INLINE
|
# define CONSTEXPR INLINE
|
||||||
# define NOEXCEPT throw()
|
# define NOEXCEPT throw()
|
||||||
# define USE_MOVE_SEMANTICS
|
# define USE_MOVE_SEMANTICS
|
||||||
|
# define FINAL
|
||||||
|
# define OVERRIDE
|
||||||
#else
|
#else
|
||||||
# define CONSTEXPR INLINE
|
# define CONSTEXPR INLINE
|
||||||
# define NOEXCEPT
|
# define NOEXCEPT
|
||||||
|
# define FINAL
|
||||||
|
# define OVERRIDE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(WIN32_VC) && !defined(LINK_ALL_STATIC) && defined(EXPORT_TEMPLATES)
|
#if defined(WIN32_VC) && !defined(LINK_ALL_STATIC) && defined(EXPORT_TEMPLATES)
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "eventQueue.h"
|
#include "eventQueue.h"
|
||||||
#include "eventParameter.h"
|
#include "eventParameter.h"
|
||||||
#include "eventStorePandaNode.h"
|
|
||||||
#include "pandaNode.h"
|
#include "pandaNode.h"
|
||||||
|
|
||||||
struct UserPersitentData {
|
struct UserPersitentData {
|
||||||
@ -77,8 +76,8 @@ contact_added_callback(btManifoldPoint &cp,
|
|||||||
if (bullet_enable_contact_events) {
|
if (bullet_enable_contact_events) {
|
||||||
|
|
||||||
Event *event = new Event("bullet-contact-added");
|
Event *event = new Event("bullet-contact-added");
|
||||||
event->add_parameter(EventParameter(new EventStorePandaNode(node0)));
|
event->add_parameter(EventParameter(node0));
|
||||||
event->add_parameter(EventParameter(new EventStorePandaNode(node1)));
|
event->add_parameter(EventParameter(node1));
|
||||||
|
|
||||||
EventQueue::get_global_event_queue()->queue_event(event);
|
EventQueue::get_global_event_queue()->queue_event(event);
|
||||||
}
|
}
|
||||||
@ -137,8 +136,8 @@ contact_destroyed_callback(void *userPersistentData) {
|
|||||||
if (bullet_enable_contact_events) {
|
if (bullet_enable_contact_events) {
|
||||||
|
|
||||||
Event *event = new Event("bullet-contact-destroyed");
|
Event *event = new Event("bullet-contact-destroyed");
|
||||||
event->add_parameter(EventParameter(new EventStorePandaNode(data->node0)));
|
event->add_parameter(EventParameter(data->node0));
|
||||||
event->add_parameter(EventParameter(new EventStorePandaNode(data->node1)));
|
event->add_parameter(EventParameter(data->node1));
|
||||||
|
|
||||||
EventQueue::get_global_event_queue()->queue_event(event);
|
EventQueue::get_global_event_queue()->queue_event(event);
|
||||||
}
|
}
|
||||||
|
@ -39,11 +39,7 @@ class GraphicsStateGuardianBase;
|
|||||||
// arbitrary point to define the coordinate system of
|
// arbitrary point to define the coordinate system of
|
||||||
// effect.
|
// effect.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA_PGRAPH Light : virtual public ReferenceCount {
|
class EXPCL_PANDA_PGRAPH Light {
|
||||||
// We inherit from ReferenceCount instead of TypedReferenceCount so
|
|
||||||
// that LightNode does not inherit from TypedObject twice. Note
|
|
||||||
// that we also inherit virtually from ReferenceCount for the same
|
|
||||||
// reason.
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE Light();
|
INLINE Light();
|
||||||
INLINE Light(const Light ©);
|
INLINE Light(const Light ©);
|
||||||
@ -66,7 +62,7 @@ public:
|
|||||||
int light_id)=0;
|
int light_id)=0;
|
||||||
|
|
||||||
virtual bool get_vector_to_light(LVector3 &result,
|
virtual bool get_vector_to_light(LVector3 &result,
|
||||||
const LPoint3 &from_object_point,
|
const LPoint3 &from_object_point,
|
||||||
const LMatrix4 &to_object_space);
|
const LMatrix4 &to_object_space);
|
||||||
|
|
||||||
GeomNode *get_viz();
|
GeomNode *get_viz();
|
||||||
@ -76,7 +72,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void fill_viz_geom(GeomNode *viz_geom);
|
virtual void fill_viz_geom(GeomNode *viz_geom);
|
||||||
INLINE void mark_viz_stale();
|
INLINE void mark_viz_stale();
|
||||||
|
|
||||||
// This enumerated class defines the relative class priority of
|
// This enumerated class defines the relative class priority of
|
||||||
// different kinds of lights. This hierarchy is only used to
|
// different kinds of lights. This hierarchy is only used to
|
||||||
// resolve multiple lights of the same priority specified by
|
// resolve multiple lights of the same priority specified by
|
||||||
@ -135,7 +131,7 @@ public:
|
|||||||
virtual TypeHandle get_type() const {
|
virtual TypeHandle get_type() const {
|
||||||
return get_class_type();
|
return get_class_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static TypeHandle _type_handle;
|
static TypeHandle _type_handle;
|
||||||
};
|
};
|
||||||
|
@ -142,8 +142,7 @@ PandaNode::
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PandaNode::
|
PandaNode::
|
||||||
PandaNode(const PandaNode ©) :
|
PandaNode(const PandaNode ©) :
|
||||||
ReferenceCount(copy),
|
TypedWritableReferenceCount(copy),
|
||||||
TypedWritable(copy),
|
|
||||||
Namable(copy),
|
Namable(copy),
|
||||||
_paths_lock("PandaNode::_paths_lock"),
|
_paths_lock("PandaNode::_paths_lock"),
|
||||||
_dirty_prev_transform(false)
|
_dirty_prev_transform(false)
|
||||||
@ -209,17 +208,6 @@ operator = (const PandaNode ©) {
|
|||||||
nassertv(false);
|
nassertv(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: PandaNode::as_reference_count
|
|
||||||
// Access: Public, Virtual
|
|
||||||
// Description: Returns the pointer cast to a ReferenceCount pointer,
|
|
||||||
// if it is in fact of that type.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
ReferenceCount *PandaNode::
|
|
||||||
as_reference_count() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PandaNode::dupe_for_flatten
|
// Function: PandaNode::dupe_for_flatten
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
|
@ -69,9 +69,8 @@ class GraphicsStateGuardianBase;
|
|||||||
// is the base class of all specialized nodes, and also
|
// is the base class of all specialized nodes, and also
|
||||||
// serves as a generic node with no special properties.
|
// serves as a generic node with no special properties.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA_PGRAPH PandaNode : public TypedWritable, public Namable,
|
class EXPCL_PANDA_PGRAPH PandaNode : public TypedWritableReferenceCount,
|
||||||
public LinkedListNode,
|
public Namable, public LinkedListNode {
|
||||||
virtual public ReferenceCount {
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
PandaNode(const string &name);
|
PandaNode(const string &name);
|
||||||
virtual ~PandaNode();
|
virtual ~PandaNode();
|
||||||
@ -84,7 +83,6 @@ private:
|
|||||||
void operator = (const PandaNode ©);
|
void operator = (const PandaNode ©);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ReferenceCount *as_reference_count();
|
|
||||||
virtual PandaNode *dupe_for_flatten() const;
|
virtual PandaNode *dupe_for_flatten() const;
|
||||||
|
|
||||||
virtual bool safe_to_flatten() const;
|
virtual bool safe_to_flatten() const;
|
||||||
|
@ -26,14 +26,16 @@ TypeHandle MouseRecorder::_type_handle;
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
MouseRecorder::
|
MouseRecorder::
|
||||||
MouseRecorder(const string &name) :
|
MouseRecorder(const string &name) :
|
||||||
DataNode(name)
|
DataNode(name)
|
||||||
{
|
{
|
||||||
_pixel_xy_input = define_input("pixel_xy", EventStoreVec2::get_class_type());
|
_pixel_xy_input = define_input("pixel_xy", EventStoreVec2::get_class_type());
|
||||||
|
_pixel_size_input = define_input("pixel_size", EventStoreVec2::get_class_type());
|
||||||
_xy_input = define_input("xy", EventStoreVec2::get_class_type());
|
_xy_input = define_input("xy", EventStoreVec2::get_class_type());
|
||||||
_button_events_input = define_input("button_events", ButtonEventList::get_class_type());
|
_button_events_input = define_input("button_events", ButtonEventList::get_class_type());
|
||||||
|
|
||||||
_pixel_xy_output = define_output("pixel_xy", EventStoreVec2::get_class_type());
|
_pixel_xy_output = define_output("pixel_xy", EventStoreVec2::get_class_type());
|
||||||
|
_pixel_size_output = define_output("pixel_size", EventStoreVec2::get_class_type());
|
||||||
_xy_output = define_output("xy", EventStoreVec2::get_class_type());
|
_xy_output = define_output("xy", EventStoreVec2::get_class_type());
|
||||||
_button_events_output = define_output("button_events", ButtonEventList::get_class_type());
|
_button_events_output = define_output("button_events", ButtonEventList::get_class_type());
|
||||||
|
|
||||||
@ -127,7 +129,7 @@ write(ostream &out, int indent_level) const {
|
|||||||
// calls.
|
// calls.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MouseRecorder::
|
void MouseRecorder::
|
||||||
do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
|
do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
|
||||||
DataNodeTransmit &output) {
|
DataNodeTransmit &output) {
|
||||||
bool has_mouse = false;
|
bool has_mouse = false;
|
||||||
LPoint2 mouse_xy;
|
LPoint2 mouse_xy;
|
||||||
@ -157,7 +159,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
|
|||||||
mouse_pixel_xy = xy->get_value();
|
mouse_pixel_xy = xy->get_value();
|
||||||
has_mouse = true;
|
has_mouse = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for button events.
|
// Look for button events.
|
||||||
if (input.has_data(_button_events_input)) {
|
if (input.has_data(_button_events_input)) {
|
||||||
const ButtonEventList *button_events;
|
const ButtonEventList *button_events;
|
||||||
@ -165,7 +167,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
|
|||||||
_live_button_events->add_events(*button_events);
|
_live_button_events->add_events(*button_events);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now rebuild the output data for our children.
|
// Now rebuild the output data for our children.
|
||||||
|
|
||||||
if (has_mouse) {
|
if (has_mouse) {
|
||||||
@ -187,8 +189,10 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
|
|||||||
_mouse_pixel_xy = mouse_pixel_xy;
|
_mouse_pixel_xy = mouse_pixel_xy;
|
||||||
_save_button_events->add_events(*_live_button_events);
|
_save_button_events->add_events(*_live_button_events);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
// We always pass the pixel_size data through.
|
||||||
|
output.set_data(_pixel_size_output, input.get_data(_pixel_size_input));
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: MouseRecorder::register_with_read_factory
|
// Function: MouseRecorder::register_with_read_factory
|
||||||
|
@ -57,11 +57,13 @@ protected:
|
|||||||
private:
|
private:
|
||||||
// inputs
|
// inputs
|
||||||
int _pixel_xy_input;
|
int _pixel_xy_input;
|
||||||
|
int _pixel_size_input;
|
||||||
int _xy_input;
|
int _xy_input;
|
||||||
int _button_events_input;
|
int _button_events_input;
|
||||||
|
|
||||||
// outputs
|
// outputs
|
||||||
int _pixel_xy_output;
|
int _pixel_xy_output;
|
||||||
|
int _pixel_size_output;
|
||||||
int _xy_output;
|
int _xy_output;
|
||||||
int _button_events_output;
|
int _button_events_output;
|
||||||
|
|
||||||
@ -79,6 +81,9 @@ public:
|
|||||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||||
virtual void write_recorder(BamWriter *manager, Datagram &dg);
|
virtual void write_recorder(BamWriter *manager, Datagram &dg);
|
||||||
|
|
||||||
|
INLINE virtual void ref() const FINAL { ReferenceCount::ref(); };
|
||||||
|
INLINE virtual bool unref() const FINAL { return ReferenceCount::unref(); };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||||
static RecorderBase *make_recorder(const FactoryParams ¶ms);
|
static RecorderBase *make_recorder(const FactoryParams ¶ms);
|
||||||
@ -106,4 +111,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -46,8 +46,13 @@ class TypedWritable;
|
|||||||
// write_recorder() to do exactly the same thing as
|
// write_recorder() to do exactly the same thing as
|
||||||
// write_datagram(), or they may choose to write
|
// write_datagram(), or they may choose to write
|
||||||
// something slightly different.
|
// something slightly different.
|
||||||
|
//
|
||||||
|
// Most types of recorders should derive from Recorder,
|
||||||
|
// as it derives from ReferenceCount, except for
|
||||||
|
// MouseRecorder, which would otherwise doubly inherit
|
||||||
|
// from ReferenceCount.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA_RECORDER RecorderBase : virtual public ReferenceCount {
|
class EXPCL_PANDA_RECORDER RecorderBase {
|
||||||
protected:
|
protected:
|
||||||
RecorderBase();
|
RecorderBase();
|
||||||
|
|
||||||
@ -63,6 +68,11 @@ public:
|
|||||||
|
|
||||||
virtual void write_recorder(BamWriter *manager, Datagram &dg);
|
virtual void write_recorder(BamWriter *manager, Datagram &dg);
|
||||||
|
|
||||||
|
// We can't let RecorderBase inherit from ReferenceCount, so we
|
||||||
|
// define these so we can still manage the reference count.
|
||||||
|
virtual void ref() const=0;
|
||||||
|
virtual bool unref() const=0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void fillin_recorder(DatagramIterator &scan, BamReader *manager);
|
void fillin_recorder(DatagramIterator &scan, BamReader *manager);
|
||||||
|
|
||||||
@ -72,7 +82,7 @@ private:
|
|||||||
F_playing = 0x0002,
|
F_playing = 0x0002,
|
||||||
};
|
};
|
||||||
short _flags;
|
short _flags;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
return _type_handle;
|
return _type_handle;
|
||||||
@ -90,9 +100,9 @@ private:
|
|||||||
static TypeHandle _type_handle;
|
static TypeHandle _type_handle;
|
||||||
|
|
||||||
friend class RecorderController;
|
friend class RecorderController;
|
||||||
|
friend class RecorderTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "recorderBase.I"
|
#include "recorderBase.I"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -93,17 +93,11 @@ begin_record(const Filename &filename) {
|
|||||||
_user_table_modified = true;
|
_user_table_modified = true;
|
||||||
|
|
||||||
// Tell all of our recorders that they're live now.
|
// Tell all of our recorders that they're live now.
|
||||||
RecorderTable::Recorders::iterator ri;
|
_user_table->set_flags(RecorderBase::F_recording);
|
||||||
for (ri = _user_table->_recorders.begin();
|
|
||||||
ri != _user_table->_recorders.end();
|
|
||||||
++ri) {
|
|
||||||
RecorderBase *recorder = (*ri).second;
|
|
||||||
recorder->_flags |= RecorderBase::F_recording;
|
|
||||||
}
|
|
||||||
|
|
||||||
recorder_cat.info()
|
recorder_cat.info()
|
||||||
<< "Recording session to " << _filename << "\n";
|
<< "Recording session to " << _filename << "\n";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +144,7 @@ begin_playback(const Filename &filename) {
|
|||||||
// Start out by reading the RecorderHeader.
|
// Start out by reading the RecorderHeader.
|
||||||
TypedWritable *object = _reader->read_object();
|
TypedWritable *object = _reader->read_object();
|
||||||
|
|
||||||
if (object == (TypedWritable *)NULL ||
|
if (object == (TypedWritable *)NULL ||
|
||||||
!object->is_of_type(RecorderHeader::get_class_type())) {
|
!object->is_of_type(RecorderHeader::get_class_type())) {
|
||||||
recorder_cat.error()
|
recorder_cat.error()
|
||||||
<< _filename << " does not contain a recorded session.\n";
|
<< _filename << " does not contain a recorded session.\n";
|
||||||
@ -176,7 +170,7 @@ begin_playback(const Filename &filename) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
recorder_cat.info()
|
recorder_cat.info()
|
||||||
<< "Playing back session from " << _filename << "\n";
|
<< "Playing back session from " << _filename << "\n";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -194,26 +188,14 @@ close() {
|
|||||||
_writer = NULL;
|
_writer = NULL;
|
||||||
|
|
||||||
// Tell all of our recorders that they're no longer recording.
|
// Tell all of our recorders that they're no longer recording.
|
||||||
RecorderTable::Recorders::iterator ri;
|
_user_table->clear_flags(RecorderBase::F_recording);
|
||||||
for (ri = _user_table->_recorders.begin();
|
|
||||||
ri != _user_table->_recorders.end();
|
|
||||||
++ri) {
|
|
||||||
RecorderBase *recorder = (*ri).second;
|
|
||||||
recorder->_flags &= ~RecorderBase::F_recording;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (_reader != (BamReader *)NULL) {
|
if (_reader != (BamReader *)NULL) {
|
||||||
delete _reader;
|
delete _reader;
|
||||||
_reader = NULL;
|
_reader = NULL;
|
||||||
|
|
||||||
// Tell all of our recorders that they're no longer playing.
|
// Tell all of our recorders that they're no longer playing.
|
||||||
RecorderTable::Recorders::iterator ri;
|
_active_table->clear_flags(RecorderBase::F_playing);
|
||||||
for (ri = _active_table->_recorders.begin();
|
|
||||||
ri != _active_table->_recorders.end();
|
|
||||||
++ri) {
|
|
||||||
RecorderBase *recorder = (*ri).second;
|
|
||||||
recorder->_flags &= ~RecorderBase::F_playing;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_dout.close();
|
_dout.close();
|
||||||
_din.close();
|
_din.close();
|
||||||
@ -244,7 +226,7 @@ record_frame() {
|
|||||||
|
|
||||||
RecorderFrame data(now, frame, _user_table_modified, _user_table);
|
RecorderFrame data(now, frame, _user_table_modified, _user_table);
|
||||||
_user_table_modified = false;
|
_user_table_modified = false;
|
||||||
|
|
||||||
_writer->write_object(&data);
|
_writer->write_object(&data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -300,27 +282,15 @@ play_frame() {
|
|||||||
if (_next_frame->_table_changed || _user_table_modified) {
|
if (_next_frame->_table_changed || _user_table_modified) {
|
||||||
// We're about to change the active table. Temporarily
|
// We're about to change the active table. Temporarily
|
||||||
// disable the playing flag on the currently-active recorders.
|
// disable the playing flag on the currently-active recorders.
|
||||||
RecorderTable::Recorders::iterator ri;
|
_active_table->clear_flags(RecorderBase::F_playing);
|
||||||
for (ri = _active_table->_recorders.begin();
|
|
||||||
ri != _active_table->_recorders.end();
|
|
||||||
++ri) {
|
|
||||||
RecorderBase *recorder = (*ri).second;
|
|
||||||
recorder->_flags &= ~RecorderBase::F_playing;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete _active_table;
|
delete _active_table;
|
||||||
_active_table = new RecorderTable(*_file_table);
|
_active_table = new RecorderTable(*_file_table);
|
||||||
_active_table->merge_from(*_user_table);
|
_active_table->merge_from(*_user_table);
|
||||||
_user_table_modified = false;
|
_user_table_modified = false;
|
||||||
|
|
||||||
// Now reenable the playing flag on the newly-active
|
// Now reenable the playing flag on the newly-active
|
||||||
// recorders.
|
// recorders.
|
||||||
for (ri = _active_table->_recorders.begin();
|
_active_table->set_flags(RecorderBase::F_playing);
|
||||||
ri != _active_table->_recorders.end();
|
|
||||||
++ri) {
|
|
||||||
RecorderBase *recorder = (*ri).second;
|
|
||||||
recorder->_flags |= RecorderBase::F_playing;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_next_frame->_table = _active_table;
|
_next_frame->_table = _active_table;
|
||||||
@ -353,7 +323,7 @@ RecorderFrame *RecorderController::
|
|||||||
read_frame() {
|
read_frame() {
|
||||||
TypedWritable *object = _reader->read_object();
|
TypedWritable *object = _reader->read_object();
|
||||||
|
|
||||||
if (object == (TypedWritable *)NULL ||
|
if (object == (TypedWritable *)NULL ||
|
||||||
!object->is_of_type(RecorderFrame::get_class_type())) {
|
!object->is_of_type(RecorderFrame::get_class_type())) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -30,14 +30,7 @@ TypeHandle RecorderFrame::_type_handle;
|
|||||||
void RecorderFrame::
|
void RecorderFrame::
|
||||||
play_frame(BamReader *manager) {
|
play_frame(BamReader *manager) {
|
||||||
DatagramIterator scan(_data, _data_pos);
|
DatagramIterator scan(_data, _data_pos);
|
||||||
|
_table->play_frame(scan, manager);
|
||||||
RecorderTable::Recorders::iterator ri;
|
|
||||||
for (ri = _table->_recorders.begin();
|
|
||||||
ri != _table->_recorders.end();
|
|
||||||
++ri) {
|
|
||||||
RecorderBase *recorder = (*ri).second;
|
|
||||||
recorder->play_frame(scan, manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We expect to use up all of the data in the datagram.
|
// We expect to use up all of the data in the datagram.
|
||||||
nassertv(scan.get_remaining_size() == 0);
|
nassertv(scan.get_remaining_size() == 0);
|
||||||
@ -77,14 +70,8 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
|||||||
_local_table = *_table;
|
_local_table = *_table;
|
||||||
manager->write_pointer(dg, &_local_table);
|
manager->write_pointer(dg, &_local_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecorderTable::Recorders::iterator ri;
|
_table->record_frame(manager, dg);
|
||||||
for (ri = _table->_recorders.begin();
|
|
||||||
ri != _table->_recorders.end();
|
|
||||||
++ri) {
|
|
||||||
RecorderBase *recorder = (*ri).second;
|
|
||||||
recorder->record_frame(manager, dg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -29,10 +29,8 @@ RecorderTable() {
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE RecorderTable::
|
INLINE RecorderTable::
|
||||||
RecorderTable(const RecorderTable ©) :
|
RecorderTable(const RecorderTable ©) {
|
||||||
_recorders(copy._recorders),
|
*this = copy;
|
||||||
_error(copy._error)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -44,13 +42,62 @@ INLINE void RecorderTable::
|
|||||||
operator = (const RecorderTable ©) {
|
operator = (const RecorderTable ©) {
|
||||||
_recorders = copy._recorders;
|
_recorders = copy._recorders;
|
||||||
_error = copy._error;
|
_error = copy._error;
|
||||||
|
|
||||||
|
Recorders::iterator ri;
|
||||||
|
for (ri = _recorders.begin(); ri != _recorders.end(); ++ri) {
|
||||||
|
ri->second->ref();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: RecorderTable::Destructor
|
// Function: RecorderTable::add_recorder
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description:
|
// Description: Adds the named recorder to the set of recorders.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE RecorderTable::
|
INLINE void RecorderTable::
|
||||||
~RecorderTable() {
|
add_recorder(const string &name, RecorderBase *recorder) {
|
||||||
|
nassertv(recorder != (RecorderBase *)NULL);
|
||||||
|
recorder->ref();
|
||||||
|
|
||||||
|
std::pair<Recorders::iterator, bool> result =
|
||||||
|
_recorders.insert(Recorders::value_type(name, recorder));
|
||||||
|
|
||||||
|
if (!result.second) {
|
||||||
|
// Take out the previous one first.
|
||||||
|
unref_delete(result.first->second);
|
||||||
|
result.first->second = recorder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: RecorderTable::get_recorder
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the recorder with the indicated name, or NULL
|
||||||
|
// if there is no such recorder.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE RecorderBase *RecorderTable::
|
||||||
|
get_recorder(const string &name) const {
|
||||||
|
Recorders::const_iterator ri = _recorders.find(name);
|
||||||
|
if (ri != _recorders.end()) {
|
||||||
|
return (*ri).second;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: RecorderTable::remove_recorder
|
||||||
|
// Access: Published
|
||||||
|
// Description: Removes the named recorder from the table. Returns
|
||||||
|
// true if successful, false if there was no such
|
||||||
|
// recorder.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool RecorderTable::
|
||||||
|
remove_recorder(const string &name) {
|
||||||
|
Recorders::iterator ri = _recorders.find(name);
|
||||||
|
if (ri != _recorders.end()) {
|
||||||
|
unref_delete(ri->second);
|
||||||
|
_recorders.erase(ri);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,19 @@
|
|||||||
|
|
||||||
TypeHandle RecorderTable::_type_handle;
|
TypeHandle RecorderTable::_type_handle;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: RecorderTable::Destructor
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
RecorderTable::
|
||||||
|
~RecorderTable() {
|
||||||
|
Recorders::iterator ri;
|
||||||
|
for (ri = _recorders.begin(); ri != _recorders.end(); ++ri) {
|
||||||
|
unref_delete(ri->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: RecorderTable::merge_from
|
// Function: RecorderTable::merge_from
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -47,12 +60,16 @@ merge_from(const RecorderTable &other) {
|
|||||||
} else if ((*ri).second->get_type() == recorder->get_type()) {
|
} else if ((*ri).second->get_type() == recorder->get_type()) {
|
||||||
// If we already had a recorder by that name with the same type,
|
// If we already had a recorder by that name with the same type,
|
||||||
// throw it away (otherwise, keep the one we had before).
|
// throw it away (otherwise, keep the one we had before).
|
||||||
(*ri).second = recorder;
|
if ((*ri).second != recorder) {
|
||||||
|
recorder->ref();
|
||||||
|
unref_delete((*ri).second);
|
||||||
|
(*ri).second = recorder;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
recorder_cat.warning()
|
recorder_cat.warning()
|
||||||
<< "Keeping recorder " << name << " of type "
|
<< "Keeping recorder " << name << " of type "
|
||||||
<< (*ri).second->get_type() << " instead of recorder of type "
|
<< (*ri).second->get_type() << " instead of recorder of type "
|
||||||
<< recorder->get_type() << "\n";
|
<< recorder->get_type() << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,51 +88,73 @@ merge_from(const RecorderTable &other) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: RecorderTable::add_recorder
|
// Function: RecorderTable::record_frame
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Adds the named recorder to the set of recorders.
|
// Description: Calls record_frame on all recorders.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void RecorderTable::
|
void RecorderTable::
|
||||||
add_recorder(const string &name, RecorderBase *recorder) {
|
record_frame(BamWriter *manager, Datagram &dg) {
|
||||||
_recorders[name] = recorder;
|
Recorders::iterator ri;
|
||||||
|
for (ri = _recorders.begin();
|
||||||
|
ri != _recorders.end();
|
||||||
|
++ri) {
|
||||||
|
RecorderBase *recorder = (*ri).second;
|
||||||
|
recorder->record_frame(manager, dg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: RecorderTable::get_recorder
|
// Function: RecorderTable::play_frame
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Returns the recorder with the indicated name, or NULL
|
// Description: Calls play_frame on all recorders.
|
||||||
// if there is no such recorder.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
RecorderBase *RecorderTable::
|
void RecorderTable::
|
||||||
get_recorder(const string &name) const {
|
play_frame(DatagramIterator &scan, BamReader *manager) {
|
||||||
Recorders::const_iterator ri = _recorders.find(name);
|
Recorders::iterator ri;
|
||||||
if (ri != _recorders.end()) {
|
for (ri = _recorders.begin();
|
||||||
return (*ri).second;
|
ri != _recorders.end();
|
||||||
|
++ri) {
|
||||||
|
RecorderBase *recorder = (*ri).second;
|
||||||
|
recorder->play_frame(scan, manager);
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: RecorderTable::remove_recorder
|
// Function: RecorderTable::set_flags
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Removes the named recorder from the table. Returns
|
// Description: Sets the given flags on all recorders.
|
||||||
// true if successful, false if there was no such
|
|
||||||
// recorder.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool RecorderTable::
|
void RecorderTable::
|
||||||
remove_recorder(const string &name) {
|
set_flags(short flags) {
|
||||||
Recorders::iterator ri = _recorders.find(name);
|
Recorders::iterator ri;
|
||||||
if (ri != _recorders.end()) {
|
for (ri = _recorders.begin();
|
||||||
_recorders.erase(ri);
|
ri != _recorders.end();
|
||||||
return true;
|
++ri) {
|
||||||
|
RecorderBase *recorder = (*ri).second;
|
||||||
|
recorder->_flags |= flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: RecorderTable::clear_flags
|
||||||
|
// Access: Published
|
||||||
|
// Description: Clears the given flags on all recorders.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void RecorderTable::
|
||||||
|
clear_flags(short flags) {
|
||||||
|
Recorders::iterator ri;
|
||||||
|
for (ri = _recorders.begin();
|
||||||
|
ri != _recorders.end();
|
||||||
|
++ri) {
|
||||||
|
RecorderBase *recorder = (*ri).second;
|
||||||
|
recorder->_flags &= ~flags;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: RecorderTable::write
|
// Function: RecorderTable::write
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void RecorderTable::
|
void RecorderTable::
|
||||||
write(ostream &out, int indent_level) const {
|
write(ostream &out, int indent_level) const {
|
||||||
@ -203,7 +242,7 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||||||
FactoryParams fparams;
|
FactoryParams fparams;
|
||||||
fparams.add_param(new BamReaderParam(scan, manager));
|
fparams.add_param(new BamReaderParam(scan, manager));
|
||||||
|
|
||||||
PT(RecorderBase) recorder =
|
RecorderBase *recorder =
|
||||||
RecorderController::get_factory()->make_instance_more_general(type, fparams);
|
RecorderController::get_factory()->make_instance_more_general(type, fparams);
|
||||||
if (recorder == (RecorderBase *)NULL) {
|
if (recorder == (RecorderBase *)NULL) {
|
||||||
recorder_cat.error()
|
recorder_cat.error()
|
||||||
@ -211,6 +250,7 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||||||
_error = true;
|
_error = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
recorder->ref();
|
||||||
bool inserted =
|
bool inserted =
|
||||||
_recorders.insert(Recorders::value_type(name, recorder)).second;
|
_recorders.insert(Recorders::value_type(name, recorder)).second;
|
||||||
nassertv(inserted);
|
nassertv(inserted);
|
||||||
|
@ -37,18 +37,25 @@ public:
|
|||||||
INLINE RecorderTable();
|
INLINE RecorderTable();
|
||||||
INLINE RecorderTable(const RecorderTable ©);
|
INLINE RecorderTable(const RecorderTable ©);
|
||||||
INLINE void operator = (const RecorderTable ©);
|
INLINE void operator = (const RecorderTable ©);
|
||||||
INLINE ~RecorderTable();
|
~RecorderTable();
|
||||||
|
|
||||||
void merge_from(const RecorderTable &other);
|
void merge_from(const RecorderTable &other);
|
||||||
|
|
||||||
void add_recorder(const string &name, RecorderBase *recorder);
|
INLINE void add_recorder(const string &name, RecorderBase *recorder);
|
||||||
RecorderBase *get_recorder(const string &name) const;
|
INLINE RecorderBase *get_recorder(const string &name) const;
|
||||||
bool remove_recorder(const string &name);
|
INLINE bool remove_recorder(const string &name);
|
||||||
|
|
||||||
|
void record_frame(BamWriter *manager, Datagram &dg);
|
||||||
|
void play_frame(DatagramIterator &scan, BamReader *manager);
|
||||||
|
void set_flags(short flags);
|
||||||
|
void clear_flags(short flags);
|
||||||
|
|
||||||
void write(ostream &out, int indent_level) const;
|
void write(ostream &out, int indent_level) const;
|
||||||
|
|
||||||
|
// RecorderBase itself doesn't inherit from ReferenceCount, so
|
||||||
typedef pmap<string, PT(RecorderBase) > Recorders;
|
// we can't put a PT() around it. Instead, we manage the reference
|
||||||
|
// count using calls to ref() and unref().
|
||||||
|
typedef pmap<string, RecorderBase*> Recorders;
|
||||||
Recorders _recorders;
|
Recorders _recorders;
|
||||||
|
|
||||||
bool _error;
|
bool _error;
|
||||||
@ -60,7 +67,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
return _type_handle;
|
return _type_handle;
|
||||||
|
@ -42,7 +42,8 @@ class DatagramIterator;
|
|||||||
// straight through to the socket if it is connected, or
|
// straight through to the socket if it is connected, or
|
||||||
// silently ignored if it is not.
|
// silently ignored if it is not.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA_RECORDER SocketStreamRecorder : public RecorderBase {
|
class EXPCL_PANDA_RECORDER SocketStreamRecorder : public RecorderBase,
|
||||||
|
public ReferenceCount {
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE SocketStreamRecorder();
|
INLINE SocketStreamRecorder();
|
||||||
INLINE SocketStreamRecorder(SocketStream *stream, bool owns_stream);
|
INLINE SocketStreamRecorder(SocketStream *stream, bool owns_stream);
|
||||||
@ -78,6 +79,9 @@ public:
|
|||||||
static void register_with_read_factory();
|
static void register_with_read_factory();
|
||||||
virtual void write_recorder(BamWriter *manager, Datagram &dg);
|
virtual void write_recorder(BamWriter *manager, Datagram &dg);
|
||||||
|
|
||||||
|
INLINE virtual void ref() const FINAL { ReferenceCount::ref(); };
|
||||||
|
INLINE virtual bool unref() const FINAL { return ReferenceCount::unref(); };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static RecorderBase *make_recorder(const FactoryParams ¶ms);
|
static RecorderBase *make_recorder(const FactoryParams ¶ms);
|
||||||
void fillin_recorder(DatagramIterator &scan, BamReader *manager);
|
void fillin_recorder(DatagramIterator &scan, BamReader *manager);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
p3grutil p3dgraph p3pgraph p3linmath p3display p3event p3putil p3gobj p3gsgbase \
|
p3grutil p3dgraph p3pgraph p3linmath p3display p3event p3putil p3gobj p3gsgbase \
|
||||||
p3mathutil p3device
|
p3mathutil p3device
|
||||||
|
|
||||||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
|
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
|
||||||
|
|
||||||
#define SOURCES \
|
#define SOURCES \
|
||||||
buttonThrower.I buttonThrower.h \
|
buttonThrower.I buttonThrower.h \
|
||||||
@ -16,12 +16,12 @@
|
|||||||
mouseInterfaceNode.I mouseInterfaceNode.h \
|
mouseInterfaceNode.I mouseInterfaceNode.h \
|
||||||
mouseSubregion.I mouseSubregion.h \
|
mouseSubregion.I mouseSubregion.h \
|
||||||
mouseWatcher.I mouseWatcher.h \
|
mouseWatcher.I mouseWatcher.h \
|
||||||
mouseWatcherGroup.h \
|
mouseWatcherBase.h mouseWatcherGroup.h \
|
||||||
mouseWatcherParameter.I mouseWatcherParameter.h \
|
mouseWatcherParameter.I mouseWatcherParameter.h \
|
||||||
mouseWatcherRegion.I mouseWatcherRegion.h \
|
mouseWatcherRegion.I mouseWatcherRegion.h \
|
||||||
trackball.h \
|
trackball.h \
|
||||||
transform2sg.h
|
transform2sg.h
|
||||||
|
|
||||||
#define INCLUDED_SOURCES \
|
#define INCLUDED_SOURCES \
|
||||||
buttonThrower.cxx \
|
buttonThrower.cxx \
|
||||||
config_tform.cxx \
|
config_tform.cxx \
|
||||||
@ -29,10 +29,12 @@
|
|||||||
mouseInterfaceNode.cxx \
|
mouseInterfaceNode.cxx \
|
||||||
mouseSubregion.cxx \
|
mouseSubregion.cxx \
|
||||||
mouseWatcher.cxx \
|
mouseWatcher.cxx \
|
||||||
|
mouseWatcherBase.cxx \
|
||||||
mouseWatcherGroup.cxx \
|
mouseWatcherGroup.cxx \
|
||||||
mouseWatcherParameter.cxx mouseWatcherRegion.cxx \
|
mouseWatcherParameter.cxx
|
||||||
|
mouseWatcherRegion.cxx \
|
||||||
trackball.cxx \
|
trackball.cxx \
|
||||||
transform2sg.cxx
|
transform2sg.cxx
|
||||||
|
|
||||||
#define INSTALL_HEADERS \
|
#define INSTALL_HEADERS \
|
||||||
buttonThrower.I buttonThrower.h \
|
buttonThrower.I buttonThrower.h \
|
||||||
@ -40,7 +42,7 @@
|
|||||||
mouseInterfaceNode.I mouseInterfaceNode.h \
|
mouseInterfaceNode.I mouseInterfaceNode.h \
|
||||||
mouseSubregion.I mouseSubregion.h \
|
mouseSubregion.I mouseSubregion.h \
|
||||||
mouseWatcher.I mouseWatcher.h \
|
mouseWatcher.I mouseWatcher.h \
|
||||||
mouseWatcherGroup.h \
|
mouseWatcherBase.h mouseWatcherGroup.h \
|
||||||
mouseWatcherParameter.I mouseWatcherParameter.h \
|
mouseWatcherParameter.I mouseWatcherParameter.h \
|
||||||
mouseWatcherRegion.I mouseWatcherRegion.h \
|
mouseWatcherRegion.I mouseWatcherRegion.h \
|
||||||
trackball.h \
|
trackball.h \
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "buttonThrower.h"
|
#include "buttonThrower.h"
|
||||||
#include "mouseSubregion.h"
|
#include "mouseSubregion.h"
|
||||||
#include "mouseWatcher.h"
|
#include "mouseWatcher.h"
|
||||||
|
#include "mouseWatcherBase.h"
|
||||||
#include "mouseWatcherGroup.h"
|
#include "mouseWatcherGroup.h"
|
||||||
#include "mouseWatcherRegion.h"
|
#include "mouseWatcherRegion.h"
|
||||||
#include "trackball.h"
|
#include "trackball.h"
|
||||||
@ -67,6 +68,7 @@ ConfigureFn(config_tform) {
|
|||||||
MouseInterfaceNode::init_type();
|
MouseInterfaceNode::init_type();
|
||||||
MouseSubregion::init_type();
|
MouseSubregion::init_type();
|
||||||
MouseWatcher::init_type();
|
MouseWatcher::init_type();
|
||||||
|
MouseWatcherBase::init_type();
|
||||||
MouseWatcherGroup::init_type();
|
MouseWatcherGroup::init_type();
|
||||||
MouseWatcherRegion::init_type();
|
MouseWatcherRegion::init_type();
|
||||||
Trackball::init_type();
|
Trackball::init_type();
|
||||||
|
@ -44,7 +44,7 @@ TypeHandle MouseWatcher::_type_handle;
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
MouseWatcher::
|
MouseWatcher::
|
||||||
MouseWatcher(const string &name) :
|
MouseWatcher(const string &name) :
|
||||||
DataNode(name)
|
DataNode(name)
|
||||||
{
|
{
|
||||||
_pixel_xy_input = define_input("pixel_xy", EventStoreVec2::get_class_type());
|
_pixel_xy_input = define_input("pixel_xy", EventStoreVec2::get_class_type());
|
||||||
@ -73,24 +73,24 @@ MouseWatcher(const string &name) :
|
|||||||
_button_down_display_region = (DisplayRegion *)NULL;
|
_button_down_display_region = (DisplayRegion *)NULL;
|
||||||
|
|
||||||
_frame.set(-1.0f, 1.0f, -1.0f, 1.0f);
|
_frame.set(-1.0f, 1.0f, -1.0f, 1.0f);
|
||||||
|
|
||||||
_inactivity_timeout = inactivity_timeout;
|
_inactivity_timeout = inactivity_timeout;
|
||||||
_has_inactivity_timeout = !IS_NEARLY_ZERO(_inactivity_timeout);
|
_has_inactivity_timeout = !IS_NEARLY_ZERO(_inactivity_timeout);
|
||||||
|
|
||||||
_num_trail_recent = 0;
|
_num_trail_recent = 0;
|
||||||
_trail_log_duration = 0.0;
|
_trail_log_duration = 0.0;
|
||||||
_trail_log = new PointerEventList();
|
_trail_log = new PointerEventList();
|
||||||
|
|
||||||
_inactivity_timeout_event = "inactivity_timeout";
|
_inactivity_timeout_event = "inactivity_timeout";
|
||||||
_last_activity = 0.0;
|
_last_activity = 0.0;
|
||||||
_inactivity_state = IS_active;
|
_inactivity_state = IS_active;
|
||||||
|
|
||||||
// When this flag is true, the mouse pointer is allowed to be
|
// When this flag is true, the mouse pointer is allowed to be
|
||||||
// "entered" into multiple regions simultaneously; when false, it
|
// "entered" into multiple regions simultaneously; when false, it
|
||||||
// will only be "within" multiple regions, but "entered" into the
|
// will only be "within" multiple regions, but "entered" into the
|
||||||
// topmost of those.
|
// topmost of those.
|
||||||
_enter_multiple = false;
|
_enter_multiple = false;
|
||||||
|
|
||||||
// When this flag is true, moving the pointer into a region is
|
// When this flag is true, moving the pointer into a region is
|
||||||
// enough to click it. The click is simulated with mouse button
|
// enough to click it. The click is simulated with mouse button
|
||||||
// one.
|
// one.
|
||||||
@ -128,7 +128,7 @@ remove_region(MouseWatcherRegion *region) {
|
|||||||
_preferred_button_down_region = (MouseWatcherRegion *)NULL;
|
_preferred_button_down_region = (MouseWatcherRegion *)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MouseWatcherGroup::do_remove_region(region);
|
return MouseWatcherBase::do_remove_region(region);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -156,7 +156,7 @@ get_over_region(const LPoint2 &pos) const {
|
|||||||
// regions the MouseWatcher will monitor each frame.
|
// regions the MouseWatcher will monitor each frame.
|
||||||
//
|
//
|
||||||
// Since the MouseWatcher itself inherits from
|
// Since the MouseWatcher itself inherits from
|
||||||
// MouseWatcherGroup, this operation is normally not
|
// MouseWatcherBase, this operation is normally not
|
||||||
// necessary--you can simply add the Regions you care
|
// necessary--you can simply add the Regions you care
|
||||||
// about one at a time. Adding a complete group is
|
// about one at a time. Adding a complete group is
|
||||||
// useful when you may want to explicitly remove the
|
// useful when you may want to explicitly remove the
|
||||||
@ -171,7 +171,7 @@ add_group(MouseWatcherGroup *group) {
|
|||||||
|
|
||||||
// See if the group is in the set/vector already
|
// See if the group is in the set/vector already
|
||||||
PT(MouseWatcherGroup) pt = group;
|
PT(MouseWatcherGroup) pt = group;
|
||||||
Groups::const_iterator gi =
|
Groups::const_iterator gi =
|
||||||
find(_groups.begin(), _groups.end(), pt);
|
find(_groups.begin(), _groups.end(), pt);
|
||||||
if (gi != _groups.end()) {
|
if (gi != _groups.end()) {
|
||||||
// Already in the set, return false
|
// Already in the set, return false
|
||||||
@ -228,7 +228,7 @@ remove_group(MouseWatcherGroup *group) {
|
|||||||
|
|
||||||
// See if the group is in the set/vector
|
// See if the group is in the set/vector
|
||||||
PT(MouseWatcherGroup) pt = group;
|
PT(MouseWatcherGroup) pt = group;
|
||||||
Groups::iterator gi =
|
Groups::iterator gi =
|
||||||
find(_groups.begin(), _groups.end(), pt);
|
find(_groups.begin(), _groups.end(), pt);
|
||||||
if (gi != _groups.end()) {
|
if (gi != _groups.end()) {
|
||||||
// Found it, now erase it
|
// Found it, now erase it
|
||||||
@ -270,7 +270,7 @@ replace_group(MouseWatcherGroup *old_group, MouseWatcherGroup *new_group) {
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!_show_regions_render2d.is_empty()) {
|
if (!_show_regions_render2d.is_empty()) {
|
||||||
old_group->do_hide_regions();
|
old_group->do_hide_regions();
|
||||||
new_group->do_show_regions(_show_regions_render2d, _show_regions_bin_name,
|
new_group->do_show_regions(_show_regions_render2d, _show_regions_bin_name,
|
||||||
_show_regions_draw_order);
|
_show_regions_draw_order);
|
||||||
}
|
}
|
||||||
#endif // NDEBUG
|
#endif // NDEBUG
|
||||||
@ -327,7 +327,7 @@ replace_group(MouseWatcherGroup *old_group, MouseWatcherGroup *new_group) {
|
|||||||
|
|
||||||
// Add the new group, if it's not already there.
|
// Add the new group, if it's not already there.
|
||||||
PT(MouseWatcherGroup) pt = new_group;
|
PT(MouseWatcherGroup) pt = new_group;
|
||||||
Groups::iterator gi =
|
Groups::iterator gi =
|
||||||
find(_groups.begin(), _groups.end(), pt);
|
find(_groups.begin(), _groups.end(), pt);
|
||||||
if (gi == _groups.end()) {
|
if (gi == _groups.end()) {
|
||||||
_groups.push_back(new_group);
|
_groups.push_back(new_group);
|
||||||
@ -338,7 +338,7 @@ replace_group(MouseWatcherGroup *old_group, MouseWatcherGroup *new_group) {
|
|||||||
new_group->do_update_regions();
|
new_group->do_update_regions();
|
||||||
}
|
}
|
||||||
#endif // NDEBUG
|
#endif // NDEBUG
|
||||||
|
|
||||||
// Remove the old group, if it is already there.
|
// Remove the old group, if it is already there.
|
||||||
pt = old_group;
|
pt = old_group;
|
||||||
gi = find(_groups.begin(), _groups.end(), pt);
|
gi = find(_groups.begin(), _groups.end(), pt);
|
||||||
@ -476,17 +476,17 @@ update_trail_node() {
|
|||||||
if (_trail_log->get_num_events() < 2) {
|
if (_trail_log->get_num_events() < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PT(GeomVertexData) data = new GeomVertexData
|
PT(GeomVertexData) data = new GeomVertexData
|
||||||
("mouseTrailSegs", GeomVertexFormat::get_v3(), Geom::UH_static);
|
("mouseTrailSegs", GeomVertexFormat::get_v3(), Geom::UH_static);
|
||||||
|
|
||||||
GeomVertexWriter vertex(data, InternalName::get_vertex());
|
GeomVertexWriter vertex(data, InternalName::get_vertex());
|
||||||
|
|
||||||
PT(GeomLinestrips) lines = new GeomLinestrips(Geom::UH_static);
|
PT(GeomLinestrips) lines = new GeomLinestrips(Geom::UH_static);
|
||||||
|
|
||||||
double xscale = 2.0 / _pixel_size->get_value().get_x();
|
double xscale = 2.0 / _pixel_size->get_value().get_x();
|
||||||
double yscale = 2.0 / _pixel_size->get_value().get_y();
|
double yscale = 2.0 / _pixel_size->get_value().get_y();
|
||||||
|
|
||||||
for (int i=0; i<(int)_trail_log->get_num_events(); i++) {
|
for (int i=0; i<(int)_trail_log->get_num_events(); i++) {
|
||||||
double x = (_trail_log->get_xpos(i) * xscale) - 1.0;
|
double x = (_trail_log->get_xpos(i) * xscale) - 1.0;
|
||||||
double y = (_trail_log->get_ypos(i) * yscale) - 1.0;
|
double y = (_trail_log->get_ypos(i) * yscale) - 1.0;
|
||||||
@ -565,7 +565,7 @@ void MouseWatcher::
|
|||||||
write(ostream &out, int indent_level) const {
|
write(ostream &out, int indent_level) const {
|
||||||
indent(out, indent_level)
|
indent(out, indent_level)
|
||||||
<< "MouseWatcher " << get_name() << ":\n";
|
<< "MouseWatcher " << get_name() << ":\n";
|
||||||
MouseWatcherGroup::write(out, indent_level + 2);
|
MouseWatcherBase::write(out, indent_level + 2);
|
||||||
|
|
||||||
LightMutexHolder holder(_lock);
|
LightMutexHolder holder(_lock);
|
||||||
if (!_groups.empty()) {
|
if (!_groups.empty()) {
|
||||||
@ -620,11 +620,11 @@ get_over_regions(MouseWatcher::Regions ®ions, const LPoint2 &pos) const {
|
|||||||
for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
|
for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
|
||||||
MouseWatcherRegion *region = (*ri);
|
MouseWatcherRegion *region = (*ri);
|
||||||
const LVecBase4 &frame = region->get_frame();
|
const LVecBase4 &frame = region->get_frame();
|
||||||
|
|
||||||
if (region->get_active() &&
|
if (region->get_active() &&
|
||||||
mx >= frame[0] && mx <= frame[1] &&
|
mx >= frame[0] && mx <= frame[1] &&
|
||||||
my >= frame[2] && my <= frame[3]) {
|
my >= frame[2] && my <= frame[3]) {
|
||||||
|
|
||||||
regions.push_back(region);
|
regions.push_back(region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -750,9 +750,9 @@ set_current_regions(MouseWatcher::Regions ®ions) {
|
|||||||
// Determine which is the "preferred region", if any. This is the
|
// Determine which is the "preferred region", if any. This is the
|
||||||
// topmost region that the mouse cursor is over, and the one that
|
// topmost region that the mouse cursor is over, and the one that
|
||||||
// we are considered "entered" into.
|
// we are considered "entered" into.
|
||||||
MouseWatcherRegion *new_preferred_region =
|
MouseWatcherRegion *new_preferred_region =
|
||||||
get_preferred_region(_current_regions);
|
get_preferred_region(_current_regions);
|
||||||
|
|
||||||
if (_button_down && new_preferred_region != _preferred_button_down_region) {
|
if (_button_down && new_preferred_region != _preferred_button_down_region) {
|
||||||
// If the button's being held down, we're only allowed to select
|
// If the button's being held down, we're only allowed to select
|
||||||
// the preferred button down region.
|
// the preferred button down region.
|
||||||
@ -786,9 +786,9 @@ clear_current_regions() {
|
|||||||
MouseWatcherParameter param;
|
MouseWatcherParameter param;
|
||||||
param.set_modifier_buttons(_mods);
|
param.set_modifier_buttons(_mods);
|
||||||
param.set_mouse(_mouse);
|
param.set_mouse(_mouse);
|
||||||
|
|
||||||
Regions::const_iterator old_ri = _current_regions.begin();
|
Regions::const_iterator old_ri = _current_regions.begin();
|
||||||
|
|
||||||
while (old_ri != _current_regions.end()) {
|
while (old_ri != _current_regions.end()) {
|
||||||
// Here's a region we don't have any more.
|
// Here's a region we don't have any more.
|
||||||
MouseWatcherRegion *old_region = (*old_ri);
|
MouseWatcherRegion *old_region = (*old_ri);
|
||||||
@ -796,7 +796,7 @@ clear_current_regions() {
|
|||||||
throw_event_pattern(_leave_pattern, old_region, ButtonHandle::none());
|
throw_event_pattern(_leave_pattern, old_region, ButtonHandle::none());
|
||||||
++old_ri;
|
++old_ri;
|
||||||
}
|
}
|
||||||
|
|
||||||
_current_regions.clear();
|
_current_regions.clear();
|
||||||
|
|
||||||
if (_preferred_region != (MouseWatcherRegion *)NULL) {
|
if (_preferred_region != (MouseWatcherRegion *)NULL) {
|
||||||
@ -815,9 +815,9 @@ clear_current_regions() {
|
|||||||
// assumes the lock is already held.
|
// assumes the lock is already held.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MouseWatcher::
|
void MouseWatcher::
|
||||||
do_show_regions(const NodePath &render2d, const string &bin_name,
|
do_show_regions(const NodePath &render2d, const string &bin_name,
|
||||||
int draw_order) {
|
int draw_order) {
|
||||||
MouseWatcherGroup::do_show_regions(render2d, bin_name, draw_order);
|
MouseWatcherBase::do_show_regions(render2d, bin_name, draw_order);
|
||||||
_show_regions_render2d = render2d;
|
_show_regions_render2d = render2d;
|
||||||
_show_regions_bin_name = bin_name;
|
_show_regions_bin_name = bin_name;
|
||||||
_show_regions_draw_order = draw_order;
|
_show_regions_draw_order = draw_order;
|
||||||
@ -839,7 +839,7 @@ do_show_regions(const NodePath &render2d, const string &bin_name,
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MouseWatcher::
|
void MouseWatcher::
|
||||||
do_hide_regions() {
|
do_hide_regions() {
|
||||||
MouseWatcherGroup::do_hide_regions();
|
MouseWatcherBase::do_hide_regions();
|
||||||
_show_regions_render2d = NodePath();
|
_show_regions_render2d = NodePath();
|
||||||
_show_regions_bin_name = string();
|
_show_regions_bin_name = string();
|
||||||
_show_regions_draw_order = 0;
|
_show_regions_draw_order = 0;
|
||||||
@ -1027,7 +1027,7 @@ press(ButtonHandle button, bool keyrepeat) {
|
|||||||
|
|
||||||
if (MouseButton::is_mouse_button(button)) {
|
if (MouseButton::is_mouse_button(button)) {
|
||||||
// Mouse buttons are inextricably linked to the mouse position.
|
// Mouse buttons are inextricably linked to the mouse position.
|
||||||
|
|
||||||
if (!_button_down) {
|
if (!_button_down) {
|
||||||
_preferred_button_down_region = _preferred_region;
|
_preferred_button_down_region = _preferred_region;
|
||||||
}
|
}
|
||||||
@ -1043,7 +1043,7 @@ press(ButtonHandle button, bool keyrepeat) {
|
|||||||
_preferred_button_down_region, button);
|
_preferred_button_down_region, button);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// It's a keyboard button; therefore, send the event to every
|
// It's a keyboard button; therefore, send the event to every
|
||||||
// region that wants keyboard buttons, regardless of the mouse
|
// region that wants keyboard buttons, regardless of the mouse
|
||||||
@ -1084,7 +1084,7 @@ release(ButtonHandle button) {
|
|||||||
if (MouseButton::is_mouse_button(button)) {
|
if (MouseButton::is_mouse_button(button)) {
|
||||||
// Button up. Send the up event associated with the region(s) we
|
// Button up. Send the up event associated with the region(s) we
|
||||||
// were over when the button went down.
|
// were over when the button went down.
|
||||||
|
|
||||||
// There is some danger of losing button-up events here. If
|
// There is some danger of losing button-up events here. If
|
||||||
// more than one button goes down together, we won't detect
|
// more than one button goes down together, we won't detect
|
||||||
// both of the button-up events properly.
|
// both of the button-up events properly.
|
||||||
@ -1097,7 +1097,7 @@ release(ButtonHandle button) {
|
|||||||
|
|
||||||
_button_down = false;
|
_button_down = false;
|
||||||
_preferred_button_down_region = (MouseWatcherRegion *)NULL;
|
_preferred_button_down_region = (MouseWatcherRegion *)NULL;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// It's a keyboard button; therefore, send the event to every
|
// It's a keyboard button; therefore, send the event to every
|
||||||
// region that wants keyboard buttons, regardless of the mouse
|
// region that wants keyboard buttons, regardless of the mouse
|
||||||
@ -1105,7 +1105,7 @@ release(ButtonHandle button) {
|
|||||||
if (_preferred_region != (MouseWatcherRegion *)NULL) {
|
if (_preferred_region != (MouseWatcherRegion *)NULL) {
|
||||||
_preferred_region->release(param);
|
_preferred_region->release(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
param.set_outside(true);
|
param.set_outside(true);
|
||||||
global_keyboard_release(param);
|
global_keyboard_release(param);
|
||||||
}
|
}
|
||||||
@ -1166,7 +1166,7 @@ keystroke(int keycode) {
|
|||||||
// highlighted in the IME.
|
// highlighted in the IME.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MouseWatcher::
|
void MouseWatcher::
|
||||||
candidate(const wstring &candidate_string, size_t highlight_start,
|
candidate(const wstring &candidate_string, size_t highlight_start,
|
||||||
size_t highlight_end, size_t cursor_pos) {
|
size_t highlight_end, size_t cursor_pos) {
|
||||||
nassertv(_lock.debug_is_locked());
|
nassertv(_lock.debug_is_locked());
|
||||||
|
|
||||||
@ -1275,7 +1275,7 @@ global_keyboard_release(const MouseWatcherParameter ¶m) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: MouseWatcher::enter_region
|
// Function: MouseWatcher::enter_region
|
||||||
// Access: Protected
|
// Access: Protected
|
||||||
// Description: Called internally to indicate the mouse pointer is
|
// Description: Called internally to indicate the mouse pointer is
|
||||||
// favoring the indicated region.
|
// favoring the indicated region.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MouseWatcher::
|
void MouseWatcher::
|
||||||
@ -1326,7 +1326,7 @@ set_no_mouse() {
|
|||||||
_geometry->set_overall_hidden(true);
|
_geometry->set_overall_hidden(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_has_mouse = false;
|
_has_mouse = false;
|
||||||
clear_current_regions();
|
clear_current_regions();
|
||||||
}
|
}
|
||||||
@ -1350,11 +1350,11 @@ set_mouse(const LVecBase2 &xy, const LVecBase2 &pixel_xy) {
|
|||||||
_geometry->set_overall_hidden(false);
|
_geometry->set_overall_hidden(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_has_mouse = true;
|
_has_mouse = true;
|
||||||
_mouse = xy;
|
_mouse = xy;
|
||||||
_mouse_pixel = pixel_xy;
|
_mouse_pixel = pixel_xy;
|
||||||
|
|
||||||
Regions regions;
|
Regions regions;
|
||||||
get_over_regions(regions, _mouse);
|
get_over_regions(regions, _mouse);
|
||||||
set_current_regions(regions);
|
set_current_regions(regions);
|
||||||
@ -1366,7 +1366,7 @@ set_mouse(const LVecBase2 &xy, const LVecBase2 &pixel_xy) {
|
|||||||
// Description: If we send any keyboard events to a region that has
|
// Description: If we send any keyboard events to a region that has
|
||||||
// the SF_other_button suppress flag set, that means we
|
// the SF_other_button suppress flag set, that means we
|
||||||
// should not send the keyboard event along the data
|
// should not send the keyboard event along the data
|
||||||
// graph.
|
// graph.
|
||||||
//
|
//
|
||||||
// This method is called as each keyboard event is sent
|
// This method is called as each keyboard event is sent
|
||||||
// to a region; it should update the internal
|
// to a region; it should update the internal
|
||||||
@ -1436,7 +1436,7 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
|||||||
// The mouse is outside the display region, even though it's
|
// The mouse is outside the display region, even though it's
|
||||||
// within the window. This is considered not having a mouse.
|
// within the window. This is considered not having a mouse.
|
||||||
set_no_mouse();
|
set_no_mouse();
|
||||||
|
|
||||||
// This also means we should suppress mouse button events below us.
|
// This also means we should suppress mouse button events below us.
|
||||||
_internal_suppress |= MouseWatcherRegion::SF_mouse_button;
|
_internal_suppress |= MouseWatcherRegion::SF_mouse_button;
|
||||||
}
|
}
|
||||||
@ -1469,7 +1469,7 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
|||||||
if (_num_trail_recent > _trail_log->get_num_events()) {
|
if (_num_trail_recent > _trail_log->get_num_events()) {
|
||||||
_num_trail_recent = _trail_log->get_num_events();
|
_num_trail_recent = _trail_log->get_num_events();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the mouse is over a particular region, or still considered
|
// If the mouse is over a particular region, or still considered
|
||||||
// owned by a region because of a recent button-down event, that
|
// owned by a region because of a recent button-down event, that
|
||||||
// region determines whether we suppress events below us.
|
// region determines whether we suppress events below us.
|
||||||
@ -1561,7 +1561,7 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
|||||||
if (_has_inactivity_timeout) {
|
if (_has_inactivity_timeout) {
|
||||||
if (activity) {
|
if (activity) {
|
||||||
note_activity();
|
note_activity();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
double now = ClockObject::get_global_clock()->get_frame_time();
|
double now = ClockObject::get_global_clock()->get_frame_time();
|
||||||
double elapsed = now - _last_activity;
|
double elapsed = now - _last_activity;
|
||||||
@ -1575,10 +1575,10 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
|||||||
|
|
||||||
case IS_inactive:
|
case IS_inactive:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_active_to_inactive:
|
case IS_active_to_inactive:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_inactive_to_active:
|
case IS_inactive_to_active:
|
||||||
_inactivity_state = IS_inactive;
|
_inactivity_state = IS_inactive;
|
||||||
break;
|
break;
|
||||||
@ -1591,7 +1591,7 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
|||||||
case IS_active:
|
case IS_active:
|
||||||
case IS_inactive:
|
case IS_inactive:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_active_to_inactive:
|
case IS_active_to_inactive:
|
||||||
// "Release" all of the currently-held buttons.
|
// "Release" all of the currently-held buttons.
|
||||||
if (tform_cat.is_debug()) {
|
if (tform_cat.is_debug()) {
|
||||||
@ -1610,7 +1610,7 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
|||||||
_inactivity_state = IS_inactive;
|
_inactivity_state = IS_inactive;
|
||||||
throw_event(_inactivity_timeout_event);
|
throw_event(_inactivity_timeout_event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_inactive_to_active:
|
case IS_inactive_to_active:
|
||||||
// "Press" all of the buttons we "released" before.
|
// "Press" all of the buttons we "released" before.
|
||||||
{
|
{
|
||||||
@ -1643,20 +1643,20 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
|||||||
for (int i = 0; i < num_events; i++) {
|
for (int i = 0; i < num_events; i++) {
|
||||||
const ButtonEvent &be = new_button_events.get_event(i);
|
const ButtonEvent &be = new_button_events.get_event(i);
|
||||||
bool suppress = true;
|
bool suppress = true;
|
||||||
|
|
||||||
if (be._type != ButtonEvent::T_keystroke &&
|
if (be._type != ButtonEvent::T_keystroke &&
|
||||||
MouseButton::is_mouse_button(be._button)) {
|
MouseButton::is_mouse_button(be._button)) {
|
||||||
suppress = ((suppress_buttons & MouseWatcherRegion::SF_mouse_button) != 0);
|
suppress = ((suppress_buttons & MouseWatcherRegion::SF_mouse_button) != 0);
|
||||||
} else {
|
} else {
|
||||||
suppress = ((suppress_buttons & MouseWatcherRegion::SF_other_button) != 0);
|
suppress = ((suppress_buttons & MouseWatcherRegion::SF_other_button) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!suppress || be._type == ButtonEvent::T_up) {
|
if (!suppress || be._type == ButtonEvent::T_up) {
|
||||||
// Don't suppress this button event; pass it through.
|
// Don't suppress this button event; pass it through.
|
||||||
_button_events->add_event(be);
|
_button_events->add_event(be);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_button_events->get_num_events() != 0) {
|
if (_button_events->get_num_events() != 0) {
|
||||||
output.set_data(_button_events_output, EventParameter(_button_events));
|
output.set_data(_button_events_output, EventParameter(_button_events));
|
||||||
}
|
}
|
||||||
@ -1673,7 +1673,7 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
|||||||
// leaves f and p unchanged, and returns false.
|
// leaves f and p unchanged, and returns false.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool MouseWatcher::
|
bool MouseWatcher::
|
||||||
constrain_display_region(DisplayRegion *display_region,
|
constrain_display_region(DisplayRegion *display_region,
|
||||||
LVecBase2 &f, LVecBase2 &p,
|
LVecBase2 &f, LVecBase2 &p,
|
||||||
Thread *current_thread) {
|
Thread *current_thread) {
|
||||||
if (!_button_down) {
|
if (!_button_down) {
|
||||||
@ -1700,7 +1700,7 @@ constrain_display_region(DisplayRegion *display_region,
|
|||||||
DisplayRegionPipelineReader dr_reader(display_region, current_thread);
|
DisplayRegionPipelineReader dr_reader(display_region, current_thread);
|
||||||
PN_stdfloat left, right, bottom, top;
|
PN_stdfloat left, right, bottom, top;
|
||||||
dr_reader.get_dimensions(left, right, bottom, top);
|
dr_reader.get_dimensions(left, right, bottom, top);
|
||||||
|
|
||||||
// Need to translate this into DisplayRegion [0, 1] space
|
// Need to translate this into DisplayRegion [0, 1] space
|
||||||
PN_stdfloat x = (f[0] + 1.0f) / 2.0f;
|
PN_stdfloat x = (f[0] + 1.0f) / 2.0f;
|
||||||
PN_stdfloat y = (f[1] + 1.0f) / 2.0f;
|
PN_stdfloat y = (f[1] + 1.0f) / 2.0f;
|
||||||
@ -1715,18 +1715,18 @@ constrain_display_region(DisplayRegion *display_region,
|
|||||||
if (_button_down) {
|
if (_button_down) {
|
||||||
_button_down_display_region = display_region;
|
_button_down_display_region = display_region;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale in DR space
|
// Scale in DR space
|
||||||
PN_stdfloat xp = (x - left) / (right - left);
|
PN_stdfloat xp = (x - left) / (right - left);
|
||||||
// Translate back into [-1, 1] space
|
// Translate back into [-1, 1] space
|
||||||
PN_stdfloat xpp = (xp * 2.0f) - 1.0f;
|
PN_stdfloat xpp = (xp * 2.0f) - 1.0f;
|
||||||
|
|
||||||
PN_stdfloat yp = (y - bottom) / (top - bottom);
|
PN_stdfloat yp = (y - bottom) / (top - bottom);
|
||||||
PN_stdfloat ypp = (yp * 2.0f) - 1.0f;
|
PN_stdfloat ypp = (yp * 2.0f) - 1.0f;
|
||||||
|
|
||||||
int xo, yo, w, h;
|
int xo, yo, w, h;
|
||||||
dr_reader.get_region_pixels_i(xo, yo, w, h);
|
dr_reader.get_region_pixels_i(xo, yo, w, h);
|
||||||
|
|
||||||
f.set(xpp, ypp);
|
f.set(xpp, ypp);
|
||||||
p.set(p[0] - xo, p[1] - yo);
|
p.set(p[0] - xo, p[1] - yo);
|
||||||
return true;
|
return true;
|
||||||
|
@ -61,11 +61,11 @@ class DisplayRegion;
|
|||||||
// it took to get there. This information is mainly useful
|
// it took to get there. This information is mainly useful
|
||||||
// for gesture-recognition code. To use trail logging,
|
// for gesture-recognition code. To use trail logging,
|
||||||
// you need to enable the generation of pointer events
|
// you need to enable the generation of pointer events
|
||||||
// in the GraphicsWindowInputDevice and set the trail
|
// in the GraphicsWindowInputDevice and set the trail
|
||||||
// log duration in the MouseWatcher. Otherwise, the
|
// log duration in the MouseWatcher. Otherwise, the
|
||||||
// trail log will be empty.
|
// trail log will be empty.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA_TFORM MouseWatcher : public DataNode, public MouseWatcherGroup {
|
class EXPCL_PANDA_TFORM MouseWatcher : public DataNode, public MouseWatcherBase {
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
MouseWatcher(const string &name = "");
|
MouseWatcher(const string &name = "");
|
||||||
~MouseWatcher();
|
~MouseWatcher();
|
||||||
@ -143,14 +143,14 @@ PUBLISHED:
|
|||||||
|
|
||||||
INLINE void set_inactivity_timeout_event(const string &event);
|
INLINE void set_inactivity_timeout_event(const string &event);
|
||||||
INLINE const string &get_inactivity_timeout_event() const;
|
INLINE const string &get_inactivity_timeout_event() const;
|
||||||
|
|
||||||
INLINE CPT(PointerEventList) get_trail_log() const;
|
INLINE CPT(PointerEventList) get_trail_log() const;
|
||||||
INLINE int num_trail_recent() const;
|
INLINE int num_trail_recent() const;
|
||||||
void set_trail_log_duration(double duration);
|
void set_trail_log_duration(double duration);
|
||||||
PT(GeomNode) get_trail_node();
|
PT(GeomNode) get_trail_node();
|
||||||
void clear_trail_node();
|
void clear_trail_node();
|
||||||
INLINE void clear_trail_log();
|
INLINE void clear_trail_log();
|
||||||
|
|
||||||
void note_activity();
|
void note_activity();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -179,7 +179,7 @@ protected:
|
|||||||
MouseWatcherRegion *region);
|
MouseWatcherRegion *region);
|
||||||
static bool has_region_in(const Regions ®ions,
|
static bool has_region_in(const Regions ®ions,
|
||||||
MouseWatcherRegion *region);
|
MouseWatcherRegion *region);
|
||||||
|
|
||||||
void throw_event_pattern(const string &pattern,
|
void throw_event_pattern(const string &pattern,
|
||||||
const MouseWatcherRegion *region,
|
const MouseWatcherRegion *region,
|
||||||
const ButtonHandle &button);
|
const ButtonHandle &button);
|
||||||
@ -188,9 +188,9 @@ protected:
|
|||||||
void press(ButtonHandle button, bool keyrepeat);
|
void press(ButtonHandle button, bool keyrepeat);
|
||||||
void release(ButtonHandle button);
|
void release(ButtonHandle button);
|
||||||
void keystroke(int keycode);
|
void keystroke(int keycode);
|
||||||
void candidate(const wstring &candidate, size_t highlight_start,
|
void candidate(const wstring &candidate, size_t highlight_start,
|
||||||
size_t highlight_end, size_t cursor_pos);
|
size_t highlight_end, size_t cursor_pos);
|
||||||
|
|
||||||
void global_keyboard_press(const MouseWatcherParameter ¶m);
|
void global_keyboard_press(const MouseWatcherParameter ¶m);
|
||||||
void global_keyboard_release(const MouseWatcherParameter ¶m);
|
void global_keyboard_release(const MouseWatcherParameter ¶m);
|
||||||
|
|
||||||
@ -207,10 +207,10 @@ private:
|
|||||||
void discard_excess_trail_log();
|
void discard_excess_trail_log();
|
||||||
void update_trail_node();
|
void update_trail_node();
|
||||||
|
|
||||||
bool constrain_display_region(DisplayRegion *display_region,
|
bool constrain_display_region(DisplayRegion *display_region,
|
||||||
LVecBase2 &f, LVecBase2 &p,
|
LVecBase2 &f, LVecBase2 &p,
|
||||||
Thread *current_thread);
|
Thread *current_thread);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This wants to be a set, but because you cannot export sets across
|
// This wants to be a set, but because you cannot export sets across
|
||||||
// dlls in windows, we will make it a vector instead
|
// dlls in windows, we will make it a vector instead
|
||||||
@ -230,7 +230,7 @@ private:
|
|||||||
int _num_trail_recent;
|
int _num_trail_recent;
|
||||||
double _trail_log_duration;
|
double _trail_log_duration;
|
||||||
PT(GeomNode) _trail_node;
|
PT(GeomNode) _trail_node;
|
||||||
|
|
||||||
Regions _current_regions;
|
Regions _current_regions;
|
||||||
PT(MouseWatcherRegion) _preferred_region;
|
PT(MouseWatcherRegion) _preferred_region;
|
||||||
PT(MouseWatcherRegion) _preferred_button_down_region;
|
PT(MouseWatcherRegion) _preferred_button_down_region;
|
||||||
@ -248,7 +248,7 @@ private:
|
|||||||
string _without_pattern;
|
string _without_pattern;
|
||||||
|
|
||||||
PT(PandaNode) _geometry;
|
PT(PandaNode) _geometry;
|
||||||
|
|
||||||
EventHandler *_eh;
|
EventHandler *_eh;
|
||||||
ModifierButtons _mods;
|
ModifierButtons _mods;
|
||||||
DisplayRegion *_display_region;
|
DisplayRegion *_display_region;
|
||||||
|
443
panda/src/tform/mouseWatcherBase.cxx
Normal file
443
panda/src/tform/mouseWatcherBase.cxx
Normal file
@ -0,0 +1,443 @@
|
|||||||
|
// Filename: mouseWatcherBase.cxx
|
||||||
|
// Created by: rdb (13Jan14)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// 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 "mouseWatcherBase.h"
|
||||||
|
#include "lineSegs.h"
|
||||||
|
#include "indent.h"
|
||||||
|
#include "lightMutexHolder.h"
|
||||||
|
|
||||||
|
TypeHandle MouseWatcherBase::_type_handle;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
MouseWatcherBase::
|
||||||
|
MouseWatcherBase() :
|
||||||
|
_lock("MouseWatcherBase")
|
||||||
|
{
|
||||||
|
_sorted = true;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
_show_regions = false;
|
||||||
|
_color.set(0.4, 0.6f, 1.0f, 1.0f);
|
||||||
|
#endif // NDEBUG
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::Destructor
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
MouseWatcherBase::
|
||||||
|
~MouseWatcherBase() {
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::add_region
|
||||||
|
// Access: Published
|
||||||
|
// Description: Adds the indicated region to the set of regions in
|
||||||
|
// the group. It is an error to add the same region to
|
||||||
|
// the set more than once.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MouseWatcherBase::
|
||||||
|
add_region(MouseWatcherRegion *region) {
|
||||||
|
PT(MouseWatcherRegion) pt = region;
|
||||||
|
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
|
||||||
|
// We will only bother to check for duplicates in the region list if
|
||||||
|
// we are building a development Panda. The overhead for doing this
|
||||||
|
// may be too high if we have many regions.
|
||||||
|
#ifdef _DEBUG
|
||||||
|
// See if the region is in the set/vector already
|
||||||
|
Regions::const_iterator ri =
|
||||||
|
find(_regions.begin(), _regions.end(), pt);
|
||||||
|
nassertv(ri == _regions.end());
|
||||||
|
#endif // _DEBUG
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Also add it to the vizzes if we have them.
|
||||||
|
if (_show_regions) {
|
||||||
|
nassertv(_vizzes.size() == _regions.size());
|
||||||
|
_vizzes.push_back(make_viz_region(pt));
|
||||||
|
}
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
_regions.push_back(pt);
|
||||||
|
_sorted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::has_region
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if the indicated region has already been
|
||||||
|
// added to the MouseWatcherBase, false otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool MouseWatcherBase::
|
||||||
|
has_region(MouseWatcherRegion *region) const {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
|
||||||
|
PT(MouseWatcherRegion) ptr = region;
|
||||||
|
|
||||||
|
if (_sorted) {
|
||||||
|
// If the vector is already sorted, we can do this the quick way.
|
||||||
|
Regions::const_iterator ri = lower_bound(_regions.begin(), _regions.end(), ptr);
|
||||||
|
return (ri != _regions.end() && (*ri) == ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the vector isn't sorted, do a linear scan.
|
||||||
|
Regions::const_iterator ri = find(_regions.begin(), _regions.end(), ptr);
|
||||||
|
return (ri != _regions.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::remove_region
|
||||||
|
// Access: Published
|
||||||
|
// Description: Removes the indicated region from the group.
|
||||||
|
// Returns true if it was successfully removed, or false
|
||||||
|
// if it wasn't there in the first place.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool MouseWatcherBase::
|
||||||
|
remove_region(MouseWatcherRegion *region) {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
return do_remove_region(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::find_region
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns a pointer to the first region found with the
|
||||||
|
// indicated name. If multiple regions share the same
|
||||||
|
// name, the one that is returned is indeterminate.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
MouseWatcherRegion *MouseWatcherBase::
|
||||||
|
find_region(const string &name) const {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
|
||||||
|
Regions::const_iterator ri;
|
||||||
|
for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
|
||||||
|
MouseWatcherRegion *region = (*ri);
|
||||||
|
if (region->get_name() == name) {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (MouseWatcherRegion *)NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::clear_regions
|
||||||
|
// Access: Published
|
||||||
|
// Description: Removes all the regions from the group.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MouseWatcherBase::
|
||||||
|
clear_regions() {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
|
||||||
|
_regions.clear();
|
||||||
|
_sorted = true;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (_show_regions) {
|
||||||
|
_show_regions_root.node()->remove_all_children();
|
||||||
|
_vizzes.clear();
|
||||||
|
}
|
||||||
|
#endif // NDEBUG
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::sort_regions
|
||||||
|
// Access: Published
|
||||||
|
// Description: Sorts all the regions in this group into pointer
|
||||||
|
// order.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MouseWatcherBase::
|
||||||
|
sort_regions() {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
do_sort_regions();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::is_sorted
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if the group has already been sorted,
|
||||||
|
// false otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool MouseWatcherBase::
|
||||||
|
is_sorted() const {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
|
||||||
|
return _sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::get_num_regions
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the number of regions in the group.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int MouseWatcherBase::
|
||||||
|
get_num_regions() const {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
|
||||||
|
return _regions.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::get_region
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the nth region of the group; returns NULL if
|
||||||
|
// there is no nth region. Note that this is not
|
||||||
|
// thread-safe; another thread might have removed the
|
||||||
|
// nth region before you called this method.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
MouseWatcherRegion *MouseWatcherBase::
|
||||||
|
get_region(int n) const {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
if (n >= 0 && n < (int)_regions.size()) {
|
||||||
|
return _regions[n];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::output
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MouseWatcherBase::
|
||||||
|
output(ostream &out) const {
|
||||||
|
out << "MouseWatcherBase (" << _regions.size() << " regions)";
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::write
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MouseWatcherBase::
|
||||||
|
write(ostream &out, int indent_level) const {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
|
||||||
|
Regions::const_iterator ri;
|
||||||
|
for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
|
||||||
|
MouseWatcherRegion *region = (*ri);
|
||||||
|
region->write(out, indent_level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::show_regions
|
||||||
|
// Access: Published
|
||||||
|
// Description: Enables the visualization of all of the regions
|
||||||
|
// handled by this MouseWatcherBase. The supplied
|
||||||
|
// NodePath should be the root of the 2-d scene graph
|
||||||
|
// for the window.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MouseWatcherBase::
|
||||||
|
show_regions(const NodePath &render2d, const string &bin_name, int draw_order) {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
do_show_regions(render2d, bin_name, draw_order);
|
||||||
|
}
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::set_color
|
||||||
|
// Access: Published
|
||||||
|
// Description: Specifies the color used to draw the region
|
||||||
|
// rectangles for the regions visualized by
|
||||||
|
// show_regions().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MouseWatcherBase::
|
||||||
|
set_color(const LColor &color) {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
|
||||||
|
_color = color;
|
||||||
|
do_update_regions();
|
||||||
|
}
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::hide_regions
|
||||||
|
// Access: Published
|
||||||
|
// Description: Stops the visualization created by a previous call to
|
||||||
|
// show_regions().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MouseWatcherBase::
|
||||||
|
hide_regions() {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
do_hide_regions();
|
||||||
|
}
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::update_regions
|
||||||
|
// Access: Published
|
||||||
|
// Description: Refreshes the visualization created by
|
||||||
|
// show_regions().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MouseWatcherBase::
|
||||||
|
update_regions() {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
do_update_regions();
|
||||||
|
}
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::do_sort_regions
|
||||||
|
// Access: Protected
|
||||||
|
// Description: Sorts all the regions in this group into pointer
|
||||||
|
// order. Assumes the lock is already held.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MouseWatcherBase::
|
||||||
|
do_sort_regions() {
|
||||||
|
if (!_sorted) {
|
||||||
|
sort(_regions.begin(), _regions.end());
|
||||||
|
_sorted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::do_remove_region
|
||||||
|
// Access: Protected
|
||||||
|
// Description: The internal implementation of remove_region();
|
||||||
|
// assumes the lock is already held.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool MouseWatcherBase::
|
||||||
|
do_remove_region(MouseWatcherRegion *region) {
|
||||||
|
// See if the region is in the vector.
|
||||||
|
PT(MouseWatcherRegion) ptr = region;
|
||||||
|
Regions::iterator ri;
|
||||||
|
|
||||||
|
if (_sorted) {
|
||||||
|
// Faster, binary search
|
||||||
|
ri = lower_bound(_regions.begin(), _regions.end(), ptr);
|
||||||
|
} else {
|
||||||
|
// Unsorted, so use slower linear scan
|
||||||
|
ri = find(_regions.begin(), _regions.end(), ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ri != _regions.end() && (*ri) == ptr) {
|
||||||
|
// Found it, now erase it
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Also remove it from the vizzes.
|
||||||
|
if (_show_regions) {
|
||||||
|
nassertr(_vizzes.size() == _regions.size(), false);
|
||||||
|
size_t index = ri - _regions.begin();
|
||||||
|
Vizzes::iterator vi = _vizzes.begin() + index;
|
||||||
|
_show_regions_root.node()->remove_child(*vi);
|
||||||
|
_vizzes.erase(vi);
|
||||||
|
}
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
_regions.erase(ri);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did not find the region to erase
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::do_show_regions
|
||||||
|
// Access: Protected, Virtual
|
||||||
|
// Description: The protected implementation of show_regions(). This
|
||||||
|
// assumes the lock is already held.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MouseWatcherBase::
|
||||||
|
do_show_regions(const NodePath &render2d, const string &bin_name,
|
||||||
|
int draw_order) {
|
||||||
|
do_hide_regions();
|
||||||
|
_show_regions = true;
|
||||||
|
_show_regions_root = render2d.attach_new_node("show_regions");
|
||||||
|
_show_regions_root.set_bin(bin_name, draw_order);
|
||||||
|
do_update_regions();
|
||||||
|
}
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::do_hide_regions
|
||||||
|
// Access: Protected, Virtual
|
||||||
|
// Description: The protected implementation of hide_regions(). This
|
||||||
|
// assumes the lock is already held.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MouseWatcherBase::
|
||||||
|
do_hide_regions() {
|
||||||
|
_show_regions_root.remove_node();
|
||||||
|
_show_regions = false;
|
||||||
|
_vizzes.clear();
|
||||||
|
}
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::do_update_regions
|
||||||
|
// Access: Protected
|
||||||
|
// Description: Internally regenerates the show_regions()
|
||||||
|
// visualization. Assumes the lock is already held.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MouseWatcherBase::
|
||||||
|
do_update_regions() {
|
||||||
|
nassertv(_lock.debug_is_locked());
|
||||||
|
|
||||||
|
if (_show_regions) {
|
||||||
|
_show_regions_root.node()->remove_all_children();
|
||||||
|
_vizzes.clear();
|
||||||
|
_vizzes.reserve(_regions.size());
|
||||||
|
|
||||||
|
Regions::const_iterator ri;
|
||||||
|
for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
|
||||||
|
_vizzes.push_back(make_viz_region(*ri));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MouseWatcherBase::make_viz_region
|
||||||
|
// Access: Private
|
||||||
|
// Description: Creates a node to represent the indicated region, and
|
||||||
|
// attaches it to the _show_regions_root. Does not add
|
||||||
|
// it to _vizzes. Assumes the lock is already held.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PandaNode *MouseWatcherBase::
|
||||||
|
make_viz_region(MouseWatcherRegion *region) {
|
||||||
|
nassertr(_lock.debug_is_locked(), NULL);
|
||||||
|
|
||||||
|
LineSegs ls("show_regions");
|
||||||
|
ls.set_color(_color);
|
||||||
|
|
||||||
|
const LVecBase4 &f = region->get_frame();
|
||||||
|
|
||||||
|
ls.move_to(LVector3::rfu(f[0], 0.0f, f[2]));
|
||||||
|
ls.draw_to(LVector3::rfu(f[1], 0.0f, f[2]));
|
||||||
|
ls.draw_to(LVector3::rfu(f[1], 0.0f, f[3]));
|
||||||
|
ls.draw_to(LVector3::rfu(f[0], 0.0f, f[3]));
|
||||||
|
ls.draw_to(LVector3::rfu(f[0], 0.0f, f[2]));
|
||||||
|
|
||||||
|
PT(PandaNode) node = ls.create();
|
||||||
|
_show_regions_root.attach_new_node(node);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
#endif // NDEBUG
|
113
panda/src/tform/mouseWatcherBase.h
Normal file
113
panda/src/tform/mouseWatcherBase.h
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// Filename: mouseWatcherBase.h
|
||||||
|
// Created by: rdb (13Jan14)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// 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 MOUSEWATCHERBASE_H
|
||||||
|
#define MOUSEWATCHERBASE_H
|
||||||
|
|
||||||
|
#include "pandabase.h"
|
||||||
|
#include "mouseWatcherRegion.h"
|
||||||
|
|
||||||
|
#include "pointerTo.h"
|
||||||
|
#include "pvector.h"
|
||||||
|
#include "nodePath.h"
|
||||||
|
#include "lightMutex.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Class : MouseWatcherBase
|
||||||
|
// Description : This represents a collection of MouseWatcherRegions
|
||||||
|
// that may be managed as a group. This is the base
|
||||||
|
// class for both MouseWatcherGroup and MouseWatcher,
|
||||||
|
// and exists so that we don't have to make MouseWatcher
|
||||||
|
// inherit from ReferenceCount more than once.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
class EXPCL_PANDA_TFORM MouseWatcherBase {
|
||||||
|
public:
|
||||||
|
MouseWatcherBase();
|
||||||
|
virtual ~MouseWatcherBase();
|
||||||
|
|
||||||
|
PUBLISHED:
|
||||||
|
void add_region(MouseWatcherRegion *region);
|
||||||
|
bool has_region(MouseWatcherRegion *region) const;
|
||||||
|
bool remove_region(MouseWatcherRegion *region);
|
||||||
|
MouseWatcherRegion *find_region(const string &name) const;
|
||||||
|
void clear_regions();
|
||||||
|
|
||||||
|
void sort_regions();
|
||||||
|
bool is_sorted() const;
|
||||||
|
|
||||||
|
int get_num_regions() const;
|
||||||
|
MouseWatcherRegion *get_region(int n) const;
|
||||||
|
MAKE_SEQ(get_regions, get_num_regions, get_region);
|
||||||
|
|
||||||
|
void output(ostream &out) const;
|
||||||
|
void write(ostream &out, int indent_level = 0) const;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
void show_regions(const NodePath &render2d,
|
||||||
|
const string &bin_name, int draw_order);
|
||||||
|
void set_color(const LColor &color);
|
||||||
|
void hide_regions();
|
||||||
|
|
||||||
|
void update_regions();
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void do_sort_regions();
|
||||||
|
bool do_remove_region(MouseWatcherRegion *region);
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
virtual void do_show_regions(const NodePath &render2d,
|
||||||
|
const string &bin_name, int draw_order);
|
||||||
|
virtual void do_hide_regions();
|
||||||
|
void do_update_regions();
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef pvector< PT(MouseWatcherRegion) > Regions;
|
||||||
|
Regions _regions;
|
||||||
|
bool _sorted;
|
||||||
|
|
||||||
|
// This mutex protects the above list of regions, as well as the
|
||||||
|
// below list of vizzes. It is also referenced directly by
|
||||||
|
// MouseWatcher, a derived class.
|
||||||
|
LightMutex _lock;
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifndef NDEBUG
|
||||||
|
PandaNode *make_viz_region(MouseWatcherRegion *region);
|
||||||
|
|
||||||
|
typedef pvector< PT(PandaNode) > Vizzes;
|
||||||
|
Vizzes _vizzes;
|
||||||
|
|
||||||
|
bool _show_regions;
|
||||||
|
NodePath _show_regions_root;
|
||||||
|
LColor _color;
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
public:
|
||||||
|
static TypeHandle get_class_type() {
|
||||||
|
return _type_handle;
|
||||||
|
}
|
||||||
|
static void init_type() {
|
||||||
|
register_type(_type_handle, "MouseWatcherBase");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static TypeHandle _type_handle;
|
||||||
|
|
||||||
|
friend class MouseWatcher;
|
||||||
|
friend class BlobWatcher;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -13,432 +13,5 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "mouseWatcherGroup.h"
|
#include "mouseWatcherGroup.h"
|
||||||
#include "lineSegs.h"
|
|
||||||
#include "indent.h"
|
|
||||||
#include "lightMutexHolder.h"
|
|
||||||
|
|
||||||
TypeHandle MouseWatcherGroup::_type_handle;
|
TypeHandle MouseWatcherGroup::_type_handle;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::Constructor
|
|
||||||
// Access: Public
|
|
||||||
// Description:
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
MouseWatcherGroup::
|
|
||||||
MouseWatcherGroup() :
|
|
||||||
_lock("MouseWatcherGroup")
|
|
||||||
{
|
|
||||||
_sorted = true;
|
|
||||||
#ifndef NDEBUG
|
|
||||||
_show_regions = false;
|
|
||||||
_color.set(0.4, 0.6f, 1.0f, 1.0f);
|
|
||||||
#endif // NDEBUG
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::Destructor
|
|
||||||
// Access: Public, Virtual
|
|
||||||
// Description:
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
MouseWatcherGroup::
|
|
||||||
~MouseWatcherGroup() {
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::add_region
|
|
||||||
// Access: Published
|
|
||||||
// Description: Adds the indicated region to the set of regions in
|
|
||||||
// the group. It is an error to add the same region to
|
|
||||||
// the set more than once.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void MouseWatcherGroup::
|
|
||||||
add_region(MouseWatcherRegion *region) {
|
|
||||||
PT(MouseWatcherRegion) pt = region;
|
|
||||||
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
|
|
||||||
// We will only bother to check for duplicates in the region list if
|
|
||||||
// we are building a development Panda. The overhead for doing this
|
|
||||||
// may be too high if we have many regions.
|
|
||||||
#ifdef _DEBUG
|
|
||||||
// See if the region is in the set/vector already
|
|
||||||
Regions::const_iterator ri =
|
|
||||||
find(_regions.begin(), _regions.end(), pt);
|
|
||||||
nassertv(ri == _regions.end());
|
|
||||||
#endif // _DEBUG
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
// Also add it to the vizzes if we have them.
|
|
||||||
if (_show_regions) {
|
|
||||||
nassertv(_vizzes.size() == _regions.size());
|
|
||||||
_vizzes.push_back(make_viz_region(pt));
|
|
||||||
}
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
_regions.push_back(pt);
|
|
||||||
_sorted = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::has_region
|
|
||||||
// Access: Published
|
|
||||||
// Description: Returns true if the indicated region has already been
|
|
||||||
// added to the MouseWatcherGroup, false otherwise.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool MouseWatcherGroup::
|
|
||||||
has_region(MouseWatcherRegion *region) const {
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
|
|
||||||
PT(MouseWatcherRegion) ptr = region;
|
|
||||||
|
|
||||||
if (_sorted) {
|
|
||||||
// If the vector is already sorted, we can do this the quick way.
|
|
||||||
Regions::const_iterator ri = lower_bound(_regions.begin(), _regions.end(), ptr);
|
|
||||||
return (ri != _regions.end() && (*ri) == ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the vector isn't sorted, do a linear scan.
|
|
||||||
Regions::const_iterator ri = find(_regions.begin(), _regions.end(), ptr);
|
|
||||||
return (ri != _regions.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::remove_region
|
|
||||||
// Access: Published
|
|
||||||
// Description: Removes the indicated region from the group.
|
|
||||||
// Returns true if it was successfully removed, or false
|
|
||||||
// if it wasn't there in the first place.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool MouseWatcherGroup::
|
|
||||||
remove_region(MouseWatcherRegion *region) {
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
return do_remove_region(region);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::find_region
|
|
||||||
// Access: Published
|
|
||||||
// Description: Returns a pointer to the first region found with the
|
|
||||||
// indicated name. If multiple regions share the same
|
|
||||||
// name, the one that is returned is indeterminate.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
MouseWatcherRegion *MouseWatcherGroup::
|
|
||||||
find_region(const string &name) const {
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
|
|
||||||
Regions::const_iterator ri;
|
|
||||||
for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
|
|
||||||
MouseWatcherRegion *region = (*ri);
|
|
||||||
if (region->get_name() == name) {
|
|
||||||
return region;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (MouseWatcherRegion *)NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::clear_regions
|
|
||||||
// Access: Published
|
|
||||||
// Description: Removes all the regions from the group.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void MouseWatcherGroup::
|
|
||||||
clear_regions() {
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
|
|
||||||
_regions.clear();
|
|
||||||
_sorted = true;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
if (_show_regions) {
|
|
||||||
_show_regions_root.node()->remove_all_children();
|
|
||||||
_vizzes.clear();
|
|
||||||
}
|
|
||||||
#endif // NDEBUG
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::sort_regions
|
|
||||||
// Access: Published
|
|
||||||
// Description: Sorts all the regions in this group into pointer
|
|
||||||
// order.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void MouseWatcherGroup::
|
|
||||||
sort_regions() {
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
do_sort_regions();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::is_sorted
|
|
||||||
// Access: Published
|
|
||||||
// Description: Returns true if the group has already been sorted,
|
|
||||||
// false otherwise.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool MouseWatcherGroup::
|
|
||||||
is_sorted() const {
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
|
|
||||||
return _sorted;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::get_num_regions
|
|
||||||
// Access: Published
|
|
||||||
// Description: Returns the number of regions in the group.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
int MouseWatcherGroup::
|
|
||||||
get_num_regions() const {
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
|
|
||||||
return _regions.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::get_region
|
|
||||||
// Access: Published
|
|
||||||
// Description: Returns the nth region of the group; returns NULL if
|
|
||||||
// there is no nth region. Note that this is not
|
|
||||||
// thread-safe; another thread might have removed the
|
|
||||||
// nth region before you called this method.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
MouseWatcherRegion *MouseWatcherGroup::
|
|
||||||
get_region(int n) const {
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
if (n >= 0 && n < (int)_regions.size()) {
|
|
||||||
return _regions[n];
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::output
|
|
||||||
// Access: Published
|
|
||||||
// Description:
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void MouseWatcherGroup::
|
|
||||||
output(ostream &out) const {
|
|
||||||
out << "MouseWatcherGroup (" << _regions.size() << " regions)";
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::write
|
|
||||||
// Access: Published
|
|
||||||
// Description:
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void MouseWatcherGroup::
|
|
||||||
write(ostream &out, int indent_level) const {
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
|
|
||||||
Regions::const_iterator ri;
|
|
||||||
for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
|
|
||||||
MouseWatcherRegion *region = (*ri);
|
|
||||||
region->write(out, indent_level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::show_regions
|
|
||||||
// Access: Published
|
|
||||||
// Description: Enables the visualization of all of the regions
|
|
||||||
// handled by this MouseWatcherGroup. The supplied
|
|
||||||
// NodePath should be the root of the 2-d scene graph
|
|
||||||
// for the window.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void MouseWatcherGroup::
|
|
||||||
show_regions(const NodePath &render2d, const string &bin_name, int draw_order) {
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
do_show_regions(render2d, bin_name, draw_order);
|
|
||||||
}
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::set_color
|
|
||||||
// Access: Published
|
|
||||||
// Description: Specifies the color used to draw the region
|
|
||||||
// rectangles for the regions visualized by
|
|
||||||
// show_regions().
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void MouseWatcherGroup::
|
|
||||||
set_color(const LColor &color) {
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
|
|
||||||
_color = color;
|
|
||||||
do_update_regions();
|
|
||||||
}
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::hide_regions
|
|
||||||
// Access: Published
|
|
||||||
// Description: Stops the visualization created by a previous call to
|
|
||||||
// show_regions().
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void MouseWatcherGroup::
|
|
||||||
hide_regions() {
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
do_hide_regions();
|
|
||||||
}
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::update_regions
|
|
||||||
// Access: Published
|
|
||||||
// Description: Refreshes the visualization created by
|
|
||||||
// show_regions().
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void MouseWatcherGroup::
|
|
||||||
update_regions() {
|
|
||||||
LightMutexHolder holder(_lock);
|
|
||||||
do_update_regions();
|
|
||||||
}
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::do_sort_regions
|
|
||||||
// Access: Protected
|
|
||||||
// Description: Sorts all the regions in this group into pointer
|
|
||||||
// order. Assumes the lock is already held.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void MouseWatcherGroup::
|
|
||||||
do_sort_regions() {
|
|
||||||
if (!_sorted) {
|
|
||||||
sort(_regions.begin(), _regions.end());
|
|
||||||
_sorted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::do_remove_region
|
|
||||||
// Access: Protected
|
|
||||||
// Description: The internal implementation of remove_region();
|
|
||||||
// assumes the lock is already held.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool MouseWatcherGroup::
|
|
||||||
do_remove_region(MouseWatcherRegion *region) {
|
|
||||||
// See if the region is in the vector.
|
|
||||||
PT(MouseWatcherRegion) ptr = region;
|
|
||||||
Regions::iterator ri;
|
|
||||||
|
|
||||||
if (_sorted) {
|
|
||||||
// Faster, binary search
|
|
||||||
ri = lower_bound(_regions.begin(), _regions.end(), ptr);
|
|
||||||
} else {
|
|
||||||
// Unsorted, so use slower linear scan
|
|
||||||
ri = find(_regions.begin(), _regions.end(), ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ri != _regions.end() && (*ri) == ptr) {
|
|
||||||
// Found it, now erase it
|
|
||||||
#ifndef NDEBUG
|
|
||||||
// Also remove it from the vizzes.
|
|
||||||
if (_show_regions) {
|
|
||||||
nassertr(_vizzes.size() == _regions.size(), false);
|
|
||||||
size_t index = ri - _regions.begin();
|
|
||||||
Vizzes::iterator vi = _vizzes.begin() + index;
|
|
||||||
_show_regions_root.node()->remove_child(*vi);
|
|
||||||
_vizzes.erase(vi);
|
|
||||||
}
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
_regions.erase(ri);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Did not find the region to erase
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::do_show_regions
|
|
||||||
// Access: Protected, Virtual
|
|
||||||
// Description: The protected implementation of show_regions(). This
|
|
||||||
// assumes the lock is already held.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void MouseWatcherGroup::
|
|
||||||
do_show_regions(const NodePath &render2d, const string &bin_name,
|
|
||||||
int draw_order) {
|
|
||||||
do_hide_regions();
|
|
||||||
_show_regions = true;
|
|
||||||
_show_regions_root = render2d.attach_new_node("show_regions");
|
|
||||||
_show_regions_root.set_bin(bin_name, draw_order);
|
|
||||||
do_update_regions();
|
|
||||||
}
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::do_hide_regions
|
|
||||||
// Access: Protected, Virtual
|
|
||||||
// Description: The protected implementation of hide_regions(). This
|
|
||||||
// assumes the lock is already held.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void MouseWatcherGroup::
|
|
||||||
do_hide_regions() {
|
|
||||||
_show_regions_root.remove_node();
|
|
||||||
_show_regions = false;
|
|
||||||
_vizzes.clear();
|
|
||||||
}
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::do_update_regions
|
|
||||||
// Access: Protected
|
|
||||||
// Description: Internally regenerates the show_regions()
|
|
||||||
// visualization. Assumes the lock is already held.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void MouseWatcherGroup::
|
|
||||||
do_update_regions() {
|
|
||||||
nassertv(_lock.debug_is_locked());
|
|
||||||
|
|
||||||
if (_show_regions) {
|
|
||||||
_show_regions_root.node()->remove_all_children();
|
|
||||||
_vizzes.clear();
|
|
||||||
_vizzes.reserve(_regions.size());
|
|
||||||
|
|
||||||
Regions::const_iterator ri;
|
|
||||||
for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
|
|
||||||
_vizzes.push_back(make_viz_region(*ri));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: MouseWatcherGroup::make_viz_region
|
|
||||||
// Access: Private
|
|
||||||
// Description: Creates a node to represent the indicated region, and
|
|
||||||
// attaches it to the _show_regions_root. Does not add
|
|
||||||
// it to _vizzes. Assumes the lock is already held.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
PandaNode *MouseWatcherGroup::
|
|
||||||
make_viz_region(MouseWatcherRegion *region) {
|
|
||||||
nassertr(_lock.debug_is_locked(), NULL);
|
|
||||||
|
|
||||||
LineSegs ls("show_regions");
|
|
||||||
ls.set_color(_color);
|
|
||||||
|
|
||||||
const LVecBase4 &f = region->get_frame();
|
|
||||||
|
|
||||||
ls.move_to(LVector3::rfu(f[0], 0.0f, f[2]));
|
|
||||||
ls.draw_to(LVector3::rfu(f[1], 0.0f, f[2]));
|
|
||||||
ls.draw_to(LVector3::rfu(f[1], 0.0f, f[3]));
|
|
||||||
ls.draw_to(LVector3::rfu(f[0], 0.0f, f[3]));
|
|
||||||
ls.draw_to(LVector3::rfu(f[0], 0.0f, f[2]));
|
|
||||||
|
|
||||||
PT(PandaNode) node = ls.create();
|
|
||||||
_show_regions_root.attach_new_node(node);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
@ -16,82 +16,20 @@
|
|||||||
#define MOUSEWATCHERGROUP_H
|
#define MOUSEWATCHERGROUP_H
|
||||||
|
|
||||||
#include "pandabase.h"
|
#include "pandabase.h"
|
||||||
#include "mouseWatcherRegion.h"
|
#include "mouseWatcherBase.h"
|
||||||
|
|
||||||
#include "pointerTo.h"
|
|
||||||
#include "referenceCount.h"
|
#include "referenceCount.h"
|
||||||
#include "pvector.h"
|
|
||||||
#include "nodePath.h"
|
|
||||||
#include "lightMutex.h"
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : MouseWatcherGroup
|
// Class : MouseWatcherGroup
|
||||||
// Description : This represents a collection of MouseWatcherRegions
|
// Description : This represents a collection of MouseWatcherRegions
|
||||||
// that may be managed as a group.
|
// that may be managed as a group. The implementation
|
||||||
|
// for this is in MouseWatcherBase; this class exists
|
||||||
|
// so that we can inherit from ReferenceCount.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA_TFORM MouseWatcherGroup : virtual public ReferenceCount {
|
class EXPCL_PANDA_TFORM MouseWatcherGroup : public MouseWatcherBase,
|
||||||
|
public ReferenceCount {
|
||||||
public:
|
public:
|
||||||
MouseWatcherGroup();
|
INLINE MouseWatcherGroup() {};
|
||||||
virtual ~MouseWatcherGroup();
|
|
||||||
|
|
||||||
PUBLISHED:
|
|
||||||
void add_region(MouseWatcherRegion *region);
|
|
||||||
bool has_region(MouseWatcherRegion *region) const;
|
|
||||||
bool remove_region(MouseWatcherRegion *region);
|
|
||||||
MouseWatcherRegion *find_region(const string &name) const;
|
|
||||||
void clear_regions();
|
|
||||||
|
|
||||||
void sort_regions();
|
|
||||||
bool is_sorted() const;
|
|
||||||
|
|
||||||
int get_num_regions() const;
|
|
||||||
MouseWatcherRegion *get_region(int n) const;
|
|
||||||
MAKE_SEQ(get_regions, get_num_regions, get_region);
|
|
||||||
|
|
||||||
void output(ostream &out) const;
|
|
||||||
void write(ostream &out, int indent_level = 0) const;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
void show_regions(const NodePath &render2d,
|
|
||||||
const string &bin_name, int draw_order);
|
|
||||||
void set_color(const LColor &color);
|
|
||||||
void hide_regions();
|
|
||||||
|
|
||||||
void update_regions();
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void do_sort_regions();
|
|
||||||
bool do_remove_region(MouseWatcherRegion *region);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
virtual void do_show_regions(const NodePath &render2d,
|
|
||||||
const string &bin_name, int draw_order);
|
|
||||||
virtual void do_hide_regions();
|
|
||||||
void do_update_regions();
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
protected:
|
|
||||||
typedef pvector< PT(MouseWatcherRegion) > Regions;
|
|
||||||
Regions _regions;
|
|
||||||
bool _sorted;
|
|
||||||
|
|
||||||
// This mutex protects the above list of regions, as well as the
|
|
||||||
// below list of vizzes. It is also referenced directly by
|
|
||||||
// MouseWatcher, a derived class.
|
|
||||||
LightMutex _lock;
|
|
||||||
|
|
||||||
private:
|
|
||||||
#ifndef NDEBUG
|
|
||||||
PandaNode *make_viz_region(MouseWatcherRegion *region);
|
|
||||||
|
|
||||||
typedef pvector< PT(PandaNode) > Vizzes;
|
|
||||||
Vizzes _vizzes;
|
|
||||||
|
|
||||||
bool _show_regions;
|
|
||||||
NodePath _show_regions_root;
|
|
||||||
LColor _color;
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
@ -105,9 +43,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static TypeHandle _type_handle;
|
static TypeHandle _type_handle;
|
||||||
|
|
||||||
friend class MouseWatcher;
|
|
||||||
friend class BlobWatcher;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "mouseWatcher.cxx"
|
#include "mouseWatcher.cxx"
|
||||||
|
#include "mouseWatcherBase.cxx"
|
||||||
#include "mouseWatcherGroup.cxx"
|
#include "mouseWatcherGroup.cxx"
|
||||||
#include "mouseWatcherParameter.cxx"
|
#include "mouseWatcherParameter.cxx"
|
||||||
#include "mouseWatcherRegion.cxx"
|
#include "mouseWatcherRegion.cxx"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user