robustify layer-ordering interface

This commit is contained in:
David Rose 2003-12-23 19:27:01 +00:00
parent 0a0084fc36
commit 9e196097ad
5 changed files with 153 additions and 67 deletions

View File

@ -100,24 +100,75 @@ GraphicsChannel::
// Function: GraphicsChannel::make_layer
// Access: Published
// Description: Creates a new GraphicsLayer, associated with the
// window, at the indicated index position. If the
// index position negative or past the end of the array,
// the end of the array is assumed. The layers will be
// rendered on top of each other, in increasing order by
// index, from back to front.
// window, with the indicated sort value. The sort
// value is an arbitrary integer, and may be zero or
// negative. The graphics layers are rendered in order
// from lower sort value to higher sort value; within
// layers of the same sort value, they are ordered in
// sequence from the first added to the last added.
////////////////////////////////////////////////////////////////////
GraphicsLayer *GraphicsChannel::
make_layer(int index) {
make_layer(int sort) {
MutexHolder holder(_lock);
PT(GraphicsLayer) layer = new GraphicsLayer(this);
if (index < 0 || index >= (int)_layers.size()) {
_layers.push_back(layer);
} else {
_layers.insert(_layers.begin() + index, layer);
}
PT(GraphicsLayer) layer = new GraphicsLayer(this, sort);
_layers.insert(layer);
return layer;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsChannel::remove_layer
// Access: Published
// Description: Removes the indicated GraphicsLayer. Returns true if
// it was successfully removed, false if it was not a
// member of the channel in the first place.
////////////////////////////////////////////////////////////////////
bool GraphicsChannel::
remove_layer(GraphicsLayer *layer) {
MutexHolder holder(_lock);
GraphicsLayers::iterator li = find_layer(layer);
if (li == _layers.end()) {
return false;
}
_layers.erase(li);
win_display_regions_changed();
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsChannel::move_layer
// Access: Published
// Description: Reinserts the indicated layer into the list with the
// indicated sort value. The layer will be rendered
// last among all of the previously-added layers with
// the same sort value. If the new sort value is the
// same as the previous sort value, the layer will be
// moved to the end of the list of layers with this sort
// value.
//
// Returns true if the layer is successfully moved,
// false if it is not a member of this channel.
////////////////////////////////////////////////////////////////////
bool GraphicsChannel::
move_layer(GraphicsLayer *layer, int sort) {
MutexHolder holder(_lock);
GraphicsLayers::iterator li = find_layer(layer);
if (li == _layers.end()) {
return false;
}
PT(GraphicsLayer) hold_layer = layer;
_layers.erase(li);
layer->_sort = sort;
_layers.insert(layer);
win_display_regions_changed();
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsChannel::get_num_layers
// Access: Published
@ -134,57 +185,17 @@ get_num_layers() const {
// Function: GraphicsChannel::get_layer
// Access: Published
// Description: Returns the nth layer associated with the channel.
// Walking through this list from 0 to (get_num_layers()
// - 1) will retrieve all of the layers in the order in
// which they will be rendered. It is therefore invalid
// to call make_layer(), remove_layer(), or move_layer()
// while traversing this list.
////////////////////////////////////////////////////////////////////
GraphicsLayer *GraphicsChannel::
get_layer(int index) const {
MutexHolder holder(_lock);
if (index >= 0 && index < (int)_layers.size()) {
return _layers[index];
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsChannel::move_layer
// Access: Published
// Description: Changes the ordering of the layers so that the
// indicated layer will move to the indicated position.
// If to_index is negative or past the end of the array,
// the end of the array is assumed.
////////////////////////////////////////////////////////////////////
void GraphicsChannel::
move_layer(int from_index, int to_index) {
MutexHolder holder(_lock);
nassertv(from_index >= 0 && from_index < (int)_layers.size());
PT(GraphicsLayer) layer = _layers[from_index];
if (to_index < 0 || to_index >= (int)_layers.size()) {
_layers.erase(_layers.begin() + from_index);
_layers.push_back(layer);
} else if (to_index > from_index) {
// Move the layer later in the list.
_layers.insert(_layers.begin() + to_index, layer);
_layers.erase(_layers.begin() + from_index);
} else if (to_index < from_index) {
// Move the layer earlier in the list.
_layers.erase(_layers.begin() + from_index);
_layers.insert(_layers.begin() + to_index, layer);
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsChannel::remove_layer
// Access: Published
// Description: Removes the nth layer. This changes the numbers of
// all subsequent layers.
////////////////////////////////////////////////////////////////////
void GraphicsChannel::
remove_layer(int index) {
MutexHolder holder(_lock);
nassertv(index >= 0 && index < (int)_layers.size());
_layers.erase(_layers.begin() + index);
nassertr(index >= 0 && index < (int)_layers.size(), NULL);
return _layers[index];
}
////////////////////////////////////////////////////////////////////
@ -267,3 +278,24 @@ win_display_regions_changed() {
_window->win_display_regions_changed();
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsChannel::find_layer
// Access: Private
// Description: Returns the iterator corresponding to the indicated
// layer, or _layers.end() if the layer is not part of
// this channel.
////////////////////////////////////////////////////////////////////
GraphicsChannel::GraphicsLayers::iterator GraphicsChannel::
find_layer(GraphicsLayer *layer) {
GraphicsLayers::iterator li = _layers.lower_bound(layer);
while (li != _layers.end() && (*li) != layer) {
if (*layer < *(*li)) {
// The layer was not found.
return _layers.end();
}
++li;
}
return li;
}

View File

@ -23,7 +23,8 @@
#include "typedReferenceCount.h"
#include "pointerTo.h"
#include "pmutex.h"
#include "pvector.h"
#include "ordered_vector.h"
#include "indirectLess.h"
class GraphicsChannel;
class GraphicsPipe;
@ -51,11 +52,12 @@ private:
PUBLISHED:
virtual ~GraphicsChannel();
GraphicsLayer *make_layer(int index = -1);
GraphicsLayer *make_layer(int sort = 0);
bool remove_layer(GraphicsLayer *layer);
bool move_layer(GraphicsLayer *layer, int sort);
int get_num_layers() const;
GraphicsLayer *get_layer(int index) const;
void move_layer(int from_index, int to_index);
void remove_layer(int index);
GraphicsWindow *get_window() const;
GraphicsPipe *get_pipe() const;
@ -74,9 +76,12 @@ protected:
GraphicsWindow *_window;
bool _is_active;
typedef pvector< PT(GraphicsLayer) > GraphicsLayers;
typedef ov_multiset< PT(GraphicsLayer), IndirectLess<GraphicsLayer> > GraphicsLayers;
GraphicsLayers _layers;
private:
GraphicsLayers::iterator find_layer(GraphicsLayer *layer);
public:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -17,6 +17,16 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: GraphicsLayer::Comparison operator
// Access: Published
// Description: Sorts the layers in order by sort parameter only.
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsLayer::
operator < (const GraphicsLayer &other) const {
return _sort < other._sort;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsLayer::is_active
// Access: Published
@ -26,3 +36,15 @@ INLINE bool GraphicsLayer::
is_active() const {
return _is_active;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsLayer::get_sort
// Access: Published
// Description: Returns the sort parameter associated with the layer.
// This defines the order in which this layer is
// rendered relative to the other layers on the channel.
////////////////////////////////////////////////////////////////////
INLINE int GraphicsLayer::
get_sort() const {
return _sort;
}

View File

@ -37,6 +37,7 @@ TypeHandle GraphicsLayer::_type_handle;
GraphicsLayer::
GraphicsLayer() {
_channel = NULL;
_sort = 0;
_is_active = true;
}
@ -47,8 +48,9 @@ GraphicsLayer() {
// layer.
////////////////////////////////////////////////////////////////////
GraphicsLayer::
GraphicsLayer(GraphicsChannel *channel)
: _channel(channel)
GraphicsLayer(GraphicsChannel *channel, int sort) :
_channel(channel),
_sort(sort)
{
_is_active = true;
}
@ -258,6 +260,24 @@ set_active(bool active) {
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsLayer::set_sort
// Access: Published
// Description: Changes the sort parameter on the layer. If the sort
// parameter is changed, the layer will be reordered
// among the other layers on the same channel. If the
// sort parameter is not changed, the layer will remain
// in the same sort position. (This is different from
// GraphicsChannel::move_layer(), which will reorder the
// layer even if the sort parameter does not change.)
////////////////////////////////////////////////////////////////////
void GraphicsLayer::
set_sort(int sort) {
if (sort != _sort) {
_channel->move_layer(this, sort);
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsLayer::channel_resized
// Access: Public

View File

@ -45,12 +45,15 @@ class CullHandler;
class EXPCL_PANDA GraphicsLayer : public TypedReferenceCount {
private:
GraphicsLayer();
GraphicsLayer(GraphicsChannel *channel);
GraphicsLayer(GraphicsChannel *channel, int sort);
private:
GraphicsLayer(const GraphicsLayer &copy);
void operator = (const GraphicsLayer &copy);
public:
INLINE bool operator < (const GraphicsLayer &other) const;
PUBLISHED:
virtual ~GraphicsLayer();
@ -70,6 +73,9 @@ PUBLISHED:
void set_active(bool active);
INLINE bool is_active() const;
void set_sort(int sort);
INLINE int get_sort() const;
public:
void channel_resized(int x, int y);
@ -79,6 +85,7 @@ private:
Mutex _lock;
GraphicsChannel *_channel;
bool _is_active;
int _sort;
typedef pvector< PT(DisplayRegion) > DisplayRegions;
DisplayRegions _display_regions;