mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 00:32:57 -04:00
Merge branch 'release/1.10.x'
This commit is contained in:
commit
d5788d9422
@ -214,23 +214,23 @@ class ParticlePanel(AppShell):
|
|||||||
('System', 'Pool Size',
|
('System', 'Pool Size',
|
||||||
'Max number of simultaneous particles',
|
'Max number of simultaneous particles',
|
||||||
self.setSystemPoolSize,
|
self.setSystemPoolSize,
|
||||||
1.0, 1.0),
|
1.0, 2000000, 1.0),
|
||||||
('System', 'Birth Rate',
|
('System', 'Birth Rate',
|
||||||
'Seconds between particle births',
|
'Seconds between particle births',
|
||||||
self.setSystemBirthRate,
|
self.setSystemBirthRate,
|
||||||
0.0, None),
|
0.0, None, None),
|
||||||
('System', 'Litter Size',
|
('System', 'Litter Size',
|
||||||
'Number of particle created at each birth',
|
'Number of particle created at each birth',
|
||||||
self.setSystemLitterSize,
|
self.setSystemLitterSize,
|
||||||
1.0, 1.0),
|
1.0, 0x7fffffff, 1.0),
|
||||||
('System', 'Litter Spread',
|
('System', 'Litter Spread',
|
||||||
'Variation in litter size',
|
'Variation in litter size',
|
||||||
self.setSystemLitterSpread,
|
self.setSystemLitterSpread,
|
||||||
0.0, 1.0),
|
0.0, 0x7fffffff, 1.0),
|
||||||
('System', 'Lifespan',
|
('System', 'Lifespan',
|
||||||
'Age in seconds at which the system (vs. particles) should die',
|
'Age in seconds at which the system (vs. particles) should die',
|
||||||
self.setSystemLifespan,
|
self.setSystemLifespan,
|
||||||
0.0, None)
|
0.0, None, None)
|
||||||
)
|
)
|
||||||
self.createFloaters(systemPage, systemFloaterDefs)
|
self.createFloaters(systemPage, systemFloaterDefs)
|
||||||
|
|
||||||
@ -269,27 +269,27 @@ class ParticlePanel(AppShell):
|
|||||||
('Factory', 'Life Span',
|
('Factory', 'Life Span',
|
||||||
'Average particle lifespan in seconds',
|
'Average particle lifespan in seconds',
|
||||||
self.setFactoryLifeSpan,
|
self.setFactoryLifeSpan,
|
||||||
0.0, None),
|
0.0, None, None),
|
||||||
('Factory', 'Life Span Spread',
|
('Factory', 'Life Span Spread',
|
||||||
'Variation in lifespan',
|
'Variation in lifespan',
|
||||||
self.setFactoryLifeSpanSpread,
|
self.setFactoryLifeSpanSpread,
|
||||||
0.0, None),
|
0.0, None, None),
|
||||||
('Factory', 'Mass',
|
('Factory', 'Mass',
|
||||||
'Average particle mass',
|
'Average particle mass',
|
||||||
self.setFactoryParticleMass,
|
self.setFactoryParticleMass,
|
||||||
0.001, None),
|
0.001, None, None),
|
||||||
('Factory', 'Mass Spread',
|
('Factory', 'Mass Spread',
|
||||||
'Variation in particle mass',
|
'Variation in particle mass',
|
||||||
self.setFactoryParticleMassSpread,
|
self.setFactoryParticleMassSpread,
|
||||||
0.0, None),
|
0.0, None, None),
|
||||||
('Factory', 'Terminal Velocity',
|
('Factory', 'Terminal Velocity',
|
||||||
'Cap on average particle velocity',
|
'Cap on average particle velocity',
|
||||||
self.setFactoryTerminalVelocity,
|
self.setFactoryTerminalVelocity,
|
||||||
0.0, None),
|
0.0, None, None),
|
||||||
('Factory', 'Terminal Vel. Spread',
|
('Factory', 'Terminal Vel. Spread',
|
||||||
'Variation in terminal velocity',
|
'Variation in terminal velocity',
|
||||||
self.setFactoryTerminalVelocitySpread,
|
self.setFactoryTerminalVelocitySpread,
|
||||||
0.0, None),
|
0.0, None, None),
|
||||||
)
|
)
|
||||||
self.createFloaters(factoryPage, factoryWidgets)
|
self.createFloaters(factoryPage, factoryWidgets)
|
||||||
|
|
||||||
@ -966,19 +966,29 @@ class ParticlePanel(AppShell):
|
|||||||
|
|
||||||
def createFloaters(self, parent, widgetDefinitions):
|
def createFloaters(self, parent, widgetDefinitions):
|
||||||
widgets = []
|
widgets = []
|
||||||
for category, label, balloonHelp, command, min, resolution in widgetDefinitions:
|
for category, label, balloonHelp, command, min, max, resolution in widgetDefinitions:
|
||||||
widgets.append(
|
widgets.append(
|
||||||
self.createFloater(parent, category, label, balloonHelp,
|
self.createFloater(parent, category, label, balloonHelp,
|
||||||
command, min, resolution)
|
command, min, max, resolution)
|
||||||
)
|
)
|
||||||
return widgets
|
return widgets
|
||||||
|
|
||||||
def createFloater(self, parent, category, text, balloonHelp,
|
def createFloater(self, parent, category, text, balloonHelp,
|
||||||
command = None, min = 0.0, resolution = None,
|
command = None, min = 0.0, max = None, resolution = None,
|
||||||
numDigits = 3, **kw):
|
numDigits = None, **kw):
|
||||||
kw['text'] = text
|
kw['text'] = text
|
||||||
kw['min'] = min
|
kw['min'] = min
|
||||||
|
if max is not None:
|
||||||
|
kw['max'] = max
|
||||||
kw['resolution'] = resolution
|
kw['resolution'] = resolution
|
||||||
|
if numDigits is None:
|
||||||
|
# If this is apparently an integer setting, show no decimals.
|
||||||
|
if resolution is not None and int(resolution) == resolution and \
|
||||||
|
(min is None or int(min) == min) and \
|
||||||
|
(max is None or int(max) == max):
|
||||||
|
numDigits = 0
|
||||||
|
else:
|
||||||
|
numDigits = 3
|
||||||
kw['numDigits'] = numDigits
|
kw['numDigits'] = numDigits
|
||||||
widget = Floater.Floater(parent, **kw)
|
widget = Floater.Floater(parent, **kw)
|
||||||
# Do this after the widget so command isn't called on creation
|
# Do this after the widget so command isn't called on creation
|
||||||
|
@ -6408,9 +6408,21 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
|
|||||||
TypeManager::is_vector_unsigned_char(type)) {
|
TypeManager::is_vector_unsigned_char(type)) {
|
||||||
// Most types are now handled by the many overloads of Dtool_WrapValue,
|
// Most types are now handled by the many overloads of Dtool_WrapValue,
|
||||||
// defined in py_panda.h.
|
// defined in py_panda.h.
|
||||||
|
if (!remap->_has_this && remap->_cppfunc != nullptr &&
|
||||||
|
remap->_cppfunc->get_simple_name() == "encrypt_string" &&
|
||||||
|
return_expr == "return_value") {
|
||||||
|
// Temporary hack to fix #684 to avoid an ABI change.
|
||||||
|
out << "#if PY_MAJOR_VERSION >= 3\n";
|
||||||
|
indent(out, indent_level)
|
||||||
|
<< "return PyBytes_FromStringAndSize((char *)return_value.data(), (Py_ssize_t)return_value.size());\n";
|
||||||
|
out << "#else\n";
|
||||||
|
indent(out, indent_level)
|
||||||
|
<< "return PyString_FromStringAndSize((char *)return_value.data(), (Py_ssize_t)return_value.size());\n";
|
||||||
|
out << "#endif\n";
|
||||||
|
} else {
|
||||||
indent(out, indent_level)
|
indent(out, indent_level)
|
||||||
<< "return Dtool_WrapValue(" << return_expr << ");\n";
|
<< "return Dtool_WrapValue(" << return_expr << ");\n";
|
||||||
|
}
|
||||||
} else if (TypeManager::is_pointer(type)) {
|
} else if (TypeManager::is_pointer(type)) {
|
||||||
bool is_const = TypeManager::is_const_pointer_to_anything(type);
|
bool is_const = TypeManager::is_const_pointer_to_anything(type);
|
||||||
bool owns_memory = remap->_return_value_needs_management;
|
bool owns_memory = remap->_return_value_needs_management;
|
||||||
|
@ -924,6 +924,10 @@ if (COMPILER=="GCC"):
|
|||||||
else:
|
else:
|
||||||
PkgDisable("OPENCV")
|
PkgDisable("OPENCV")
|
||||||
|
|
||||||
|
if GetTarget() == "darwin" and not PkgSkip("OPENAL"):
|
||||||
|
LibName("OPENAL", "-framework AudioToolbox")
|
||||||
|
LibName("OPENAL", "-framework CoreAudio")
|
||||||
|
|
||||||
if not PkgSkip("ASSIMP") and \
|
if not PkgSkip("ASSIMP") and \
|
||||||
os.path.isfile(GetThirdpartyDir() + "assimp/lib/libassimp.a"):
|
os.path.isfile(GetThirdpartyDir() + "assimp/lib/libassimp.a"):
|
||||||
# Also pick up IrrXML, which is needed when linking statically.
|
# Also pick up IrrXML, which is needed when linking statically.
|
||||||
|
@ -1612,7 +1612,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
// Find the first non-NaN vertex.
|
// Find the first non-NaN vertex.
|
||||||
while (!found_any && i < cdata->_num_vertices) {
|
while (!found_any && i < cdata->_num_vertices) {
|
||||||
reader.set_row(cdata->_first_vertex + i);
|
reader.set_row(cdata->_first_vertex + i);
|
||||||
LPoint3 first_vertex = mat.xform_point(reader.get_data3());
|
LPoint3 first_vertex = mat.xform_point_general(reader.get_data3());
|
||||||
if (!first_vertex.is_nan()) {
|
if (!first_vertex.is_nan()) {
|
||||||
min_point = first_vertex;
|
min_point = first_vertex;
|
||||||
max_point = first_vertex;
|
max_point = first_vertex;
|
||||||
@ -1624,7 +1624,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
|
|
||||||
for (; i < cdata->_num_vertices; ++i) {
|
for (; i < cdata->_num_vertices; ++i) {
|
||||||
reader.set_row_unsafe(cdata->_first_vertex + i);
|
reader.set_row_unsafe(cdata->_first_vertex + i);
|
||||||
LPoint3 vertex = mat.xform_point(reader.get_data3());
|
LPoint3 vertex = mat.xform_point_general(reader.get_data3());
|
||||||
|
|
||||||
min_point.set(min(min_point[0], vertex[0]),
|
min_point.set(min(min_point[0], vertex[0]),
|
||||||
min(min_point[1], vertex[1]),
|
min(min_point[1], vertex[1]),
|
||||||
@ -1677,7 +1677,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
int ii = index.get_data1i();
|
int ii = index.get_data1i();
|
||||||
if (ii != strip_cut_index) {
|
if (ii != strip_cut_index) {
|
||||||
reader.set_row(ii);
|
reader.set_row(ii);
|
||||||
LPoint3 first_vertex = mat.xform_point(reader.get_data3());
|
LPoint3 first_vertex = mat.xform_point_general(reader.get_data3());
|
||||||
if (!first_vertex.is_nan()) {
|
if (!first_vertex.is_nan()) {
|
||||||
min_point = first_vertex;
|
min_point = first_vertex;
|
||||||
max_point = first_vertex;
|
max_point = first_vertex;
|
||||||
@ -1693,7 +1693,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
reader.set_row_unsafe(ii);
|
reader.set_row_unsafe(ii);
|
||||||
LPoint3 vertex = mat.xform_point(reader.get_data3());
|
LPoint3 vertex = mat.xform_point_general(reader.get_data3());
|
||||||
|
|
||||||
min_point.set(min(min_point[0], vertex[0]),
|
min_point.set(min(min_point[0], vertex[0]),
|
||||||
min(min_point[1], vertex[1]),
|
min(min_point[1], vertex[1]),
|
||||||
|
@ -3136,6 +3136,19 @@ get_texture(TextureStage *stage) const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively searches the scene graph for references to the given texture,
|
||||||
|
* and replaces them with the new texture.
|
||||||
|
*/
|
||||||
|
void NodePath::
|
||||||
|
replace_texture(Texture *tex, Texture *new_tex) {
|
||||||
|
nassertv_always(!is_empty());
|
||||||
|
nassertv(tex != nullptr);
|
||||||
|
nassertv(new_tex != nullptr);
|
||||||
|
|
||||||
|
r_replace_texture(node(), tex, new_tex);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the sampler state that has been given for the base-level texture
|
* Returns the sampler state that has been given for the base-level texture
|
||||||
* that has been set on this particular node. If no sampler state was given,
|
* that has been set on this particular node. If no sampler state was given,
|
||||||
@ -6425,6 +6438,53 @@ r_find_all_textures(PandaNode *node, TextureStage *stage,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively replaces references to the given texture on this section of the
|
||||||
|
* scene graph with the given other texture.
|
||||||
|
*/
|
||||||
|
void NodePath::
|
||||||
|
r_replace_texture(PandaNode *node, Texture *tex, Texture *new_tex) {
|
||||||
|
// Consider the state of the node itself.
|
||||||
|
{
|
||||||
|
CPT(RenderState) node_state = node->get_state();
|
||||||
|
const TextureAttrib *ta;
|
||||||
|
if (node_state->get_attrib(ta)) {
|
||||||
|
CPT(RenderAttrib) new_ta = ta->replace_texture(tex, new_tex);
|
||||||
|
if (new_ta != ta) {
|
||||||
|
node->set_state(node_state->set_attrib(new_ta));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is a GeomNode, consider the state of any of its Geoms.
|
||||||
|
if (node->is_geom_node()) {
|
||||||
|
GeomNode *gnode;
|
||||||
|
DCAST_INTO_V(gnode, node);
|
||||||
|
|
||||||
|
int num_geoms = gnode->get_num_geoms();
|
||||||
|
for (int i = 0; i < num_geoms; i++) {
|
||||||
|
CPT(RenderState) geom_state = gnode->get_geom_state(i);
|
||||||
|
|
||||||
|
// Look for a TextureAttrib on the state.
|
||||||
|
const TextureAttrib *ta;
|
||||||
|
if (geom_state->get_attrib(ta)) {
|
||||||
|
CPT(RenderAttrib) new_ta = ta->replace_texture(tex, new_tex);
|
||||||
|
if (new_ta != ta) {
|
||||||
|
gnode->set_geom_state(i, geom_state->set_attrib(new_ta));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now consider children.
|
||||||
|
PandaNode::Children cr = node->get_children();
|
||||||
|
size_t num_children = cr.get_num_children();
|
||||||
|
for (size_t i = 0; i < num_children; ++i) {
|
||||||
|
PandaNode *child = cr.get_child(i);
|
||||||
|
r_replace_texture(child, tex, new_tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -620,6 +620,7 @@ PUBLISHED:
|
|||||||
bool has_texture_off(TextureStage *stage) const;
|
bool has_texture_off(TextureStage *stage) const;
|
||||||
Texture *get_texture() const;
|
Texture *get_texture() const;
|
||||||
Texture *get_texture(TextureStage *stage) const;
|
Texture *get_texture(TextureStage *stage) const;
|
||||||
|
void replace_texture(Texture *tex, Texture *new_tex);
|
||||||
const SamplerState &get_texture_sampler() const;
|
const SamplerState &get_texture_sampler() const;
|
||||||
const SamplerState &get_texture_sampler(TextureStage *stage) const;
|
const SamplerState &get_texture_sampler(TextureStage *stage) const;
|
||||||
|
|
||||||
@ -1003,6 +1004,7 @@ private:
|
|||||||
Texture *r_find_texture(PandaNode *node, TextureStage *stage) const;
|
Texture *r_find_texture(PandaNode *node, TextureStage *stage) const;
|
||||||
void r_find_all_textures(PandaNode *node, TextureStage *stage,
|
void r_find_all_textures(PandaNode *node, TextureStage *stage,
|
||||||
Textures &textures) const;
|
Textures &textures) const;
|
||||||
|
static void r_replace_texture(PandaNode *node, Texture *tex, Texture *new_tex);
|
||||||
|
|
||||||
typedef phash_set<TextureStage *, pointer_hash> TextureStages;
|
typedef phash_set<TextureStage *, pointer_hash> TextureStages;
|
||||||
TextureStage *r_find_texture_stage(PandaNode *node, const RenderState *state,
|
TextureStage *r_find_texture_stage(PandaNode *node, const RenderState *state,
|
||||||
|
@ -101,7 +101,7 @@ int ScissorAttrib::
|
|||||||
compare_to_impl(const RenderAttrib *other) const {
|
compare_to_impl(const RenderAttrib *other) const {
|
||||||
const ScissorAttrib *ta = (const ScissorAttrib *)other;
|
const ScissorAttrib *ta = (const ScissorAttrib *)other;
|
||||||
|
|
||||||
if (!_off && !ta->_off) {
|
if (_off && ta->_off) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,6 +250,32 @@ unify_texture_stages(TextureStage *stage) const {
|
|||||||
return return_new(attrib);
|
return return_new(attrib);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new TextureAttrib, just like this one, but with all references to
|
||||||
|
* the given texture replaced with the new texture.
|
||||||
|
*/
|
||||||
|
CPT(RenderAttrib) TextureAttrib::
|
||||||
|
replace_texture(Texture *tex, Texture *new_tex) const {
|
||||||
|
TextureAttrib *attrib = nullptr;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < _on_stages.size(); ++i) {
|
||||||
|
const StageNode &sn = _on_stages[i];
|
||||||
|
if (sn._texture == tex) {
|
||||||
|
if (attrib == nullptr) {
|
||||||
|
attrib = new TextureAttrib(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
attrib->_on_stages[i]._texture = new_tex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrib != nullptr) {
|
||||||
|
return return_new(attrib);
|
||||||
|
} else {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new TextureAttrib, very much like this one, but with the number
|
* Returns a new TextureAttrib, very much like this one, but with the number
|
||||||
* of on_stages reduced to be no more than max_texture_stages. The number of
|
* of on_stages reduced to be no more than max_texture_stages. The number of
|
||||||
|
@ -89,6 +89,7 @@ PUBLISHED:
|
|||||||
CPT(RenderAttrib) add_off_stage(TextureStage *stage, int override = 0) 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;
|
||||||
|
CPT(RenderAttrib) replace_texture(Texture *tex, Texture *new_tex) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CPT(TextureAttrib) filter_to_max(int max_texture_stages) const;
|
CPT(TextureAttrib) filter_to_max(int max_texture_stages) const;
|
||||||
|
@ -1843,10 +1843,10 @@ get_character_glyphs(int character, const TextProperties *properties,
|
|||||||
// Maybe we should remap the character to something else--e.g. a small
|
// Maybe we should remap the character to something else--e.g. a small
|
||||||
// capital.
|
// capital.
|
||||||
const UnicodeLatinMap::Entry *map_entry =
|
const UnicodeLatinMap::Entry *map_entry =
|
||||||
UnicodeLatinMap::look_up(character);
|
UnicodeLatinMap::look_up((char32_t)character);
|
||||||
if (map_entry != nullptr) {
|
if (map_entry != nullptr) {
|
||||||
if (properties->get_small_caps() &&
|
if (properties->get_small_caps() &&
|
||||||
map_entry->_toupper_character != character) {
|
map_entry->_toupper_character != (char32_t)character) {
|
||||||
character = map_entry->_toupper_character;
|
character = map_entry->_toupper_character;
|
||||||
map_entry = UnicodeLatinMap::look_up(character);
|
map_entry = UnicodeLatinMap::look_up(character);
|
||||||
glyph_scale = properties->get_small_caps_scale();
|
glyph_scale = properties->get_small_caps_scale();
|
||||||
@ -1871,7 +1871,7 @@ get_character_glyphs(int character, const TextProperties *properties,
|
|||||||
got_glyph = font->get_glyph(map_entry->_ascii_equiv, glyph);
|
got_glyph = font->get_glyph(map_entry->_ascii_equiv, glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!got_glyph && map_entry->_toupper_character != character) {
|
if (!got_glyph && map_entry->_toupper_character != (char32_t)character) {
|
||||||
// If we still couldn't find it, try the uppercase equivalent.
|
// If we still couldn't find it, try the uppercase equivalent.
|
||||||
character = map_entry->_toupper_character;
|
character = map_entry->_toupper_character;
|
||||||
map_entry = UnicodeLatinMap::look_up(character);
|
map_entry = UnicodeLatinMap::look_up(character);
|
||||||
|
@ -149,3 +149,22 @@ def test_nodepath_python_tags():
|
|||||||
rc1 = sys.getrefcount(path.python_tags)
|
rc1 = sys.getrefcount(path.python_tags)
|
||||||
rc2 = sys.getrefcount(path.python_tags)
|
rc2 = sys.getrefcount(path.python_tags)
|
||||||
assert rc1 == rc2
|
assert rc1 == rc2
|
||||||
|
|
||||||
|
|
||||||
|
def test_nodepath_replace_texture():
|
||||||
|
from panda3d.core import NodePath, Texture
|
||||||
|
|
||||||
|
tex1 = Texture()
|
||||||
|
tex2 = Texture()
|
||||||
|
|
||||||
|
path1 = NodePath("node1")
|
||||||
|
path1.set_texture(tex1)
|
||||||
|
path1.replace_texture(tex1, tex2)
|
||||||
|
assert path1.get_texture() == tex2
|
||||||
|
|
||||||
|
path1 = NodePath("node1")
|
||||||
|
path2 = path1.attach_new_node("node2")
|
||||||
|
path2.set_texture(tex1)
|
||||||
|
path1.replace_texture(tex1, tex2)
|
||||||
|
assert not path1.has_texture()
|
||||||
|
assert path2.get_texture() == tex2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user