diff --git a/.gitignore b/.gitignore
index 9e6808d..e2c1395 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,7 @@ export_presets.cfg
.godot/
*.user
Properties/
+build/
+build.*/
+*.dll
+doc/cpp-demo/MyGame/addons/
diff --git a/Dear ImGui for Godot Demo.csproj b/Dear ImGui for Godot Demo.csproj
index a62941d..c4a6c35 100644
--- a/Dear ImGui for Godot Demo.csproj
+++ b/Dear ImGui for Godot Demo.csproj
@@ -5,6 +5,10 @@
DearImGuiforGodotDemo
True
+
+
+
+
diff --git a/addons/imgui-godot/ImGuiGodot/ImGuiLayer.cs b/addons/imgui-godot/ImGuiGodot/ImGuiLayer.cs
index 240d104..bc197ee 100644
--- a/addons/imgui-godot/ImGuiGodot/ImGuiLayer.cs
+++ b/addons/imgui-godot/ImGuiGodot/ImGuiLayer.cs
@@ -2,6 +2,7 @@ using Godot;
using ImGuiNET;
using System;
using System.Collections.Generic;
+using System.Runtime.InteropServices;
namespace ImGuiGodot;
@@ -229,6 +230,29 @@ public partial class ImGuiLayer : CanvasLayer
}
}
+ // WIP, this will probably be changed or moved
+ public unsafe Godot.Collections.Array GetImGuiPtrs(string version, int ioSize, int vertSize, int idxSize)
+ {
+ if (version != ImGui.GetVersion() ||
+ ioSize != Marshal.SizeOf() ||
+ vertSize != Marshal.SizeOf() ||
+ idxSize != sizeof(ushort))
+ {
+ throw new PlatformNotSupportedException($"ImGui version mismatch, use {ImGui.GetVersion()}-docking");
+ }
+
+ IntPtr mem_alloc = IntPtr.Zero;
+ IntPtr mem_free = IntPtr.Zero;
+ void* user_data = null;
+ ImGui.GetAllocatorFunctions(ref mem_alloc, ref mem_free, ref user_data);
+
+ return new(){
+ (long)ImGui.GetCurrentContext(),
+ (long)mem_alloc,
+ (long)mem_free
+ };
+ }
+
private static void OnNodeRemoved(Node node)
{
// signals declared in C# don't (yet?) work like normal Godot signals,
diff --git a/doc/cpp-demo/.clang-format b/doc/cpp-demo/.clang-format
new file mode 100644
index 0000000..c6eaef4
--- /dev/null
+++ b/doc/cpp-demo/.clang-format
@@ -0,0 +1,14 @@
+Language: Cpp
+BasedOnStyle: Microsoft
+AccessModifierOffset: -4
+AllowAllArgumentsOnNextLine: false
+AlignEscapedNewlines: Left
+AlwaysBreakTemplateDeclarations: Yes
+BinPackArguments: false
+BinPackParameters: true
+PointerAlignment: Left
+
+BreakBeforeBraces: Custom
+BraceWrapping:
+ AfterNamespace: false
+ AfterExternBlock: false
diff --git a/doc/cpp-demo/CMakeLists.txt b/doc/cpp-demo/CMakeLists.txt
new file mode 100644
index 0000000..98bb373
--- /dev/null
+++ b/doc/cpp-demo/CMakeLists.txt
@@ -0,0 +1,50 @@
+cmake_minimum_required(VERSION 3.24)
+
+# set up vcpkg
+if (WIN32)
+ set(VCPKG_TARGET_TRIPLET x64-windows-static-md)
+endif()
+file(TO_CMAKE_PATH "$ENV{VCPKG_ROOT}" VCPKG_ROOT)
+set(CMAKE_TOOLCHAIN_FILE "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
+
+project(demoext CXX)
+
+if (NOT TARGET godot-cpp)
+ include(FetchContent)
+ FetchContent_Declare(
+ godot-cpp
+ GIT_REPOSITORY https://github.com/godotengine/godot-cpp
+ GIT_TAG master # watch out, something will break eventually
+ )
+ FetchContent_MakeAvailable(godot-cpp)
+endif()
+
+find_package(imgui CONFIG REQUIRED)
+find_package(implot CONFIG REQUIRED)
+find_package(freetype CONFIG REQUIRED)
+find_package(GTest CONFIG REQUIRED)
+
+add_library(demoext SHARED)
+add_subdirectory(src)
+
+target_link_libraries(demoext PUBLIC
+ godot-cpp
+ imgui::imgui
+ freetype
+ implot::implot
+ )
+target_include_directories(demoext PRIVATE src)
+target_compile_features(demoext PRIVATE cxx_std_20)
+target_compile_definitions(demoext PUBLIC IMGUI_DISABLE_INCLUDE_IMCONFIG_H)
+
+set_property(TARGET demoext PROPERTY OUTPUT_NAME "demoext.$,debug,release>")
+
+install(TARGETS demoext RUNTIME DESTINATION bin)
+
+enable_testing()
+add_executable(demotest test/test.cpp)
+target_include_directories(demotest PRIVATE src)
+target_link_libraries(demotest PRIVATE GTest::gtest_main demoext)
+
+include(GoogleTest)
+gtest_discover_tests(demotest)
diff --git a/doc/cpp-demo/CMakePresets.json b/doc/cpp-demo/CMakePresets.json
new file mode 100644
index 0000000..ead05cb
--- /dev/null
+++ b/doc/cpp-demo/CMakePresets.json
@@ -0,0 +1,40 @@
+{
+ "version": 1,
+ "cmakeMinimumRequired": {
+ "major": 3,
+ "minor": 20,
+ "patch": 0
+ },
+ "configurePresets": [
+ {
+ "name": "debug",
+ "generator": "Ninja",
+ "binaryDir": "${sourceDir}/build.debug",
+ "cacheVariables": {
+ "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
+ "CMAKE_INSTALL_PREFIX": "MyGame",
+ "CMAKE_BUILD_TYPE": "Debug"
+ }
+ },
+ {
+ "name": "release",
+ "generator": "Ninja",
+ "binaryDir": "${sourceDir}/build.release",
+ "cacheVariables": {
+ "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
+ "CMAKE_INSTALL_PREFIX": "MyGame",
+ "CMAKE_BUILD_TYPE": "RelWithDebInfo",
+ "CMAKE_INTERPROCEDURAL_OPTIMIZATION": "ON"
+ }
+ },
+ {
+ "name": "msvc",
+ "generator": "Visual Studio 17 2022",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
+ "CMAKE_INSTALL_PREFIX": "MyGame"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/doc/cpp-demo/MyGame/MyGame.csproj b/doc/cpp-demo/MyGame/MyGame.csproj
new file mode 100644
index 0000000..67ed622
--- /dev/null
+++ b/doc/cpp-demo/MyGame/MyGame.csproj
@@ -0,0 +1,10 @@
+
+
+ net6.0
+ true
+ True
+
+
+
+
+
\ No newline at end of file
diff --git a/doc/cpp-demo/MyGame/MyGame.sln b/doc/cpp-demo/MyGame/MyGame.sln
new file mode 100644
index 0000000..07b6668
--- /dev/null
+++ b/doc/cpp-demo/MyGame/MyGame.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyGame", "MyGame.csproj", "{3FFFFA7D-AD43-4770-AE3F-2BA38FF919E4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ ExportDebug|Any CPU = ExportDebug|Any CPU
+ ExportRelease|Any CPU = ExportRelease|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3FFFFA7D-AD43-4770-AE3F-2BA38FF919E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3FFFFA7D-AD43-4770-AE3F-2BA38FF919E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3FFFFA7D-AD43-4770-AE3F-2BA38FF919E4}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
+ {3FFFFA7D-AD43-4770-AE3F-2BA38FF919E4}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
+ {3FFFFA7D-AD43-4770-AE3F-2BA38FF919E4}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
+ {3FFFFA7D-AD43-4770-AE3F-2BA38FF919E4}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/doc/cpp-demo/MyGame/default_env.tres b/doc/cpp-demo/MyGame/default_env.tres
new file mode 100644
index 0000000..0645b88
--- /dev/null
+++ b/doc/cpp-demo/MyGame/default_env.tres
@@ -0,0 +1,7 @@
+[gd_resource type="Environment" load_steps=2 format=3 uid="uid://dtd3q2x2ulcsi"]
+
+[sub_resource type="Sky" id="1"]
+
+[resource]
+background_mode = 2
+sky = SubResource("1")
diff --git a/doc/cpp-demo/MyGame/demoext.gdextension b/doc/cpp-demo/MyGame/demoext.gdextension
new file mode 100644
index 0000000..beef10c
--- /dev/null
+++ b/doc/cpp-demo/MyGame/demoext.gdextension
@@ -0,0 +1,14 @@
+[configuration]
+
+entry_symbol = "demoext_init"
+
+[libraries]
+
+macos.debug = "res://bin/demoext.debug.framework"
+macos.release = "res://bin/demoext.release.framework"
+windows.debug.x86_64 = "res://bin/demoext.debug.dll"
+windows.release.x86_64 = "res://bin/demoext.release.dll"
+linux.debug.x86_64 = "res://bin/demoext.debug.so"
+linux.release.x86_64 = "res://bin/demoext.release.so"
+linux.debug.arm64 = "res://bin/demoext.debug.so"
+linux.release.arm64 = "res://bin/demoext.release.so"
diff --git a/doc/cpp-demo/MyGame/icon.svg b/doc/cpp-demo/MyGame/icon.svg
new file mode 100644
index 0000000..adc26df
--- /dev/null
+++ b/doc/cpp-demo/MyGame/icon.svg
@@ -0,0 +1 @@
+
diff --git a/doc/cpp-demo/MyGame/icon.svg.import b/doc/cpp-demo/MyGame/icon.svg.import
new file mode 100644
index 0000000..a43c953
--- /dev/null
+++ b/doc/cpp-demo/MyGame/icon.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d08m2uvixtsgf"
+path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://icon.svg"
+dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
+
+[params]
+
+compress/mode=0
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/bptc_ldr=0
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/doc/cpp-demo/MyGame/main.tscn b/doc/cpp-demo/MyGame/main.tscn
new file mode 100644
index 0000000..cf383cd
--- /dev/null
+++ b/doc/cpp-demo/MyGame/main.tscn
@@ -0,0 +1,11 @@
+[gd_scene format=3 uid="uid://d02ytucir7qh2"]
+
+[node name="Control" type="Control"]
+layout_mode = 3
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="MyCppNode" type="MyCppNode" parent="."]
diff --git a/doc/cpp-demo/MyGame/project.godot b/doc/cpp-demo/MyGame/project.godot
new file mode 100644
index 0000000..02f9404
--- /dev/null
+++ b/doc/cpp-demo/MyGame/project.godot
@@ -0,0 +1,36 @@
+; Engine configuration file.
+; It's best edited using the editor UI and not directly,
+; since the parameters that go here are not all obvious.
+;
+; Format:
+; [section] ; section goes between []
+; param=value ; assign values to parameters
+
+config_version=5
+
+[application]
+
+config/name="MyGame"
+run/main_scene="res://main.tscn"
+config/features=PackedStringArray("4.0", "C#")
+config/icon="res://icon.svg"
+
+[autoload]
+
+ImGuiLayer="*res://addons/imgui-godot/ImGuiLayer.tscn"
+
+[dotnet]
+
+project/assembly_name="MyGame"
+
+[editor_plugins]
+
+enabled=PackedStringArray("res://addons/imgui-godot/plugin.cfg")
+
+[native_extensions]
+
+paths=["res://demoext.gdextension"]
+
+[rendering]
+
+environment/defaults/default_environment="res://default_env.tres"
diff --git a/doc/cpp-demo/README.md b/doc/cpp-demo/README.md
new file mode 100644
index 0000000..02e4ced
--- /dev/null
+++ b/doc/cpp-demo/README.md
@@ -0,0 +1,8 @@
+
+A sample GDExtension using ImGui with a context from imgui-godot. Uses vcpkg and CMake for easy setup and fast builds.
+
+```
+cmake --preset msvc
+
+cmake --build build --target install --config Debug
+```
diff --git a/doc/cpp-demo/src/CMakeLists.txt b/doc/cpp-demo/src/CMakeLists.txt
new file mode 100644
index 0000000..fc1c2e3
--- /dev/null
+++ b/doc/cpp-demo/src/CMakeLists.txt
@@ -0,0 +1,5 @@
+target_sources(demoext PRIVATE
+ main.cpp
+ mycppnode.cpp
+ mycppnode.h
+)
diff --git a/doc/cpp-demo/src/main.cpp b/doc/cpp-demo/src/main.cpp
new file mode 100644
index 0000000..30f73b5
--- /dev/null
+++ b/doc/cpp-demo/src/main.cpp
@@ -0,0 +1,36 @@
+#include
+#include
+#include
+#include
+#include
+
+using namespace godot;
+
+void initialize_demo_module(ModuleInitializationLevel p_level)
+{
+ if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE)
+ return;
+
+ ClassDB::register_class();
+}
+
+void uninitialize_demo_module(ModuleInitializationLevel p_level)
+{
+ if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE)
+ return;
+}
+
+extern "C" {
+GDNativeBool GDN_EXPORT demoext_init(const GDNativeInterface* p_interface,
+ const GDNativeExtensionClassLibraryPtr p_library,
+ GDNativeInitialization* r_initialization)
+{
+ godot::GDExtensionBinding::InitObject init_obj(p_interface, p_library, r_initialization);
+
+ init_obj.register_initializer(initialize_demo_module);
+ init_obj.register_terminator(uninitialize_demo_module);
+ init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
+
+ return init_obj.init();
+}
+}
diff --git a/doc/cpp-demo/src/mycppnode.cpp b/doc/cpp-demo/src/mycppnode.cpp
new file mode 100644
index 0000000..e8087f9
--- /dev/null
+++ b/doc/cpp-demo/src/mycppnode.cpp
@@ -0,0 +1,66 @@
+#include "mycppnode.h"
+#include
+#include
+#include
+#include
+#include
+using namespace godot;
+
+struct MyCppNode::Impl
+{
+};
+
+MyCppNode::MyCppNode() : impl(std::make_unique())
+{
+}
+
+MyCppNode::~MyCppNode()
+{
+}
+
+void MyCppNode::_bind_methods()
+{
+}
+
+void MyCppNode::_ready()
+{
+ // TODO: don't run in editor mode
+ set_process(false);
+ Node* igl = get_node_or_null("/root/ImGuiLayer");
+ if (!igl)
+ return;
+
+ godot::Array imgui_ptrs = igl->call(
+ "GetImGuiPtrs",
+ ImGui::GetVersion(),
+ sizeof(ImGuiIO),
+ sizeof(ImDrawVert),
+ sizeof(ImDrawIdx)
+ );
+
+ if (imgui_ptrs.size() < 3)
+ return;
+
+ int64_t ctx = imgui_ptrs[0];
+ int64_t mem_alloc = imgui_ptrs[1];
+ int64_t mem_free = imgui_ptrs[2];
+
+ ImGui::SetCurrentContext((ImGuiContext*)ctx);
+ ImGui::SetAllocatorFunctions((ImGuiMemAllocFunc)mem_alloc, (ImGuiMemFreeFunc)mem_free);
+ ImPlot::CreateContext();
+ set_process(true);
+}
+
+void MyCppNode::_exit_tree()
+{
+ ImPlot::DestroyContext();
+}
+
+void MyCppNode::_process(double delta)
+{
+ ImPlot::ShowDemoWindow();
+
+ ImGui::Begin("Cpp Window");
+ ImGui::Text("hello from C++");
+ ImGui::End();
+}
diff --git a/doc/cpp-demo/src/mycppnode.h b/doc/cpp-demo/src/mycppnode.h
new file mode 100644
index 0000000..a0e5f90
--- /dev/null
+++ b/doc/cpp-demo/src/mycppnode.h
@@ -0,0 +1,27 @@
+#pragma once
+#include
+#include
+
+using godot::Node;
+using godot::InputEvent;
+using godot::Ref;
+
+class MyCppNode : public Node
+{
+ GDCLASS(MyCppNode, Node);
+
+protected:
+ static void _bind_methods();
+
+public:
+ void _ready() override;
+ void _exit_tree() override;
+ void _process(double delta) override;
+
+ MyCppNode();
+ ~MyCppNode();
+
+private:
+ struct Impl;
+ std::unique_ptr impl;
+};
diff --git a/doc/cpp-demo/test/test.cpp b/doc/cpp-demo/test/test.cpp
new file mode 100644
index 0000000..80ca8e9
--- /dev/null
+++ b/doc/cpp-demo/test/test.cpp
@@ -0,0 +1,8 @@
+#include
+#include
+#include
+
+TEST(SomethingTest, DoAThing)
+{
+ ASSERT_TRUE(true);
+}
diff --git a/doc/cpp-demo/vcpkg.json b/doc/cpp-demo/vcpkg.json
new file mode 100644
index 0000000..b2ee4d4
--- /dev/null
+++ b/doc/cpp-demo/vcpkg.json
@@ -0,0 +1,21 @@
+{
+ "dependencies": [
+ {
+ "name": "imgui",
+ "features": [
+ "docking-experimental",
+ "freetype"
+ ]
+ },
+ "implot",
+ "imguizmo",
+ "gtest"
+ ],
+ "builtin-baseline": "6f7ffeb18f99796233b958aaaf14ec7bd4fb64b2",
+ "overrides": [
+ {
+ "name": "imgui",
+ "version": "1.88"
+ }
+ ]
+}
\ No newline at end of file