Merge branch 'release/1.10.x'

This commit is contained in:
rdb 2019-07-10 12:22:56 +02:00
commit d5788d9422
11 changed files with 160 additions and 26 deletions

View File

@ -214,23 +214,23 @@ class ParticlePanel(AppShell):
('System', 'Pool Size',
'Max number of simultaneous particles',
self.setSystemPoolSize,
1.0, 1.0),
1.0, 2000000, 1.0),
('System', 'Birth Rate',
'Seconds between particle births',
self.setSystemBirthRate,
0.0, None),
0.0, None, None),
('System', 'Litter Size',
'Number of particle created at each birth',
self.setSystemLitterSize,
1.0, 1.0),
1.0, 0x7fffffff, 1.0),
('System', 'Litter Spread',
'Variation in litter size',
self.setSystemLitterSpread,
0.0, 1.0),
0.0, 0x7fffffff, 1.0),
('System', 'Lifespan',
'Age in seconds at which the system (vs. particles) should die',
self.setSystemLifespan,
0.0, None)
0.0, None, None)
)
self.createFloaters(systemPage, systemFloaterDefs)
@ -269,27 +269,27 @@ class ParticlePanel(AppShell):
('Factory', 'Life Span',
'Average particle lifespan in seconds',
self.setFactoryLifeSpan,
0.0, None),
0.0, None, None),
('Factory', 'Life Span Spread',
'Variation in lifespan',
self.setFactoryLifeSpanSpread,
0.0, None),
0.0, None, None),
('Factory', 'Mass',
'Average particle mass',
self.setFactoryParticleMass,
0.001, None),
0.001, None, None),
('Factory', 'Mass Spread',
'Variation in particle mass',
self.setFactoryParticleMassSpread,
0.0, None),
0.0, None, None),
('Factory', 'Terminal Velocity',
'Cap on average particle velocity',
self.setFactoryTerminalVelocity,
0.0, None),
0.0, None, None),
('Factory', 'Terminal Vel. Spread',
'Variation in terminal velocity',
self.setFactoryTerminalVelocitySpread,
0.0, None),
0.0, None, None),
)
self.createFloaters(factoryPage, factoryWidgets)
@ -966,19 +966,29 @@ class ParticlePanel(AppShell):
def createFloaters(self, parent, widgetDefinitions):
widgets = []
for category, label, balloonHelp, command, min, resolution in widgetDefinitions:
for category, label, balloonHelp, command, min, max, resolution in widgetDefinitions:
widgets.append(
self.createFloater(parent, category, label, balloonHelp,
command, min, resolution)
command, min, max, resolution)
)
return widgets
def createFloater(self, parent, category, text, balloonHelp,
command = None, min = 0.0, resolution = None,
numDigits = 3, **kw):
command = None, min = 0.0, max = None, resolution = None,
numDigits = None, **kw):
kw['text'] = text
kw['min'] = min
if max is not None:
kw['max'] = max
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
widget = Floater.Floater(parent, **kw)
# Do this after the widget so command isn't called on creation

View File

@ -6408,9 +6408,21 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
TypeManager::is_vector_unsigned_char(type)) {
// Most types are now handled by the many overloads of Dtool_WrapValue,
// defined in py_panda.h.
indent(out, indent_level)
<< "return Dtool_WrapValue(" << return_expr << ");\n";
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)
<< "return Dtool_WrapValue(" << return_expr << ");\n";
}
} else if (TypeManager::is_pointer(type)) {
bool is_const = TypeManager::is_const_pointer_to_anything(type);
bool owns_memory = remap->_return_value_needs_management;

View File

@ -924,6 +924,10 @@ if (COMPILER=="GCC"):
else:
PkgDisable("OPENCV")
if GetTarget() == "darwin" and not PkgSkip("OPENAL"):
LibName("OPENAL", "-framework AudioToolbox")
LibName("OPENAL", "-framework CoreAudio")
if not PkgSkip("ASSIMP") and \
os.path.isfile(GetThirdpartyDir() + "assimp/lib/libassimp.a"):
# Also pick up IrrXML, which is needed when linking statically.

View File

@ -1612,7 +1612,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
// Find the first non-NaN vertex.
while (!found_any && i < cdata->_num_vertices) {
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()) {
min_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) {
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(min_point[1], vertex[1]),
@ -1677,7 +1677,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
int ii = index.get_data1i();
if (ii != strip_cut_index) {
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()) {
min_point = first_vertex;
max_point = first_vertex;
@ -1693,7 +1693,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
continue;
}
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(min_point[1], vertex[1]),

View File

@ -3136,6 +3136,19 @@ get_texture(TextureStage *stage) const {
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
* 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);
}
}
/**
*
*/

View File

@ -620,6 +620,7 @@ PUBLISHED:
bool has_texture_off(TextureStage *stage) const;
Texture *get_texture() 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(TextureStage *stage) const;
@ -1003,6 +1004,7 @@ private:
Texture *r_find_texture(PandaNode *node, TextureStage *stage) const;
void r_find_all_textures(PandaNode *node, TextureStage *stage,
Textures &textures) const;
static void r_replace_texture(PandaNode *node, Texture *tex, Texture *new_tex);
typedef phash_set<TextureStage *, pointer_hash> TextureStages;
TextureStage *r_find_texture_stage(PandaNode *node, const RenderState *state,

View File

@ -101,7 +101,7 @@ int ScissorAttrib::
compare_to_impl(const RenderAttrib *other) const {
const ScissorAttrib *ta = (const ScissorAttrib *)other;
if (!_off && !ta->_off) {
if (_off && ta->_off) {
return 0;
}

View File

@ -250,6 +250,32 @@ unify_texture_stages(TextureStage *stage) const {
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
* of on_stages reduced to be no more than max_texture_stages. The number of

View File

@ -89,6 +89,7 @@ PUBLISHED:
CPT(RenderAttrib) add_off_stage(TextureStage *stage, int override = 0) const;
CPT(RenderAttrib) remove_off_stage(TextureStage *stage) const;
CPT(RenderAttrib) unify_texture_stages(TextureStage *stage) const;
CPT(RenderAttrib) replace_texture(Texture *tex, Texture *new_tex) const;
public:
CPT(TextureAttrib) filter_to_max(int max_texture_stages) const;

View File

@ -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
// capital.
const UnicodeLatinMap::Entry *map_entry =
UnicodeLatinMap::look_up(character);
UnicodeLatinMap::look_up((char32_t)character);
if (map_entry != nullptr) {
if (properties->get_small_caps() &&
map_entry->_toupper_character != character) {
map_entry->_toupper_character != (char32_t)character) {
character = map_entry->_toupper_character;
map_entry = UnicodeLatinMap::look_up(character);
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);
}
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.
character = map_entry->_toupper_character;
map_entry = UnicodeLatinMap::look_up(character);

View File

@ -149,3 +149,22 @@ def test_nodepath_python_tags():
rc1 = sys.getrefcount(path.python_tags)
rc2 = sys.getrefcount(path.python_tags)
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