Análisis del código fuente de Godot 4: obtenga el script

Obtener lista de propiedades

Levanté pasto y golpeé conejos hoy, y obtuve el contenido del guión

Dado que el valor del atributo ya se puede obtener, vaya un paso más allá y obtenga la lista de nombres de atributos.

if (SameText(drGet.propertyName, "propertyNames", DRGRAPH_FLAG_CASESENSITIVE)) {
	List<PropertyInfo> *p_list = new List<PropertyInfo>;
	bool p_reversed = true;
	destObject->get_property_list(p_list, p_reversed);
	cofs << "OK";
	for (List<PropertyInfo>::Iterator it = p_list->begin(); it != p_list->end(); ++it) {
		Variant value = destObject->get(it->name);
		cofs << str_format(U"%s[%s] = %s", it->name.utf8().get_data(),
			VarType2String(it->type).c_str(), value.operator String().utf8().get_data());
	}
	delete p_list;
	cofs << GetObjectHint(destObject);	
}

En consecuencia, se puede obtener una lista de nombres de funciones y una lista de subobjetos

if (SameText(drGet.propertyName, "methodNames", DRGRAPH_FLAG_CASESENSITIVE)) {
	List<MethodInfo> *p_list = new List<MethodInfo>;
	destObject->get_method_list(p_list);
	cofs << "OK";
	for (List<MethodInfo>::Iterator it = p_list->begin(); it != p_list->end(); ++it) {
		String content = it->name + "(";
		for (List<PropertyInfo>::Iterator iter = it->arguments.begin(); iter != it->arguments.end(); ++iter) {
			if (iter != it->arguments.begin())
				content += ", ";
			content += str_format("%s %s", VarType2String(iter->type).c_str(), iter->name.utf8().get_data()).c_str();
		}
		content += ")";
		cofs << content;
	}
	delete p_list;
	cofs << GetObjectHint(destObject);	
}
if (SameText(drGet.propertyName, "childNames", DRGRAPH_FLAG_CASESENSITIVE)) {
	if (Node *node = dynamic_cast<Node *>(destObject)) {
		int count = node->get_child_count();
		for (int i = 0; i < count; ++i) {
			Node *subNode = node->get_child(i);
			cofs << str_format(U"%s[%s]", subNode->get_name().operator String().utf8().get_data(),
					subNode->get_class_name().operator String().utf8().get_data());
		}
		cofs << GetObjectHint(destObject);
	}
}

Entre ellos, se espera que la obtención de información del objeto (GetObjectHint) muestre alguna información correspondiente del objeto.

#define CAST(T, ptr) dynamic_cast<T>(static_cast<T>(ptr))
std::string GetObjectHint(void* ptr) {
	String result = U"未处理对象";
	if (Object *object = CAST(Object *, ptr)) {
		result = str_format(U" ---==== [%s]类型对象 0X%08x ====---", object->get_class_name().operator String().utf8().get_data(), int(ptr));
		if (Node *node = CAST(Node *, ptr)) {
			String path = node->get_name();
			Node *parent = node->get_parent();
			while (parent) {
				path = parent->get_name().operator String() + U"." + path;
				parent = parent->get_parent();
			}
			result += U":\n\t\t\t\t\t\t路径信息:";
			result += path + U"\n\t\t\t\t\t\t子对象信息:";
			int count = node->get_child_count();
			for (int i = 0; i < count; ++i) {
				Node *subNode = node->get_child(i);
				result += str_format(U" %s[%s]", String2std(subNode->get_name().operator String()).c_str(),
						String2std(subNode->get_class_name().operator String()).c_str());
			}
		}
	} else if (Engine *engine = CAST(Engine *, ptr)) {
		result = str_format(U"[Engine]类型对象 0X%08x", int(ptr));
	}
	return String2std(result);
}

Pruébelo y obtenga todos los nombres de propiedad del nodo raíz (Libro): Book.propertyNames

261. 15:58:53:368 > 【主线程】 > [Pipe.发送] > 发送数据中内容[DrGraph.78: Request - wait 1000 ms]: 
	[int]类型 > 值 = 2
	[UnicodeString]类型 > 值 = Book
	[UnicodeString]类型 > 值 = propertyNames
262. 15:58:53:614 > 【主线程】 > [Pipe.Read] > 发送数据[DrGraph.78: Request - wait 1000 ms]成功返回 2396 字节... > PIPE响应中内容[godot -> DrGraph.78: Response - no return]: 
	[int]类型 > 值 = 3
	[UnicodeString]类型 > 值 = OK
	[UnicodeString]类型 > 值 = book.gd[NIL] = <null>
	[UnicodeString]类型 > 值 = singlePage[BOOL] = false
	[UnicodeString]类型 > 值 = middleBarWidth[INT] = 0
	[UnicodeString]类型 > 值 = shader_rect[OBJECT] = ShaderRect:<ColorRect#26944209309>
	[UnicodeString]类型 > 值 = currentPageMode[BOOL] = false
	[UnicodeString]类型 > 值 = currentAreaType[INT] = 5
	[UnicodeString]类型 > 值 = triggleAreaMoment[INT] = 745493
	[UnicodeString]类型 > 值 = currentPageIndex[INT] = 30
	[UnicodeString]类型 > 值 = pageCount[INT] = 100
	[UnicodeString]类型 > 值 = pageImgPath[STRING] = res://Pages/
	[UnicodeString]类型 > 值 = leftMouseDownMoment[INT] = 0
	[UnicodeString]类型 > 值 = underAutoTurnPage[BOOL] = false
	[UnicodeString]类型 > 值 = leftMouseDownPos[VECTOR2] = (0, 0)
	[UnicodeString]类型 > 值 = dllStream[OBJECT] = <DllStream#67024979098>
	[UnicodeString]类型 > 值 = AutoTurnObject[OBJECT] = <RefCounted#-9223372009692462686>
	[UnicodeString]类型 > 值 = Node2D[NIL] = <null>
	[UnicodeString]类型 > 值 = Transform[NIL] = <null>
	[UnicodeString]类型 > 值 = position[VECTOR2] = (0, 0)
	[UnicodeString]类型 > 值 = rotation[FLOAT] = 0
	[UnicodeString]类型 > 值 = rotation_degrees[FLOAT] = 0
	[UnicodeString]类型 > 值 = scale[VECTOR2] = (1, 1)
	[UnicodeString]类型 > 值 = skew[FLOAT] = 0
	[UnicodeString]类型 > 值 = transform[TRANSFORM2D] = [X: (1, 0), Y: (0, 1), O: (0, 0)]
	[UnicodeString]类型 > 值 = global_position[VECTOR2] = (0, 0)
	[UnicodeString]类型 > 值 = global_rotation[FLOAT] = 0
	[UnicodeString]类型 > 值 = global_rotation_degrees[FLOAT] = 0
	[UnicodeString]类型 > 值 = global_scale[VECTOR2] = (1, 1)
	[UnicodeString]类型 > 值 = global_skew[FLOAT] = 0
	[UnicodeString]类型 > 值 = global_transform[TRANSFORM2D] = [X: (1, 0), Y: (0, 1), O: (0, 0)]
	[UnicodeString]类型 > 值 = CanvasItem[NIL] = <null>
	[UnicodeString]类型 > 值 = Visibility[NIL] = <null>
	[UnicodeString]类型 > 值 = visible[BOOL] = true
	[UnicodeString]类型 > 值 = modulate[COLOR] = (1, 1, 1, 1)
	[UnicodeString]类型 > 值 = self_modulate[COLOR] = (1, 1, 1, 1)
	[UnicodeString]类型 > 值 = show_behind_parent[BOOL] = false
	[UnicodeString]类型 > 值 = top_level[BOOL] = false
	[UnicodeString]类型 > 值 = clip_children[INT] = 0
	[UnicodeString]类型 > 值 = light_mask[INT] = 1
	[UnicodeString]类型 > 值 = visibility_layer[INT] = 1
	[UnicodeString]类型 > 值 = Ordering[NIL] = <null>
	[UnicodeString]类型 > 值 = z_index[INT] = 0
	[UnicodeString]类型 > 值 = z_as_relative[BOOL] = true
	[UnicodeString]类型 > 值 = y_sort_enabled[BOOL] = false
	[UnicodeString]类型 > 值 = Texture[NIL] = <null>
	[UnicodeString]类型 > 值 = texture_filter[INT] = 0
	[UnicodeString]类型 > 值 = texture_repeat[INT] = 0
	[UnicodeString]类型 > 值 = Material[NIL] = <null>
	[UnicodeString]类型 > 值 = material[OBJECT] = <Object#null>
	[UnicodeString]类型 > 值 = use_parent_material[BOOL] = false
	[UnicodeString]类型 > 值 = Node[NIL] = <null>
	[UnicodeString]类型 > 值 = _import_path[NODE_PATH] = 
	[UnicodeString]类型 > 值 = name[STRING_NAME] = Book
	[UnicodeString]类型 > 值 = unique_name_in_owner[BOOL] = false
	[UnicodeString]类型 > 值 = scene_file_path[STRING] = res://book.tscn
	[UnicodeString]类型 > 值 = owner[OBJECT] = <Object#null>
	[UnicodeString]类型 > 值 = multiplayer[OBJECT] = <SceneMultiplayer#-9223372011168857674>
	[UnicodeString]类型 > 值 = Process[NIL] = <null>
	[UnicodeString]类型 > 值 = process_mode[INT] = 0
	[UnicodeString]类型 > 值 = process_priority[INT] = 0
	[UnicodeString]类型 > 值 = Editor Description[NIL] = <null>
	[UnicodeString]类型 > 值 = editor_description[STRING] = 
	[UnicodeString]类型 > 值 = script[OBJECT] = <GDScript#-9223372010984308353>
	[UnicodeString]类型 > 值 =  ---==== [Node2D]类型对象 0X4d7c5600 ====---:
						路径信息:root.Book
						子对象信息: LeftPage[Sprite2D] RightPage[Sprite2D] ShaderRect[ColorRect] LeftButton[Button] RightButton[Button] AutoTurnTimer[Timer] DrGraph[Node]

Ver propiedad de script: [UnicodeString] tipo > valor = script[OBJECT] = <GDScript#-9223372010984308353>

Luego eche un vistazo a Book.script.propertyNames y descubra que se devuelve el contenido del script

Eche un vistazo más de cerca, es el valor del atributo script/source. Luego eche un vistazo a este atributo solo: Book.script.script/source, y obtendrá el contenido del script correspondiente

Es interesante, el nombre del atributo es script/source

Análisis de código fuente

Encuentre script/fuente en el código fuente, hay dos lugares en gdscript.cpp, debería ser este

void GDScript::_get_property_list(List<PropertyInfo> *p_properties) const {
	p_properties->push_back(PropertyInfo(Variant::STRING, "script/source", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
}

Resulta que cuando el objeto GDScript devuelve una lista de nombres de atributos, se agrega tal cosa

De esta forma, al tomar la lista de nombres de atributos, hay un atributo llamado script/source

Baje para ver qué acciones se toman al obtener este atributo, y depura y realiza un seguimiento.

Variant Object::get(const StringName &p_name, bool *r_valid) const {
	Variant ret;

	if (script_instance) {
		if (script_instance->get(p_name, ret)) {
			if (r_valid) {
				*r_valid = true;
			}
			return ret;
		}
	}
	if (_extension && _extension->get) {
// C style pointer casts should never trigger a compiler warning because the risk is assumed by the user, so GCC should keep quiet about it.
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
#endif

		if (_extension->get(_extension_instance, (const GDExtensionStringNamePtr)&p_name, (GDExtensionVariantPtr)&ret)) {
			if (r_valid) {
				*r_valid = true;
			}
			return ret;
		}
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
	}

	// Try built-in getter.
	{
		if (ClassDB::get_property(const_cast<Object *>(this), p_name, ret)) {
			if (r_valid) {
				*r_valid = true;
			}
			return ret;
		}
	}

	if (p_name == CoreStringNames::get_singleton()->_script) {
		ret = get_script();
		if (r_valid) {
			*r_valid = true;
		}
		return ret;
	}

	const Variant *const *V = metadata_properties.getptr(p_name);

	if (V) {
		ret = **V;
		if (r_valid) {
			*r_valid = true;
		}
		return ret;

	} else {
#ifdef TOOLS_ENABLED
		if (script_instance) {
			bool valid;
			ret = script_instance->property_get_fallback(p_name, &valid);
			if (valid) {
				if (r_valid) {
					*r_valid = true;
				}
				return ret;
			}
		}
#endif
		// Something inside the object... :|
		bool success = _getv(p_name, ret);
		if (success) {
			if (r_valid) {
				*r_valid = true;
			}
			return ret;
		}

		if (r_valid) {
			*r_valid = false;
		}
		return Variant();
	}
}

Específicamente, se procesa en  bool success = _getv(p_name, ret);  y se procesa directamente en GDScript::_get

bool GDScript::_get(const StringName &p_name, Variant &r_ret) const {
	{
		const GDScript *top = this;
		while (top) {
			{
				HashMap<StringName, Variant>::ConstIterator E = top->constants.find(p_name);
				if (E) {
					r_ret = E->value;
					return true;
				}
			}

			{
				HashMap<StringName, Ref<GDScript>>::ConstIterator E = subclasses.find(p_name);
				if (E) {
					r_ret = E->value;
					return true;
				}
			}
			top = top->_base;
		}

		if (p_name == GDScriptLanguage::get_singleton()->strings._script_source) {
			r_ret = get_source_code();
			return true;
		}
	}

	return false;
}

La depuración muestra que en las constantes, cada información constante [clave/valor] se guarda

 La estructura personalizada (clase) se guarda en subclases

 Finalmente, en la función get_source_code, devuelve directamente la fuente

String GDScript::get_source_code() const {
	return source;
}

Es decir, el contenido del texto del script.

Eso es todo.

Obtener el valor de la variable en el script

De lo anterior, puede ver la lógica de adquisición de atributos. En el proceso de adquisición de atributos de secuencia de comandos/fuente, verifique las constantes y subclases, luego intente obtener el valor de la variable en él.

Enviar Book.script.AREA_OUT, el resultado es exitoso

estructura personalizada

Continuar probando estructuras personalizadas

Enviar Book.script.TAutoTurn, el resultado se devuelve como objeto: <GDScript#-9223372010833313372>

279. 16:18:07:517 > 【主线程】 > [Pipe.发送] > 发送数据中内容[DrGraph.87: Request - wait 1000 ms]: 
	[int]类型 > 值 = 2
	[UnicodeString]类型 > 值 = Book.script
	[UnicodeString]类型 > 值 = TAutoTurn
280. 16:18:07:617 > 【主线程】 > [Pipe.Read] > 发送数据[DrGraph.87: Request - wait 1000 ms]成功返回 168 字节... > PIPE响应中内容[godot -> DrGraph.87: Response - no return]: 
	[int]类型 > 值 = 3
	[UnicodeString]类型 > 值 = OK
	[UnicodeString]类型 > 值 = <GDScript#-9223372010833313372>

Consulte la lista de nombres de propiedades de objetos

281. 16:18:21:175 > 【主线程】 > [Pipe.发送] > 发送数据中内容[DrGraph.88: Request - wait 1000 ms]: 
	[int]类型 > 值 = 2
	[UnicodeString]类型 > 值 = Book.script.TAutoTurn
	[UnicodeString]类型 > 值 = propertyNames
282. 16:18:21:272 > 【主线程】 > [Pipe.Read] > 发送数据[DrGraph.88: Request - wait 1000 ms]成功返回 423 字节... > PIPE响应中内容[godot -> DrGraph.88: Response - no return]: 
	[int]类型 > 值 = 3
	[UnicodeString]类型 > 值 = OK
	[UnicodeString]类型 > 值 = GDScript[NIL] = <null>
	[UnicodeString]类型 > 值 = script/source[STRING] = 
	[UnicodeString]类型 > 值 = Script[NIL] = <null>
	[UnicodeString]类型 > 值 = source_code[STRING] = 
	[UnicodeString]类型 > 值 = Resource[NIL] = <null>
	[UnicodeString]类型 > 值 = Resource[NIL] = <null>
	[UnicodeString]类型 > 值 = resource_local_to_scene[BOOL] = false
	[UnicodeString]类型 > 值 = resource_path[STRING] = 
	[UnicodeString]类型 > 值 = resource_name[STRING] = 
	[UnicodeString]类型 > 值 = RefCounted[NIL] = <null>
	[UnicodeString]类型 > 值 =  ---==== [GDScript]类型对象 0X4d771310 ====---:
						路径信息:
						子对象信息:

También hay atributos script/source y source_code, pero parece que no hay contenido y la prueba aún no tiene contenido para devolver

 Pero es suficiente para obtener esta información.

Supongo que te gusta

Origin blog.csdn.net/drgraph/article/details/131919983
Recomendado
Clasificación