Exemple #1
0
static enum RPC_Error _parse_value(uchar **str, struct RPC_Node *node)
{
  enum RPC_Error status;

  if( (node->children = calloc(1, sizeof *node)) == NULL )
    return RPC_FAIL;

  if( (status=_parse_node(str,&node->children[0])) != RPC_OK )
  {
    free(node->children);
    return status;
  }

  node->numChildren = 1;
  node->type = RPC_VALUE;

  return RPC_OK;
}
Exemple #2
0
struct RPC_Node *parse_rpc_string(uchar *str)
{
  enum RPC_Error status;
  struct RPC_Node *node = calloc(1, sizeof *node);

  if( !node )
    return NULL;

  status = _parse_node(&str, node);

  if( status != RPC_OK )
  {
    free(node);
    return NULL;
  }
  else
    return node;
}
Exemple #3
0
Error SceneState::pack(Node *p_scene) {
	ERR_FAIL_NULL_V( p_scene, ERR_INVALID_PARAMETER );


	clear();

	Node *scene = p_scene;

	Map<StringName,int> name_map;
	HashMap<Variant,int,VariantHasher> variant_map;
	Map<Node*,int> node_map;
	Map<Node*,int> nodepath_map;

	//if using scene inheritance, pack the scene it inherits from
	if (scene->get_scene_inherited_state().is_valid()) {
		String path = scene->get_scene_inherited_state()->get_path();
		Ref<PackedScene> instance = ResourceLoader::load(path);
		if (instance.is_valid()) {

			base_scene_idx=_vm_get_variant(instance,variant_map);
		}
	}
	//instanced, only direct sub-scnes are supported of course


	Error err = _parse_node(scene,scene,-1,name_map,variant_map,node_map,nodepath_map);
	if (err) {
		clear();
		ERR_FAIL_V(err);
	}

	err = _parse_connections(scene,scene,name_map,variant_map,node_map,nodepath_map);
	if (err) {
		clear();
		ERR_FAIL_V(err);
	}

	names.resize(name_map.size());

	for(Map<StringName,int>::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;
	}

	node_paths.resize(nodepath_map.size());
	for(Map<Node*,int>::Element *E=nodepath_map.front();E;E=E->next()) {

		node_paths[E->get()]=scene->get_path_to(E->key());
	}


	return OK;
}
Exemple #4
0
Error SceneState::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map,Map<Node*,int> &nodepath_map) {


	// this function handles all the work related to properly packing scenes, be it
	// instanced or inherited.
	// given the complexity of this process, an attempt will be made to properly
	// document it. if you fail to understand something, please ask!

	//discard nodes that do not belong to be processed
	if (p_node!=p_owner && p_node->get_owner()!=p_owner && !p_owner->is_editable_instance(p_node->get_owner()))
		return OK;

	// save the child instanced scenes that are chosen as editable, so they can be restored
	// upon load back
	if (p_node!=p_owner && p_node->get_filename()!=String() && p_owner->is_editable_instance(p_node))
		editable_instances.push_back(p_owner->get_path_to(p_node));

	NodeData nd;

	nd.name=_nm_get_string(p_node->get_name(),name_map);
	nd.instance=-1; //not instanced by default

	// if this node is part of an instanced scene or sub-instanced scene
	// we need to get the corresponding instance states.
	// with the instance states, we can query for identical properties/groups
	// and only save what has changed

	List<PackState> pack_state_stack;

	bool instanced_by_owner=true;

	{
		Node *n=p_node;

		while(n) {

			if (n==p_owner) {

				Ref<SceneState> state = n->get_scene_inherited_state();
				if (state.is_valid()) {
					int node = state->find_node_by_path(n->get_path_to(p_node));
					if (node>=0) {
						//this one has state for this node, save
						PackState ps;
						ps.node=node;
						ps.state=state;
						pack_state_stack.push_front(ps);
						instanced_by_owner=false;
					}
				}

				if (p_node->get_filename()!=String() && p_node->get_owner()==p_owner && instanced_by_owner) {

					if (p_node->get_scene_instance_load_placeholder()) {
						//it's a placeholder, use the placeholder path
						nd.instance=_vm_get_variant(p_node->get_filename(),variant_map);
						nd.instance|=FLAG_INSTANCE_IS_PLACEHOLDER;
					} else {
						//must instance ourselves
						Ref<PackedScene> instance = ResourceLoader::load(p_node->get_filename());
						if (!instance.is_valid()) {
							return ERR_CANT_OPEN;
						}

						nd.instance=_vm_get_variant(instance,variant_map);
					}
				}
				n=NULL;
			} else {
				if (n->get_filename()!=String()) {
					//is an instance
					Ref<SceneState> state = n->get_scene_instance_state();
					if (state.is_valid()) {
						int node = state->find_node_by_path(n->get_path_to(p_node));
						if (node>=0) {
							//this one has state for this node, save
							PackState ps;
							ps.node=node;
							ps.state=state;
							pack_state_stack.push_back(ps);
						}
					}

				}
				n=n->get_owner();
			}
		}
	}

#if 0

	Ref<SceneState> base_scene = p_node->get_scene_inherited_state(); //for inheritance
	Ref<SceneState> instance_state;
	int instance_state_node=-1;

	if (base_scene.is_valid() && (p_node==p_owner || p_node->get_owner()==p_owner)) {
		//scene inheritance in use, see if this node is actually inherited
		NodePath path = p_owner->get_path_to(p_node);
		instance_state_node = base_scene->find_node_by_path(path);
		if (instance_state_node>=0) {
			instance_state=base_scene;
		}
	}

	// check that this is a directly instanced scene from the scene being packed, if so
	// this information must be saved. Of course, if using scene instancing and this node
	// does belong to base scene, ignore.

	if (instance_state.is_null() && p_node!=p_owner && p_node->get_owner()==p_owner && p_node->get_filename()!="") {

		//instanced, only direct sub-scnes are supported of course
		Ref<PackedScene> instance = ResourceLoader::load(p_node->get_filename());
		if (!instance.is_valid()) {
			return ERR_CANT_OPEN;
		}

		nd.instance=_vm_get_variant(instance,variant_map);

	} else {

		nd.instance=-1;
	}

	// finally, if this does not belong to scene inheritance, check
	// if it belongs to scene instancing

	if (instance_state.is_null() && p_node!=p_owner) {
		//if not affected by scene inheritance, this may be
		if (p_node->get_owner()==p_owner && p_node->get_filename()!=String()) {
			instance_state=p_node->get_scene_instance_state();
			if (instance_state.is_valid()) {
				instance_state_node=instance_state->find_node_by_path(p_node->get_path_to(p_node));
			}

		} else if (p_node->get_owner()!=p_owner && p_owner->is_editable_instance(p_node->get_owner())) {
			instance_state=p_node->get_owner()->get_scene_instance_state();
			if (instance_state.is_valid()) {
				instance_state_node=instance_state->find_node_by_path(p_node->get_owner()->get_path_to(p_node));
			}
		}
	}
#endif
	int subscene_prop_search_from=0;

	// all setup, we then proceed to check all properties for the node
	// and save the ones that are worth saving

	List<PropertyInfo> plist;
	p_node->get_property_list(&plist);

	bool saved_script=false;

	for (List<PropertyInfo>::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 );


		bool isdefault = ((E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO) && value.is_zero()) || ((E->get().usage & PROPERTY_USAGE_STORE_IF_NONONE) && value.is_one());

//		if (nd.instance<0 && ((E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO) && value.is_zero()) || ((E->get().usage & PROPERTY_USAGE_STORE_IF_NONONE) && value.is_one())) {
//			continue;
//		}



		//print_line("PASSED!");
		//print_line("at: "+String(p_node->get_name())+"::"+name+": -  nz: "+itos(E->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO)+" no: "+itos(E->get().usage&PROPERTY_USAGE_STORE_IF_NONONE));
		//print_line("value: "+String(value)+" is zero: "+itos(value.is_zero())+" is one" +itos(value.is_one()));

		if (pack_state_stack.size()) {
			// we are on part of an instanced subscene
			// or part of instanced scene.
			// only save what has been changed
			// only save changed properties in instance

			if (E->get().usage & PROPERTY_USAGE_NO_INSTANCE_STATE || E->get().name=="__meta__") {
				//property has requested that no instance state is saved, sorry
				//also, meta won't be overriden or saved
				continue;
			}

			bool exists=false;
			Variant original;

			for (List<PackState>::Element *F=pack_state_stack.back();F;F=F->prev()) {
				//check all levels of pack to see if the property exists somewhere
				const PackState &ps=F->get();

				original = ps.state->get_property_value(ps.node,E->get().name,exists);
				if (exists) {
					break;
				}
			}
#if 0
// this workaround ended up causing problems:
https://github.com/godotengine/godot/issues/3127
			if (saved_script && exists && p_node->get_script_instance()) {
				//if this is an overriden value by another script, save it anyway
				//as the script change will erase it
				//https://github.com/godotengine/godot/issues/2958

				bool valid=false;
				p_node->get_script_instance()->get_property_type(name,&valid);
				if (valid) {
					exists=false;
					isdefault=false;
				}
			}

#endif
			if (exists && bool(Variant::evaluate(Variant::OP_EQUAL,value,original))) {
				//exists and did not change
				continue;
			}

			if (!exists && isdefault) {
				//does not exist in original node, but it's the default value
				//so safe to skip too.
				continue;
			}


		} else  {

			if (isdefault) {
				//it's the default value, no point in saving it
				continue;
			}
		}

		if (name=="script/script")
			saved_script=true;

		NodeData::Property prop;
		prop.name=_nm_get_string( name,name_map);
		prop.value=_vm_get_variant( value, variant_map);
		nd.properties.push_back(prop);

	}


	// save the groups this node is into
	// discard groups that come from the original scene

	List<Node::GroupInfo> groups;
	p_node->get_groups(&groups);
	for(List<Node::GroupInfo>::Element *E=groups.front();E;E=E->next()) {
		Node::GroupInfo &gi=E->get();

		if (!gi.persistent)
			continue;
//		if (instance_state_node>=0 && instance_state->is_node_in_group(instance_state_node,gi.name))
//			continue; //group was instanced, don't add here

		bool skip=false;
		for (List<PackState>::Element *F=pack_state_stack.front();F;F=F->next()) {
			//check all levels of pack to see if the group was added somewhere
			const PackState &ps=F->get();
			if (ps.state->is_node_in_group(ps.node,gi.name)) {
				skip=true;
				break;
			}
		}

		if (skip)
			continue;

		nd.groups.push_back(_nm_get_string(gi.name,name_map));
	}


	// save the right owner
	// for the saved scene root this is -1
	// for nodes of the saved scene this is 0
	// for nodes of instanced scenes this is >0

	if (p_node==p_owner) {
		//saved scene root
		nd.owner=-1;
	} else if (p_node->get_owner()==p_owner) {
		//part of saved scene
		nd.owner=0;
	} else {

		nd.owner=-1;
#if 0
		// this is pointless, if this was instanced by something else,
		// the owner will already be set.

		if (node_map.has(p_node->get_owner())) {
			//maybe an existing saved node
			nd.owner=node_map[p_node->get_owner()];
		} else {
			//not saved, use nodepath map
			int sidx;
			if (nodepath_map.has(p_node->get_owner())) {
				sidx=nodepath_map[p_node->get_owner()];
			} else {
				sidx=nodepath_map.size();
				nodepath_map[p_node->get_owner()]=sidx;
			}

			nd.owner=FLAG_ID_IS_PATH|sidx;

		}
#endif


	}

	// Save the right type. If this node was created by an instance
	// then flag that the node should not be created but reused	
	if (pack_state_stack.empty()) {
		//this node is not part of an instancing process, so save the type
		nd.type=_nm_get_string(p_node->get_type(),name_map);
	} else {
		// this node is part of an instanced process, so do not save the type.
		// instead, save that it was instanced
		nd.type=TYPE_INSTANCED;
	}


	// determine whether to save this node or not
	// if this node is part of an instanced sub-scene, we can skip storing it if basically
	// no properties changed and no groups were added to it.
	// below condition is true for all nodes of the scene being saved, and ones in subscenes
	// that hold changes

	bool save_node = nd.properties.size() || nd.groups.size(); // some local properties or groups exist
	save_node = save_node || p_node==p_owner; // owner is always saved
	save_node = save_node || (p_node->get_owner()==p_owner && instanced_by_owner); //part of scene and not instanced


	int idx = nodes.size();
	int parent_node=NO_PARENT_SAVED;

	if (save_node) {

		//don't save the node if nothing and subscene

		node_map[p_node]=idx;

		//ok validate parent node
		if (p_parent_idx==NO_PARENT_SAVED) {

			int sidx;
			if (nodepath_map.has(p_node->get_parent())) {
				sidx=nodepath_map[p_node->get_parent()];
			} else {
				sidx=nodepath_map.size();
				nodepath_map[p_node->get_parent()]=sidx;
			}

			nd.parent=FLAG_ID_IS_PATH|sidx;
		} else {
			nd.parent=p_parent_idx;
		}

		parent_node=idx;
		nodes.push_back(nd);

	}


	for(int i=0;i<p_node->get_child_count();i++) {

		Node *c=p_node->get_child(i);
		Error err = _parse_node(p_owner,c,parent_node,name_map,variant_map,node_map,nodepath_map);
		if (err)
			return err;
	}

	return OK;

}