|
9 | 9 | </Type> |
10 | 10 |
|
11 | 11 | <Type Name="godot::StringName"> |
12 | | - <Intrinsic Name="get_data_ptr" Expression="(*reinterpret_cast<const char32_t***>(opaque))[1]" /> |
| 12 | + <Intrinsic Name="get_data_ptr" Expression="(*reinterpret_cast<const char32_t***>(opaque))[1]"/> |
13 | 13 | <DisplayString Condition="get_data_ptr()">{get_data_ptr(),s32}</DisplayString> |
14 | 14 | <Expand> |
15 | 15 | <Item Name="opaque_ptr">*reinterpret_cast<void**>(opaque)</Item> |
16 | 16 | <Item Name="cname">get_data_ptr(),s32</Item> |
17 | 17 | </Expand> |
18 | 18 | </Type> |
19 | 19 |
|
20 | | - <!-- Development notes: At the current state no AI can directly generate a natvis entry for each `godot::` type. |
21 | | - The testdata used for evaluation https://github.com/JetBrains/godot-support/wiki/Developing-godot%E2%80%90cpp.natvis |
22 | | - The change of the memory layout would require adjustments of the natvis |
23 | | -
|
24 | | - Approach: |
25 | | - 1. For each type, inspect `opaque` bytes in LLDB using `memory read -size 8 -count N -format address` on |
26 | | - the address stored in opaque (e.g. `*(void**)demo_type.opaque`) to map the actual field layout. |
27 | | - 2. Verify specific field values match known test data (e.g. array size=1, int value=42, string content). |
28 | | - 3. Write natvis expressions only after the field offsets are confirmed. |
29 | | -
|
30 | | - Evaluator constraints (JetBrains natvis engine, I haven't checked anything else): |
31 | | - - Supports: reinterpret_cast, pointer arithmetic on built-in types, array indexing ([n]), Intrinsics |
32 | | - - Does NOT support: calling member functions (e.g. size()) |
33 | | - - Nested type visualizers work: `{*(godot::String*)(opaque+8)}` delegates to the String natvis entry |
34 | | -
|
35 | | - Patterns used: |
36 | | - - Opaque wrapper types (String, StringName, Array, Dictionary, ...): cast opaque slice to the |
37 | | - godot-cpp type pointer — `*(godot::TypeName*)(opaque+N)` — and let that type's natvis handle display |
38 | | - - Engine heap-allocated types stored as pointer (Transform2D, AABB, Basis, ...): double-deref — |
39 | | - `**(godot::TypeName**)(opaque+N)` |
40 | | - - Engine internals without a godot-cpp wrapper (ArrayPrivate, CowData, HashMap): use raw |
41 | | - reinterpret_cast + index arithmetic, document offsets with a comment verified by LLDB |
42 | | -
|
43 | | - Future upcomming improvements: |
44 | | - - JetBrains natvis support is going to become x-plat https://youtrack.jetbrains.com/issue/CPP-35297 |
45 | | - --> |
| 20 | + <!-- Developer notes: https://jb.gg/godot-cpp-natvis --> |
46 | 21 |
|
47 | 22 | <!-- opaque[0..7] holds ArrayPrivate*. Dereference as unsigned long long* to read ArrayPrivate |
48 | 23 | fields as 8-byte slots: [0]=refcount, [1]=unknown, [2]=_cowdata._ptr, [3]=read_only, ... |
49 | 24 | Index [2] reaches _cowdata._ptr at offset +16 (verified by LLDB memory dump). |
50 | 25 | Cast _ptr to unsigned long long* so [-1] reads the CowData element count 8 bytes before data. --> |
51 | 26 | <Type Name="godot::Array"> |
52 | | - <Intrinsic Name="_cow" Expression="(unsigned long long*)(*reinterpret_cast<unsigned long long**>(opaque))[2]" /> |
| 27 | + <Intrinsic Name="_cow" |
| 28 | + Expression="(unsigned long long*)(*reinterpret_cast<unsigned long long**>(opaque))[2]"/> |
53 | 29 | <DisplayString Condition="!*reinterpret_cast<void**>(opaque) || !_cow()">{{empty}}</DisplayString> |
54 | 30 | <DisplayString>{{size={_cow()[-1]}}}</DisplayString> |
55 | 31 | <Expand> |
|
66 | 42 | HashMap: [_elements(8)][unknown(8)][_head(8)][_last(8)][_capacity_index(4)][_num_elements(4)] |
67 | 43 | HashMapElement: [next(8)][prev(8)][key:Variant(24)][value:Variant(24)] --> |
68 | 44 | <Type Name="godot::Dictionary"> |
69 | | - <Intrinsic Name="_p" Expression="*reinterpret_cast<unsigned char**>(opaque)" /> |
70 | | - <Intrinsic Name="_size" Expression="*(unsigned int*)(_p() + 52)" /> |
71 | | - <Intrinsic Name="_head" Expression="*reinterpret_cast<unsigned char**>(_p() + 32)" /> |
| 45 | + <Intrinsic Name="_p" Expression="*reinterpret_cast<unsigned char**>(opaque)"/> |
| 46 | + <Intrinsic Name="_size" Expression="*(unsigned int*)(_p() + 52)"/> |
| 47 | + <Intrinsic Name="_head" Expression="*reinterpret_cast<unsigned char**>(_p() + 32)"/> |
72 | 48 | <DisplayString Condition="!_p()">{{empty}}</DisplayString> |
73 | 49 | <DisplayString>{{size={_size()}}}</DisplayString> |
74 | 50 | <Expand> |
75 | 51 | <Item Name="[size]">_size()</Item> |
76 | 52 | <CustomListItems MaxItemsPerView="5000"> |
77 | 53 | <Variable Name="elem" InitialValue="(unsigned char*)_head()"/> |
78 | | - <Variable Name="idx" InitialValue="0"/> |
| 54 | + <Variable Name="idx" InitialValue="0"/> |
79 | 55 | <Loop Condition="elem != 0"> |
80 | 56 | <Item Name="[{idx}]">(godot::Variant*)(elem + 16),[2]</Item> |
81 | 57 | <Exec>elem = *(unsigned char**)elem</Exec> |
|
93 | 69 | DICTIONARY=27 ARRAY=28 |
94 | 70 | Layout: opaque[0..3]=type(int32), opaque[4..7]=pad, opaque[8..23]=_data union --> |
95 | 71 | <Type Name="godot::Variant"> |
96 | | - <Intrinsic Name="_type" Expression="*reinterpret_cast<int*>(opaque)" /> |
| 72 | + <Intrinsic Name="_type" Expression="*reinterpret_cast<int*>(opaque)"/> |
97 | 73 | <DisplayString Condition="_type() == 0">nil</DisplayString> |
98 | 74 | <DisplayString Condition="_type() == 1">{*reinterpret_cast<bool*>(opaque+8)}</DisplayString> |
99 | 75 | <DisplayString Condition="_type() == 2">{*reinterpret_cast<long long*>(opaque+8)}</DisplayString> |
|
125 | 101 | <DisplayString Condition="_type() == 18">{**(godot::Transform3D**)(opaque+8)}</DisplayString> |
126 | 102 | <DisplayString Condition="_type() == 19">{**(godot::Projection**)(opaque+8)}</DisplayString> |
127 | 103 | <!-- OBJECT: opaque+8=ObjectID, opaque+16=Object* --> |
128 | | - <DisplayString Condition="_type() == 24">Object(id={*reinterpret_cast<unsigned long long*>(opaque+8)})</DisplayString> |
| 104 | + <DisplayString Condition="_type() == 24">Object(id={*reinterpret_cast<unsigned long long*>(opaque+8)}) |
| 105 | + </DisplayString> |
129 | 106 | <DisplayString>{{type={_type()}}}</DisplayString> |
130 | 107 | <Expand> |
131 | 108 | <Item Name="[type]">_type()</Item> |
|
0 commit comments