From a5f1d6a5bd771af866dcd4b1bd0be9b81c1a8ca9 Mon Sep 17 00:00:00 2001 From: Yuri Dolukhanyan Date: Mon, 25 May 2026 16:58:24 +0400 Subject: [PATCH 1/3] natvis: added new visualizers for godot-cpp types Extends the existing visualizer set with: Packed arrays: - godot::PackedByteArray - godot::PackedInt32Array, godot::PackedInt64Array - godot::PackedFloat32Array, godot::PackedFloat64Array - godot::PackedStringArray - godot::PackedVector2Array, godot::PackedVector3Array, godot::PackedVector4Array - godot::PackedColorArray Math primitives: - godot::Vector2'3'4, godot::Vector2i'3i'4i - godot::Quaternion - godot::Color - godot::Plane - godot::Rect2'2i - godot::AABB - godot::Basis - godot::Transform2D, godot::Transform3D - godot::Projection and godot::NodePath (absolute, path, subpath) --- natvis/godot-cpp.natvis | 362 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 359 insertions(+), 3 deletions(-) diff --git a/natvis/godot-cpp.natvis b/natvis/godot-cpp.natvis index 380327f99..9fcf43105 100644 --- a/natvis/godot-cpp.natvis +++ b/natvis/godot-cpp.natvis @@ -27,11 +27,11 @@ {{empty}} - {{size={_cow()[-1]}}} + {{size={_cow()[-2]}}} - _cow()[-1] + _cow()[-2] - _cow()[-1] + _cow()[-2] (godot::Variant*)_cow() @@ -132,4 +132,360 @@ *(godot::Array*)(opaque+8) + + + + + + {{empty}} + {{size={_cow()[-2]}}} + + _cow()[-2] + + _cow()[-2] + (unsigned char*)_cow() + + + + + + + {{empty}} + {{size={_cow()[-2]}}} + + _cow()[-2] + + _cow()[-2] + (int*)_cow() + + + + + + + {{empty}} + {{size={_cow()[-2]}}} + + _cow()[-2] + + _cow()[-2] + (long long*)_cow() + + + + + + + {{empty}} + {{size={_cow()[-2]}}} + + _cow()[-2] + + _cow()[-2] + (float*)_cow() + + + + + + + {{empty}} + {{size={_cow()[-2]}}} + + _cow()[-2] + + _cow()[-2] + (double*)_cow() + + + + + + + {{empty}} + {{size={_cow()[-2]}}} + + _cow()[-2] + + _cow()[-2] + (godot::String*)_cow() + + + + + + + {{empty}} + {{size={_cow()[-2]}}} + + _cow()[-2] + + _cow()[-2] + (godot::Vector2*)_cow() + + + + + + + {{empty}} + {{size={_cow()[-2]}}} + + _cow()[-2] + + _cow()[-2] + (godot::Vector3*)_cow() + + + + + + + {{empty}} + {{size={_cow()[-2]}}} + + _cow()[-2] + + _cow()[-2] + (godot::Vector4*)_cow() + + + + + + + {{empty}} + {{size={_cow()[-2]}}} + + _cow()[-2] + + _cow()[-2] + (godot::Color*)_cow() + + + + + + ({x,g}, {y,g}) + + x + y + + + + + ({x}, {y}) + + x + y + + + + + ({x,g}, {y,g}, {z,g}) + + x + y + z + + + + + ({x}, {y}, {z}) + + x + y + z + + + + + ({x,g}, {y,g}, {z,g}, {w,g}) + + x + y + z + w + + + + + ({x}, {y}, {z}, {w}) + + x + y + z + w + + + + + ({x,g}, {y,g}, {z,g}, {w,g}) + + x + y + z + w + + + + + ({r,g}, {g,g}, {b,g}, {a,g}) + + r + g + b + a + + + + + [N: {normal}, D: {d,g}] + + normal,nr + d + + + + + [P: {position}, S: {size}] + + position,nr + size,nr + + + + + [P: {position}, S: {size}] + + position,nr + size,nr + + + + + [P: {position}, S: {size}] + + position,nr + size,nr + + + + + [X: {rows[0]}, Y: {rows[1]}, Z: {rows[2]}] + + rows[0],nr + rows[1],nr + rows[2],nr + + + + + [X: {columns[0]}, Y: {columns[1]}, Z: {columns[2]}, W: {columns[3]}] + + columns[0],nr + columns[1],nr + columns[2],nr + columns[3],nr + + + + + [X: {columns[0]}, Y: {columns[1]}, O: {columns[2]}] + + columns[0],nr + columns[1],nr + columns[2],nr + + + + + [X: ({basis.rows[0].x,g}, {basis.rows[1].x,g}, {basis.rows[2].x,g}), Y: ({basis.rows[0].y,g}, + {basis.rows[1].y,g}, {basis.rows[2].y,g}), Z: ({basis.rows[0].z,g}, {basis.rows[1].z,g}, + {basis.rows[2].z,g}), O: {origin}] + + + + ({basis.rows[0].x,g}, {basis.rows[1].x,g}, {basis.rows[2].x,g}) + + basis.rows[0].x + basis.rows[1].x + basis.rows[2].x + + + + ({basis.rows[0].y,g}, {basis.rows[1].y,g}, {basis.rows[2].y,g}) + + basis.rows[0].y + basis.rows[1].y + basis.rows[2].y + + + + ({basis.rows[0].z,g}, {basis.rows[1].z,g}, {basis.rows[2].z,g}) + + basis.rows[0].z + basis.rows[1].z + basis.rows[2].z + + + origin,nr + + + + + + + + + [empty] + {{absolute={_absolute()}, path[{_path_ptr()[-2]}], subpath[{_subpath_ptr()[-2]}]}} + + + _absolute() + + [empty] + {{size={_path_ptr()[-2]}}} + + + _path_ptr()[-2] + (godot::StringName*)_path_ptr() + + + + + [empty] + {{size={_subpath_ptr()[-2]}}} + + + _subpath_ptr()[-2] + (godot::StringName*)_subpath_ptr() + + + + + From d5a0c91a57db95a209b1acc53c961e2767865338 Mon Sep 17 00:00:00 2001 From: Yuri Dolukhanyan Date: Tue, 26 May 2026 13:41:37 +0400 Subject: [PATCH 2/3] [natvis] empty Array conidition visualization, Varinat ExpandedItem changed into Item with value naming --- natvis/godot-cpp.natvis | 53 +++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/natvis/godot-cpp.natvis b/natvis/godot-cpp.natvis index 9fcf43105..2f85864ca 100644 --- a/natvis/godot-cpp.natvis +++ b/natvis/godot-cpp.natvis @@ -29,8 +29,9 @@ {{empty}} {{size={_cow()[-2]}}} - _cow()[-2] - + _cow()[-2] + 0,d + _cow()[-2] (godot::Variant*)_cow() @@ -106,30 +107,30 @@ {{type={_type()}}} _type() - *(godot::String*)(opaque+8) - *(godot::Vector2*)(opaque+8) - *(godot::Vector2i*)(opaque+8) - *(godot::Rect2*)(opaque+8) - *(godot::Rect2i*)(opaque+8) - *(godot::Vector3*)(opaque+8) - *(godot::Vector3i*)(opaque+8) - **(godot::Transform2D**)(opaque+8) - *(godot::Vector4*)(opaque+8) - *(godot::Vector4i*)(opaque+8) - *(godot::Plane*)(opaque+8) - *(godot::Quaternion*)(opaque+8) - **(godot::AABB**)(opaque+8) - **(godot::Basis**)(opaque+8) - **(godot::Transform3D**)(opaque+8) - **(godot::Projection**)(opaque+8) - *(godot::Color*)(opaque+8) - *(godot::StringName*)(opaque+8) - *(godot::NodePath*)(opaque+8) - *(godot::RID*)(opaque+8) - *(godot::Callable*)(opaque+8) - *(godot::Signal*)(opaque+8) - *(godot::Dictionary*)(opaque+8) - *(godot::Array*)(opaque+8) + *(godot::String*)(opaque+8) + *(godot::Vector2*)(opaque+8) + *(godot::Vector2i*)(opaque+8) + *(godot::Rect2*)(opaque+8) + *(godot::Rect2i*)(opaque+8) + *(godot::Vector3*)(opaque+8) + *(godot::Vector3i*)(opaque+8) + **(godot::Transform2D**)(opaque+8) + *(godot::Vector4*)(opaque+8) + *(godot::Vector4i*)(opaque+8) + *(godot::Plane*)(opaque+8) + *(godot::Quaternion*)(opaque+8) + **(godot::AABB**)(opaque+8) + **(godot::Basis**)(opaque+8) + **(godot::Transform3D**)(opaque+8) + **(godot::Projection**)(opaque+8) + *(godot::Color*)(opaque+8) + *(godot::StringName*)(opaque+8) + *(godot::NodePath*)(opaque+8) + *(godot::RID*)(opaque+8) + *(godot::Callable*)(opaque+8) + *(godot::Signal*)(opaque+8) + *(godot::Dictionary*)(opaque+8) + *(godot::Array*)(opaque+8) From b8dd1bc6c67de179d200b8628dfe46a5463e8a64 Mon Sep 17 00:00:00 2001 From: Yuri Dolukhanyan Date: Tue, 26 May 2026 19:08:28 +0400 Subject: [PATCH 3/3] [natvis] fix of the size reading logic with bit manipulation (regarding godot::Array, godot::Packed*Array, godot::NodePath), primitive types now have Item [value] --- natvis/godot-cpp.natvis | 174 +++++++++++++++++++++++++--------------- 1 file changed, 111 insertions(+), 63 deletions(-) diff --git a/natvis/godot-cpp.natvis b/natvis/godot-cpp.natvis index 2f85864ca..34ebdf971 100644 --- a/natvis/godot-cpp.natvis +++ b/natvis/godot-cpp.natvis @@ -23,16 +23,25 @@ fields as 8-byte slots: [0]=refcount, [1]=unknown, [2]=_cowdata._ptr, [3]=read_only, ... Index [2] reaches _cowdata._ptr at offset +16 (verified by LLDB memory dump). Cast _ptr to unsigned long long* so [-1] reads the CowData element count 8 bytes before data. --> + + - {{empty}} - {{size={_cow()[-2]}}} + + {{empty}} + {{size={_size()}}} - _cow()[-2] - 0,d - - _cow()[-2] + 0,d + _size() + + _size() (godot::Variant*)_cow() @@ -107,6 +116,9 @@ {{type={_type()}}} _type() + *reinterpret_cast<bool*>(opaque+8) + *reinterpret_cast<long long*>(opaque+8) + *reinterpret_cast<double*>(opaque+8) *(godot::String*)(opaque+8) *(godot::Vector2*)(opaque+8) *(godot::Vector2i*)(opaque+8) @@ -135,26 +147,31 @@ + opaque (16 bytes): + [0..7] reserved / 0 (godot-cpp over-allocates; engine type is 8 bytes) + [8..15] CowData::_ptr (T*) - points to first data element + CowData allocation block layout (same as godot::Array): + _ptr - 16: uint64_t size <- what _size() reads + _ptr - 8: SafeNumeric refcount + _ptr + 0: T data[size] <- _cow() points here + _size() uses the alignment-aware formula: *(uint64_t*)(((_cow() - 1) as uintptr_t) & ~15) + Subtracting 1 byte and masking with ~15 always lands on + the closest 16-byte-aligned address at or just before _cow() - 1, + which is exactly where, the size lives. + Only differs between the Packed*Array types. --> + {{empty}} - {{size={_cow()[-2]}}} + {{size={_size()}}} - _cow()[-2] - - _cow()[-2] + 0,d + _size() + + _size() (unsigned char*)_cow() @@ -163,12 +180,15 @@ + {{empty}} - {{size={_cow()[-2]}}} + {{size={_size()}}} - _cow()[-2] - - _cow()[-2] + 0,d + _size() + + _size() (int*)_cow() @@ -177,12 +197,15 @@ + {{empty}} - {{size={_cow()[-2]}}} + {{size={_size()}}} - _cow()[-2] - - _cow()[-2] + 0,d + _size() + + _size() (long long*)_cow() @@ -191,12 +214,15 @@ + {{empty}} - {{size={_cow()[-2]}}} + {{size={_size()}}} - _cow()[-2] - - _cow()[-2] + 0,d + _size() + + _size() (float*)_cow() @@ -205,12 +231,15 @@ + {{empty}} - {{size={_cow()[-2]}}} + {{size={_size()}}} - _cow()[-2] - - _cow()[-2] + 0,d + _size() + + _size() (double*)_cow() @@ -219,12 +248,15 @@ + {{empty}} - {{size={_cow()[-2]}}} + {{size={_size()}}} - _cow()[-2] - - _cow()[-2] + 0,d + _size() + + _size() (godot::String*)_cow() @@ -233,12 +265,15 @@ + {{empty}} - {{size={_cow()[-2]}}} + {{size={_size()}}} - _cow()[-2] - - _cow()[-2] + 0,d + _size() + + _size() (godot::Vector2*)_cow() @@ -247,12 +282,15 @@ + {{empty}} - {{size={_cow()[-2]}}} + {{size={_size()}}} - _cow()[-2] - - _cow()[-2] + 0,d + _size() + + _size() (godot::Vector3*)_cow() @@ -261,12 +299,15 @@ + {{empty}} - {{size={_cow()[-2]}}} + {{size={_size()}}} - _cow()[-2] - - _cow()[-2] + 0,d + _size() + + _size() (godot::Vector4*)_cow() @@ -275,12 +316,15 @@ + {{empty}} - {{size={_cow()[-2]}}} + {{size={_size()}}} - _cow()[-2] - - _cow()[-2] + 0,d + _size() + + _size() (godot::Color*)_cow() @@ -461,28 +505,32 @@ Expression="*reinterpret_cast<unsigned long long**>(_cow() + 16)"/> + + [empty] - {{absolute={_absolute()}, path[{_path_ptr()[-2]}], subpath[{_subpath_ptr()[-2]}]}} + {{absolute={_absolute()}, path[{_path_size()}], subpath[{_subpath_size()}]}} _absolute() [empty] - {{size={_path_ptr()[-2]}}} + {{size={_path_size()}}} - - _path_ptr()[-2] + + _path_size() (godot::StringName*)_path_ptr() [empty] - {{size={_subpath_ptr()[-2]}}} + {{size={_subpath_size()}}} - - _subpath_ptr()[-2] + + _subpath_size() (godot::StringName*)_subpath_ptr()