diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 6ec23f96fb4..b77a4e0fe32 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -43,7 +43,8 @@ bool Skeleton::_set(const StringName& p_path, const Variant& p_value) { int which=path.get_slice("/",1).to_int(); String what=path.get_slice("/",2); - + + if (which==bones.size() && what=="name") { add_bone(p_value); @@ -94,7 +95,7 @@ bool Skeleton::_get(const StringName& p_name,Variant &r_ret) const { if (what=="name") r_ret=get_bone_name(which); - if (what=="parent") + else if (what=="parent") r_ret=get_bone_parent(which); else if (what=="rest") r_ret=get_bone_rest(which); @@ -250,7 +251,7 @@ void Skeleton::add_bone(const String& p_name) { ERR_FAIL_COND( bones[i].name=="p_name"); } - + Bone b; b.name=p_name; bones.push_back(b); diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index ac1826a0b8b..3bd7314778f 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -26,564 +26,564 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "packed_scene.h" -#include "globals.h" -#include "io/resource_loader.h" - -bool PackedScene::can_instance() const { - - return nodes.size()>0; -} - -Node *PackedScene::instance(bool p_gen_edit_state) const { - - int nc = nodes.size(); - ERR_FAIL_COND_V(nc==0,NULL); - - const StringName*snames=NULL; - int sname_count=names.size(); - if (sname_count) - snames=&names[0]; - - const Variant*props=NULL; - int prop_count=variants.size(); - if (prop_count) - props=&variants[0]; - - Vector properties; - - const NodeData *nd = &nodes[0]; - - Node **ret_nodes=(Node**)alloca( sizeof(Node*)*nc ); - - - for(int i=0;i=0) { - //instance existing - Ref sdata = props[ n.instance ]; - ERR_FAIL_COND_V( !sdata.is_valid(), NULL); - node = sdata->instance(); - ERR_FAIL_COND_V(!node,NULL); - if (p_gen_edit_state) - node->generate_instance_state(); - - } else { - //create anew - Object * obj = ObjectTypeDB::instance(snames[ n.type ]); - ERR_FAIL_COND_V(!obj,NULL); - node = obj->cast_to(); - ERR_FAIL_COND_V(!node,NULL); - - } - - - //properties - int nprop_count=n.properties.size(); - if (nprop_count) { - - const NodeData::Property* nprops=&n.properties[0]; - - for(int j=0;jset(snames[ nprops[j].name ],props[ nprops[j].value ],&valid); - } - } - - //name - - //groups - for(int j=0;jadd_to_group( snames[ n.groups[j] ], true ); - } - - - ret_nodes[i]=node; - - if (i>0) { - ERR_FAIL_INDEX_V(n.parent,i,NULL); - ERR_FAIL_COND_V(!ret_nodes[n.parent],NULL); - ret_nodes[n.parent]->_add_child_nocheck(node,snames[n.name]); - } else { - node->_set_name_nocheck( snames[ n.name ] ); - } - - - if (n.owner>=0) { - - ERR_FAIL_INDEX_V(n.owner,i,NULL); - node->_set_owner_nocheck(ret_nodes[n.owner]); - } - - } - - - //do connections - - int cc = connections.size(); - const ConnectionData *cdata = connections.ptr(); - - for(int i=0;i binds; - if (c.binds.size()) { - binds.resize(c.binds.size()); - for(int j=0;jconnect( snames[ c.signal], ret_nodes[ c.to ], snames[ c.method], binds,CONNECT_PERSIST|c.flags ); - } - - Node *s = ret_nodes[0]; - - if (get_path()!="" && get_path().find("::")==-1) - s->set_filename(get_path()); - return ret_nodes[0]; - -} - - -static int _nm_get_string(const String& p_string, Map &name_map) { - - if (name_map.has(p_string)) - return name_map[p_string]; - - int idx = name_map.size(); - name_map[p_string]=idx; - return idx; -} - -static int _vm_get_variant(const Variant& p_variant, HashMap &variant_map) { - - if (variant_map.has(p_variant)) - return variant_map[p_variant]; - - int idx = variant_map.size(); - variant_map[p_variant]=idx; - return idx; -} - -Error PackedScene::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map &name_map,HashMap &variant_map,Map &node_map) { - - if (p_node!=p_owner && (p_node->get_owner()!=p_owner)) - return OK; //nothing to do with this node, may either belong to another scene or be onowned - - NodeData nd; - - nd.name=_nm_get_string(p_node->get_name(),name_map); - nd.type=_nm_get_string(p_node->get_type(),name_map); - nd.parent=p_parent_idx; - - - Dictionary instance_state; - Set instance_groups; - - - if (p_node!=p_owner && p_node->get_filename()!="") { - //instanced - Ref instance = ResourceLoader::load(p_node->get_filename()); - if (!instance.is_valid()) { - return ERR_CANT_OPEN; - } - - nd.instance=_vm_get_variant(instance,variant_map); - instance_state = p_node->get_instance_state(); - Vector ig = p_node->get_instance_groups(); - for(int i=0;i plist; - p_node->get_property_list(&plist); - for (List::Element *E=plist.front();E;E=E->next()) { - - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) - continue; - - String name = E->get().name; - Variant value = p_node->get( E->get().name ); - - if (E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero()) - continue; - - - if (nd.instance>=0) { - //only save changed properties in instance - if (!instance_state.has(name)) - continue; - if (instance_state[name]==value) - continue; - - } - - NodeData::Property prop; - prop.name=_nm_get_string( name,name_map); - prop.value=_vm_get_variant( value, variant_map); - nd.properties.push_back(prop); - - } - - - List groups; - p_node->get_groups(&groups); - for(List::Element *E=groups.front();E;E=E->next()) { - Node::GroupInfo &gi=E->get(); - - if (!gi.persistent) - continue; - if (nd.instance>=0 && instance_groups.has(gi.name)) - continue; //group was instanced, don't add here - - nd.groups.push_back(_nm_get_string(gi.name,name_map)); - } - - if (node_map.has(p_node->get_owner())) - nd.owner=node_map[p_node->get_owner()]; - else - nd.owner=-1; - - int idx = nodes.size(); - node_map[p_node]=idx; - nodes.push_back(nd); - - - - for(int i=0;iget_child_count();i++) { - - Node *c=p_node->get_child(i); - Error err = _parse_node(p_owner,c,idx,name_map,variant_map,node_map); - if (err) - return err; - } - - return OK; - -} - -Error PackedScene::_parse_connections(Node *p_owner,Node *p_node, Map &name_map,HashMap &variant_map,Map &node_map) { - - if (p_node!=p_owner && (p_node->get_owner()!=p_owner)) - return OK; //nothing to do with this node, may either belong to another scene or be onowned - - List signals; - p_node->get_signal_list(&signals); - - ERR_FAIL_COND_V( !node_map.has(p_node), ERR_BUG); - NodeData &nd = nodes[node_map[p_node]]; - Set instance_connections; - - if (nd.instance>=0) { - - Vector iconns = p_node->get_instance_connections(); - for(int i=0;i::Element *E=signals.front();E;E=E->next()) { - - List conns; - p_node->get_signal_connection_list(E->get().name,&conns); - for(List::Element *F=conns.front();F;F=F->next()) { - - const Node::Connection &c = F->get(); - if (!(c.flags&CONNECT_PERSIST)) - continue; - - if (nd.instance>=0 && instance_connections.has(c)) - continue; //came from instance, don't save! - - Node *n=c.target->cast_to(); - if (!n) - continue; - - if (!node_map.has(n)) { - WARN_PRINT("Connection to node outside scene??") - continue; - } - - ConnectionData cd; - cd.from=node_map[p_node]; - cd.to=node_map[n]; - cd.method=_nm_get_string(c.method,name_map); - cd.signal=_nm_get_string(c.signal,name_map); - cd.flags=c.flags; - for(int i=0;iget_child_count();i++) { - - Node *c=p_node->get_child(i); - Error err = _parse_connections(p_owner,c,name_map,variant_map,node_map); - if (err) - return err; - } - - return OK; -} - - -Error PackedScene::pack(Node *p_scene) { - ERR_FAIL_NULL_V( p_scene, ERR_INVALID_PARAMETER ); - - - clear(); - - Node *scene = p_scene; - - Map name_map; - HashMap variant_map; - Map node_map; - - Error err = _parse_node(scene,scene,-1,name_map,variant_map,node_map); - if (err) { - clear(); - ERR_FAIL_V(err); - } - - err = _parse_connections(scene,scene,name_map,variant_map,node_map); - if (err) { - clear(); - ERR_FAIL_V(err); - } - - names.resize(name_map.size()); - - for(Map::Element *E=name_map.front();E;E=E->next()) { - - names[E->get()]=E->key(); - } - - variants.resize(variant_map.size()); - const Variant *K=NULL; - while((K=variant_map.next(K))) { - - int idx = variant_map[*K]; - variants[idx]=*K; - } - - return OK; -} - -void PackedScene::clear() { - - names.clear(); - variants.clear(); - nodes.clear(); - connections.clear(); - -} - -void PackedScene::_set_bundled_scene(const Dictionary& d) { - - - ERR_FAIL_COND( !d.has("names")); - ERR_FAIL_COND( !d.has("variants")); - ERR_FAIL_COND( !d.has("node_count")); - ERR_FAIL_COND( !d.has("nodes")); - ERR_FAIL_COND( !d.has("conn_count")); - ERR_FAIL_COND( !d.has("conns")); -// ERR_FAIL_COND( !d.has("path")); - - DVector snames = d["names"]; - if (snames.size()) { - - int namecount = snames.size(); - names.resize(namecount); - DVector::Read r =snames.read(); - for(int i=0;i snodes = d["nodes"]; - DVector::Read r = snodes.read(); - int idx=0; - for(int i=0;i sconns = d["conns"]; - DVector::Read r = sconns.read(); - int idx=0; - for(int i=0;i rnames; - rnames.resize(names.size()); - - if (names.size()) { - - DVector::Write r=rnames.write(); - - for(int i=0;i rnodes; - d["node_count"]=nodes.size(); - - for(int i=0;i rconns; - d["conn_count"]=connections.size(); - - for(int i=0;i0; +} + +Node *PackedScene::instance(bool p_gen_edit_state) const { + + int nc = nodes.size(); + ERR_FAIL_COND_V(nc==0,NULL); + + const StringName*snames=NULL; + int sname_count=names.size(); + if (sname_count) + snames=&names[0]; + + const Variant*props=NULL; + int prop_count=variants.size(); + if (prop_count) + props=&variants[0]; + + Vector properties; + + const NodeData *nd = &nodes[0]; + + Node **ret_nodes=(Node**)alloca( sizeof(Node*)*nc ); + + + for(int i=0;i=0) { + //instance existing + Ref sdata = props[ n.instance ]; + ERR_FAIL_COND_V( !sdata.is_valid(), NULL); + node = sdata->instance(); + ERR_FAIL_COND_V(!node,NULL); + if (p_gen_edit_state) + node->generate_instance_state(); + + } else { + //create anew + Object * obj = ObjectTypeDB::instance(snames[ n.type ]); + ERR_FAIL_COND_V(!obj,NULL); + node = obj->cast_to(); + ERR_FAIL_COND_V(!node,NULL); + + } + + + //properties + int nprop_count=n.properties.size(); + if (nprop_count) { + + const NodeData::Property* nprops=&n.properties[0]; + + for(int j=0;jset(snames[ nprops[j].name ],props[ nprops[j].value ],&valid); + } + } + + //name + + //groups + for(int j=0;jadd_to_group( snames[ n.groups[j] ], true ); + } + + + ret_nodes[i]=node; + + if (i>0) { + ERR_FAIL_INDEX_V(n.parent,i,NULL); + ERR_FAIL_COND_V(!ret_nodes[n.parent],NULL); + ret_nodes[n.parent]->_add_child_nocheck(node,snames[n.name]); + } else { + node->_set_name_nocheck( snames[ n.name ] ); + } + + + if (n.owner>=0) { + + ERR_FAIL_INDEX_V(n.owner,i,NULL); + node->_set_owner_nocheck(ret_nodes[n.owner]); + } + + } + + + //do connections + + int cc = connections.size(); + const ConnectionData *cdata = connections.ptr(); + + for(int i=0;i binds; + if (c.binds.size()) { + binds.resize(c.binds.size()); + for(int j=0;jconnect( snames[ c.signal], ret_nodes[ c.to ], snames[ c.method], binds,CONNECT_PERSIST|c.flags ); + } + + Node *s = ret_nodes[0]; + + if (get_path()!="" && get_path().find("::")==-1) + s->set_filename(get_path()); + return ret_nodes[0]; + +} + + +static int _nm_get_string(const String& p_string, Map &name_map) { + + if (name_map.has(p_string)) + return name_map[p_string]; + + int idx = name_map.size(); + name_map[p_string]=idx; + return idx; +} + +static int _vm_get_variant(const Variant& p_variant, HashMap &variant_map) { + + if (variant_map.has(p_variant)) + return variant_map[p_variant]; + + int idx = variant_map.size(); + variant_map[p_variant]=idx; + return idx; +} + +Error PackedScene::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map &name_map,HashMap &variant_map,Map &node_map) { + + if (p_node!=p_owner && (p_node->get_owner()!=p_owner)) + return OK; //nothing to do with this node, may either belong to another scene or be onowned + + NodeData nd; + + nd.name=_nm_get_string(p_node->get_name(),name_map); + nd.type=_nm_get_string(p_node->get_type(),name_map); + nd.parent=p_parent_idx; + + + Dictionary instance_state; + Set instance_groups; + + + if (p_node!=p_owner && p_node->get_filename()!="") { + //instanced + Ref instance = ResourceLoader::load(p_node->get_filename()); + if (!instance.is_valid()) { + return ERR_CANT_OPEN; + } + + nd.instance=_vm_get_variant(instance,variant_map); + instance_state = p_node->get_instance_state(); + Vector ig = p_node->get_instance_groups(); + for(int i=0;i plist; + p_node->get_property_list(&plist); + for (List::Element *E=plist.front();E;E=E->next()) { + + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + continue; + + String name = E->get().name; + Variant value = p_node->get( E->get().name ); + + if (E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero()) + continue; + + + if (nd.instance>=0) { + //only save changed properties in instance + if (!instance_state.has(name)) + continue; + if (instance_state[name]==value) + continue; + + } + + NodeData::Property prop; + prop.name=_nm_get_string( name,name_map); + prop.value=_vm_get_variant( value, variant_map); + nd.properties.push_back(prop); + + } + + + List groups; + p_node->get_groups(&groups); + for(List::Element *E=groups.front();E;E=E->next()) { + Node::GroupInfo &gi=E->get(); + + if (!gi.persistent) + continue; + if (nd.instance>=0 && instance_groups.has(gi.name)) + continue; //group was instanced, don't add here + + nd.groups.push_back(_nm_get_string(gi.name,name_map)); + } + + if (node_map.has(p_node->get_owner())) + nd.owner=node_map[p_node->get_owner()]; + else + nd.owner=-1; + + int idx = nodes.size(); + node_map[p_node]=idx; + nodes.push_back(nd); + + + + for(int i=0;iget_child_count();i++) { + + Node *c=p_node->get_child(i); + Error err = _parse_node(p_owner,c,idx,name_map,variant_map,node_map); + if (err) + return err; + } + + return OK; + +} + +Error PackedScene::_parse_connections(Node *p_owner,Node *p_node, Map &name_map,HashMap &variant_map,Map &node_map) { + + if (p_node!=p_owner && (p_node->get_owner()!=p_owner)) + return OK; //nothing to do with this node, may either belong to another scene or be onowned + + List signals; + p_node->get_signal_list(&signals); + + ERR_FAIL_COND_V( !node_map.has(p_node), ERR_BUG); + NodeData &nd = nodes[node_map[p_node]]; + Set instance_connections; + + if (nd.instance>=0) { + + Vector iconns = p_node->get_instance_connections(); + for(int i=0;i::Element *E=signals.front();E;E=E->next()) { + + List conns; + p_node->get_signal_connection_list(E->get().name,&conns); + for(List::Element *F=conns.front();F;F=F->next()) { + + const Node::Connection &c = F->get(); + if (!(c.flags&CONNECT_PERSIST)) + continue; + + if (nd.instance>=0 && instance_connections.has(c)) + continue; //came from instance, don't save! + + Node *n=c.target->cast_to(); + if (!n) + continue; + + if (!node_map.has(n)) { + WARN_PRINT("Connection to node outside scene??") + continue; + } + + ConnectionData cd; + cd.from=node_map[p_node]; + cd.to=node_map[n]; + cd.method=_nm_get_string(c.method,name_map); + cd.signal=_nm_get_string(c.signal,name_map); + cd.flags=c.flags; + for(int i=0;iget_child_count();i++) { + + Node *c=p_node->get_child(i); + Error err = _parse_connections(p_owner,c,name_map,variant_map,node_map); + if (err) + return err; + } + + return OK; +} + + +Error PackedScene::pack(Node *p_scene) { + ERR_FAIL_NULL_V( p_scene, ERR_INVALID_PARAMETER ); + + + clear(); + + Node *scene = p_scene; + + Map name_map; + HashMap variant_map; + Map node_map; + + Error err = _parse_node(scene,scene,-1,name_map,variant_map,node_map); + if (err) { + clear(); + ERR_FAIL_V(err); + } + + err = _parse_connections(scene,scene,name_map,variant_map,node_map); + if (err) { + clear(); + ERR_FAIL_V(err); + } + + names.resize(name_map.size()); + + for(Map::Element *E=name_map.front();E;E=E->next()) { + + names[E->get()]=E->key(); + } + + variants.resize(variant_map.size()); + const Variant *K=NULL; + while((K=variant_map.next(K))) { + + int idx = variant_map[*K]; + variants[idx]=*K; + } + + return OK; +} + +void PackedScene::clear() { + + names.clear(); + variants.clear(); + nodes.clear(); + connections.clear(); + +} + +void PackedScene::_set_bundled_scene(const Dictionary& d) { + + + ERR_FAIL_COND( !d.has("names")); + ERR_FAIL_COND( !d.has("variants")); + ERR_FAIL_COND( !d.has("node_count")); + ERR_FAIL_COND( !d.has("nodes")); + ERR_FAIL_COND( !d.has("conn_count")); + ERR_FAIL_COND( !d.has("conns")); +// ERR_FAIL_COND( !d.has("path")); + + DVector snames = d["names"]; + if (snames.size()) { + + int namecount = snames.size(); + names.resize(namecount); + DVector::Read r =snames.read(); + for(int i=0;i snodes = d["nodes"]; + DVector::Read r = snodes.read(); + int idx=0; + for(int i=0;i sconns = d["conns"]; + DVector::Read r = sconns.read(); + int idx=0; + for(int i=0;i rnames; + rnames.resize(names.size()); + + if (names.size()) { + + DVector::Write r=rnames.write(); + + for(int i=0;i rnodes; + d["node_count"]=nodes.size(); + + for(int i=0;i rconns; + d["conn_count"]=connections.size(); + + for(int i=0;i(p_node); + p_skeleton->add_bone(p_node->name); if (p_parent>=0) p_skeleton->set_bone_parent(r_bone,p_parent);