initial pgui stuff

This commit is contained in:
David Rose
2001-07-03 23:45:03 +00:00
parent 3732087de4
commit 68e199f696
38 changed files with 2732 additions and 276 deletions
+1 -1
View File
@@ -16,7 +16,7 @@
parametrics pnm \
pnmimagetypes pnmimage sgattrib sgmanip sgraph sgraphutil \
switchnode text tform tiff lerp loader putil effects \
audio gui pandabase
audio gui pgui pandabase
+3 -3
View File
@@ -48,8 +48,8 @@
#define INCLUDED_SOURCES \
allAttributesWrapper.cxx allTransitionsWrapper.cxx \
arcChain.cxxbitMask32Transition.cxx \
boundedObject.cxxconfig_graph.cxx graphReducer.cxx \
arcChain.cxx bitMask32Transition.cxx \
boundedObject.cxx config_graph.cxx graphReducer.cxx \
immediateAttribute.cxx immediateTransition.cxx \
lmatrix4fTransition.cxx multiNodeAttribute.cxx \
multiNodeTransition.cxx namedNode.cxx node.cxx \
@@ -58,7 +58,7 @@
nodeTransition.cxx nodeTransitionCache.cxx \
nodeTransitionCacheEntry.cxx nodeTransitionWrapper.cxx \
nodeTransitions.cxx \
nullAttributeWrapper.cxxnullLevelState.cxx \
nullAttributeWrapper.cxx nullLevelState.cxx \
nullTransitionWrapper.cxx onAttribute.cxx onOffAttribute.cxx \
onOffTransition.cxx onTransition.cxx pt_NamedNode.cxx \
pt_Node.cxx pt_NodeRelation.cxx vector_PT_Node.cxx \
+62 -7
View File
@@ -301,27 +301,82 @@ operator = (const ArcChain &copy) {
}
////////////////////////////////////////////////////////////////////
// Function: ArcChain::has_node
// Function: ArcChain::is_empty
// Access: Public
// Description: Returns true if there is at least a top node in the
// chain, or false otherwise.
// Description: Returns true if the ArcChain contains no nodes and no
// arcs.
////////////////////////////////////////////////////////////////////
INLINE_GRAPH bool ArcChain::
has_node() const {
return (_head != (ArcComponent *)NULL);
is_empty() const {
return (_head == (ArcComponent *)NULL);
}
////////////////////////////////////////////////////////////////////
// Function: ArcChain::is_singleton
// Access: Public
// Description: Returns true if the ArcChain contains exactly one
// node, and no arcs.
////////////////////////////////////////////////////////////////////
INLINE_GRAPH bool ArcChain::
is_singleton() const {
return (_head != (ArcComponent *)NULL && _head->is_top_node());
}
////////////////////////////////////////////////////////////////////
// Function: ArcChain::has_arcs
// Access: Public
// Description: Returns true if there are any arcs in the chain, or
// false otherwise.
// Description: Returns true if the ArcChain contains at least one
// arc, and therefore at least two nodes. This is the
// same thing as asking get_num_arcs() > 0, but is
// easier to compute.
////////////////////////////////////////////////////////////////////
INLINE_GRAPH bool ArcChain::
has_arcs() const {
return (_head != (ArcComponent *)NULL && !_head->is_top_node());
}
////////////////////////////////////////////////////////////////////
// Function: ArcChain::get_num_arcs
// Access: Public
// Description: Returns the number of arcs in the path.
////////////////////////////////////////////////////////////////////
INLINE_GRAPH int ArcChain::
get_num_arcs() const {
if (!has_arcs()) {
return 0;
}
return get_num_nodes() - 1;
}
////////////////////////////////////////////////////////////////////
// Function: ArcChain::node
// Access: Public
// Description: Returns the bottom node of the path, or NULL if the
// path is empty.
////////////////////////////////////////////////////////////////////
INLINE_GRAPH Node *ArcChain::
node() const {
if (is_empty()) {
return (Node *)NULL;
}
return _head->get_node();
}
////////////////////////////////////////////////////////////////////
// Function: ArcChain::arc
// Access: Public
// Description: Returns the bottom arc of the path, or NULL if the
// path is empty or is a singleton.
////////////////////////////////////////////////////////////////////
INLINE_GRAPH NodeRelation *ArcChain::
arc() const {
if (!has_arcs()) {
// A singleton or empty list.
return (NodeRelation *)NULL;
}
return _head->get_arc();
}
////////////////////////////////////////////////////////////////////
// Function: ArcChain::begin
// Access: Public
+89
View File
@@ -60,6 +60,95 @@ operator = (const ArcComponent &copy) {
}
}
////////////////////////////////////////////////////////////////////
// Function: ArcChain::get_num_nodes
// Access: Public
// Description: Returns the number of nodes in the path. This is
// always one more than the number of arcs (except for
// a completely empty path).
////////////////////////////////////////////////////////////////////
int ArcChain::
get_num_nodes() const {
int num = 0;
ArcComponent *comp = _head;
while (comp != (ArcComponent *)NULL) {
num++;
comp = comp->get_next();
}
return num;
}
////////////////////////////////////////////////////////////////////
// Function: ArcChain::get_node
// Access: Public
// Description: Returns the nth node of the path, where 0 is the
// bottom node and get_num_nodes() - 1 is the top node.
// This requires iterating through the path.
////////////////////////////////////////////////////////////////////
Node *ArcChain::
get_node(int index) const {
nassertr(index >= 0 && index < get_num_nodes(), NULL);
ArcComponent *comp = _head;
while (index > 0) {
// If this assertion fails, the index was out of range.
nassertr(comp != (ArcComponent *)NULL, NULL);
comp = comp->get_next();
index--;
}
// If this assertion fails, the index was out of range.
nassertr(comp != (ArcComponent *)NULL, NULL);
return comp->get_node();
}
////////////////////////////////////////////////////////////////////
// Function: ArcChain::get_arc
// Access: Public
// Description: Returns the nth arc of the path, where 0 is the arc
// above the bottom node node and get_num_arcs() - 1 is
// the arc below the top node. This requires iterating
// through the path.
////////////////////////////////////////////////////////////////////
NodeRelation *ArcChain::
get_arc(int index) const {
nassertr(index >= 0 && index < get_num_arcs(), NULL);
ArcComponent *comp = _head;
while (index > 0) {
// If this assertion fails, the index was out of range.
nassertr(comp != (ArcComponent *)NULL, NULL);
comp = comp->get_next();
index--;
}
// If either assertion fails, the index was out of range.
nassertr(comp != (ArcComponent *)NULL, NULL);
nassertr(comp->has_arc(), NULL);
return comp->get_arc();
}
////////////////////////////////////////////////////////////////////
// Function: ArcChain::get_top_node
// Access: Public
// Description: Returns the top node of the path, or NULL if the path
// is empty. This requires iterating through the path.
////////////////////////////////////////////////////////////////////
Node *ArcChain::
get_top_node() const {
if (is_empty()) {
return (Node *)NULL;
}
ArcComponent *comp = _head;
while (!comp->is_top_node()) {
comp = comp->get_next();
nassertr(comp != (ArcComponent *)NULL, NULL);
}
return comp->get_node();
}
////////////////////////////////////////////////////////////////////
// Function: ArcChain::r_output
// Access: Private
+16 -1
View File
@@ -141,8 +141,23 @@ public:
INLINE_GRAPH ArcChain(const ArcChain &copy);
INLINE_GRAPH void operator = (const ArcChain &copy);
INLINE_GRAPH bool has_node() const;
// Methods to query an ArcChain's contents.
PUBLISHED:
INLINE_GRAPH bool is_empty() const;
INLINE_GRAPH bool is_singleton() const;
INLINE_GRAPH bool has_arcs() const;
int get_num_nodes() const;
Node *get_node(int index) const;
INLINE_GRAPH int get_num_arcs() const;
NodeRelation *get_arc(int index) const;
Node *get_top_node() const;
INLINE_GRAPH Node *node() const;
INLINE_GRAPH NodeRelation *arc() const;
public:
// Methods to make an ArcChain behave like an STL container.
INLINE_GRAPH const_iterator begin() const;
INLINE_GRAPH const_iterator end() const;
+40
View File
@@ -0,0 +1,40 @@
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
dtoolutil:c dtoolbase:c dtool:m
#begin lib_target
#define TARGET pgui
#define LOCAL_LIBS \
text tform graph linmath event putil gobj \
mathutil sgraph sgraphutil
// #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
#define SOURCES \
config_pgui.h \
pgButton.I pgButton.h \
pgFrameStyle.I pgFrameStyle.h \
pgItem.I pgItem.h \
pgMouseWatcherRegion.I pgMouseWatcherRegion.h \
pgTop.I pgTop.h
// #define INCLUDED_SOURCES \
#define SOURCES $[SOURCES] \
config_pgui.cxx \
pgButton.cxx \
pgFrameStyle.cxx \
pgItem.cxx \
pgMouseWatcherRegion.cxx \
pgTop.cxx
#define INSTALL_HEADERS \
pgButton.I pgButton.h \
pgFrameStyle.I pgFrameStyle.h \
pgItem.I pgItem.h \
pgMouseWatcherRegion.I pgMouseWatcherRegion.h \
pgTop.I pgTop.h
#define IGATESCAN all
#end lib_target
+35
View File
@@ -0,0 +1,35 @@
// Filename: config_pgui.cxx
// Created by: drose (02Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "config_pgui.h"
#include "pgButton.h"
#include "pgItem.h"
#include "pgMouseWatcherRegion.h"
#include "pgTop.h"
#include "dconfig.h"
Configure(config_pgui);
NotifyCategoryDef(pgui, "");
ConfigureFn(config_pgui) {
PGButton::init_type();
PGItem::init_type();
PGMouseWatcherRegion::init_type();
PGTop::init_type();
}
+27
View File
@@ -0,0 +1,27 @@
// Filename: config_pgui.h
// Created by: drose (02Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef CONFIG_PGUI_H
#define CONFIG_PGUI_H
#include <pandabase.h>
#include <notifyCategoryProxy.h>
NotifyCategoryDecl(pgui, EXPCL_PANDA, EXPTP_PANDA);
#endif
+78
View File
@@ -0,0 +1,78 @@
// Filename: pgButton.I
// Created by: drose (03Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: PGButton::setup
// Access: Published
// Description: Sets up the button using the indicated NodePath as
// arbitrary geometry.
////////////////////////////////////////////////////////////////////
INLINE void PGButton::
setup(const ArcChain &ready) {
setup(ready, ready, ready, ready);
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::setup
// Access: Published
// Description: Sets up the button using the indicated NodePath as
// arbitrary geometry.
////////////////////////////////////////////////////////////////////
INLINE void PGButton::
setup(const ArcChain &ready, const ArcChain &depressed) {
setup(ready, depressed, ready, ready);
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::setup
// Access: Published
// Description: Sets up the button using the indicated NodePath as
// arbitrary geometry.
////////////////////////////////////////////////////////////////////
INLINE void PGButton::
setup(const ArcChain &ready, const ArcChain &depressed,
const ArcChain &rollover) {
setup(ready, depressed, rollover, ready);
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::set_active
// Access: Public
// Description: Toggles the active/inactive state of the button. In
// the case of a PGButton, this also changes its visual
// appearance.
////////////////////////////////////////////////////////////////////
INLINE void PGButton::
set_active(bool active) {
if (active != get_active()) {
set_state(active ? S_ready : S_inactive);
PGItem::set_active(active);
}
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::get_click_event
// Access: Published
// Description: Returns the event name that will be thrown when the
// button is clicked normally.
////////////////////////////////////////////////////////////////////
INLINE string PGButton::
get_click_event() const {
return "click-" + get_id();
}
+212
View File
@@ -0,0 +1,212 @@
// Filename: pgButton.cxx
// Created by: drose (03Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "pgButton.h"
#include "throw_event.h"
#include "renderRelation.h"
#include "colorTransition.h"
TypeHandle PGButton::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: PGButton::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
PGButton::
PGButton(const string &name) : PGItem(name)
{
_button_down = false;
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PGButton::
~PGButton() {
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PGButton::
PGButton(const PGButton &copy) :
PGItem(copy)
{
_button_down = false;
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void PGButton::
operator = (const PGButton &copy) {
PGItem::operator = (copy);
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::make_copy
// Access: Public, Virtual
// Description: Returns a newly-allocated Node that is a shallow copy
// of this one. It will be a different Node pointer,
// but its internal data may or may not be shared with
// that of the original Node.
////////////////////////////////////////////////////////////////////
Node *PGButton::
make_copy() const {
return new PGButton(*this);
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::enter
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever the
// mouse enters the region.
////////////////////////////////////////////////////////////////////
void PGButton::
enter() {
if (get_active()) {
set_state(_button_down ? S_depressed : S_rollover);
}
PGItem::enter();
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::exit
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever the
// mouse exits the region.
////////////////////////////////////////////////////////////////////
void PGButton::
exit() {
if (get_active()) {
set_state(S_ready);
}
PGItem::exit();
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::button_down
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever a
// mouse or keyboard button is depressed while the mouse
// is within the region.
////////////////////////////////////////////////////////////////////
void PGButton::
button_down(ButtonHandle button) {
if (get_active()) {
_button_down = true;
set_state(S_depressed);
}
PGItem::button_down(button);
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::button_up
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever a
// mouse or keyboard button previously depressed with
// button_down() is release. The bool is_within flag is
// true if the button was released while the mouse was
// still within the region, or false if it was released
// outside the region.
////////////////////////////////////////////////////////////////////
void PGButton::
button_up(ButtonHandle button, bool is_within) {
_button_down = false;
if (get_active()) {
if (is_within) {
set_state(S_rollover);
click();
} else {
set_state(S_ready);
}
}
PGItem::button_up(button, is_within);
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::click
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever the
// button is clicked normally.
////////////////////////////////////////////////////////////////////
void PGButton::
click() {
throw_event(get_click_event());
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::setup
// Access: Published
// Description: Sets up the button as a default text button using the
// indicated label string. The TextNode defined by
// PGItem::get_text_node() will be used to create the
// label geometry. This automatically sets up the frame
// according to the size of the text.
////////////////////////////////////////////////////////////////////
void PGButton::
setup(const string &label) {
TextNode *text_node = get_text_node();
text_node->set_text(label);
PT_Node geom = text_node->generate();
new RenderRelation(get_state_def(S_ready), geom);
NodeRelation *dep = new RenderRelation(get_state_def(S_depressed), geom);
new RenderRelation(get_state_def(S_rollover), geom);
new RenderRelation(get_state_def(S_inactive), geom);
PGFrameStyle style;
style.set_type(PGFrameStyle::T_flat);
style.set_color(1.0, 1.0, 1.0, 1.0);
set_frame_style(S_ready, style);
style.set_color(0.0, 0.0, 0.0, 1.0);
set_frame_style(S_depressed, style);
ColorTransition *col_trans = new ColorTransition(Colorf(0.0, 1.0, 1.0, 1.0));
dep->set_transition(col_trans);
style.set_color(1.0, 1.0, 0.0, 1.0);
set_frame_style(S_rollover, style);
style.set_color(0.6, 0.6, 0.6, 1.0);
set_frame_style(S_inactive, style);
set_frame(text_node->get_card_actual());
}
////////////////////////////////////////////////////////////////////
// Function: PGButton::setup
// Access: Published
// Description: Sets up the button using the indicated NodePath as
// arbitrary geometry.
////////////////////////////////////////////////////////////////////
void PGButton::
setup(const ArcChain &ready, const ArcChain &depressed,
const ArcChain &rollover, const ArcChain &inactive) {
instance_to_state_def(S_ready, ready);
instance_to_state_def(S_depressed, depressed);
instance_to_state_def(S_rollover, rollover);
instance_to_state_def(S_inactive, inactive);
}
+95
View File
@@ -0,0 +1,95 @@
// Filename: pgButton.h
// Created by: drose (03Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef PGBUTTON_H
#define PGBUTTON_H
#include "pandabase.h"
#include "pgItem.h"
#include "arcChain.h"
////////////////////////////////////////////////////////////////////
// Class : PGButton
// Description : This is a particular kind of PGItem that is
// specialized to behave like a normal button object.
// It keeps track of its own state, and handles mouse
// events sensibly.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PGButton : public PGItem {
PUBLISHED:
PGButton(const string &name = "");
virtual ~PGButton();
public:
PGButton(const PGButton &copy);
void operator = (const PGButton &copy);
virtual Node *make_copy() const;
virtual void enter();
virtual void exit();
virtual void button_down(ButtonHandle button);
virtual void button_up(ButtonHandle button, bool is_within);
virtual void click();
PUBLISHED:
enum State {
S_ready = 0,
S_depressed,
S_rollover,
S_inactive
};
void setup(const string &label);
INLINE void setup(const ArcChain &ready);
INLINE void setup(const ArcChain &ready, const ArcChain &depressed);
INLINE void setup(const ArcChain &ready, const ArcChain &depressed,
const ArcChain &rollover);
void setup(const ArcChain &ready, const ArcChain &depressed,
const ArcChain &rollover, const ArcChain &inactive);
INLINE void set_active(bool active);
INLINE string get_click_event() const;
private:
bool _button_down;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
PGItem::init_type();
register_type(_type_handle, "PGButton",
PGItem::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "pgButton.I"
#endif
+150
View File
@@ -0,0 +1,150 @@
// Filename: pgFrameStyle.I
// Created by: drose (03Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE PGFrameStyle::
PGFrameStyle() {
_type = T_none;
_color.set(1.0, 1.0, 1.0, 1.0);
_width = 0.01;
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE PGFrameStyle::
PGFrameStyle(const PGFrameStyle &copy) :
_type(copy._type),
_color(copy._color),
_width(copy._width)
{
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE void PGFrameStyle::
operator = (const PGFrameStyle &copy) {
_type = copy._type;
_color = copy._color;
_width = copy._width;
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::Destructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE PGFrameStyle::
~PGFrameStyle() {
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::set_type
// Access: Published
// Description: Sets the basic type of frame.
////////////////////////////////////////////////////////////////////
INLINE void PGFrameStyle::
set_type(PGFrameStyle::Type type) {
_type = type;
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::get_type
// Access: Published
// Description: Returns the basic type of frame.
////////////////////////////////////////////////////////////////////
INLINE PGFrameStyle::Type PGFrameStyle::
get_type() const {
return _type;
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::set_color
// Access: Published
// Description: Sets the dominant color of the frame.
////////////////////////////////////////////////////////////////////
INLINE void PGFrameStyle::
set_color(float r, float g, float b, float a) {
set_color(Colorf(r, g, b, a));
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::set_color
// Access: Published
// Description: Sets the dominant color of the frame.
////////////////////////////////////////////////////////////////////
INLINE void PGFrameStyle::
set_color(const Colorf &color) {
_color = color;
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::set_color
// Access: Published
// Description: Returns the dominant color of the frame.
////////////////////////////////////////////////////////////////////
INLINE const Colorf &PGFrameStyle::
get_color() const {
return _color;
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::set_width
// Access: Published
// Description: Sets the width parameter, which has meaning only for
// certain frame types. For instance, this is the width
// of the bevel for T_bevel_in or T_bevel_out. The
// units are in screen units.
////////////////////////////////////////////////////////////////////
INLINE void PGFrameStyle::
set_width(float width) {
_width = width;
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::get_width
// Access: Published
// Description: Returns the width parameter, which has meaning only
// for certain frame types. For instance, this is the
// width of the bevel for T_bevel_in or T_bevel_out.
// The units are in screen units.
////////////////////////////////////////////////////////////////////
INLINE float PGFrameStyle::
get_width() const {
return _width;
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle ostream output
// Description:
////////////////////////////////////////////////////////////////////
INLINE ostream &
operator << (ostream &out, const PGFrameStyle &pfs) {
pfs.output(out);
return out;
}
+133
View File
@@ -0,0 +1,133 @@
// Filename: pgFrameStyle.cxx
// Created by: drose (03Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "pgFrameStyle.h"
#include "geomTristrip.h"
#include "geomNode.h"
#include "transparencyProperty.h"
#include "transparencyTransition.h"
#include "renderRelation.h"
ostream &
operator << (ostream &out, PGFrameStyle::Type type) {
switch (type) {
case PGFrameStyle::T_none:
return out << "none";
case PGFrameStyle::T_flat:
return out << "flat";
case PGFrameStyle::T_bevel_out:
return out << "bevel_out";
case PGFrameStyle::T_bevel_in:
return out << "bevel_in";
}
return out << "**unknown(" << (int)type << ")**";
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::output
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void PGFrameStyle::
output(ostream &out) const {
out << _type << " color = " << _color << " width = " << _width;
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::generate_into
// Access: Public
// Description: Generates geometry representing a frame of the
// indicated size, and parents it to the indicated node,
// with a scene graph sort order of -1.
//
// The return value is the generated arc, if any, or
// NULL if nothing is generated.
////////////////////////////////////////////////////////////////////
NodeRelation *PGFrameStyle::
generate_into(Node *node, const LVecBase4f &frame) {
NodeRelation *arc = (NodeRelation *)NULL;
PT(Geom) geom;
switch (_type) {
case T_none:
return (NodeRelation *)NULL;
case T_flat:
geom = generate_flat_geom(frame);
break;
default:
break;
}
if (geom != (Geom *)NULL) {
// We've got a basic Geom; create a GeomNode for it.
PT(GeomNode) gnode = new GeomNode("frame");
gnode->add_geom(geom);
arc = new RenderRelation(node, gnode, -1);
}
if (arc != (NodeRelation *)NULL && _color[3] != 1.0) {
// We've got some alpha on the color; we need transparency.
TransparencyProperty::Mode mode = TransparencyProperty::M_alpha;
TransparencyTransition *tt = new TransparencyTransition(mode);
arc->set_transition(tt);
}
return arc;
}
////////////////////////////////////////////////////////////////////
// Function: PGFrameStyle::generate_flat_geom
// Access: Public
// Description: Generates the Geom object appropriate to a T_flat
// frame.
////////////////////////////////////////////////////////////////////
PT(Geom) PGFrameStyle::
generate_flat_geom(const LVecBase4f &frame) {
PT(Geom) geom = new GeomTristrip;
float left = frame[0];
float right = frame[1];
float bottom = frame[2];
float top = frame[3];
PTA_int lengths(0);
lengths.push_back(4);
PTA_Vertexf verts;
verts.push_back(Vertexf(left, 0.0, top));
verts.push_back(Vertexf(left, 0.0, bottom));
verts.push_back(Vertexf(right, 0.0, top));
verts.push_back(Vertexf(right, 0.0, bottom));
geom->set_num_prims(1);
geom->set_lengths(lengths);
geom->set_coords(verts, G_PER_VERTEX);
PTA_Colorf colors;
colors.push_back(_color);
geom->set_colors(colors, G_OVERALL);
return geom;
}
+79
View File
@@ -0,0 +1,79 @@
// Filename: pgFrameStyle.h
// Created by: drose (03Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef PGFRAMESTYLE_H
#define PGFRAMESTYLE_H
#include "pandabase.h"
#include "luse.h"
#include "geom.h"
#include "pointerTo.h"
class NodeRelation;
class Node;
////////////////////////////////////////////////////////////////////
// Class : PGFrameStyle
// Description :
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PGFrameStyle {
PUBLISHED:
INLINE PGFrameStyle();
INLINE PGFrameStyle(const PGFrameStyle &copy);
INLINE void operator = (const PGFrameStyle &copy);
INLINE ~PGFrameStyle();
enum Type {
T_none,
T_flat,
T_bevel_out,
T_bevel_in
};
INLINE void set_type(Type type);
INLINE Type get_type() const;
INLINE void set_color(float r, float g, float b, float a);
INLINE void set_color(const Colorf &color);
INLINE const Colorf &get_color() const;
INLINE void set_width(float width);
INLINE float get_width() const;
void output(ostream &out) const;
public:
NodeRelation *generate_into(Node *node, const LVecBase4f &frame);
private:
PT(Geom) generate_flat_geom(const LVecBase4f &frame);
private:
Type _type;
Colorf _color;
float _width;
};
INLINE ostream &operator << (ostream &out, const PGFrameStyle &pfs);
ostream &operator << (ostream &out, PGFrameStyle::Type type);
#include "pgFrameStyle.I"
#endif
+233
View File
@@ -0,0 +1,233 @@
// Filename: pgItem.I
// Created by: drose (02Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: PGItem::get_region
// Access: Public
// Description: Returns the MouseWatcherRegion associated with this
// item. Every PGItem has a MouseWatcherRegion
// associated with it, that is created when the PGItem
// is created; it does not change during the lifetime of
// the PGItem. Even items that do not have a frame have
// an associated MouseWatcherRegion, although it will
// not be used in this case.
////////////////////////////////////////////////////////////////////
INLINE PGMouseWatcherRegion *PGItem::
get_region() const {
return _region;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::set_frame
// Access: Published
// Description: Sets the bounding rectangle of the item, in local
// coordinates. This is the region on screen within
// which the mouse will be considered to be within the
// item. Normally, it should correspond to the bounding
// rectangle of the visible geometry of the item.
////////////////////////////////////////////////////////////////////
INLINE void PGItem::
set_frame(float left, float right, float bottom, float top) {
set_frame(LVecBase4f(left, right, bottom, top));
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::set_frame
// Access: Published
// Description: Sets the bounding rectangle of the item, in local
// coordinates. This is the region on screen within
// which the mouse will be considered to be within the
// item. Normally, it should correspond to the bounding
// rectangle of the visible geometry of the item.
////////////////////////////////////////////////////////////////////
INLINE void PGItem::
set_frame(const LVecBase4f &frame) {
_has_frame = true;
_frame = frame;
mark_frames_stale();
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::get_frame
// Access: Published
// Description: Returns the bounding rectangle of the item. See
// set_frame(). It is an error to call this if
// has_frame() returns false.
////////////////////////////////////////////////////////////////////
INLINE const LVecBase4f &PGItem::
get_frame() const {
nassertr(has_frame(), _frame);
return _frame;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::has_frame
// Access: Published
// Description: Returns true if the item has a bounding rectangle;
// see set_frame().
////////////////////////////////////////////////////////////////////
INLINE bool PGItem::
has_frame() const {
return _has_frame;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::clear_frame
// Access: Published
// Description: Removes the bounding rectangle from the item. It
// will no longer be possible to position the mouse
// within the item; see set_frame().
////////////////////////////////////////////////////////////////////
INLINE void PGItem::
clear_frame() {
_has_frame = false;
mark_frames_stale();
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::set_state
// Access: Published
// Description: Sets the "state" of this particular PGItem.
//
// The PGItem node will render as if it were the
// subgraph assigned to the corresponding index via
// set_state_def().
////////////////////////////////////////////////////////////////////
INLINE void PGItem::
set_state(int state) {
_state = state;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::get_state
// Access: Published
// Description: Returns the "state" of this particular PGItem. See
// set_state().
////////////////////////////////////////////////////////////////////
INLINE int PGItem::
get_state() const {
return _state;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::set_active
// Access: Published
// Description: Sets whether the PGItem is active for mouse watching.
// This is not necessarily related to the
// active/inactive appearance of the item, which is
// controlled by set_state(), but it does affect whether
// it responds to mouse events.
////////////////////////////////////////////////////////////////////
INLINE void PGItem::
set_active(bool active) {
_active = active;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::get_active
// Access: Published
// Description: Returns whether the PGItem is currently active for
// mouse events. See set_active().
////////////////////////////////////////////////////////////////////
INLINE bool PGItem::
get_active() const {
return _active;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::get_id
// Access: Published
// Description: Returns the unique ID assigned to this PGItem. This
// will be assigned to the region created with the
// MouseWatcher, and will thus be used to generate event
// names.
////////////////////////////////////////////////////////////////////
INLINE const string &PGItem::
get_id() const {
return _region->get_name();
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::get_enter_event
// Access: Published
// Description: Returns the event name that will be thrown when the
// item is active and the mouse enters its frame.
////////////////////////////////////////////////////////////////////
INLINE string PGItem::
get_enter_event() const {
return "enter-" + get_id();
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::get_exit_event
// Access: Published
// Description: Returns the event name that will be thrown when the
// item is active and the mouse exits its frame.
////////////////////////////////////////////////////////////////////
INLINE string PGItem::
get_exit_event() const {
return "exit-" + get_id();
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::get_button_down_event
// Access: Published
// Description: Returns the event name that will be thrown when the
// item is active and a mouse or keyboard button is
// depressed while the mouse is within the frame.
//
// This event will be thrown with one parameter, which
// will be the name of the button that generated the
// event.
////////////////////////////////////////////////////////////////////
INLINE string PGItem::
get_button_down_event() const {
return "bdown-" + get_id();
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::get_button_up_event
// Access: Published
// Description: Returns the event name that will be thrown when the
// item is active and a mouse or keyboard button,
// formerly clicked down is within the frame, is
// released.
//
// This event will be thrown with two parameters, the
// first of which will be the name of the button that
// generated the event, and the second of which will be
// a boolean flag indicating true if the mouse was
// within the frame while the button was released.
////////////////////////////////////////////////////////////////////
INLINE string PGItem::
get_button_up_event() const {
return "bup-" + get_id();
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::set_text_node
// Access: Published, Static
// Description: Changes the TextNode object that will be used by all
// PGItems to generate default labels given a string.
// This can be loaded with the default font, etc.
////////////////////////////////////////////////////////////////////
INLINE void PGItem::
set_text_node(TextNode *node) {
_text_node = node;
}
+396
View File
@@ -0,0 +1,396 @@
// Filename: pgItem.cxx
// Created by: drose (02Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "pgItem.h"
#include "namedNode.h"
#include "throw_event.h"
#include "string_utils.h"
#include "arcChain.h"
TypeHandle PGItem::_type_handle;
PT(TextNode) PGItem::_text_node;
////////////////////////////////////////////////////////////////////
// Function: PGItem::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
PGItem::
PGItem(const string &name) : NamedNode(name)
{
_has_frame = false;
_frame.set(0, 0, 0, 0);
_region = new PGMouseWatcherRegion(this);
_state = 0;
_active = true;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PGItem::
~PGItem() {
nassertv(_region->_item == this);
_region->_item = (PGItem *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PGItem::
PGItem(const PGItem &copy) :
NamedNode(copy),
_has_frame(copy._has_frame),
_frame(copy._frame),
_state(copy._state),
_active(copy._active)
{
_region = new PGMouseWatcherRegion(this);
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void PGItem::
operator = (const PGItem &copy) {
NamedNode::operator = (copy);
_has_frame = copy._has_frame;
_frame = copy._frame;
_state = copy._state;
_active = copy._active;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::make_copy
// Access: Public, Virtual
// Description: Returns a newly-allocated Node that is a shallow copy
// of this one. It will be a different Node pointer,
// but its internal data may or may not be shared with
// that of the original Node.
////////////////////////////////////////////////////////////////////
Node *PGItem::
make_copy() const {
return new PGItem(*this);
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::activate_region
// Access: Public, Virtual
// Description: Applies the indicated scene graph transform and order
// as determined by the traversal from PGTop.
////////////////////////////////////////////////////////////////////
void PGItem::
activate_region(const LMatrix4f &transform, int sort) {
LPoint3f ll(_frame[0], 0.0, _frame[2]);
LPoint3f ur(_frame[1], 0.0, _frame[3]);
ll = ll * transform;
ur = ur * transform;
_region->set_frame(ll[0], ur[0], ll[2], ur[2]);
_region->set_sort(sort);
_region->set_active(true);
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::enter
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever the
// mouse enters the region.
////////////////////////////////////////////////////////////////////
void PGItem::
enter() {
throw_event(get_enter_event());
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::exit
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever the
// mouse exits the region.
////////////////////////////////////////////////////////////////////
void PGItem::
exit() {
throw_event(get_exit_event());
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::button_down
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever a
// mouse or keyboard button is depressed while the mouse
// is within the region.
////////////////////////////////////////////////////////////////////
void PGItem::
button_down(ButtonHandle button) {
throw_event(get_button_down_event(), button.get_name());
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::button_up
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever a
// mouse or keyboard button previously depressed with
// button_down() is release. The bool is_within flag is
// true if the button was released while the mouse was
// still within the region, or false if it was released
// outside the region.
////////////////////////////////////////////////////////////////////
void PGItem::
button_up(ButtonHandle button, bool is_within) {
throw_event(get_button_up_event(),
EventParameter(button.get_name()),
EventParameter(is_within));
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::get_num_state_defs
// Access: Published
// Description: Returns one more than the highest-numbered state def
// that was ever assigned to the PGItem. The complete
// set of state defs assigned may then be retrieved by
// indexing from 0 to (get_num_state_defs() - 1).
//
// This is only an upper limit on the actual number of
// state defs, since there may be holes in the list.
////////////////////////////////////////////////////////////////////
int PGItem::
get_num_state_defs() const {
return _state_defs.size();
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::has_state_def
// Access: Published
// Description: Returns true if get_state_def() has ever been called
// for the indicated state (thus defining a render
// subgraph for this state index), false otherwise.
////////////////////////////////////////////////////////////////////
bool PGItem::
has_state_def(int state) const {
if (state < 0 || state >= (int)_state_defs.size()) {
return false;
}
return (_state_defs[state]._node != (Node *)NULL);
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::clear_state_def
// Access: Published
// Description: Resets the NodePath assigned to the indicated state
// to its initial default, with only a frame
// representation if appropriate.
////////////////////////////////////////////////////////////////////
void PGItem::
clear_state_def(int state) {
if (state < 0 || state >= (int)_state_defs.size()) {
return;
}
Node *def = _state_defs[state]._node;
if (def != (Node *)NULL) {
// Remove all the children from this node.
int num_children = def->get_num_children(RenderRelation::get_class_type());
while (num_children > 0) {
nassertv(num_children == def->get_num_children(RenderRelation::get_class_type()));
NodeRelation *arc =
def->get_child(RenderRelation::get_class_type(), num_children - 1);
remove_arc(arc);
num_children--;
}
}
_state_defs[state]._frame_arc = (NodeRelation *)NULL;
_state_defs[state]._frame_stale = true;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::get_state_def
// Access: Published
// Description: Returns the Node that is the root of the subgraph
// that will be drawn when the PGItem is in the
// indicated state. The first time this is called for a
// particular state index, it may create the Node.
////////////////////////////////////////////////////////////////////
Node *PGItem::
get_state_def(int state) {
nassertr(state < 1000, (Node *)NULL); // Sanity check.
slot_state_def(state);
if (_state_defs[state]._node == (Node *)NULL) {
// Create a new node.
_state_defs[state]._node = new NamedNode("state_" + format_string(state));
_state_defs[state]._frame_stale = true;
}
if (_state_defs[state]._frame_stale) {
update_frame(state);
}
return _state_defs[state]._node;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::instance_to_state_def
// Access: Published
// Description: Parents an instance of the bottom node of the
// indicated ArcChain (normally a NodePath) to the
// indicated state index.
////////////////////////////////////////////////////////////////////
void PGItem::
instance_to_state_def(int state, const ArcChain &chain) {
if (chain.empty()) {
// If the chain is empty, quietly do nothing.
return;
}
NodeRelation *new_arc =
new RenderRelation(get_state_def(state), chain.node());
if (chain.has_arcs()) {
// If the chain has an arc, copy the transitions from it.
new_arc->copy_transitions_from(chain.arc());
}
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::get_frame_style
// Access: Published
// Description: Returns the kind of frame that will be drawn behind
// the item when it is in the indicated state.
////////////////////////////////////////////////////////////////////
PGFrameStyle PGItem::
get_frame_style(int state) {
if (state < 0 || state >= (int)_state_defs.size()) {
return PGFrameStyle();
}
return _state_defs[state]._frame_style;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::set_frame_style
// Access: Published
// Description: Changes the kind of frame that will be drawn behind
// the item when it is in the indicated state.
////////////////////////////////////////////////////////////////////
void PGItem::
set_frame_style(int state, const PGFrameStyle &style) {
// Get the state def node, mainly to ensure that this state is
// slotted and listed as having been defined.
Node *def = get_state_def(state);
nassertv(def != (Node *)NULL);
_state_defs[state]._frame_style = style;
_state_defs[state]._frame_stale = true;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::get_text_node
// Access: Published, Static
// Description: Returns the TextNode object that will be used by all
// PGItems to generate default labels given a string.
// This can be loaded with the default font, etc.
////////////////////////////////////////////////////////////////////
TextNode *PGItem::
get_text_node() {
if (_text_node == (TextNode *)NULL) {
_text_node = new TextNode("pguiText");
_text_node->freeze();
_text_node->set_text_color(0.0, 0.0, 0.0, 1.0);
_text_node->set_align(TM_ALIGN_CENTER);
}
return _text_node;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::slot_state_def
// Access: Private
// Description: Ensures there is a slot in the array for the given
// state definition.
////////////////////////////////////////////////////////////////////
void PGItem::
slot_state_def(int state) {
while (state >= (int)_state_defs.size()) {
StateDef def;
def._frame_stale = true;
_state_defs.push_back(def);
}
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::update_frame
// Access: Private
// Description: Generates a new instance of the frame geometry for
// the indicated state.
////////////////////////////////////////////////////////////////////
void PGItem::
update_frame(int state) {
// First, remove the old frame geometry, if any.
if (state >= 0 && state < (int)_state_defs.size()) {
NodeRelation *old_arc = _state_defs[state]._frame_arc;
if (old_arc != (NodeRelation *)NULL) {
if (old_arc->is_attached()) {
remove_arc(old_arc);
_state_defs[state]._frame_arc = (NodeRelation *)NULL;
}
}
}
// We must turn off the stale flag first, before we call
// get_state_def(), to prevent get_state_def() from being a
// recursive call.
_state_defs[state]._frame_stale = false;
// Now create new frame geometry.
if (has_frame()) {
Node *node = get_state_def(state);
nassertv(node != (Node *)NULL);
_state_defs[state]._frame_arc =
_state_defs[state]._frame_style.generate_into(node, _frame);
}
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::mark_frames_stale
// Access: Private
// Description: Marks all the frames in all states stale, so that
// they will be regenerated the next time each state is
// requested.
////////////////////////////////////////////////////////////////////
void PGItem::
mark_frames_stale() {
StateDefs::iterator di;
for (di = _state_defs.begin(); di != _state_defs.end(); ++di) {
// Remove the old frame, if any.
NodeRelation *old_arc = (*di)._frame_arc;
if (old_arc != (NodeRelation *)NULL) {
if (old_arc->is_attached()) {
remove_arc(old_arc);
(*di)._frame_arc = (NodeRelation *)NULL;
}
}
(*di)._frame_stale = true;
}
}
+145
View File
@@ -0,0 +1,145 @@
// Filename: pgItem.h
// Created by: drose (02Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef PGITEM_H
#define PGITEM_H
#include "pandabase.h"
#include "pgMouseWatcherRegion.h"
#include "pgFrameStyle.h"
#include "namedNode.h"
#include "nodeRelation.h"
#include "luse.h"
#include "pointerTo.h"
#include "pt_Node.h"
#include "pt_NodeRelation.h"
#include "textNode.h"
class ArcChain;
////////////////////////////////////////////////////////////////////
// Class : PGItem
// Description : This is the base class for all the various kinds of
// gui widget objects.
//
// It is a Node which corresponds to a rectangular
// region on the screen, and it may have any number of
// "state" subgraphs, one of which is rendered at any
// given time according to its current state.
//
// The PGItem node must be parented to the scene graph
// somewhere beneath a PGTop node in order for this
// behavior to work.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PGItem : public NamedNode {
PUBLISHED:
PGItem(const string &name = "");
virtual ~PGItem();
public:
PGItem(const PGItem &copy);
void operator = (const PGItem &copy);
virtual Node *make_copy() const;
void activate_region(const LMatrix4f &transform, int sort);
INLINE PGMouseWatcherRegion *get_region() const;
virtual void enter();
virtual void exit();
virtual void button_down(ButtonHandle button);
virtual void button_up(ButtonHandle button, bool is_within);
PUBLISHED:
INLINE void set_frame(float left, float right, float bottom, float top);
INLINE void set_frame(const LVecBase4f &frame);
INLINE const LVecBase4f &get_frame() const;
INLINE bool has_frame() const;
INLINE void clear_frame();
INLINE void set_state(int state);
INLINE int get_state() const;
INLINE void set_active(bool active);
INLINE bool get_active() const;
int get_num_state_defs() const;
void clear_state_def(int state);
bool has_state_def(int state) const;
Node *get_state_def(int state);
void instance_to_state_def(int state, const ArcChain &chain);
PGFrameStyle get_frame_style(int state);
void set_frame_style(int state, const PGFrameStyle &style);
INLINE const string &get_id() const;
INLINE string get_enter_event() const;
INLINE string get_exit_event() const;
INLINE string get_button_down_event() const;
INLINE string get_button_up_event() const;
static TextNode *get_text_node();
INLINE static void set_text_node(TextNode *node);
private:
void slot_state_def(int state);
void update_frame(int state);
void mark_frames_stale();
bool _has_frame;
LVecBase4f _frame;
int _state;
bool _active;
PT(PGMouseWatcherRegion) _region;
class StateDef {
public:
PT_Node _node;
PGFrameStyle _frame_style;
PT_NodeRelation _frame_arc;
bool _frame_stale;
};
typedef pvector<StateDef> StateDefs;
StateDefs _state_defs;
static PT(TextNode) _text_node;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
NamedNode::init_type();
register_type(_type_handle, "PGItem",
NamedNode::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "pgItem.I"
#endif
+18
View File
@@ -0,0 +1,18 @@
// Filename: pgMouseWatcherRegion.I
// Created by: drose (02Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
+106
View File
@@ -0,0 +1,106 @@
// Filename: pgMouseWatcherRegion.cxx
// Created by: drose (02Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "pgMouseWatcherRegion.h"
#include "pgItem.h"
#include "string_utils.h"
TypeHandle PGMouseWatcherRegion::_type_handle;
int PGMouseWatcherRegion::_next_index = 0;
////////////////////////////////////////////////////////////////////
// Function: PGMouseWatcherRegion::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PGMouseWatcherRegion::
PGMouseWatcherRegion(PGItem *item) :
#ifndef CPPPARSER
MouseWatcherRegion("pg" + format_string(_next_index++), 0, 0, 0, 0),
#endif
_item(item)
{
}
////////////////////////////////////////////////////////////////////
// Function: PGMouseWatcherRegion::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PGMouseWatcherRegion::
~PGMouseWatcherRegion() {
}
////////////////////////////////////////////////////////////////////
// Function: PGMouseWatcherRegion::enter
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever the
// mouse enters the region.
////////////////////////////////////////////////////////////////////
void PGMouseWatcherRegion::
enter() {
if (_item != (PGItem *)NULL) {
_item->enter();
}
}
////////////////////////////////////////////////////////////////////
// Function: PGMouseWatcherRegion::exit
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever the
// mouse exits the region.
////////////////////////////////////////////////////////////////////
void PGMouseWatcherRegion::
exit() {
if (_item != (PGItem *)NULL) {
_item->exit();
}
}
////////////////////////////////////////////////////////////////////
// Function: PGMouseWatcherRegion::button_down
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever a
// mouse or keyboard button is depressed while the mouse
// is within the region.
////////////////////////////////////////////////////////////////////
void PGMouseWatcherRegion::
button_down(ButtonHandle button) {
if (_item != (PGItem *)NULL) {
_item->button_down(button);
}
}
////////////////////////////////////////////////////////////////////
// Function: PGMouseWatcherRegion::button_up
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever a
// mouse or keyboard button previously depressed with
// button_down() is release. The bool is_within flag is
// true if the button was released while the mouse was
// still within the region, or false if it was released
// outside the region.
////////////////////////////////////////////////////////////////////
void PGMouseWatcherRegion::
button_up(ButtonHandle button, bool is_within) {
if (_item != (PGItem *)NULL) {
_item->button_up(button, is_within);
}
}
+71
View File
@@ -0,0 +1,71 @@
// Filename: pgMouseWatcherRegion.h
// Created by: drose (02Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef PGMOUSEWATCHERREGION_H
#define PGMOUSEWATCHERREGION_H
#include "pandabase.h"
#include "mouseWatcherRegion.h"
class PGItem;
////////////////////////////////////////////////////////////////////
// Class : PGMouseWatcherRegion
// Description : This is a specialization on MouseWatcherRegion, to
// add a bit more fields that are relevant to the PG
// system. Each PGItem corresponds to exactly one
// PGMouseWatcherRegion.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PGMouseWatcherRegion : public MouseWatcherRegion {
public:
PGMouseWatcherRegion(PGItem *item);
virtual ~PGMouseWatcherRegion();
virtual void enter();
virtual void exit();
virtual void button_down(ButtonHandle button);
virtual void button_up(ButtonHandle button, bool is_within);
private:
PGItem *_item;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
MouseWatcherRegion::init_type();
register_type(_type_handle, "PGMouseWatcherRegion",
MouseWatcherRegion::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
static int _next_index;
friend class PGItem;
};
#include "pgMouseWatcherRegion.I"
#endif
+56
View File
@@ -0,0 +1,56 @@
// Filename: pgTop.I
// Created by: drose (02Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: PGTop::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE PGTop::
PGTop(const PGTop &copy) :
NamedNode(copy),
_watcher(copy._watcher)
{
_gsg = (GraphicsStateGuardian *)NULL;
_trav = (RenderTraverser *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: PGTop::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void PGTop::
operator = (const PGTop &copy) {
NamedNode::operator = (copy);
_watcher = copy._watcher;
}
////////////////////////////////////////////////////////////////////
// Function: PGTop::get_mouse_watcher
// Access: Published
// Description: Returns the MouseWatcher pointer that the PGTop object
// registers its PG items with, or NULL if the
// MouseWatcher has not yet been set.
////////////////////////////////////////////////////////////////////
INLINE MouseWatcher *PGTop::
get_mouse_watcher() const {
return _watcher;
}
+256
View File
@@ -0,0 +1,256 @@
// Filename: pgTop.cxx
// Created by: drose (02Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "pgTop.h"
#include "pgItem.h"
#include "arcChain.h"
#include "graphicsStateGuardian.h"
#include "config_sgraphutil.h"
#include "renderRelation.h"
#include "geomNode.h"
#include "allTransitionsWrapper.h"
#include "allAttributesWrapper.h"
#include "wrt.h"
#include "switchNode.h"
#include "transformTransition.h"
#include "nodeTransitionWrapper.h"
#include "directRenderTraverser.h"
#include "omniBoundingVolume.h"
#include "pruneTransition.h"
TypeHandle PGTop::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: PGTop::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
PGTop::
PGTop(const string &name) : NamedNode(name)
{
_gsg = (GraphicsStateGuardian *)NULL;
_trav = (RenderTraverser *)NULL;
// A PGTop node normally has an infinite bounding volume. Screw
// culling.
set_bound(OmniBoundingVolume());
set_final(true);
}
////////////////////////////////////////////////////////////////////
// Function: PGTop::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PGTop::
~PGTop() {
}
////////////////////////////////////////////////////////////////////
// Function: PGTop::make_copy
// Access: Public, Virtual
// Description: Returns a newly-allocated Node that is a shallow copy
// of this one. It will be a different Node pointer,
// but its internal data may or may not be shared with
// that of the original Node.
////////////////////////////////////////////////////////////////////
Node *PGTop::
make_copy() const {
return new PGTop(*this);
}
////////////////////////////////////////////////////////////////////
// Function: PGTop::sub_render
// Access: Public, Virtual
// Description: Gets called during the draw traversal to render this
// node and all nodes below it. In the case of the
// PGTop node, this uses a depth-first left-to-right
// traversal to render all of the GeomNodes and PGItems
// in the scene graph order.
////////////////////////////////////////////////////////////////////
bool PGTop::
sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &,
RenderTraverser *trav) {
_attrib = attrib;
_gsg = trav->get_gsg();
const ArcChain &chain = trav->get_arc_chain();
// Empty our set of regions in preparation for re-adding whichever
// ones we encounter in the traversal that are current.
clear_regions();
_sort_index = 0;
// Start the traversal below the current node.
const DownRelationPointers &drp =
find_connection(RenderRelation::get_class_type()).get_down();
DownRelationPointers::const_iterator drpi;
for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
NodeRelation *arc = (*drpi);
if (!arc->has_transition(PruneTransition::get_class_type())) {
ArcChain next_chain(chain);
next_chain.push_back(arc);
r_traverse(arc->get_child(), next_chain);
}
}
// We don't need the normal render traverser to do anything else;
// we've done it all.
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PGTop::has_sub_render
// Access: Public, Virtual
// Description: Should be redefined to return true if the function
// sub_render(), above, expects to be called during
// traversal.
////////////////////////////////////////////////////////////////////
bool PGTop::
has_sub_render() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PGTop::set_mouse_watcher
// Access: Published
// Description: Sets the MouseWatcher pointer that the PGTop object
// registers its PG items with. This must be set before
// the PG items are active.
////////////////////////////////////////////////////////////////////
void PGTop::
set_mouse_watcher(MouseWatcher *watcher) {
if (_watcher != (MouseWatcher *)NULL) {
_watcher->remove_group(this);
}
_watcher = watcher;
if (_watcher != (MouseWatcher *)NULL) {
_watcher->add_group(this);
}
}
////////////////////////////////////////////////////////////////////
// Function: PGTop::r_traverse
// Access: Private
// Description: Handles the main recursive traversal of the scene
// graph for nodes below the PGTop node. This
// implements a depth-first traversal.
////////////////////////////////////////////////////////////////////
void PGTop::
r_traverse(Node *node, const ArcChain &chain) {
if (implicit_app_traversal) {
node->app_traverse();
}
node->draw_traverse();
_gsg->_nodes_pcollector.add_level(1);
if (node->is_of_type(PGItem::get_class_type())) {
PGItem *pgi = DCAST(PGItem, node);
if (pgi->has_frame() && pgi->get_active()) {
// The item has a frame, so we want to generate a region for it
// and update the MouseWatcher.
// Get the complete net transform to the PGItem from the top.
LMatrix4f mat;
NodeTransitionWrapper ntw(TransformTransition::get_class_type());
wrt(pgi, chain.begin(), chain.end(), (Node *)NULL,
ntw, RenderRelation::get_class_type());
const TransformTransition *tt;
if (!get_transition_into(tt, ntw)) {
// No relative transform.
mat = LMatrix4f::ident_mat();
return;
}
mat = tt->get_matrix();
// Now apply this transform to the item's frame.
pgi->activate_region(mat, _sort_index);
_sort_index++;
add_region(pgi->get_region());
}
if (pgi->has_state_def(pgi->get_state())) {
// This item has a current state definition that we should use
// to render the item.
Node *def = pgi->get_state_def(pgi->get_state());
// Get the net transitions to the PGItem.
AllTransitionsWrapper complete_trans;
wrt(pgi, chain.begin(), chain.end(), this,
complete_trans, RenderRelation::get_class_type());
// We'll use a normal DirectRenderTraverser to do the rendering
// of the subgraph.
DirectRenderTraverser drt(_gsg, RenderRelation::get_class_type());
drt.traverse(def, _attrib, complete_trans);
}
} else if (node->is_of_type(GeomNode::get_class_type())) {
_gsg->_geom_nodes_pcollector.add_level(1);
GeomNode *geom = DCAST(GeomNode, node);
// Get the complete state of the GeomNode.
AllTransitionsWrapper complete_trans;
wrt(geom, chain.begin(), chain.end(), this,
complete_trans, RenderRelation::get_class_type());
AllAttributesWrapper complete_state;
complete_state.apply_from(_attrib, complete_trans);
_gsg->set_state(complete_state.get_attributes(), true);
// Finally, draw the Geom.
_gsg->prepare_display_region();
geom->draw(_gsg);
}
// Continue the traversal.
const DownRelationPointers &drp =
node->find_connection(RenderRelation::get_class_type()).get_down();
if (node->is_of_type(SwitchNode::get_class_type())) {
SwitchNode *swnode = DCAST(SwitchNode, node);
swnode->compute_switch(_trav);
size_t i = 0;
for (i = 0; i < drp.size(); i++) {
if (swnode->is_child_visible(RenderRelation::get_class_type(), i)) {
NodeRelation *arc = drp[i];
if (!arc->has_transition(PruneTransition::get_class_type())) {
ArcChain next_chain(chain);
next_chain.push_back(arc);
r_traverse(arc->get_child(), next_chain);
}
}
}
} else {
DownRelationPointers::const_iterator drpi;
for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
NodeRelation *arc = (*drpi);
if (!arc->has_transition(PruneTransition::get_class_type())) {
ArcChain next_chain(chain);
next_chain.push_back(arc);
r_traverse(arc->get_child(), next_chain);
}
}
}
}
+99
View File
@@ -0,0 +1,99 @@
// Filename: pgTop.h
// Created by: drose (02Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef PGTOP_H
#define PGTOP_H
#include "pandabase.h"
#include "namedNode.h"
#include "mouseWatcherGroup.h"
#include "mouseWatcher.h"
#include "pointerTo.h"
#include "allAttributesWrapper.h"
class GraphicsStateGuardian;
class RenderTraverser;
class ArcChain;
////////////////////////////////////////////////////////////////////
// Class : PGTop
// Description : The "top" node of the new Panda GUI system. This
// node must be parented to the 2-d scene graph, and all
// PG objects should be parented to this node or
// somewhere below it. PG objects not parented within
// this hierarchy will not even be visible.
//
// This node begins the special traversal of the PG
// objects that registers each node within the
// MouseWatcher and forces everything to render in a
// depth-first, left-to-right order, appropriate for 2-d
// objects.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PGTop : public NamedNode, public MouseWatcherGroup {
PUBLISHED:
PGTop(const string &name = "");
virtual ~PGTop();
public:
INLINE PGTop(const PGTop &copy);
INLINE void operator = (const PGTop &copy);
virtual Node *make_copy() const;
virtual bool sub_render(const AllAttributesWrapper &attrib,
AllTransitionsWrapper &trans,
RenderTraverser *trav);
virtual bool has_sub_render() const;
PUBLISHED:
void set_mouse_watcher(MouseWatcher *watcher);
INLINE MouseWatcher *get_mouse_watcher() const;
private:
void r_traverse(Node *node, const ArcChain &chain);
PT(MouseWatcher) _watcher;
GraphicsStateGuardian *_gsg;
RenderTraverser *_trav;
AllAttributesWrapper _attrib;
int _sort_index;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
NamedNode::init_type();
MouseWatcherGroup::init_type();
register_type(_type_handle, "PGTop",
NamedNode::get_class_type(),
MouseWatcherGroup::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "pgTop.I"
#endif
+25 -83
View File
@@ -51,6 +51,26 @@ NodePath(Node *top_node, TypeHandle graph_type) :
{
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::Constructor
// Access: Public
// Description: Creates a NodePath that contains one arc, and the two
// Nodes connected to that arc.
//
// If the NodeRelation pointer is NULL, this quietly
// creates an empty NodePath.
////////////////////////////////////////////////////////////////////
INLINE NodePath::
NodePath(NodeRelation *arc) :
_graph_type(RenderRelation::get_class_type()),
_error_type(ET_ok)
{
if (arc != (NodeRelation *)NULL) {
_graph_type = arc->get_type();
extend_by(arc);
}
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::Constructor
// Access: Public
@@ -183,12 +203,9 @@ compare_to(const NodePath &other) const {
// Access: Public
// Description: Changes the type of graph that the NodePath will
// search for. By default, this is RenderRelation.
// This may only be called when the NodePath contains no
// arcs (e.g. is_empty() || is_singleton()).
////////////////////////////////////////////////////////////////////
INLINE void NodePath::
set_graph_type(TypeHandle graph_type) {
nassertv(_head == (ArcComponent *)NULL);
_graph_type = graph_type;
}
@@ -242,17 +259,6 @@ get_max_search_depth() {
return _max_search_depth;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::is_empty
// Access: Public
// Description: Returns true if the NodePath contains no nodes and no
// arcs.
////////////////////////////////////////////////////////////////////
INLINE bool NodePath::
is_empty() const {
return !ArcChain::has_node();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_error_type
// Access: Public
@@ -264,74 +270,6 @@ get_error_type() const {
return _error_type;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::is_singleton
// Access: Public
// Description: Returns true if the NodePath contains exactly one
// node, and no arcs.
////////////////////////////////////////////////////////////////////
INLINE bool NodePath::
is_singleton() const {
return ArcChain::has_node() && !ArcChain::has_arcs();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::has_arcs
// Access: Public
// Description: Returns true if the NodePath contains at least one
// arc, and therefore at least two nodes. This is the
// same thing as asking get_num_arcs() > 0, but is
// easier to compute.
////////////////////////////////////////////////////////////////////
INLINE bool NodePath::
has_arcs() const {
return ArcChain::has_arcs();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_num_arcs
// Access: Public
// Description: Returns the number of arcs in the path.
////////////////////////////////////////////////////////////////////
INLINE int NodePath::
get_num_arcs() const {
if (!has_arcs()) {
return 0;
}
return get_num_nodes() - 1;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::node
// Access: Public
// Description: Returns the bottom node of the path, or NULL if the
// path is empty.
////////////////////////////////////////////////////////////////////
INLINE Node *NodePath::
node() const {
nassertr(_error_type == ET_ok, (Node *)NULL);
if (is_empty()) {
return (Node *)NULL;
}
return _head->get_node();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::arc
// Access: Public
// Description: Returns the bottom arc of the path, or NULL if the
// path is empty or is a singleton.
////////////////////////////////////////////////////////////////////
INLINE NodeRelation *NodePath::
arc() const {
nassertr(_error_type == ET_ok, (NodeRelation *)NULL);
if (!has_arcs()) {
// A singleton or empty list.
return (NodeRelation *)NULL;
}
return _head->get_arc();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_num_children
// Access: Public
@@ -449,7 +387,11 @@ attach_new_node(const string &name, int sort) const {
////////////////////////////////////////////////////////////////////
INLINE void NodePath::
output(ostream &out) const {
out << as_string(0);
if (_error_type == ET_ok && is_empty()) {
out << "**empty**";
} else {
out << as_string(0);
}
}
////////////////////////////////////////////////////////////////////
-99
View File
@@ -150,16 +150,6 @@ extend_by(NodeRelation *darc) {
return false;
}
if (darc->get_type() != get_graph_type() &&
darc->get_type() != NodeRelation::get_stashed_type()) {
if (sgmanip_cat.is_debug()) {
sgmanip_cat.debug()
<< "Cannot extend " << *this << " by arc " << *darc
<< "; wrong graph type.\n";
}
return false;
}
_head = new ArcComponent(darc, _head);
return true;
@@ -418,95 +408,6 @@ find_singular_transform() const {
return NodePath::not_found();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_node
// Access: Public
// Description: Returns the nth node of the path, where 0 is the
// bottom node and get_num_nodes() - 1 is the top node.
// This requires iterating through the path.
////////////////////////////////////////////////////////////////////
Node *NodePath::
get_node(int index) const {
nassertr(index >= 0 && index < get_num_nodes(), NULL);
ArcComponent *comp = _head;
while (index > 0) {
// If this assertion fails, the index was out of range.
nassertr(comp != (ArcComponent *)NULL, NULL);
comp = comp->get_next();
index--;
}
// If this assertion fails, the index was out of range.
nassertr(comp != (ArcComponent *)NULL, NULL);
return comp->get_node();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_num_nodes
// Access: Public
// Description: Returns the number of nodes in the path. This is
// always one more than the number of arcs (except for
// a completely empty path).
////////////////////////////////////////////////////////////////////
int NodePath::
get_num_nodes() const {
int num = 0;
ArcComponent *comp = _head;
while (comp != (ArcComponent *)NULL) {
num++;
comp = comp->get_next();
}
return num;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_arc
// Access: Public
// Description: Returns the nth arc of the path, where 0 is the arc
// above the bottom node node and get_num_arcs() - 1 is
// the arc below the top node. This requires iterating
// through the path.
////////////////////////////////////////////////////////////////////
NodeRelation *NodePath::
get_arc(int index) const {
nassertr(index >= 0 && index < get_num_arcs(), NULL);
ArcComponent *comp = _head;
while (index > 0) {
// If this assertion fails, the index was out of range.
nassertr(comp != (ArcComponent *)NULL, NULL);
comp = comp->get_next();
index--;
}
// If either assertion fails, the index was out of range.
nassertr(comp != (ArcComponent *)NULL, NULL);
nassertr(comp->has_arc(), NULL);
return comp->get_arc();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_top_node
// Access: Public
// Description: Returns the top node of the path, or NULL if the path
// is empty. This requires iterating through the path.
////////////////////////////////////////////////////////////////////
Node *NodePath::
get_top_node() const {
if (is_empty()) {
return (Node *)NULL;
}
ArcComponent *comp = _head;
while (!comp->is_top_node()) {
comp = comp->get_next();
nassertr(comp != (ArcComponent *)NULL, NULL);
}
return comp->get_node();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::share_with
// Access: Public
+2 -11
View File
@@ -148,6 +148,7 @@ PUBLISHED:
INLINE NodePath(TypeHandle graph_type = RenderRelation::get_class_type());
INLINE NodePath(Node *top_node, TypeHandle graph_type = RenderRelation::get_class_type());
INLINE NodePath(NodeRelation *arc);
INLINE NodePath(const ArcChain &chain, TypeHandle graph_type);
INLINE NodePath(const NodePath &copy);
@@ -183,19 +184,9 @@ PUBLISHED:
// Methods to query a NodePath's contents.
INLINE bool is_empty() const;
INLINE ErrorType get_error_type() const;
INLINE bool is_singleton() const;
INLINE bool has_arcs() const;
int get_num_nodes() const;
Node *get_node(int index) const;
INLINE int get_num_arcs() const;
NodeRelation *get_arc(int index) const;
Node *get_top_node() const;
INLINE Node *node() const;
INLINE NodeRelation *arc() const;
// Most of these methods are inherited from ArcChain.
// Methods to manage the disconnected NodePaths that can result if
+1 -1
View File
@@ -74,7 +74,7 @@ FrustumCullTraverser(ArcChain &arc_chain, Node *root,
}
}
bool needs_top_node = !_arc_chain.has_node();
bool needs_top_node = _arc_chain.is_empty();
if (needs_top_node) {
// If the ArcChain supplied in is initially empty, put the root
// node in it.
+9 -7
View File
@@ -10,15 +10,17 @@
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
#define SOURCES \
buttonThrower.h config_tform.h dataValve.I dataValve.h \
driveInterface.I driveInterface.h mouseWatcher.I \
mouseWatcher.h mouseWatcherRegion.I mouseWatcherRegion.h \
planarSlider.h trackball.h transform2sg.h
buttonThrower.h config_tform.h dataValve.I dataValve.h \
driveInterface.I driveInterface.h mouseWatcher.I \
mouseWatcher.h mouseWatcherGroup.h \
mouseWatcherRegion.I mouseWatcherRegion.h \
planarSlider.h trackball.h transform2sg.h
#define INCLUDED_SOURCES \
buttonThrower.cxx config_tform.cxx dataValve.cxx \
driveInterface.cxx mouseWatcher.cxx mouseWatcherRegion.cxx \
planarSlider.cxx trackball.cxx transform2sg.cxx
buttonThrower.cxx config_tform.cxx dataValve.cxx \
driveInterface.cxx mouseWatcher.cxx mouseWatcherGroup.cxx \
mouseWatcherRegion.cxx \
planarSlider.cxx trackball.cxx transform2sg.cxx
#define INSTALL_HEADERS \
buttonThrower.h dataValve.I dataValve.h \
+2
View File
@@ -22,6 +22,7 @@
#include "driveInterface.h"
#include "buttonThrower.h"
#include "mouseWatcher.h"
#include "mouseWatcherGroup.h"
#include "mouseWatcherRegion.h"
#include "planarSlider.h"
#include "trackball.h"
@@ -49,6 +50,7 @@ ConfigureFn(config_tform) {
DriveInterface::init_type();
ButtonThrower::init_type();
MouseWatcher::init_type();
MouseWatcherGroup::init_type();
MouseWatcherRegion::init_type();
PlanarSlider::init_type();
Trackball::init_type();
+1 -1
View File
@@ -296,7 +296,7 @@ set_extra_handler(EventHandler *eh) {
// can be registered with a mouseWatcher so that events
// can be dealt with much sooner.
////////////////////////////////////////////////////////////////////
INLINE EventHandler* MouseWatcher::
INLINE EventHandler *MouseWatcher::
get_extra_handler(void) const {
return _eh;
}
+83 -52
View File
@@ -59,34 +59,10 @@ MouseWatcher::
~MouseWatcher() {
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcher::add_region
// Access: Published
// Description: Adds the indicated region to the set of regions that
// are to be watched. Returns true if it was
// successfully added, or false if it was already on the
// list.
////////////////////////////////////////////////////////////////////
bool MouseWatcher::
add_region(MouseWatcherRegion *region) {
return _regions.insert(region).second;
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcher::has_region
// Access: Published
// Description: Returns true if the indicated region has already been
// added to the MouseWatcher, false otherwise.
////////////////////////////////////////////////////////////////////
bool MouseWatcher::
has_region(MouseWatcherRegion *region) const {
return _regions.count(region) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcher::remove_region
// Access: Published
// Description: Removes the indicated region from the Watcher.
// 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.
////////////////////////////////////////////////////////////////////
@@ -98,27 +74,7 @@ remove_region(MouseWatcherRegion *region) {
if (region == _button_down_region) {
_button_down_region = (MouseWatcherRegion *)NULL;
}
return _regions.erase(region) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcher::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 *MouseWatcher::
find_region(const string &name) const {
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;
return MouseWatcherGroup::remove_region(region);
}
////////////////////////////////////////////////////////////////////
@@ -151,6 +107,27 @@ get_over_region(const LPoint2f &pos) const {
}
}
// Also check all of our sub-groups.
Groups::const_iterator gi;
for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
MouseWatcherGroup *group = (*gi);
for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
MouseWatcherRegion *region = (*ri);
const LVecBase4f &frame = region->get_frame();
if (region->get_active() &&
pos[0] >= frame[0] && pos[0] <= frame[1] &&
pos[1] >= frame[2] && pos[1] <= frame[3]) {
// We're over this region. Is it preferred to the other one?
if (over_region == (MouseWatcherRegion *)NULL ||
*region < *over_region) {
over_region = region;
}
}
}
}
return over_region;
}
@@ -180,6 +157,59 @@ write(ostream &out, int indent_level) const {
MouseWatcherRegion *region = (*ri);
region->write(out, indent_level + 2);
}
if (!_groups.empty()) {
Groups::const_iterator gi;
for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
MouseWatcherGroup *group = (*gi);
indent(out, indent_level + 2)
<< "Subgroup:\n";
for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
MouseWatcherRegion *region = (*ri);
region->write(out, indent_level + 4);
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcher::add_group
// Access: Public
// Description: Adds the indicated group of regions to the set of
// regions the MouseWatcher will monitor each frame.
//
// Since the MouseWatcher itself inherits from
// MouseWatcherGroup, this operation is normally not
// necessary--you can simply add the Regions you care
// about one at a time. Adding a complete group is
// useful when you may want to explicitly remove the
// regions as a group later.
//
// Returns true if the group was successfully added, or
// false if it was already on the list.
////////////////////////////////////////////////////////////////////
bool MouseWatcher::
add_group(MouseWatcherGroup *group) {
return _groups.insert(group).second;
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcher::remove_group
// Access: Public
// Description: Removes the indicated group from the set of extra
// groups associated with the MouseWatcher. Returns
// true if successful, or false if the group was already
// removed or was never added via add_group().
////////////////////////////////////////////////////////////////////
bool MouseWatcher::
remove_group(MouseWatcherGroup *group) {
if (group->has_region(_current_region)) {
_current_region = (MouseWatcherRegion *)NULL;
}
if (group->has_region(_button_down_region)) {
_button_down_region = (MouseWatcherRegion *)NULL;
}
return _groups.erase(group) != 0;
}
////////////////////////////////////////////////////////////////////
@@ -198,10 +228,12 @@ set_current_region(MouseWatcherRegion *region) {
#endif
if (region != _current_region) {
if (_current_region != (MouseWatcherRegion *)NULL) {
_current_region->exit();
throw_event_pattern(_leave_pattern, _current_region);
}
_current_region = region;
if (_current_region != (MouseWatcherRegion *)NULL) {
_current_region->enter();
throw_event_pattern(_enter_pattern, _current_region);
}
}
@@ -219,9 +251,11 @@ throw_event_pattern(const string &pattern, const MouseWatcherRegion *region,
if (pattern.empty()) {
return;
}
#ifndef NDEBUG
if (region != (MouseWatcherRegion *)NULL) {
region->test_ref_count_integrity();
}
#endif
string event;
for (size_t p = 0; p < pattern.size(); ++p) {
@@ -323,13 +357,9 @@ transmit_data(NodeAttributes &data) {
// There is some danger of losing button-up events here. If
// more than one button goes down together, we won't detect
// both of the button-up events properly.
// We should probably throw a different button_up event based
// on whether the _current_region is NULL or not, so the
// calling code can differentiate between button_up within the
// starting region, and button_up outside the region.
// Presently, changing this will break the GUI code.
if (_button_down_region != (MouseWatcherRegion *)NULL) {
bool is_within = (_current_region == _button_down_region);
_button_down_region->button_up(be._button, is_within);
throw_event_pattern(_button_up_pattern, _button_down_region,
be._button.get_name());
}
@@ -343,6 +373,7 @@ transmit_data(NodeAttributes &data) {
}
_button_down = true;
if (_button_down_region != (MouseWatcherRegion *)NULL) {
_button_down_region->button_down(be._button);
throw_event_pattern(_button_down_pattern, _button_down_region,
be._button.get_name());
}
+10 -9
View File
@@ -22,6 +22,7 @@
#include <pandabase.h>
#include "mouseWatcherRegion.h"
#include "mouseWatcherGroup.h"
#include <dataNode.h>
#include <vec3DataTransition.h>
@@ -52,15 +53,12 @@
// scene graph. It will move the geometry around
// according to the mouse's known position.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA MouseWatcher : public DataNode {
class EXPCL_PANDA MouseWatcher : public DataNode, public MouseWatcherGroup {
PUBLISHED:
MouseWatcher(const string &name = "");
~MouseWatcher();
bool add_region(MouseWatcherRegion *region);
bool has_region(MouseWatcherRegion *region) const;
bool remove_region(MouseWatcherRegion *region);
MouseWatcherRegion *find_region(const string &name) const;
INLINE bool has_mouse() const;
INLINE const LPoint2f &get_mouse() const;
@@ -93,26 +91,29 @@ PUBLISHED:
INLINE void clear_geometry();
INLINE void set_extra_handler(EventHandler *eh);
INLINE EventHandler* get_extra_handler(void) const;
INLINE EventHandler *get_extra_handler(void) const;
public:
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level = 0) const;
bool add_group(MouseWatcherGroup *group);
bool remove_group(MouseWatcherGroup *group);
private:
void set_current_region(MouseWatcherRegion *region);
void throw_event_pattern(const string &pattern,
const MouseWatcherRegion *region,
const string &button_name = string());
typedef pset< PT(MouseWatcherRegion) > Regions;
Regions _regions;
typedef pset< PT(MouseWatcherGroup) > Groups;
Groups _groups;
bool _has_mouse;
LPoint2f _mouse;
MouseWatcherRegion *_current_region;
MouseWatcherRegion *_button_down_region;
PT(MouseWatcherRegion) _current_region;
PT(MouseWatcherRegion) _button_down_region;
bool _button_down;
string _button_down_pattern;
+87
View File
@@ -0,0 +1,87 @@
// Filename: mouseWatcherGroup.cxx
// Created by: drose (02Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "mouseWatcherGroup.h"
TypeHandle MouseWatcherGroup::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherGroup::add_region
// Access: Published
// Description: Adds the indicated region to the set of regions in
// the group. Returns true if it was successfully
// added, or false if it was already on the list.
////////////////////////////////////////////////////////////////////
bool MouseWatcherGroup::
add_region(MouseWatcherRegion *region) {
return _regions.insert(region).second;
}
////////////////////////////////////////////////////////////////////
// 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 {
return _regions.count(region) != 0;
}
////////////////////////////////////////////////////////////////////
// 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) {
return _regions.erase(region) != 0;
}
////////////////////////////////////////////////////////////////////
// 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 {
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() {
_regions.clear();
}
+60
View File
@@ -0,0 +1,60 @@
// Filename: mouseWatcherGroup.h
// Created by: drose (02Jul01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef MOUSEWATCHERGROUP_H
#define MOUSEWATCHERGROUP_H
#include "pandabase.h"
#include "mouseWatcherRegion.h"
#include "pointerTo.h"
#include "referenceCount.h"
#include "pset.h"
////////////////////////////////////////////////////////////////////
// Class : MouseWatcherGroup
// Description : This represents a collection of MouseWatcherRegions
// that may be managed as a group.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA MouseWatcherGroup : virtual public ReferenceCount {
PUBLISHED:
bool 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();
protected:
typedef pset< PT(MouseWatcherRegion) > Regions;
Regions _regions;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
register_type(_type_handle, "MouseWatcherGroup");
}
private:
static TypeHandle _type_handle;
friend class MouseWatcher;
};
#endif
+44
View File
@@ -43,3 +43,47 @@ write(ostream &out, int indent_level) const {
indent(out, indent_level) << get_name() << " lrbt = " << _frame << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherRegion::enter
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever the
// mouse enters the region.
////////////////////////////////////////////////////////////////////
void MouseWatcherRegion::
enter() {
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherRegion::exit
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever the
// mouse exits the region.
////////////////////////////////////////////////////////////////////
void MouseWatcherRegion::
exit() {
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherRegion::button_down
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever a
// mouse or keyboard button is depressed while the mouse
// is within the region.
////////////////////////////////////////////////////////////////////
void MouseWatcherRegion::
button_down(ButtonHandle) {
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherRegion::button_up
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever a
// mouse or keyboard button previously depressed with
// button_down() is release. The bool is_within flag is
// true if the button was released while the mouse was
// still within the region, or false if it was released
// outside the region.
////////////////////////////////////////////////////////////////////
void MouseWatcherRegion::
button_up(ButtonHandle, bool) {
}
+6
View File
@@ -24,6 +24,7 @@
#include <namable.h>
#include <typedReferenceCount.h>
#include <luse.h>
#include <buttonHandle.h>
////////////////////////////////////////////////////////////////////
// Class : MouseWatcherRegion
@@ -56,6 +57,11 @@ PUBLISHED:
public:
INLINE bool operator < (const MouseWatcherRegion &other) const;
virtual void enter();
virtual void exit();
virtual void button_down(ButtonHandle button);
virtual void button_up(ButtonHandle button, bool is_within);
private:
LVecBase4f _frame;
float _area;
+1
View File
@@ -3,4 +3,5 @@
#include "config_tform.cxx"
#include "dataValve.cxx"
#include "driveInterface.cxx"
#include "planarSlider.cxx"
+1 -1
View File
@@ -1,7 +1,7 @@
#include "mouseWatcher.cxx"
#include "mouseWatcherGroup.cxx"
#include "mouseWatcherRegion.cxx"
#include "planarSlider.cxx"
#include "trackball.cxx"
#include "transform2sg.cxx"