mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
one override per TextureStage, instead of a global override per TextureAttrib
This commit is contained in:
parent
2475878a70
commit
9d62ca9f98
@ -91,6 +91,7 @@
|
|||||||
#include "bitArray.h"
|
#include "bitArray.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "uvScrollNode.h"
|
#include "uvScrollNode.h"
|
||||||
|
#include "textureStagePool.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -1568,7 +1569,7 @@ make_texture_stage(const EggTexture *egg_tex) {
|
|||||||
stage->set_color(egg_tex->get_color());
|
stage->set_color(egg_tex->get_color());
|
||||||
}
|
}
|
||||||
|
|
||||||
return stage;
|
return TextureStagePool::get_stage(stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
texturePoolFilter.I texturePoolFilter.h \
|
texturePoolFilter.I texturePoolFilter.h \
|
||||||
textureReloadRequest.I textureReloadRequest.h \
|
textureReloadRequest.I textureReloadRequest.h \
|
||||||
textureStage.I textureStage.h \
|
textureStage.I textureStage.h \
|
||||||
|
textureStagePool.I textureStagePool.h \
|
||||||
transformBlend.I transformBlend.h \
|
transformBlend.I transformBlend.h \
|
||||||
transformBlendTable.I transformBlendTable.h \
|
transformBlendTable.I transformBlendTable.h \
|
||||||
transformTable.I transformTable.h \
|
transformTable.I transformTable.h \
|
||||||
@ -131,6 +132,7 @@
|
|||||||
texturePoolFilter.cxx \
|
texturePoolFilter.cxx \
|
||||||
textureReloadRequest.cxx \
|
textureReloadRequest.cxx \
|
||||||
textureStage.cxx \
|
textureStage.cxx \
|
||||||
|
textureStagePool.cxx \
|
||||||
transformBlend.cxx \
|
transformBlend.cxx \
|
||||||
transformBlendTable.cxx \
|
transformBlendTable.cxx \
|
||||||
transformTable.cxx \
|
transformTable.cxx \
|
||||||
@ -201,6 +203,7 @@
|
|||||||
texturePoolFilter.I texturePoolFilter.h \
|
texturePoolFilter.I texturePoolFilter.h \
|
||||||
textureReloadRequest.I textureReloadRequest.h \
|
textureReloadRequest.I textureReloadRequest.h \
|
||||||
textureStage.I textureStage.h \
|
textureStage.I textureStage.h \
|
||||||
|
textureStagePool.I textureStagePool.h \
|
||||||
transformBlend.I transformBlend.h \
|
transformBlend.I transformBlend.h \
|
||||||
transformBlendTable.I transformBlendTable.h \
|
transformBlendTable.I transformBlendTable.h \
|
||||||
transformTable.I transformTable.h \
|
transformTable.I transformTable.h \
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "texturePoolFilter.cxx"
|
#include "texturePoolFilter.cxx"
|
||||||
#include "textureReloadRequest.cxx"
|
#include "textureReloadRequest.cxx"
|
||||||
#include "textureStage.cxx"
|
#include "textureStage.cxx"
|
||||||
|
#include "textureStagePool.cxx"
|
||||||
#include "transformBlend.cxx"
|
#include "transformBlend.cxx"
|
||||||
#include "transformBlendTable.cxx"
|
#include "transformBlendTable.cxx"
|
||||||
#include "transformTable.cxx"
|
#include "transformTable.cxx"
|
||||||
|
@ -35,7 +35,28 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE Material *MaterialPool::
|
INLINE Material *MaterialPool::
|
||||||
get_material(Material *temp) {
|
get_material(Material *temp) {
|
||||||
return get_ptr()->ns_get_material(temp);
|
return get_global_ptr()->ns_get_material(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MaterialPool::release_material
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Removes the indicated material from the pool.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void MaterialPool::
|
||||||
|
release_material(Material *material) {
|
||||||
|
get_global_ptr()->ns_release_material(material);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MaterialPool::release_all_materials
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Releases all materials in the pool and restores the
|
||||||
|
// pool to the empty state.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void MaterialPool::
|
||||||
|
release_all_materials() {
|
||||||
|
get_global_ptr()->ns_release_all_materials();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -48,7 +69,7 @@ get_material(Material *temp) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE int MaterialPool::
|
INLINE int MaterialPool::
|
||||||
garbage_collect() {
|
garbage_collect() {
|
||||||
return get_ptr()->ns_garbage_collect();
|
return get_global_ptr()->ns_garbage_collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -59,7 +80,7 @@ garbage_collect() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void MaterialPool::
|
INLINE void MaterialPool::
|
||||||
list_contents(ostream &out) {
|
list_contents(ostream &out) {
|
||||||
get_ptr()->ns_list_contents(out);
|
get_global_ptr()->ns_list_contents(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -27,7 +27,7 @@ MaterialPool *MaterialPool::_global_ptr = (MaterialPool *)NULL;
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MaterialPool::
|
void MaterialPool::
|
||||||
write(ostream &out) {
|
write(ostream &out) {
|
||||||
get_ptr()->ns_list_contents(out);
|
get_global_ptr()->ns_list_contents(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -53,6 +53,31 @@ ns_get_material(Material *temp) {
|
|||||||
return (*mi).second;
|
return (*mi).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MaterialPool::ns_release_material
|
||||||
|
// Access: Private
|
||||||
|
// Description: The nonstatic implementation of release_material().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MaterialPool::
|
||||||
|
ns_release_material(Material *temp) {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
|
||||||
|
CPT(Material) cpttemp = temp;
|
||||||
|
_materials.erase(cpttemp);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: MaterialPool::ns_release_all_materials
|
||||||
|
// Access: Private
|
||||||
|
// Description: The nonstatic implementation of release_all_materials().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void MaterialPool::
|
||||||
|
ns_release_all_materials() {
|
||||||
|
LightMutexHolder holder(_lock);
|
||||||
|
|
||||||
|
_materials.clear();
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: MaterialPool::ns_garbage_collect
|
// Function: MaterialPool::ns_garbage_collect
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -104,13 +129,13 @@ ns_list_contents(ostream &out) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: MaterialPool::get_ptr
|
// Function: MaterialPool::get_global_ptr
|
||||||
// Access: Private, Static
|
// Access: Private, Static
|
||||||
// Description: Initializes and/or returns the global pointer to the
|
// Description: Initializes and/or returns the global pointer to the
|
||||||
// one MaterialPool object in the system.
|
// one MaterialPool object in the system.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
MaterialPool *MaterialPool::
|
MaterialPool *MaterialPool::
|
||||||
get_ptr() {
|
get_global_ptr() {
|
||||||
if (_global_ptr == (MaterialPool *)NULL) {
|
if (_global_ptr == (MaterialPool *)NULL) {
|
||||||
_global_ptr = new MaterialPool;
|
_global_ptr = new MaterialPool;
|
||||||
}
|
}
|
||||||
|
@ -42,18 +42,25 @@
|
|||||||
class EXPCL_PANDA_GOBJ MaterialPool {
|
class EXPCL_PANDA_GOBJ MaterialPool {
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE static Material *get_material(Material *temp);
|
INLINE static Material *get_material(Material *temp);
|
||||||
|
INLINE static void release_material(Material *temp);
|
||||||
|
INLINE static void release_all_materials();
|
||||||
|
|
||||||
INLINE static int garbage_collect();
|
INLINE static int garbage_collect();
|
||||||
INLINE static void list_contents(ostream &out);
|
INLINE static void list_contents(ostream &out);
|
||||||
|
|
||||||
static void write(ostream &out);
|
static void write(ostream &out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
INLINE MaterialPool();
|
INLINE MaterialPool();
|
||||||
|
|
||||||
Material *ns_get_material(Material *temp);
|
Material *ns_get_material(Material *temp);
|
||||||
|
void ns_release_material(Material *temp);
|
||||||
|
void ns_release_all_materials();
|
||||||
|
|
||||||
int ns_garbage_collect();
|
int ns_garbage_collect();
|
||||||
void ns_list_contents(ostream &out) const;
|
void ns_list_contents(ostream &out) const;
|
||||||
|
|
||||||
static MaterialPool *get_ptr();
|
static MaterialPool *get_global_ptr();
|
||||||
|
|
||||||
static MaterialPool *_global_ptr;
|
static MaterialPool *_global_ptr;
|
||||||
|
|
||||||
|
@ -114,16 +114,6 @@ get_priority() const {
|
|||||||
return _priority;
|
return _priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: TextureStage::opertor <
|
|
||||||
// Access: Published
|
|
||||||
// Description: Compare if the sort order is lower
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE bool TextureStage::
|
|
||||||
operator < (const TextureStage &other) const {
|
|
||||||
return (_sort < other._sort);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TextureStage::set_texcoord_name
|
// Function: TextureStage::set_texcoord_name
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -673,6 +663,36 @@ uses_last_saved_result() const {
|
|||||||
return _uses_last_saved_result;
|
return _uses_last_saved_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStage::operator ==
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool TextureStage::
|
||||||
|
operator == (const TextureStage &other) const {
|
||||||
|
return compare_to(other) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStage::operator !=
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool TextureStage::
|
||||||
|
operator != (const TextureStage &other) const {
|
||||||
|
return compare_to(other) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStage::operator <
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool TextureStage::
|
||||||
|
operator < (const TextureStage &other) const {
|
||||||
|
return compare_to(other) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TextureStage::get_default
|
// Function: TextureStage::get_default
|
||||||
// Access: Published, Static
|
// Access: Published, Static
|
||||||
|
@ -104,6 +104,122 @@ TextureStage::
|
|||||||
~TextureStage() {
|
~TextureStage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStage::compare_to
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns a number less than zero if this TextureStage
|
||||||
|
// sorts before the other one, greater than zero if it
|
||||||
|
// sorts after, or zero if they are equivalent. The
|
||||||
|
// sorting order is arbitrary and largely meaningless,
|
||||||
|
// except to differentiate different stages.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int TextureStage::
|
||||||
|
compare_to(const TextureStage &other) const {
|
||||||
|
// We put the sort parameter first, so that we sorting a list of
|
||||||
|
// TextureStages will happen to put them in sorted order, even
|
||||||
|
// though we don't promise to do that. But there's no reason not to
|
||||||
|
// do so, and it might be more convenient for the developer.
|
||||||
|
if (get_sort() != other.get_sort()) {
|
||||||
|
return get_sort() < other.get_sort() ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The remaining parameters are arbitrary. We start with the name,
|
||||||
|
// because that's most likely to be consistent between similar
|
||||||
|
// TextureStages, and different between different TextureStages.
|
||||||
|
int compare = strcmp(get_name().c_str(), other.get_name().c_str());
|
||||||
|
if (compare != 0) {
|
||||||
|
return compare;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_priority() != other.get_priority()) {
|
||||||
|
return get_priority() < other.get_priority() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_texcoord_name() != other.get_texcoord_name()) {
|
||||||
|
return get_texcoord_name() < other.get_texcoord_name() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_mode() != other.get_mode()) {
|
||||||
|
return get_mode() < other.get_mode() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_rgb_scale() != other.get_rgb_scale()) {
|
||||||
|
return get_rgb_scale() < other.get_rgb_scale() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_alpha_scale() != other.get_alpha_scale()) {
|
||||||
|
return get_alpha_scale() < other.get_alpha_scale() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_saved_result() != other.get_saved_result()) {
|
||||||
|
return get_saved_result() < other.get_saved_result() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_mode() != other.get_mode()) {
|
||||||
|
return get_mode() < other.get_mode() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_mode() == M_combine) {
|
||||||
|
if (get_combine_rgb_mode() != other.get_combine_rgb_mode()) {
|
||||||
|
return get_combine_rgb_mode() < other.get_combine_rgb_mode() ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_num_combine_rgb_operands() != other.get_num_combine_rgb_operands()) {
|
||||||
|
return get_num_combine_rgb_operands() < other.get_num_combine_rgb_operands() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_num_combine_rgb_operands() >= 1) {
|
||||||
|
if (get_combine_rgb_source0() != other.get_combine_rgb_source0()) {
|
||||||
|
return get_combine_rgb_source0() < other.get_combine_rgb_source0() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_combine_rgb_operand0() != other.get_combine_rgb_operand0()) {
|
||||||
|
return get_combine_rgb_operand0() < other.get_combine_rgb_operand0() ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (get_num_combine_rgb_operands() >= 2) {
|
||||||
|
if (get_combine_rgb_source1() != other.get_combine_rgb_source1()) {
|
||||||
|
return get_combine_rgb_source1() < other.get_combine_rgb_source1() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_combine_rgb_operand1() != other.get_combine_rgb_operand1()) {
|
||||||
|
return get_combine_rgb_operand1() < other.get_combine_rgb_operand1() ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (get_num_combine_rgb_operands() >= 3) {
|
||||||
|
if (get_combine_rgb_source2() != other.get_combine_rgb_source2()) {
|
||||||
|
return get_combine_rgb_source2() < other.get_combine_rgb_source2() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_combine_rgb_operand2() != other.get_combine_rgb_operand2()) {
|
||||||
|
return get_combine_rgb_operand2() < other.get_combine_rgb_operand2() ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (get_combine_alpha_mode() != other.get_combine_alpha_mode()) {
|
||||||
|
return get_combine_alpha_mode() < other.get_combine_alpha_mode() ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_num_combine_alpha_operands() != other.get_num_combine_alpha_operands()) {
|
||||||
|
return get_num_combine_alpha_operands() < other.get_num_combine_alpha_operands() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_num_combine_alpha_operands() >= 1) {
|
||||||
|
if (get_combine_alpha_source0() != other.get_combine_alpha_source0()) {
|
||||||
|
return get_combine_alpha_source0() < other.get_combine_alpha_source0() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_combine_alpha_operand0() != other.get_combine_alpha_operand0()) {
|
||||||
|
return get_combine_alpha_operand0() < other.get_combine_alpha_operand0() ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (get_num_combine_alpha_operands() >= 2) {
|
||||||
|
if (get_combine_alpha_source1() != other.get_combine_alpha_source1()) {
|
||||||
|
return get_combine_alpha_source1() < other.get_combine_alpha_source1() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_combine_alpha_operand1() != other.get_combine_alpha_operand1()) {
|
||||||
|
return get_combine_alpha_operand1() < other.get_combine_alpha_operand1() ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (get_num_combine_alpha_operands() >= 3) {
|
||||||
|
if (get_combine_alpha_source2() != other.get_combine_alpha_source2()) {
|
||||||
|
return get_combine_alpha_source2() < other.get_combine_alpha_source2() ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (get_combine_alpha_operand2() != other.get_combine_alpha_operand2()) {
|
||||||
|
return get_combine_alpha_operand2() < other.get_combine_alpha_operand2() ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TextureStage::Destructor
|
// Function: TextureStage::Destructor
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -109,8 +109,6 @@ PUBLISHED:
|
|||||||
INLINE void set_priority(int priority);
|
INLINE void set_priority(int priority);
|
||||||
INLINE int get_priority() const;
|
INLINE int get_priority() const;
|
||||||
|
|
||||||
INLINE bool operator < (const TextureStage &other) const;
|
|
||||||
|
|
||||||
INLINE void set_texcoord_name(InternalName *name);
|
INLINE void set_texcoord_name(InternalName *name);
|
||||||
INLINE void set_texcoord_name(const string &texcoord_name);
|
INLINE void set_texcoord_name(const string &texcoord_name);
|
||||||
INLINE InternalName *get_texcoord_name() const;
|
INLINE InternalName *get_texcoord_name() const;
|
||||||
@ -173,6 +171,12 @@ PUBLISHED:
|
|||||||
INLINE bool uses_primary_color() const;
|
INLINE bool uses_primary_color() const;
|
||||||
INLINE bool uses_last_saved_result() const;
|
INLINE bool uses_last_saved_result() const;
|
||||||
|
|
||||||
|
INLINE bool operator == (const TextureStage &other) const;
|
||||||
|
INLINE bool operator != (const TextureStage &other) const;
|
||||||
|
INLINE bool operator < (const TextureStage &other) const;
|
||||||
|
|
||||||
|
int compare_to(const TextureStage &other) const;
|
||||||
|
|
||||||
void write(ostream &out) const;
|
void write(ostream &out) const;
|
||||||
void output(ostream &out) const;
|
void output(ostream &out) const;
|
||||||
|
|
||||||
|
115
panda/src/gobj/textureStagePool.I
Normal file
115
panda/src/gobj/textureStagePool.I
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
// Filename: textureStagePool.I
|
||||||
|
// Created by: drose (03May10)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the revised BSD
|
||||||
|
// license. You should have received a copy of this license along
|
||||||
|
// with this source code in a file named "LICENSE."
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::get_stage
|
||||||
|
// Access: Public, Static
|
||||||
|
// Description: Returns a TextureStage pointer that represents the
|
||||||
|
// same TextureStage described by temp, except that it is a
|
||||||
|
// shared pointer.
|
||||||
|
//
|
||||||
|
// Each call to get_stage() passing an equivalent
|
||||||
|
// TextureStage pointer will return the same shared pointer.
|
||||||
|
//
|
||||||
|
// If you modify the shared pointer, it will
|
||||||
|
// automatically disassociate it from the pool.
|
||||||
|
//
|
||||||
|
// Also, the return value may be a different pointer
|
||||||
|
// than that passed in, or it may be the same pointer.
|
||||||
|
// In either case, the passed in pointer has now been
|
||||||
|
// sacrificed to the greater good and should not be used
|
||||||
|
// again (like any other PointerTo, it will be freed
|
||||||
|
// when the last reference count is removed).
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE TextureStage *TextureStagePool::
|
||||||
|
get_stage(TextureStage *temp) {
|
||||||
|
return get_global_ptr()->ns_get_stage(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::release_stage
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Removes the indicated TextureStage from the pool.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void TextureStagePool::
|
||||||
|
release_stage(TextureStage *stage) {
|
||||||
|
get_global_ptr()->ns_release_stage(stage);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::release_all_stages
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Releases all TextureStages in the pool and restores the
|
||||||
|
// pool to the empty state.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void TextureStagePool::
|
||||||
|
release_all_stages() {
|
||||||
|
get_global_ptr()->ns_release_all_stages();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::set_mode
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Specifies the fundamental operating mode of the
|
||||||
|
// TextureStagePool.
|
||||||
|
//
|
||||||
|
// If this is M_none, each call to get_stage() returns
|
||||||
|
// the same TextureStage pointer that was passed in (the
|
||||||
|
// pool is effectively disabled). If this is M_name,
|
||||||
|
// each call to get_stage() returns the last
|
||||||
|
// TextureStage passed in with the same name, whether it
|
||||||
|
// has different properties or not. If this is
|
||||||
|
// M_unique, then each call to get_stage() returns only
|
||||||
|
// TextureStages with identical properties.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void TextureStagePool::
|
||||||
|
set_mode(TextureStagePool::Mode mode) {
|
||||||
|
get_global_ptr()->ns_set_mode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::get_mode
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Returns the fundamental operating mode of the
|
||||||
|
// TextureStagePool. See set_mode().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE TextureStagePool::Mode TextureStagePool::
|
||||||
|
get_mode() {
|
||||||
|
return get_global_ptr()->ns_get_mode();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::garbage_collect
|
||||||
|
// Access: Public, Static
|
||||||
|
// Description: Releases only those TextureStages in the pool that have a
|
||||||
|
// reference count of exactly 1; i.e. only those
|
||||||
|
// TextureStages that are not being used outside of the pool.
|
||||||
|
// Returns the number of TextureStages released.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE int TextureStagePool::
|
||||||
|
garbage_collect() {
|
||||||
|
return get_global_ptr()->ns_garbage_collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::list_contents
|
||||||
|
// Access: Public, Static
|
||||||
|
// Description: Lists the contents of the TextureStage pool to the
|
||||||
|
// indicated output stream.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void TextureStagePool::
|
||||||
|
list_contents(ostream &out) {
|
||||||
|
get_global_ptr()->ns_list_contents(out);
|
||||||
|
}
|
332
panda/src/gobj/textureStagePool.cxx
Normal file
332
panda/src/gobj/textureStagePool.cxx
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
// Filename: textureStagePool.cxx
|
||||||
|
// Created by: drose (03May10)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the revised BSD
|
||||||
|
// license. You should have received a copy of this license along
|
||||||
|
// with this source code in a file named "LICENSE."
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
#include "textureStagePool.h"
|
||||||
|
#include "config_gobj.h"
|
||||||
|
#include "mutexHolder.h"
|
||||||
|
#include "configVariableEnum.h"
|
||||||
|
|
||||||
|
TextureStagePool *TextureStagePool::_global_ptr = (TextureStagePool *)NULL;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::write
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Lists the contents of the TextureStage pool to the
|
||||||
|
// indicated output stream.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void TextureStagePool::
|
||||||
|
write(ostream &out) {
|
||||||
|
get_global_ptr()->ns_list_contents(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::Constructor
|
||||||
|
// Access: Private
|
||||||
|
// Description: The constructor is not intended to be called
|
||||||
|
// directly; there's only supposed to be one TextureStagePool
|
||||||
|
// in the universe and it constructs itself.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
TextureStagePool::
|
||||||
|
TextureStagePool() {
|
||||||
|
ConfigVariableEnum<Mode> texture_stage_pool_mode
|
||||||
|
("texture-stage-pool-mode", M_none,
|
||||||
|
PRC_DESC("Defines the initial value of TextureStagePool::set_mode(). "
|
||||||
|
"Set this to 'none' to disable the use of the TextureStagePool, "
|
||||||
|
"to 'name' to group TextureStages by name only, or 'unique' "
|
||||||
|
"to group together only identical TextureStages."));
|
||||||
|
_mode = texture_stage_pool_mode.get_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::ns_get_stage
|
||||||
|
// Access: Public
|
||||||
|
// Description: The nonstatic implementation of get_stage().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
TextureStage *TextureStagePool::
|
||||||
|
ns_get_stage(TextureStage *temp) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
|
|
||||||
|
switch (_mode) {
|
||||||
|
case M_none:
|
||||||
|
return temp;
|
||||||
|
|
||||||
|
case M_name:
|
||||||
|
{
|
||||||
|
StagesByName::iterator ni = _stages_by_name.find(temp->get_name());
|
||||||
|
if (ni == _stages_by_name.end()) {
|
||||||
|
ni = _stages_by_name.insert(StagesByName::value_type(temp->get_name(), temp)).first;
|
||||||
|
} else {
|
||||||
|
if ((*ni).first != (*ni).second->get_name()) {
|
||||||
|
// The pointer no longer matches the original name. Save a
|
||||||
|
// new one.
|
||||||
|
(*ni).second = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (*ni).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
case M_unique:
|
||||||
|
{
|
||||||
|
CPT(TextureStage) cpttemp = temp;
|
||||||
|
StagesByProperties::iterator si = _stages_by_properties.find(cpttemp);
|
||||||
|
if (si == _stages_by_properties.end()) {
|
||||||
|
si = _stages_by_properties.insert(StagesByProperties::value_type(new TextureStage(*temp), temp)).first;
|
||||||
|
} else {
|
||||||
|
if (*(*si).first != *(*si).second) {
|
||||||
|
// The pointer no longer matches its original value. Save a new
|
||||||
|
// one.
|
||||||
|
(*si).second = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (*si).second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::ns_release_stage
|
||||||
|
// Access: Private
|
||||||
|
// Description: The nonstatic implementation of release_stage().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void TextureStagePool::
|
||||||
|
ns_release_stage(TextureStage *temp) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
|
|
||||||
|
switch (_mode) {
|
||||||
|
case M_none:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case M_name:
|
||||||
|
_stages_by_name.erase(temp->get_name());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case M_unique:
|
||||||
|
{
|
||||||
|
CPT(TextureStage) cpttemp = temp;
|
||||||
|
_stages_by_properties.erase(cpttemp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::ns_release_all_stages
|
||||||
|
// Access: Private
|
||||||
|
// Description: The nonstatic implementation of release_all_stages().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void TextureStagePool::
|
||||||
|
ns_release_all_stages() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
|
|
||||||
|
_stages_by_name.clear();
|
||||||
|
_stages_by_properties.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::ns_set_mode
|
||||||
|
// Access: Private
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void TextureStagePool::
|
||||||
|
ns_set_mode(TextureStagePool::Mode mode) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
|
|
||||||
|
if (_mode != mode) {
|
||||||
|
_stages_by_name.clear();
|
||||||
|
_stages_by_properties.clear();
|
||||||
|
_mode = mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::ns_get_mode
|
||||||
|
// Access: Private
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
TextureStagePool::Mode TextureStagePool::
|
||||||
|
ns_get_mode() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
|
|
||||||
|
return _mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::ns_garbage_collect
|
||||||
|
// Access: Private
|
||||||
|
// Description: The nonstatic implementation of garbage_collect().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int TextureStagePool::
|
||||||
|
ns_garbage_collect() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
|
|
||||||
|
switch (_mode) {
|
||||||
|
case M_none:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case M_name:
|
||||||
|
{
|
||||||
|
int num_released = 0;
|
||||||
|
StagesByName new_set;
|
||||||
|
|
||||||
|
StagesByName::iterator ni;
|
||||||
|
for (ni = _stages_by_name.begin(); ni != _stages_by_name.end(); ++ni) {
|
||||||
|
const string &name = (*ni).first;
|
||||||
|
TextureStage *ts2 = (*ni).second;
|
||||||
|
if (name != ts2->get_name() || ts2->get_ref_count() == 1) {
|
||||||
|
if (gobj_cat.is_debug()) {
|
||||||
|
gobj_cat.debug()
|
||||||
|
<< "Releasing " << name << "\n";
|
||||||
|
}
|
||||||
|
++num_released;
|
||||||
|
} else {
|
||||||
|
new_set.insert(new_set.end(), *ni);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_stages_by_name.swap(new_set);
|
||||||
|
return num_released;
|
||||||
|
}
|
||||||
|
|
||||||
|
case M_unique:
|
||||||
|
{
|
||||||
|
int num_released = 0;
|
||||||
|
StagesByProperties new_set;
|
||||||
|
|
||||||
|
StagesByProperties::iterator si;
|
||||||
|
for (si = _stages_by_properties.begin(); si != _stages_by_properties.end(); ++si) {
|
||||||
|
const TextureStage *ts1 = (*si).first;
|
||||||
|
TextureStage *ts2 = (*si).second;
|
||||||
|
if ((*ts1) != (*ts2) || ts2->get_ref_count() == 1) {
|
||||||
|
if (gobj_cat.is_debug()) {
|
||||||
|
gobj_cat.debug()
|
||||||
|
<< "Releasing " << *ts1 << "\n";
|
||||||
|
}
|
||||||
|
++num_released;
|
||||||
|
} else {
|
||||||
|
new_set.insert(new_set.end(), *si);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_stages_by_properties.swap(new_set);
|
||||||
|
return num_released;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::ns_list_contents
|
||||||
|
// Access: Private
|
||||||
|
// Description: The nonstatic implementation of list_contents().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void TextureStagePool::
|
||||||
|
ns_list_contents(ostream &out) const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
|
|
||||||
|
out << "TextureStagePool in mode " << _mode << "\n";
|
||||||
|
|
||||||
|
switch (_mode) {
|
||||||
|
case M_none:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case M_name:
|
||||||
|
{
|
||||||
|
out << _stages_by_name.size() << " TextureStages:\n";
|
||||||
|
StagesByName::const_iterator ni;
|
||||||
|
for (ni = _stages_by_name.begin(); ni != _stages_by_name.end(); ++ni) {
|
||||||
|
const string &name = (*ni).first;
|
||||||
|
TextureStage *ts2 = (*ni).second;
|
||||||
|
out << " " << name
|
||||||
|
<< " (count = " << ts2->get_ref_count() << ")\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case M_unique:
|
||||||
|
{
|
||||||
|
out << _stages_by_properties.size() << " TextureStages:\n";
|
||||||
|
StagesByProperties::const_iterator si;
|
||||||
|
for (si = _stages_by_properties.begin(); si != _stages_by_properties.end(); ++si) {
|
||||||
|
const TextureStage *ts1 = (*si).first;
|
||||||
|
TextureStage *ts2 = (*si).second;
|
||||||
|
out << " " << *ts1
|
||||||
|
<< " (count = " << ts2->get_ref_count() << ")\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::get_global_ptr
|
||||||
|
// Access: Private, Static
|
||||||
|
// Description: Initializes and/or returns the global pointer to the
|
||||||
|
// one TextureStagePool object in the system.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
TextureStagePool *TextureStagePool::
|
||||||
|
get_global_ptr() {
|
||||||
|
if (_global_ptr == (TextureStagePool *)NULL) {
|
||||||
|
_global_ptr = new TextureStagePool;
|
||||||
|
}
|
||||||
|
return _global_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::Mode output operator
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
ostream &
|
||||||
|
operator << (ostream &out, TextureStagePool::Mode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case TextureStagePool::M_none:
|
||||||
|
return out << "none";
|
||||||
|
|
||||||
|
case TextureStagePool::M_name:
|
||||||
|
return out << "name";
|
||||||
|
|
||||||
|
case TextureStagePool::M_unique:
|
||||||
|
return out << "unique";
|
||||||
|
}
|
||||||
|
|
||||||
|
return out << "**invalid mode (" << (int)mode << ")**";
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStagePool::Mode input operator
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
istream &
|
||||||
|
operator >> (istream &in, TextureStagePool::Mode &mode) {
|
||||||
|
string word;
|
||||||
|
in >> word;
|
||||||
|
|
||||||
|
if (cmp_nocase(word, "none") == 0) {
|
||||||
|
mode = TextureStagePool::M_none;
|
||||||
|
} else if (cmp_nocase(word, "name") == 0) {
|
||||||
|
mode = TextureStagePool::M_name;
|
||||||
|
} else if (cmp_nocase(word, "unique") == 0) {
|
||||||
|
mode = TextureStagePool::M_unique;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
gobj_cat->error() << "Invalid TextureStagePool mode value: " << word << "\n";
|
||||||
|
mode = TextureStagePool::M_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
93
panda/src/gobj/textureStagePool.h
Normal file
93
panda/src/gobj/textureStagePool.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Filename: textureStagePool.h
|
||||||
|
// Created by: drose (03May10)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the revised BSD
|
||||||
|
// license. You should have received a copy of this license along
|
||||||
|
// with this source code in a file named "LICENSE."
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef TEXTURESTAGEPOOL_H
|
||||||
|
#define TEXTURESTAGEPOOL_H
|
||||||
|
|
||||||
|
#include "pandabase.h"
|
||||||
|
#include "textureStage.h"
|
||||||
|
#include "pointerTo.h"
|
||||||
|
#include "pmutex.h"
|
||||||
|
#include "pset.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Class : TextureStagePool
|
||||||
|
// Description : The TextureStagePool (there is only one in the universe)
|
||||||
|
// serves to unify different pointers to the same
|
||||||
|
// TextureStage, mainly to help developers use a common
|
||||||
|
// pointer to access things that are loaded from
|
||||||
|
// different model files.
|
||||||
|
//
|
||||||
|
// It runs in one of three different modes, according to
|
||||||
|
// set_mode(). See that method for more information.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
class EXPCL_PANDA_GOBJ TextureStagePool {
|
||||||
|
PUBLISHED:
|
||||||
|
enum Mode {
|
||||||
|
M_none,
|
||||||
|
M_name,
|
||||||
|
M_unique,
|
||||||
|
};
|
||||||
|
|
||||||
|
INLINE static TextureStage *get_stage(TextureStage *temp);
|
||||||
|
INLINE static void release_stage(TextureStage *temp);
|
||||||
|
INLINE static void release_all_stages();
|
||||||
|
|
||||||
|
INLINE static void set_mode(Mode mode);
|
||||||
|
INLINE static Mode get_mode();
|
||||||
|
|
||||||
|
INLINE static int garbage_collect();
|
||||||
|
INLINE static void list_contents(ostream &out);
|
||||||
|
static void write(ostream &out);
|
||||||
|
|
||||||
|
private:
|
||||||
|
TextureStagePool();
|
||||||
|
|
||||||
|
TextureStage *ns_get_stage(TextureStage *temp);
|
||||||
|
void ns_release_stage(TextureStage *temp);
|
||||||
|
void ns_release_all_stages();
|
||||||
|
|
||||||
|
void ns_set_mode(Mode mode);
|
||||||
|
Mode ns_get_mode();
|
||||||
|
|
||||||
|
int ns_garbage_collect();
|
||||||
|
void ns_list_contents(ostream &out) const;
|
||||||
|
|
||||||
|
static TextureStagePool *get_global_ptr();
|
||||||
|
|
||||||
|
static TextureStagePool *_global_ptr;
|
||||||
|
|
||||||
|
Mutex _lock;
|
||||||
|
|
||||||
|
// We store a map of CPT(TextureStage) to PT(TextureStage). These are two
|
||||||
|
// equivalent structures, but different pointers. The first pointer
|
||||||
|
// never leaves this class. If the second pointer changes value,
|
||||||
|
// we'll notice it and return a new one.
|
||||||
|
typedef pmap<CPT(TextureStage), PT(TextureStage), indirect_compare_to<const TextureStage *> > StagesByProperties;
|
||||||
|
StagesByProperties _stages_by_properties;
|
||||||
|
|
||||||
|
typedef pmap<string, PT(TextureStage) > StagesByName;
|
||||||
|
StagesByName _stages_by_name;
|
||||||
|
|
||||||
|
Mode _mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, TextureStagePool::Mode mode);
|
||||||
|
EXPCL_PANDA_GOBJ istream &operator >> (istream &in, TextureStagePool::Mode &mode);
|
||||||
|
|
||||||
|
#include "textureStagePool.I"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -3420,26 +3420,21 @@ set_texture(Texture *tex, int priority) {
|
|||||||
void NodePath::
|
void NodePath::
|
||||||
set_texture(TextureStage *stage, Texture *tex, int priority) {
|
set_texture(TextureStage *stage, Texture *tex, int priority) {
|
||||||
nassertv_always(!is_empty());
|
nassertv_always(!is_empty());
|
||||||
if (tex->get_texture_type() == Texture::TT_2d_texture_array){
|
|
||||||
pgraph_cat.error() << "Texture::TT_2d_texture_array is not supported by" << \
|
|
||||||
" the fixed pipeline.\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const RenderAttrib *attrib =
|
const RenderAttrib *attrib =
|
||||||
node()->get_attrib(TextureAttrib::get_class_slot());
|
node()->get_attrib(TextureAttrib::get_class_slot());
|
||||||
if (attrib != (const RenderAttrib *)NULL) {
|
if (attrib != (const RenderAttrib *)NULL) {
|
||||||
priority = max(priority,
|
|
||||||
node()->get_state()->get_override(TextureAttrib::get_class_slot()));
|
|
||||||
const TextureAttrib *tsa = DCAST(TextureAttrib, attrib);
|
const TextureAttrib *tsa = DCAST(TextureAttrib, attrib);
|
||||||
|
int sg_priority = node()->get_state()->get_override(TextureAttrib::get_class_slot());
|
||||||
|
|
||||||
// Modify the existing TextureAttrib to add the indicated
|
// Modify the existing TextureAttrib to add the indicated
|
||||||
// texture.
|
// texture.
|
||||||
node()->set_attrib(tsa->add_on_stage(stage, tex), priority);
|
node()->set_attrib(tsa->add_on_stage(stage, tex, priority), sg_priority);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Create a new TextureAttrib for this node.
|
// Create a new TextureAttrib for this node.
|
||||||
CPT(TextureAttrib) tsa = DCAST(TextureAttrib, TextureAttrib::make());
|
CPT(TextureAttrib) tsa = DCAST(TextureAttrib, TextureAttrib::make());
|
||||||
node()->set_attrib(tsa->add_on_stage(stage, tex), priority);
|
node()->set_attrib(tsa->add_on_stage(stage, tex, priority));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3476,20 +3471,19 @@ set_texture_off(TextureStage *stage, int priority) {
|
|||||||
const RenderAttrib *attrib =
|
const RenderAttrib *attrib =
|
||||||
node()->get_attrib(TextureAttrib::get_class_slot());
|
node()->get_attrib(TextureAttrib::get_class_slot());
|
||||||
if (attrib != (const RenderAttrib *)NULL) {
|
if (attrib != (const RenderAttrib *)NULL) {
|
||||||
priority = max(priority,
|
|
||||||
node()->get_state()->get_override(TextureAttrib::get_class_slot()));
|
|
||||||
const TextureAttrib *tsa = DCAST(TextureAttrib, attrib);
|
const TextureAttrib *tsa = DCAST(TextureAttrib, attrib);
|
||||||
|
int sg_priority = node()->get_state()->get_override(TextureAttrib::get_class_slot());
|
||||||
|
|
||||||
// Modify the existing TextureAttrib to add the indicated texture
|
// Modify the existing TextureAttrib to add the indicated texture
|
||||||
// to the "off" list. This also, incidentally, removes it from
|
// to the "off" list. This also, incidentally, removes it from
|
||||||
// the "on" list if it is there.
|
// the "on" list if it is there.
|
||||||
node()->set_attrib(tsa->add_off_stage(stage), priority);
|
node()->set_attrib(tsa->add_off_stage(stage, priority), sg_priority);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Create a new TextureAttrib for this node that turns off the
|
// Create a new TextureAttrib for this node that turns off the
|
||||||
// indicated stage.
|
// indicated stage.
|
||||||
CPT(TextureAttrib) tsa = DCAST(TextureAttrib, TextureAttrib::make());
|
CPT(TextureAttrib) tsa = DCAST(TextureAttrib, TextureAttrib::make());
|
||||||
node()->set_attrib(tsa->add_off_stage(stage), priority);
|
node()->set_attrib(tsa->add_off_stage(stage, priority));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: RenderAttrib::compose
|
// Function: RenderAttrib::compose
|
||||||
// Access: Public
|
// Access: Published
|
||||||
// Description: Returns a new RenderAttrib object that represents the
|
// Description: Returns a new RenderAttrib object that represents the
|
||||||
// composition of this attrib with the other attrib. In
|
// composition of this attrib with the other attrib. In
|
||||||
// most cases, this is the same as the other attrib; a
|
// most cases, this is the same as the other attrib; a
|
||||||
@ -30,7 +30,7 @@ compose(const RenderAttrib *other) const {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: RenderAttrib::invert_compose
|
// Function: RenderAttrib::invert_compose
|
||||||
// Access: Public
|
// Access: Published
|
||||||
// Description: Returns a new RenderAttrib object that represents the
|
// Description: Returns a new RenderAttrib object that represents the
|
||||||
// composition of the inverse of this attrib with the
|
// composition of the inverse of this attrib with the
|
||||||
// other attrib. In most cases, this is the same as the
|
// other attrib. In most cases, this is the same as the
|
||||||
|
@ -80,7 +80,7 @@ RenderAttrib::
|
|||||||
//
|
//
|
||||||
// This should return false if a RenderAttrib on a
|
// This should return false if a RenderAttrib on a
|
||||||
// higher node will compose into a RenderAttrib on a
|
// higher node will compose into a RenderAttrib on a
|
||||||
// lower node that has a higher override value, or false
|
// lower node that has a higher override value, or true
|
||||||
// if the lower RenderAttrib will completely replace the
|
// if the lower RenderAttrib will completely replace the
|
||||||
// state.
|
// state.
|
||||||
//
|
//
|
||||||
|
@ -65,10 +65,12 @@ private:
|
|||||||
public:
|
public:
|
||||||
virtual ~RenderAttrib();
|
virtual ~RenderAttrib();
|
||||||
|
|
||||||
|
PUBLISHED:
|
||||||
INLINE CPT(RenderAttrib) compose(const RenderAttrib *other) const;
|
INLINE CPT(RenderAttrib) compose(const RenderAttrib *other) const;
|
||||||
INLINE CPT(RenderAttrib) invert_compose(const RenderAttrib *other) const;
|
INLINE CPT(RenderAttrib) invert_compose(const RenderAttrib *other) const;
|
||||||
virtual bool lower_attrib_can_override() const;
|
virtual bool lower_attrib_can_override() const;
|
||||||
|
|
||||||
|
public:
|
||||||
INLINE bool always_reissue() const;
|
INLINE bool always_reissue() const;
|
||||||
|
|
||||||
virtual bool has_cull_callback() const;
|
virtual bool has_cull_callback() const;
|
||||||
|
@ -37,13 +37,11 @@ TextureAttrib() {
|
|||||||
INLINE TextureAttrib::
|
INLINE TextureAttrib::
|
||||||
TextureAttrib(const TextureAttrib ©) :
|
TextureAttrib(const TextureAttrib ©) :
|
||||||
_on_stages(copy._on_stages),
|
_on_stages(copy._on_stages),
|
||||||
_on_ptr_stages(copy._on_ptr_stages),
|
_render_stages(copy._render_stages),
|
||||||
_on_ff_stages(copy._on_ff_stages),
|
_render_ff_stages(copy._render_ff_stages),
|
||||||
_ff_tc_index(copy._ff_tc_index),
|
|
||||||
_next_implicit_sort(copy._next_implicit_sort),
|
_next_implicit_sort(copy._next_implicit_sort),
|
||||||
_off_stages(copy._off_stages),
|
_off_stages(copy._off_stages),
|
||||||
_off_all_stages(copy._off_all_stages),
|
_off_all_stages(copy._off_all_stages),
|
||||||
_on_textures(copy._on_textures),
|
|
||||||
_sort_seq(copy._sort_seq),
|
_sort_seq(copy._sort_seq),
|
||||||
_filtered_seq(UpdateSeq::old())
|
_filtered_seq(UpdateSeq::old())
|
||||||
{
|
{
|
||||||
@ -92,7 +90,7 @@ get_texture() const {
|
|||||||
INLINE int TextureAttrib::
|
INLINE int TextureAttrib::
|
||||||
get_num_on_stages() const {
|
get_num_on_stages() const {
|
||||||
check_sorted();
|
check_sorted();
|
||||||
return _on_stages.size();
|
return _render_stages.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -103,8 +101,8 @@ get_num_on_stages() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE TextureStage *TextureAttrib::
|
INLINE TextureStage *TextureAttrib::
|
||||||
get_on_stage(int n) const {
|
get_on_stage(int n) const {
|
||||||
nassertr(n >= 0 && n < (int)_on_stages.size(), (TextureStage *)NULL);
|
nassertr(n >= 0 && n < (int)_render_stages.size(), (TextureStage *)NULL);
|
||||||
return _on_stages[n]._stage;
|
return _render_stages[n]->_stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -117,11 +115,11 @@ get_on_stage(int n) const {
|
|||||||
INLINE int TextureAttrib::
|
INLINE int TextureAttrib::
|
||||||
get_num_on_ff_stages() const {
|
get_num_on_ff_stages() const {
|
||||||
check_sorted();
|
check_sorted();
|
||||||
return _on_ff_stages.size();
|
return _render_ff_stages.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TextureAttrib::get_on_ff_stage
|
// Function: TextureAttrib::get_render_ff_stage
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Returns the nth stage turned on by the attribute,
|
// Description: Returns the nth stage turned on by the attribute,
|
||||||
// sorted in render order, including only those relevant
|
// sorted in render order, including only those relevant
|
||||||
@ -130,8 +128,8 @@ get_num_on_ff_stages() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE TextureStage *TextureAttrib::
|
INLINE TextureStage *TextureAttrib::
|
||||||
get_on_ff_stage(int n) const {
|
get_on_ff_stage(int n) const {
|
||||||
nassertr(n >= 0 && n < (int)_on_ff_stages.size(), (TextureStage *)NULL);
|
nassertr(n >= 0 && n < (int)_render_ff_stages.size(), (TextureStage *)NULL);
|
||||||
return _on_ff_stages[n]._stage;
|
return _render_ff_stages[n]->_stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -141,13 +139,13 @@ get_on_ff_stage(int n) const {
|
|||||||
// this returns a unique index number for the texture
|
// this returns a unique index number for the texture
|
||||||
// coordinate name used by that TextureStage. It is
|
// coordinate name used by that TextureStage. It is
|
||||||
// guaranteed to remain the same index number for each
|
// guaranteed to remain the same index number for each
|
||||||
// texcoord name, even if the texture render order
|
// texcoord name (for a given set of TextureStages),
|
||||||
// changes.
|
// even if the texture render order changes.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE int TextureAttrib::
|
INLINE int TextureAttrib::
|
||||||
get_ff_tc_index(int n) const {
|
get_ff_tc_index(int n) const {
|
||||||
nassertr(n >= 0 && n < (int)_ff_tc_index.size(), 0);
|
nassertr(n >= 0 && n < (int)_render_ff_stages.size(), -1);
|
||||||
return _ff_tc_index[n];
|
return _render_ff_stages[n]->_ff_tc_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -158,7 +156,7 @@ get_ff_tc_index(int n) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool TextureAttrib::
|
INLINE bool TextureAttrib::
|
||||||
has_on_stage(TextureStage *stage) const {
|
has_on_stage(TextureStage *stage) const {
|
||||||
return _on_textures.find(stage) != _on_textures.end();
|
return _on_stages.find(StageNode(stage)) != _on_stages.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -169,10 +167,10 @@ has_on_stage(TextureStage *stage) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE Texture *TextureAttrib::
|
INLINE Texture *TextureAttrib::
|
||||||
get_on_texture(TextureStage *stage) const {
|
get_on_texture(TextureStage *stage) const {
|
||||||
OnTextures::const_iterator ti;
|
Stages::const_iterator si;
|
||||||
ti = _on_textures.find(stage);
|
si = _on_stages.find(StageNode(stage));
|
||||||
if (ti != _on_textures.end()) {
|
if (si != _on_stages.end()) {
|
||||||
return (*ti).second;
|
return (*si)._texture;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -197,7 +195,7 @@ get_num_off_stages() const {
|
|||||||
INLINE TextureStage *TextureAttrib::
|
INLINE TextureStage *TextureAttrib::
|
||||||
get_off_stage(int n) const {
|
get_off_stage(int n) const {
|
||||||
nassertr(n >= 0 && n < (int)_off_stages.size(), (TextureStage *)NULL);
|
nassertr(n >= 0 && n < (int)_off_stages.size(), (TextureStage *)NULL);
|
||||||
return _off_stages[n];
|
return _off_stages[n]._stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -208,7 +206,7 @@ get_off_stage(int n) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool TextureAttrib::
|
INLINE bool TextureAttrib::
|
||||||
has_off_stage(TextureStage *stage) const {
|
has_off_stage(TextureStage *stage) const {
|
||||||
return _off_stages.find(stage) != _off_stages.end() ||
|
return _off_stages.find(StageNode(stage)) != _off_stages.end() ||
|
||||||
(_off_all_stages && !has_on_stage(stage));
|
(_off_all_stages && !has_on_stage(stage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,14 +250,17 @@ check_sorted() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TextureAttrib::OnStageNode::Constructor
|
// Function: TextureAttrib::StageNode::Constructor
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE TextureAttrib::OnStageNode::
|
INLINE TextureAttrib::StageNode::
|
||||||
OnStageNode(TextureStage *stage, unsigned int implicit_sort) :
|
StageNode(const TextureStage *stage, unsigned int implicit_sort, int override) :
|
||||||
_stage(stage),
|
// Yeah, we cast away the constness here. Just too much trouble to
|
||||||
_implicit_sort(implicit_sort)
|
// deal with it properly.
|
||||||
|
_stage((TextureStage *)stage),
|
||||||
|
_implicit_sort(implicit_sort),
|
||||||
|
_override(override)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,15 +273,15 @@ OnStageNode(TextureStage *stage, unsigned int implicit_sort) :
|
|||||||
// within priority, within order by sort.
|
// within priority, within order by sort.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool TextureAttrib::CompareTextureStagePriorities::
|
INLINE bool TextureAttrib::CompareTextureStagePriorities::
|
||||||
operator () (const TextureAttrib::OnStageNode &a,
|
operator () (const TextureAttrib::StageNode *a,
|
||||||
const TextureAttrib::OnStageNode &b) const {
|
const TextureAttrib::StageNode *b) const {
|
||||||
if (a._stage->get_priority() != b._stage->get_priority()) {
|
if (a->_stage->get_priority() != b->_stage->get_priority()) {
|
||||||
return a._stage->get_priority() > b._stage->get_priority();
|
return a->_stage->get_priority() > b->_stage->get_priority();
|
||||||
}
|
}
|
||||||
if (a._stage->get_sort() != b._stage->get_sort()) {
|
if (a->_stage->get_sort() != b->_stage->get_sort()) {
|
||||||
return a._stage->get_sort() < b._stage->get_sort();
|
return a->_stage->get_sort() < b->_stage->get_sort();
|
||||||
}
|
}
|
||||||
return a._implicit_sort < b._implicit_sort;
|
return a->_implicit_sort < b->_implicit_sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -290,12 +291,12 @@ operator () (const TextureAttrib::OnStageNode &a,
|
|||||||
// texture stages in order by sort.
|
// texture stages in order by sort.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool TextureAttrib::CompareTextureStageSort::
|
INLINE bool TextureAttrib::CompareTextureStageSort::
|
||||||
operator () (const TextureAttrib::OnStageNode &a,
|
operator () (const TextureAttrib::StageNode *a,
|
||||||
const TextureAttrib::OnStageNode &b) const {
|
const TextureAttrib::StageNode *b) const {
|
||||||
if (a._stage->get_sort() != b._stage->get_sort()) {
|
if (a->_stage->get_sort() != b->_stage->get_sort()) {
|
||||||
return a._stage->get_sort() < b._stage->get_sort();
|
return a->_stage->get_sort() < b->_stage->get_sort();
|
||||||
}
|
}
|
||||||
return a._implicit_sort < b._implicit_sort;
|
return a->_implicit_sort < b->_implicit_sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -305,7 +306,7 @@ operator () (const TextureAttrib::OnStageNode &a,
|
|||||||
// texture stages in order by pointer.
|
// texture stages in order by pointer.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool TextureAttrib::CompareTextureStagePointer::
|
INLINE bool TextureAttrib::CompareTextureStagePointer::
|
||||||
operator () (const TextureAttrib::OnStageNode &a,
|
operator () (const TextureAttrib::StageNode &a,
|
||||||
const TextureAttrib::OnStageNode &b) const {
|
const TextureAttrib::StageNode &b) const {
|
||||||
return a._stage < b._stage;
|
return a._stage < b._stage;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "datagram.h"
|
#include "datagram.h"
|
||||||
#include "datagramIterator.h"
|
#include "datagramIterator.h"
|
||||||
#include "dcast.h"
|
#include "dcast.h"
|
||||||
|
#include "textureStagePool.h"
|
||||||
|
|
||||||
CPT(RenderAttrib) TextureAttrib::_empty_attrib;
|
CPT(RenderAttrib) TextureAttrib::_empty_attrib;
|
||||||
CPT(RenderAttrib) TextureAttrib::_all_off_attrib;
|
CPT(RenderAttrib) TextureAttrib::_all_off_attrib;
|
||||||
@ -108,10 +109,9 @@ make_default() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
int TextureAttrib::
|
int TextureAttrib::
|
||||||
find_on_stage(const TextureStage *stage) const {
|
find_on_stage(const TextureStage *stage) const {
|
||||||
for (int n = 0; n < (int)_on_stages.size(); ++n) {
|
Stages::const_iterator si = _on_stages.find(StageNode(stage));
|
||||||
if (_on_stages[n]._stage == stage) {
|
if (si != _on_stages.end()) {
|
||||||
return n;
|
return (int)(si - _on_stages.begin());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
@ -125,37 +125,15 @@ find_on_stage(const TextureStage *stage) const {
|
|||||||
// turned on by this attrib.
|
// turned on by this attrib.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
CPT(RenderAttrib) TextureAttrib::
|
CPT(RenderAttrib) TextureAttrib::
|
||||||
add_on_stage(TextureStage *stage, Texture *tex) const {
|
add_on_stage(TextureStage *stage, Texture *tex, int override) const {
|
||||||
TextureAttrib *attrib = new TextureAttrib(*this);
|
TextureAttrib *attrib = new TextureAttrib(*this);
|
||||||
pair<OnTextures::iterator, bool> insert_result =
|
Stages::iterator si = attrib->_on_stages.insert(StageNode(stage)).first;
|
||||||
attrib->_on_textures.insert(OnTextures::value_type(stage, tex));
|
(*si)._override = override;
|
||||||
if (insert_result.second) {
|
(*si)._texture = tex;
|
||||||
// If the insert was successful--we have added a new stage that
|
|
||||||
// wasn't present before--then add the stage to the linear list
|
|
||||||
// also.
|
|
||||||
attrib->_on_stages.push_back(OnStageNode(stage, attrib->_next_implicit_sort));
|
|
||||||
++(attrib->_next_implicit_sort);
|
|
||||||
|
|
||||||
// Also ensure it is removed from the off_stages list.
|
|
||||||
attrib->_off_stages.erase(stage);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// If the insert was unsuccessful, it means there was already a
|
|
||||||
// definition for that stage. Replace it.
|
|
||||||
(*insert_result.first).second = tex;
|
|
||||||
|
|
||||||
// Also update the implicit sort.
|
|
||||||
OnStages::iterator si;
|
|
||||||
for (si = attrib->_on_stages.begin(); si != attrib->_on_stages.end(); ++si) {
|
|
||||||
if ((*si)._stage == stage) {
|
|
||||||
(*si)._implicit_sort = attrib->_next_implicit_sort;
|
(*si)._implicit_sort = attrib->_next_implicit_sort;
|
||||||
++(attrib->_next_implicit_sort);
|
++(attrib->_next_implicit_sort);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// In either case, we now need to re-sort the attrib list.
|
// We now need to re-sort the attrib list.
|
||||||
attrib->_sort_seq = UpdateSeq::old();
|
attrib->_sort_seq = UpdateSeq::old();
|
||||||
attrib->_filtered_seq = UpdateSeq::old();
|
attrib->_filtered_seq = UpdateSeq::old();
|
||||||
|
|
||||||
@ -173,17 +151,9 @@ CPT(RenderAttrib) TextureAttrib::
|
|||||||
remove_on_stage(TextureStage *stage) const {
|
remove_on_stage(TextureStage *stage) const {
|
||||||
TextureAttrib *attrib = new TextureAttrib(*this);
|
TextureAttrib *attrib = new TextureAttrib(*this);
|
||||||
|
|
||||||
OnTextures::iterator ti = attrib->_on_textures.find(stage);
|
Stages::iterator si = attrib->_on_stages.find(StageNode(stage));
|
||||||
if (ti != attrib->_on_textures.end()) {
|
if (si != attrib->_on_stages.end()) {
|
||||||
attrib->_on_textures.erase(ti);
|
|
||||||
|
|
||||||
OnStages::iterator si;
|
|
||||||
for (si = attrib->_on_stages.begin(); si != attrib->_on_stages.end(); ++si) {
|
|
||||||
if ((*si)._stage == stage) {
|
|
||||||
attrib->_on_stages.erase(si);
|
attrib->_on_stages.erase(si);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
attrib->_sort_seq = UpdateSeq::old();
|
attrib->_sort_seq = UpdateSeq::old();
|
||||||
attrib->_filtered_seq = UpdateSeq::old();
|
attrib->_filtered_seq = UpdateSeq::old();
|
||||||
@ -200,23 +170,17 @@ remove_on_stage(TextureStage *stage) const {
|
|||||||
// turned off by this attrib.
|
// turned off by this attrib.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
CPT(RenderAttrib) TextureAttrib::
|
CPT(RenderAttrib) TextureAttrib::
|
||||||
add_off_stage(TextureStage *stage) const {
|
add_off_stage(TextureStage *stage, int override) const {
|
||||||
TextureAttrib *attrib = new TextureAttrib(*this);
|
TextureAttrib *attrib = new TextureAttrib(*this);
|
||||||
if (!_off_all_stages) {
|
if (!_off_all_stages) {
|
||||||
attrib->_off_stages.insert(stage);
|
StageNode sn(stage);
|
||||||
|
Stages::iterator sfi = attrib->_off_stages.insert(sn).first;
|
||||||
|
(*sfi)._override = override;
|
||||||
|
|
||||||
// Also ensure it is removed from the on_stages list.
|
// Also ensure it is removed from the on_stages list.
|
||||||
OnTextures::iterator ti = attrib->_on_textures.find(stage);
|
Stages::iterator si = attrib->_on_stages.find(sn);
|
||||||
if (ti != attrib->_on_textures.end()) {
|
if (si != attrib->_on_stages.end()) {
|
||||||
attrib->_on_textures.erase(ti);
|
|
||||||
|
|
||||||
OnStages::iterator si;
|
|
||||||
for (si = attrib->_on_stages.begin(); si != attrib->_on_stages.end(); ++si) {
|
|
||||||
if ((*si)._stage == stage) {
|
|
||||||
attrib->_on_stages.erase(si);
|
attrib->_on_stages.erase(si);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
attrib->_sort_seq = UpdateSeq::old();
|
attrib->_sort_seq = UpdateSeq::old();
|
||||||
attrib->_filtered_seq = UpdateSeq::old();
|
attrib->_filtered_seq = UpdateSeq::old();
|
||||||
}
|
}
|
||||||
@ -234,7 +198,7 @@ add_off_stage(TextureStage *stage) const {
|
|||||||
CPT(RenderAttrib) TextureAttrib::
|
CPT(RenderAttrib) TextureAttrib::
|
||||||
remove_off_stage(TextureStage *stage) const {
|
remove_off_stage(TextureStage *stage) const {
|
||||||
TextureAttrib *attrib = new TextureAttrib(*this);
|
TextureAttrib *attrib = new TextureAttrib(*this);
|
||||||
attrib->_off_stages.erase(stage);
|
attrib->_off_stages.erase(StageNode(stage));
|
||||||
return return_new(attrib);
|
return return_new(attrib);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,41 +217,35 @@ unify_texture_stages(TextureStage *stage) const {
|
|||||||
attrib->_off_all_stages = _off_all_stages;
|
attrib->_off_all_stages = _off_all_stages;
|
||||||
bool any_changed = false;
|
bool any_changed = false;
|
||||||
|
|
||||||
OnStages::const_iterator si;
|
Stages::const_iterator si;
|
||||||
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
|
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
|
||||||
TextureStage *this_stage = (*si)._stage;
|
TextureStage *this_stage = (*si)._stage;
|
||||||
Texture *tex = get_on_texture(this_stage);
|
|
||||||
nassertr(tex != (Texture *)NULL, this);
|
|
||||||
|
|
||||||
if (this_stage->get_name() == stage->get_name()) {
|
if (this_stage->get_name() == stage->get_name()) {
|
||||||
this_stage = stage;
|
this_stage = stage;
|
||||||
any_changed = true;
|
any_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inserted = attrib->_on_textures.insert(OnTextures::value_type(this_stage, tex)).second;
|
Stages::iterator osi = attrib->_on_stages.insert(StageNode(this_stage)).first;
|
||||||
if (inserted) {
|
(*osi)._texture = (*si)._texture;
|
||||||
// If the texture was successfully inserted, it was the first
|
(*osi)._ff_tc_index = (*si)._ff_tc_index;
|
||||||
// appearance of this stage. Add it to the on_stages list.
|
(*osi)._implicit_sort = (*si)._implicit_sort;
|
||||||
attrib->_on_stages.push_back(OnStageNode(this_stage, (*si)._implicit_sort));
|
(*osi)._override = (*si)._override;
|
||||||
} else {
|
|
||||||
// If the texture was not successfully inserted, it was a
|
|
||||||
// duplicate texture stage. This should only be possible if we
|
|
||||||
// have just collapsed a stage.
|
|
||||||
nassertr(this_stage == stage, this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attrib->_next_implicit_sort = _next_implicit_sort;
|
attrib->_next_implicit_sort = _next_implicit_sort;
|
||||||
|
|
||||||
OffStages::const_iterator fsi;
|
Stages::const_iterator fsi;
|
||||||
for (fsi = _off_stages.begin(); fsi != _off_stages.end(); ++fsi) {
|
for (fsi = _off_stages.begin(); fsi != _off_stages.end(); ++fsi) {
|
||||||
if ((*fsi) != stage &&
|
TextureStage *this_stage = (*fsi)._stage;
|
||||||
(*fsi)->get_name() == stage->get_name()) {
|
|
||||||
attrib->_off_stages.insert(stage);
|
if (this_stage != stage &&
|
||||||
|
this_stage->get_name() == stage->get_name()) {
|
||||||
|
this_stage = stage;
|
||||||
any_changed = true;
|
any_changed = true;
|
||||||
} else {
|
|
||||||
attrib->_off_stages.insert(*fsi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attrib->_off_stages.insert(StageNode(this_stage));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!any_changed) {
|
if (!any_changed) {
|
||||||
@ -330,7 +288,7 @@ filter_to_max(int max_texture_stages) const {
|
|||||||
// case of equal priority, we prefer the stage with the lower sort.
|
// case of equal priority, we prefer the stage with the lower sort.
|
||||||
check_sorted();
|
check_sorted();
|
||||||
|
|
||||||
OnStages priority_stages = _on_stages;
|
RenderStages priority_stages = _render_stages;
|
||||||
|
|
||||||
// This sort function uses the STL function object defined above.
|
// This sort function uses the STL function object defined above.
|
||||||
sort(priority_stages.begin(), priority_stages.end(),
|
sort(priority_stages.begin(), priority_stages.end(),
|
||||||
@ -343,13 +301,11 @@ filter_to_max(int max_texture_stages) const {
|
|||||||
// And create a new attrib reflecting these stages.
|
// And create a new attrib reflecting these stages.
|
||||||
PT(TextureAttrib) attrib = new TextureAttrib;
|
PT(TextureAttrib) attrib = new TextureAttrib;
|
||||||
|
|
||||||
OnStages::const_iterator si;
|
RenderStages::const_iterator ri;
|
||||||
for (si = priority_stages.begin(); si != priority_stages.end(); ++si) {
|
for (ri = priority_stages.begin(); ri != priority_stages.end(); ++ri) {
|
||||||
TextureStage *stage = (*si)._stage;
|
attrib->_on_stages.insert(*(*ri));
|
||||||
attrib->_on_textures[stage] = get_on_texture(stage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attrib->_on_stages.swap(priority_stages);
|
|
||||||
attrib->_next_implicit_sort = _next_implicit_sort;
|
attrib->_next_implicit_sort = _next_implicit_sort;
|
||||||
|
|
||||||
CPT(RenderAttrib) new_attrib = return_new(attrib);
|
CPT(RenderAttrib) new_attrib = return_new(attrib);
|
||||||
@ -388,10 +344,13 @@ output(ostream &out) const {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
out << "off";
|
out << "off";
|
||||||
OffStages::const_iterator fi;
|
Stages::const_iterator fi;
|
||||||
for (fi = _off_stages.begin(); fi != _off_stages.end(); ++fi) {
|
for (fi = _off_stages.begin(); fi != _off_stages.end(); ++fi) {
|
||||||
TextureStage *stage = (*fi);
|
TextureStage *stage = (*fi)._stage;
|
||||||
out << " " << stage->get_name();
|
out << " " << stage->get_name();
|
||||||
|
if ((*fi)._override != 0) {
|
||||||
|
out << "^" << (*fi)._override;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_on_stages.empty()) {
|
if (!_on_stages.empty()) {
|
||||||
@ -399,16 +358,19 @@ output(ostream &out) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OnStages::const_iterator si;
|
RenderStages::const_iterator ri;
|
||||||
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
|
for (ri = _render_stages.begin(); ri != _render_stages.end(); ++ri) {
|
||||||
TextureStage *stage = (*si)._stage;
|
const StageNode &sn = *(*ri);
|
||||||
OnTextures::const_iterator ti = _on_textures.find(stage);
|
TextureStage *stage = sn._stage;
|
||||||
if (ti != _on_textures.end()) {
|
Texture *tex = sn._texture;
|
||||||
Texture *tex = (*ti).second;
|
if (tex != NULL) {
|
||||||
out << " " << stage->get_name() << ":" << tex->get_name();
|
out << " " << stage->get_name() << ":" << tex->get_name();
|
||||||
} else {
|
} else {
|
||||||
out << " " << stage->get_name();
|
out << " " << stage->get_name();
|
||||||
}
|
}
|
||||||
|
if (sn._override != 0) {
|
||||||
|
out << "^" << sn._override;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,9 +385,9 @@ output(ostream &out) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool TextureAttrib::
|
bool TextureAttrib::
|
||||||
has_cull_callback() const {
|
has_cull_callback() const {
|
||||||
OnTextures::const_iterator nti;
|
Stages::const_iterator si;
|
||||||
for (nti = _on_textures.begin(); nti != _on_textures.end(); ++nti) {
|
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
|
||||||
Texture *texture = (*nti).second;
|
Texture *texture = (*si)._texture;
|
||||||
if (texture->has_cull_callback()) {
|
if (texture->has_cull_callback()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -449,9 +411,9 @@ has_cull_callback() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool TextureAttrib::
|
bool TextureAttrib::
|
||||||
cull_callback(CullTraverser *trav, const CullTraverserData &data) const {
|
cull_callback(CullTraverser *trav, const CullTraverserData &data) const {
|
||||||
OnTextures::const_iterator nti;
|
Stages::const_iterator si;
|
||||||
for (nti = _on_textures.begin(); nti != _on_textures.end(); ++nti) {
|
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
|
||||||
Texture *texture = (*nti).second;
|
Texture *texture = (*si)._texture;
|
||||||
if (!texture->cull_callback(trav, data)) {
|
if (!texture->cull_callback(trav, data)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -484,52 +446,10 @@ compare_to_impl(const RenderAttrib *other) const {
|
|||||||
return (int)_off_all_stages - (int)ta->_off_all_stages;
|
return (int)_off_all_stages - (int)ta->_off_all_stages;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, verify that the texture assigned to each stage is the
|
Stages::const_iterator si = _on_stages.begin();
|
||||||
// same.
|
Stages::const_iterator osi = ta->_on_stages.begin();
|
||||||
OnTextures::const_iterator li = _on_textures.begin();
|
|
||||||
OnTextures::const_iterator oli = ta->_on_textures.begin();
|
|
||||||
|
|
||||||
while (li != _on_textures.end() && oli != ta->_on_textures.end()) {
|
while (si != _on_stages.end() && osi != ta->_on_stages.end()) {
|
||||||
TextureStage *stage = (*li).first;
|
|
||||||
TextureStage *other_stage = (*oli).first;
|
|
||||||
|
|
||||||
if (stage != other_stage) {
|
|
||||||
return stage < other_stage ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Texture *tex = (*li).second;
|
|
||||||
Texture *other_tex = (*oli).second;
|
|
||||||
|
|
||||||
if (tex != other_tex) {
|
|
||||||
return tex < other_tex ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
++li;
|
|
||||||
++oli;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (li != _on_textures.end()) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (oli != ta->_on_textures.end()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then, we also have to check the linear list of texture stages, to
|
|
||||||
// ensure primarily that the implicit sort numbers match between the
|
|
||||||
// two attribs. (If they did not, then a later call to
|
|
||||||
// texture_stage->set_sort() might make these attribs apply textures
|
|
||||||
// differently, even if they are the same now.)
|
|
||||||
check_sorted();
|
|
||||||
ta->check_sorted();
|
|
||||||
|
|
||||||
nassertr(_on_ptr_stages.size() == _on_stages.size() &&
|
|
||||||
ta->_on_ptr_stages.size() == ta->_on_stages.size(), 0)
|
|
||||||
|
|
||||||
OnStages::const_iterator si = _on_ptr_stages.begin();
|
|
||||||
OnStages::const_iterator osi = ta->_on_ptr_stages.begin();
|
|
||||||
|
|
||||||
while (si != _on_ptr_stages.end() && osi != ta->_on_ptr_stages.end()) {
|
|
||||||
TextureStage *stage = (*si)._stage;
|
TextureStage *stage = (*si)._stage;
|
||||||
TextureStage *other_stage = (*osi)._stage;
|
TextureStage *other_stage = (*osi)._stage;
|
||||||
|
|
||||||
@ -537,6 +457,13 @@ compare_to_impl(const RenderAttrib *other) const {
|
|||||||
return stage < other_stage ? -1 : 1;
|
return stage < other_stage ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Texture *texture = (*si)._texture;
|
||||||
|
Texture *other_texture = (*osi)._texture;
|
||||||
|
|
||||||
|
if (texture != other_texture) {
|
||||||
|
return texture < other_texture ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
int implicit_sort = (*si)._implicit_sort;
|
int implicit_sort = (*si)._implicit_sort;
|
||||||
int other_implicit_sort = (*osi)._implicit_sort;
|
int other_implicit_sort = (*osi)._implicit_sort;
|
||||||
|
|
||||||
@ -544,29 +471,43 @@ compare_to_impl(const RenderAttrib *other) const {
|
|||||||
return implicit_sort < other_implicit_sort ? -1 : 1;
|
return implicit_sort < other_implicit_sort ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int override = (*si)._override;
|
||||||
|
int other_override = (*osi)._override;
|
||||||
|
|
||||||
|
if (override != other_override) {
|
||||||
|
return override < other_override ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
++si;
|
++si;
|
||||||
++osi;
|
++osi;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (si != _on_ptr_stages.end()) {
|
if (si != _on_stages.end()) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (osi != ta->_on_ptr_stages.end()) {
|
if (osi != ta->_on_stages.end()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, ensure that the set of off stages is the same.
|
// Finally, ensure that the set of off stages is the same.
|
||||||
OffStages::const_iterator fi = _off_stages.begin();
|
Stages::const_iterator fi = _off_stages.begin();
|
||||||
OffStages::const_iterator ofi = ta->_off_stages.begin();
|
Stages::const_iterator ofi = ta->_off_stages.begin();
|
||||||
|
|
||||||
while (fi != _off_stages.end() && ofi != ta->_off_stages.end()) {
|
while (fi != _off_stages.end() && ofi != ta->_off_stages.end()) {
|
||||||
TextureStage *stage = (*fi);
|
TextureStage *stage = (*fi)._stage;
|
||||||
TextureStage *other_stage = (*ofi);
|
TextureStage *other_stage = (*ofi)._stage;
|
||||||
|
|
||||||
if (stage != other_stage) {
|
if (stage != other_stage) {
|
||||||
return stage < other_stage ? -1 : 1;
|
return stage < other_stage ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int override = (*fi)._override;
|
||||||
|
int other_override = (*ofi)._override;
|
||||||
|
|
||||||
|
if (override != other_override) {
|
||||||
|
return override < other_override ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
++fi;
|
++fi;
|
||||||
++ofi;
|
++ofi;
|
||||||
}
|
}
|
||||||
@ -612,145 +553,120 @@ compose_impl(const RenderAttrib *other) const {
|
|||||||
// This is a three-way merge between ai, bi, and ci, except that bi
|
// This is a three-way merge between ai, bi, and ci, except that bi
|
||||||
// and ci should have no intersection and therefore needn't be
|
// and ci should have no intersection and therefore needn't be
|
||||||
// compared to each other.
|
// compared to each other.
|
||||||
OnTextures::const_iterator ai = _on_textures.begin();
|
Stages::const_iterator ai = _on_stages.begin();
|
||||||
OnTextures::const_iterator bi = ta->_on_textures.begin();
|
Stages::const_iterator bi = ta->_on_stages.begin();
|
||||||
OffStages::const_iterator ci = ta->_off_stages.begin();
|
Stages::const_iterator ci = ta->_off_stages.begin();
|
||||||
|
|
||||||
// TextureStages that are kept from the original attrib are inserted
|
|
||||||
// into a_stages. Those that are inherited from the secondary
|
|
||||||
// attrib are inserted into b_stages.
|
|
||||||
pset<TextureStage *> a_stages;
|
|
||||||
pset<TextureStage *> b_stages;
|
|
||||||
|
|
||||||
// Create a new TextureAttrib that will hold the result.
|
// Create a new TextureAttrib that will hold the result.
|
||||||
TextureAttrib *attrib = new TextureAttrib;
|
TextureAttrib *attrib = new TextureAttrib;
|
||||||
|
|
||||||
while (ai != _on_textures.end() &&
|
while (ai != _on_stages.end() &&
|
||||||
bi != ta->_on_textures.end() &&
|
bi != ta->_on_stages.end() &&
|
||||||
ci != ta->_off_stages.end()) {
|
ci != ta->_off_stages.end()) {
|
||||||
if ((*ai).first < (*bi).first) {
|
if ((*ai)._stage < (*bi)._stage) {
|
||||||
if ((*ai).first < (*ci)) {
|
if ((*ai)._stage < (*ci)._stage) {
|
||||||
// Here is a stage that we have in the original, which is not
|
// Here is a stage that we have in the original, which is not
|
||||||
// present in the secondary.
|
// present in the secondary.
|
||||||
attrib->_on_textures.insert(attrib->_on_textures.end(), *ai);
|
attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
|
||||||
a_stages.insert((*ai).first);
|
|
||||||
++ai;
|
++ai;
|
||||||
|
|
||||||
} else if ((*ci) < (*ai).first) {
|
} else if ((*ci)._stage < (*ai)._stage) {
|
||||||
// Here is a stage that is turned off in the secondary, but
|
// Here is a stage that is turned off in the secondary, but
|
||||||
// was not present in the original.
|
// was not present in the original.
|
||||||
++ci;
|
++ci;
|
||||||
|
|
||||||
} else { // (*ci) == (*ai).first
|
} else { // (*ci)._stage == (*ai)._stage
|
||||||
// Here is a stage that is turned off in the secondary, and
|
// Here is a stage that is turned off in the secondary, and
|
||||||
// was present in the original.
|
// was present in the original.
|
||||||
|
if ((*ai)._override > (*ci)._override) {
|
||||||
|
// But never mind, keep it anyway.
|
||||||
|
attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
|
||||||
|
}
|
||||||
|
|
||||||
++ai;
|
++ai;
|
||||||
++ci;
|
++ci;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ((*bi).first < (*ai).first) {
|
} else if ((*bi)._stage < (*ai)._stage) {
|
||||||
// Here is a new stage we have in the secondary, that was not
|
// Here is a new stage we have in the secondary, that was not
|
||||||
// present in the original.
|
// present in the original.
|
||||||
attrib->_on_textures.insert(attrib->_on_textures.end(), *bi);
|
attrib->_on_stages.insert(attrib->_on_stages.end(), *bi);
|
||||||
b_stages.insert((*bi).first);
|
|
||||||
++bi;
|
++bi;
|
||||||
|
|
||||||
} else { // (*bi).first == (*ai).first
|
} else { // (*bi)._stage == (*ai)._stage
|
||||||
// Here is a stage we have in both.
|
// Here is a stage we have in both.
|
||||||
attrib->_on_textures.insert(attrib->_on_textures.end(), *bi);
|
if ((*ai)._override > (*bi)._override) {
|
||||||
b_stages.insert((*bi).first);
|
attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
|
||||||
|
} else {
|
||||||
|
attrib->_on_stages.insert(attrib->_on_stages.end(), *bi);
|
||||||
|
}
|
||||||
++ai;
|
++ai;
|
||||||
++bi;
|
++bi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ai != _on_textures.end() && bi != ta->_on_textures.end()) {
|
while (ai != _on_stages.end() && bi != ta->_on_stages.end()) {
|
||||||
if ((*ai).first < (*bi).first) {
|
if ((*ai)._stage < (*bi)._stage) {
|
||||||
// Here is a stage that we have in the original, which is not
|
// Here is a stage that we have in the original, which is not
|
||||||
// present in the secondary.
|
// present in the secondary.
|
||||||
attrib->_on_textures.insert(attrib->_on_textures.end(), *ai);
|
attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
|
||||||
a_stages.insert((*ai).first);
|
|
||||||
++ai;
|
++ai;
|
||||||
|
|
||||||
} else if ((*bi).first < (*ai).first) {
|
} else if ((*bi)._stage < (*ai)._stage) {
|
||||||
// Here is a new stage we have in the secondary, that was not
|
// Here is a new stage we have in the secondary, that was not
|
||||||
// present in the original.
|
// present in the original.
|
||||||
attrib->_on_textures.insert(attrib->_on_textures.end(), *bi);
|
attrib->_on_stages.insert(attrib->_on_stages.end(), *bi);
|
||||||
b_stages.insert((*bi).first);
|
|
||||||
++bi;
|
++bi;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Here is a stage we have in both.
|
// Here is a stage we have in both.
|
||||||
attrib->_on_textures.insert(attrib->_on_textures.end(), *bi);
|
if ((*ai)._override > (*bi)._override) {
|
||||||
b_stages.insert((*bi).first);
|
attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
|
||||||
|
} else {
|
||||||
|
attrib->_on_stages.insert(attrib->_on_stages.end(), *bi);
|
||||||
|
}
|
||||||
++ai;
|
++ai;
|
||||||
++bi;
|
++bi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ai != _on_textures.end() && ci != ta->_off_stages.end()) {
|
while (ai != _on_stages.end() && ci != ta->_off_stages.end()) {
|
||||||
if ((*ai).first < (*ci)) {
|
if ((*ai)._stage < (*ci)._stage) {
|
||||||
// Here is a stage that we have in the original, which is not
|
// Here is a stage that we have in the original, which is not
|
||||||
// present in the secondary.
|
// present in the secondary.
|
||||||
attrib->_on_textures.insert(attrib->_on_textures.end(), *ai);
|
attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
|
||||||
a_stages.insert((*ai).first);
|
|
||||||
++ai;
|
++ai;
|
||||||
|
|
||||||
} else if ((*ci) < (*ai).first) {
|
} else if ((*ci)._stage < (*ai)._stage) {
|
||||||
// Here is a stage that is turned off in the secondary, but
|
// Here is a stage that is turned off in the secondary, but
|
||||||
// was not present in the original.
|
// was not present in the original.
|
||||||
++ci;
|
++ci;
|
||||||
|
|
||||||
} else { // (*ci) == (*ai).first
|
} else { // (*ci)._stage == (*ai)._stage
|
||||||
// Here is a stage that is turned off in the secondary, and
|
// Here is a stage that is turned off in the secondary, and
|
||||||
// was present in the original.
|
// was present in the original.
|
||||||
|
if ((*ai)._override > (*ci)._override) {
|
||||||
|
// But never mind, keep it anyway.
|
||||||
|
attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
|
||||||
|
}
|
||||||
++ai;
|
++ai;
|
||||||
++ci;
|
++ci;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ai != _on_textures.end()) {
|
while (ai != _on_stages.end()) {
|
||||||
attrib->_on_textures.insert(attrib->_on_textures.end(), *ai);
|
attrib->_on_stages.insert(attrib->_on_stages.end(), *ai);
|
||||||
a_stages.insert((*ai).first);
|
|
||||||
++ai;
|
++ai;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (bi != ta->_on_textures.end()) {
|
while (bi != ta->_on_stages.end()) {
|
||||||
attrib->_on_textures.insert(attrib->_on_textures.end(), *bi);
|
attrib->_on_stages.insert(attrib->_on_stages.end(), *bi);
|
||||||
b_stages.insert((*bi).first);
|
|
||||||
++bi;
|
++bi;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we need to build up the linear list. We must put this in
|
|
||||||
// order so that the original stages are first, followed by the
|
|
||||||
// secondary stages. If a texture stage is listed in both, it
|
|
||||||
// receives the secondary sort.
|
|
||||||
|
|
||||||
OnStages::const_iterator asi;
|
|
||||||
for (asi = _on_stages.begin(); asi != _on_stages.end(); ++asi) {
|
|
||||||
TextureStage *stage = (*asi)._stage;
|
|
||||||
|
|
||||||
if (a_stages.find(stage) != a_stages.end()) {
|
|
||||||
// This stage came from the original, and thus receives the
|
|
||||||
// original sort.
|
|
||||||
int implicit_sort = (*asi)._implicit_sort;
|
|
||||||
attrib->_on_stages.push_back(OnStageNode(stage, implicit_sort));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OnStages::const_iterator bsi;
|
|
||||||
for (bsi = ta->_on_stages.begin(); bsi != ta->_on_stages.end(); ++bsi) {
|
|
||||||
TextureStage *stage = (*bsi)._stage;
|
|
||||||
|
|
||||||
if (b_stages.find(stage) != b_stages.end()) {
|
|
||||||
// This stage was inherited from the secondary, and thus
|
|
||||||
// receives the secondary sort.
|
|
||||||
int implicit_sort = _next_implicit_sort + (*bsi)._implicit_sort;
|
|
||||||
attrib->_on_stages.push_back(OnStageNode(stage, implicit_sort));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
attrib->_next_implicit_sort = _next_implicit_sort + ta->_next_implicit_sort;
|
attrib->_next_implicit_sort = _next_implicit_sort + ta->_next_implicit_sort;
|
||||||
|
attrib->_sort_seq = UpdateSeq::old();
|
||||||
|
attrib->_filtered_seq = UpdateSeq::old();
|
||||||
|
|
||||||
return return_new(attrib);
|
return return_new(attrib);
|
||||||
}
|
}
|
||||||
@ -796,23 +712,24 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
|||||||
// Write the off_stages information
|
// Write the off_stages information
|
||||||
dg.add_bool(_off_all_stages);
|
dg.add_bool(_off_all_stages);
|
||||||
dg.add_uint16(get_num_off_stages());
|
dg.add_uint16(get_num_off_stages());
|
||||||
OffStages::const_iterator fi;
|
Stages::const_iterator fi;
|
||||||
for (fi = _off_stages.begin(); fi != _off_stages.end(); ++fi) {
|
for (fi = _off_stages.begin(); fi != _off_stages.end(); ++fi) {
|
||||||
TextureStage *stage = (*fi);
|
TextureStage *stage = (*fi)._stage;
|
||||||
manager->write_pointer(dg, stage);
|
manager->write_pointer(dg, stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the on_stages information
|
// Write the on_stages information
|
||||||
dg.add_uint16(get_num_on_stages());
|
dg.add_uint16(get_num_on_stages());
|
||||||
OnStages::const_iterator si;
|
Stages::const_iterator si;
|
||||||
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
|
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
|
||||||
TextureStage *stage = (*si)._stage;
|
TextureStage *stage = (*si)._stage;
|
||||||
Texture *tex = get_on_texture(stage);
|
Texture *tex = (*si)._texture;
|
||||||
nassertv(tex != (Texture *)NULL);
|
nassertv(tex != (Texture *)NULL);
|
||||||
|
|
||||||
manager->write_pointer(dg, stage);
|
manager->write_pointer(dg, stage);
|
||||||
manager->write_pointer(dg, tex);
|
manager->write_pointer(dg, tex);
|
||||||
dg.add_uint16((*si)._implicit_sort);
|
dg.add_uint16((*si)._implicit_sort);
|
||||||
|
dg.add_int32((*si)._override);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -827,27 +744,33 @@ int TextureAttrib::
|
|||||||
complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||||
int pi = RenderAttrib::complete_pointers(p_list, manager);
|
int pi = RenderAttrib::complete_pointers(p_list, manager);
|
||||||
|
|
||||||
OffStages::iterator ci;
|
Stages::iterator ci;
|
||||||
for (ci = _off_stages.begin(); ci != _off_stages.end(); ++ci) {
|
for (ci = _off_stages.begin(); ci != _off_stages.end(); ++ci) {
|
||||||
TextureStage *ts = DCAST(TextureStage, p_list[pi++]);
|
TextureStage *ts = DCAST(TextureStage, p_list[pi++]);
|
||||||
*ci = ts;
|
*ci = StageNode(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sn = 0;
|
size_t sni = 0;
|
||||||
while (sn < _on_stages.size()) {
|
while (sni < _on_stages.size()) {
|
||||||
TextureStage *ts = DCAST(TextureStage, p_list[pi++]);
|
// Filter the TextureStage through the TextureStagePool.
|
||||||
|
PT(TextureStage) ts = DCAST(TextureStage, p_list[pi++]);
|
||||||
|
ts = TextureStagePool::get_stage(ts);
|
||||||
|
|
||||||
|
// The Texture pointer filters itself through the TexturePool, so
|
||||||
|
// we don't have to do anything special here.
|
||||||
Texture *tex = DCAST(Texture, p_list[pi++]);
|
Texture *tex = DCAST(Texture, p_list[pi++]);
|
||||||
|
|
||||||
if (tex != (Texture *)NULL) {
|
if (tex != (Texture *)NULL) {
|
||||||
_on_textures[ts] = tex;
|
StageNode &sn = _on_stages[sni];
|
||||||
_on_stages[sn]._stage = ts;
|
sn._stage = ts;
|
||||||
++sn;
|
sn._texture = tex;
|
||||||
|
++sni;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// If we couldn't load a texture pointer, turn off that
|
// If we couldn't load a texture pointer, turn off that
|
||||||
// particular texture stage.
|
// particular texture stage.
|
||||||
_off_stages.push_back(ts);
|
_off_stages.push_back(StageNode(ts));
|
||||||
_on_stages.erase(_on_stages.begin() + sn);
|
_on_stages.erase(_on_stages.begin() + sni);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_sort_seq = UpdateSeq::old();
|
_sort_seq = UpdateSeq::old();
|
||||||
@ -897,7 +820,7 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||||||
_off_stages.reserve(num_off_stages);
|
_off_stages.reserve(num_off_stages);
|
||||||
for (i = 0; i < num_off_stages; i++) {
|
for (i = 0; i < num_off_stages; i++) {
|
||||||
manager->read_pointer(scan);
|
manager->read_pointer(scan);
|
||||||
_off_stages.push_back(NULL);
|
_off_stages.push_back(StageNode(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the _on_stages data.
|
// Read the _on_stages data.
|
||||||
@ -917,8 +840,14 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||||||
} else {
|
} else {
|
||||||
implicit_sort = (unsigned int)i;
|
implicit_sort = (unsigned int)i;
|
||||||
}
|
}
|
||||||
|
int override = 0;
|
||||||
|
if (manager->get_file_minor_ver() >= 23) {
|
||||||
|
override = scan.get_int32();
|
||||||
|
}
|
||||||
|
|
||||||
_next_implicit_sort = max(_next_implicit_sort, implicit_sort + 1);
|
_next_implicit_sort = max(_next_implicit_sort, implicit_sort + 1);
|
||||||
_on_stages.push_back(OnStageNode(NULL, implicit_sort));
|
_on_stages.push_back(StageNode(NULL, _next_implicit_sort, override));
|
||||||
|
++_next_implicit_sort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -931,25 +860,17 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void TextureAttrib::
|
void TextureAttrib::
|
||||||
sort_on_stages() {
|
sort_on_stages() {
|
||||||
// First, we have to build up the tc_index mapping. We need a
|
|
||||||
// unique number for each different texcoord name for the various
|
|
||||||
// TextureStages.
|
|
||||||
|
|
||||||
// It's important that this assignment not be based on the whims of
|
|
||||||
// render order--it mustn't change arbitrarily--so we must first
|
|
||||||
// sort the on_stages list into pointer order for this purpose.
|
|
||||||
_on_ptr_stages = _on_stages;
|
|
||||||
sort(_on_ptr_stages.begin(), _on_ptr_stages.end(), CompareTextureStagePointer());
|
|
||||||
|
|
||||||
typedef pmap<const InternalName *, int> UsedTexcoordIndex;
|
typedef pmap<const InternalName *, int> UsedTexcoordIndex;
|
||||||
UsedTexcoordIndex used_texcoord_index;
|
UsedTexcoordIndex used_texcoord_index;
|
||||||
|
|
||||||
typedef pmap<const TextureStage *, int> TexcoordMap;
|
_render_stages.clear();
|
||||||
TexcoordMap tc_map;
|
_render_ff_stages.clear();
|
||||||
|
|
||||||
OnStages::const_iterator si;
|
Stages::iterator si;
|
||||||
for (si = _on_ptr_stages.begin(); si != _on_ptr_stages.end(); ++si) {
|
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
|
||||||
TextureStage *stage = (*si)._stage;
|
StageNode &sn = (*si);
|
||||||
|
TextureStage *stage = sn._stage;
|
||||||
|
nassertv(stage != NULL);
|
||||||
if (stage->is_fixed_function()) {
|
if (stage->is_fixed_function()) {
|
||||||
const InternalName *name = stage->get_texcoord_name();
|
const InternalName *name = stage->get_texcoord_name();
|
||||||
|
|
||||||
@ -958,32 +879,24 @@ sort_on_stages() {
|
|||||||
// particular texcoord name; otherwise, it will return the same
|
// particular texcoord name; otherwise, it will return the same
|
||||||
// index number it returned before.
|
// index number it returned before.
|
||||||
UsedTexcoordIndex::iterator ti = used_texcoord_index.insert(UsedTexcoordIndex::value_type(name, (int)used_texcoord_index.size())).first;
|
UsedTexcoordIndex::iterator ti = used_texcoord_index.insert(UsedTexcoordIndex::value_type(name, (int)used_texcoord_index.size())).first;
|
||||||
int texcoord_index = (*ti).second;
|
(*si)._ff_tc_index = (*ti).second;
|
||||||
|
|
||||||
tc_map[stage] = texcoord_index;
|
_render_ff_stages.push_back(&sn);
|
||||||
}
|
} else {
|
||||||
|
(*si)._ff_tc_index = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we can sort the on_stages list into render order.
|
_render_stages.push_back(&sn);
|
||||||
sort(_on_stages.begin(), _on_stages.end(), CompareTextureStageSort());
|
|
||||||
|
|
||||||
_on_ff_stages.clear();
|
|
||||||
_ff_tc_index.clear();
|
|
||||||
|
|
||||||
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
|
|
||||||
TextureStage *stage = (*si)._stage;
|
|
||||||
if (stage->is_fixed_function()) {
|
|
||||||
_on_ff_stages.push_back(*si);
|
|
||||||
int texcoord_index = tc_map[stage];
|
|
||||||
_ff_tc_index.push_back(texcoord_index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'd like to clear the _filtered map, in case the priority orders
|
sort(_render_stages.begin(), _render_stages.end(), CompareTextureStageSort());
|
||||||
// have changed as well, but we can't do that here: too dangerous.
|
sort(_render_ff_stages.begin(), _render_ff_stages.end(), CompareTextureStageSort());
|
||||||
// Clearing _filtered might cause TextureAttribs to be deleted, and
|
|
||||||
// hence removed from the map that we might be in the middle of
|
// We'd like to clear the _filtered map, in case the TextureStage
|
||||||
// traversing!
|
// priority values have changed as well, but we can't do that here:
|
||||||
|
// it's too dangerous. Clearing _filtered might cause
|
||||||
|
// TextureAttribs to be deleted, and hence removed from the map that
|
||||||
|
// we might be in the middle of traversing!
|
||||||
|
|
||||||
_sort_seq = TextureStage::get_sort_seq();
|
_sort_seq = TextureStage::get_sort_seq();
|
||||||
}
|
}
|
||||||
|
@ -72,9 +72,9 @@ PUBLISHED:
|
|||||||
|
|
||||||
INLINE bool is_identity() const;
|
INLINE bool is_identity() const;
|
||||||
|
|
||||||
CPT(RenderAttrib) add_on_stage(TextureStage *stage, Texture *tex) const;
|
CPT(RenderAttrib) add_on_stage(TextureStage *stage, Texture *tex, int override = 0) const;
|
||||||
CPT(RenderAttrib) remove_on_stage(TextureStage *stage) const;
|
CPT(RenderAttrib) remove_on_stage(TextureStage *stage) const;
|
||||||
CPT(RenderAttrib) add_off_stage(TextureStage *stage) const;
|
CPT(RenderAttrib) add_off_stage(TextureStage *stage, int override = 0) const;
|
||||||
CPT(RenderAttrib) remove_off_stage(TextureStage *stage) const;
|
CPT(RenderAttrib) remove_off_stage(TextureStage *stage) const;
|
||||||
CPT(RenderAttrib) unify_texture_stages(TextureStage *stage) const;
|
CPT(RenderAttrib) unify_texture_stages(TextureStage *stage) const;
|
||||||
|
|
||||||
@ -96,43 +96,45 @@ private:
|
|||||||
void sort_on_stages();
|
void sort_on_stages();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class OnStageNode {
|
class StageNode {
|
||||||
public:
|
public:
|
||||||
INLINE OnStageNode(TextureStage *stage, unsigned int implicit_sort);
|
INLINE StageNode(const TextureStage *stage,
|
||||||
|
unsigned int implicit_sort = 0,
|
||||||
|
int override = 0);
|
||||||
|
|
||||||
PT(TextureStage) _stage;
|
PT(TextureStage) _stage;
|
||||||
|
PT(Texture) _texture;
|
||||||
|
int _ff_tc_index;
|
||||||
unsigned int _implicit_sort;
|
unsigned int _implicit_sort;
|
||||||
|
int _override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CompareTextureStagePriorities {
|
class CompareTextureStagePriorities {
|
||||||
public:
|
public:
|
||||||
INLINE bool operator () (const TextureAttrib::OnStageNode &a, const TextureAttrib::OnStageNode &b) const;
|
INLINE bool operator () (const TextureAttrib::StageNode *a, const TextureAttrib::StageNode *b) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CompareTextureStageSort {
|
class CompareTextureStageSort {
|
||||||
public:
|
public:
|
||||||
INLINE bool operator () (const TextureAttrib::OnStageNode &a, const TextureAttrib::OnStageNode &b) const;
|
INLINE bool operator () (const TextureAttrib::StageNode *a, const TextureAttrib::StageNode *b) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CompareTextureStagePointer {
|
class CompareTextureStagePointer {
|
||||||
public:
|
public:
|
||||||
INLINE bool operator () (const TextureAttrib::OnStageNode &a, const TextureAttrib::OnStageNode &b) const;
|
INLINE bool operator () (const TextureAttrib::StageNode &a, const TextureAttrib::StageNode &b) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef pvector<OnStageNode> OnStages;
|
typedef ov_set<StageNode, CompareTextureStagePointer> Stages;
|
||||||
OnStages _on_stages; // list of all "on" stages, sorted in render order.
|
Stages _on_stages; // set of all "on" stages, indexed by pointer.
|
||||||
OnStages _on_ptr_stages; // above, sorted in pointer order.
|
|
||||||
OnStages _on_ff_stages; // fixed-function stages only, in render order.
|
typedef pvector<StageNode *> RenderStages;
|
||||||
vector_int _ff_tc_index;
|
RenderStages _render_stages; // all "on" stages, sorted in render order.
|
||||||
|
RenderStages _render_ff_stages; // fixed-function stages only, in render order.
|
||||||
unsigned int _next_implicit_sort;
|
unsigned int _next_implicit_sort;
|
||||||
|
|
||||||
typedef ov_set<PT(TextureStage) > OffStages;
|
Stages _off_stages;
|
||||||
OffStages _off_stages;
|
|
||||||
bool _off_all_stages;
|
bool _off_all_stages;
|
||||||
|
|
||||||
typedef pmap<PT(TextureStage), PT(Texture) > OnTextures;
|
|
||||||
OnTextures _on_textures;
|
|
||||||
|
|
||||||
typedef pmap< int, CPT(TextureAttrib) > Filtered;
|
typedef pmap< int, CPT(TextureAttrib) > Filtered;
|
||||||
Filtered _filtered;
|
Filtered _filtered;
|
||||||
|
|
||||||
|
@ -44,3 +44,14 @@ operator + (const TextureStageCollection &other) const {
|
|||||||
a += other;
|
a += other;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextureStageCollection::CompareTextureStageSort::operator ()
|
||||||
|
// Access: Public
|
||||||
|
// Description: This STL function object is used to sort a list of
|
||||||
|
// texture stages in order by sort.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool TextureStageCollection::CompareTextureStageSort::
|
||||||
|
operator () (const TextureStage *a, const TextureStage *b) const {
|
||||||
|
return a->get_sort() < b->get_sort();
|
||||||
|
}
|
||||||
|
@ -272,7 +272,7 @@ size() const {
|
|||||||
void TextureStageCollection::
|
void TextureStageCollection::
|
||||||
sort() {
|
sort() {
|
||||||
::sort(_texture_stages.begin(), _texture_stages.end(),
|
::sort(_texture_stages.begin(), _texture_stages.end(),
|
||||||
IndirectLess<TextureStage>());
|
CompareTextureStageSort());
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -56,6 +56,12 @@ PUBLISHED:
|
|||||||
private:
|
private:
|
||||||
typedef PTA(PT(TextureStage)) TextureStages;
|
typedef PTA(PT(TextureStage)) TextureStages;
|
||||||
TextureStages _texture_stages;
|
TextureStages _texture_stages;
|
||||||
|
|
||||||
|
class CompareTextureStageSort {
|
||||||
|
public:
|
||||||
|
INLINE bool operator () (const TextureStage *a, const TextureStage *b) const;
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
INLINE ostream &operator << (ostream &out, const TextureStageCollection &col) {
|
INLINE ostream &operator << (ostream &out, const TextureStageCollection &col) {
|
||||||
|
@ -33,7 +33,7 @@ static const unsigned short _bam_major_ver = 6;
|
|||||||
// Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData.
|
// Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData.
|
||||||
|
|
||||||
static const unsigned short _bam_first_minor_ver = 14;
|
static const unsigned short _bam_first_minor_ver = 14;
|
||||||
static const unsigned short _bam_minor_ver = 22;
|
static const unsigned short _bam_minor_ver = 23;
|
||||||
// Bumped to minor version 14 on 12/19/07 to change default ColorAttrib.
|
// Bumped to minor version 14 on 12/19/07 to change default ColorAttrib.
|
||||||
// Bumped to minor version 15 on 4/9/08 to add TextureAttrib::_implicit_sort.
|
// Bumped to minor version 15 on 4/9/08 to add TextureAttrib::_implicit_sort.
|
||||||
// Bumped to minor version 16 on 5/13/08 to add Texture::_quality_level.
|
// Bumped to minor version 16 on 5/13/08 to add Texture::_quality_level.
|
||||||
@ -43,6 +43,7 @@ static const unsigned short _bam_minor_ver = 22;
|
|||||||
// Bumped to minor version 20 on 4/21/09 to add MovingPartBase::_forced_channel.
|
// Bumped to minor version 20 on 4/21/09 to add MovingPartBase::_forced_channel.
|
||||||
// Bumped to minor version 21 on 2/26/08 to add BamEnums::BamObjectCode.
|
// Bumped to minor version 21 on 2/26/08 to add BamEnums::BamObjectCode.
|
||||||
// Bumped to minor version 22 on 7/31/09 to add UvScrollNode R speed.
|
// Bumped to minor version 22 on 7/31/09 to add UvScrollNode R speed.
|
||||||
|
// Bumped to minor version 23 on 5/4/10 to add internal TextureAttrib overrides.
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user