Get property list
Raised grass and beat rabbits today, and got the script content
Since the attribute value can already be obtained, then go one step further and obtain the list of attribute names
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);
}
Correspondingly, a list of function names and a list of subobjects can be obtained
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);
}
}
Among them, obtaining object information (GetObjectHint) is expected to display some corresponding information of the object
#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);
}
Test it and get all the property names of the root node (Book): 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]
See script property: [UnicodeString] type > value = script[OBJECT] = <GDScript#-9223372010984308353>
Then take a look at Book.script.propertyNames and find that the script content is returned
Take a closer look, it is the value of the attribute script/source. Then take a look at this attribute alone: Book.script.script/source, and you will get the corresponding script content
It's interesting, the attribute name is script/source
Source code analysis
Find script/source in the source code, there are two places in gdscript.cpp, it should be this
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));
}
It turns out that when the GDScript object returns a list of attribute names, such a thing is added
In this way, when taking the list of attribute names, there is an attribute named script/source
Come down to see what actions are taken when getting this attribute, and debug and follow up
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();
}
}
Specifically, it is processed in bool success = _getv(p_name, ret); and directly processed in 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;
}
Debugging shows that in constants, each constant information [key / value] is saved
The custom structure (class) is saved in subclasses
Finally, in the get_source_code function, directly return the source
String GDScript::get_source_code() const {
return source;
}
That is, the script text content.
That's it.
Get the value of the variable in the script
From the above, you can see the attribute acquisition logic. In the process of script/source attribute acquisition, constants and subclasses are checked, so try to get the variable value in it
Send Book.script.AREA_OUT, the result is successful
custom structure
Continue to test custom structures
Send Book.script.TAutoTurn, the result is returned as object: <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>
Check the list of object property names
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 ====---:
路径信息:
子对象信息:
There are also script/source and source_code attributes, but it seems that there is no content, and the test still has no content to return
But it is enough to get this information