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.