robustify layer-ordering interface
This commit is contained in:
parent
0a0084fc36
commit
9e196097ad
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ©);
|
||||
void operator = (const GraphicsLayer ©);
|
||||
|
||||
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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue