├── .clang-format ├── .editorconfig ├── .gitattributes ├── .github ├── actions │ ├── import │ │ └── action.yml │ └── run-test-project │ │ └── action.yml └── workflows │ ├── dotnet.yml │ ├── gdext.yml │ └── godot.yml ├── .gitignore ├── .gitmodules ├── Dear ImGui for Godot Demo.csproj ├── Dear ImGui for Godot Demo.sln ├── LICENSE ├── README.md ├── addons └── imgui-godot │ ├── ImGuiGodot │ ├── ImGuiController.cs │ ├── ImGuiExtensions.cs │ ├── ImGuiGD.cs │ ├── ImGuiLayer.cs │ ├── ImGuiSync.cs │ ├── Internal │ │ ├── BackendNative.cs │ │ ├── BackendNet.cs │ │ ├── CanvasRenderer.cs │ │ ├── DummyRenderer.cs │ │ ├── Fonts.cs │ │ ├── IBackend.cs │ │ ├── IRenderer.cs │ │ ├── Input.cs │ │ ├── InputLocal.cs │ │ ├── RdRenderer.cs │ │ ├── RdRendererThreadSafe.cs │ │ ├── State.cs │ │ ├── Util.cs │ │ └── Viewports.cs │ └── Widgets.cs │ ├── data │ ├── ImGuiRoot.tscn │ ├── ImGuiShader.glsl │ └── ImGuiShader.glsl.import │ ├── plugin.cfg │ └── scripts │ ├── ImGuiConfig.gd │ ├── ImGuiFont.gd │ ├── ImGuiPlugin.gd │ └── ImGuiRoot.gd ├── data ├── Hack-Regular.ttf ├── Hack-Regular.ttf.import ├── MPLUS2-Regular.ttf ├── MPLUS2-Regular.ttf.import ├── buttongroup.tres ├── default_env.tres ├── demo.tscn ├── demo2.tscn ├── gui_in_3d.tscn ├── gui_panel_3d.tscn ├── icon.svg ├── icon.svg.import ├── robot_eye.tres └── sample_config.tres ├── doc ├── .gdignore ├── examples │ ├── CSharpGameProject │ │ ├── CSharpGameProject.csproj │ │ ├── CSharpGameProject.sln │ │ ├── Globals.cs │ │ ├── Main.cs │ │ ├── README.md │ │ ├── Sprite.cs │ │ ├── addons.json │ │ ├── export_presets.cfg │ │ ├── icon.svg │ │ ├── icon.svg.import │ │ ├── main.tscn │ │ └── project.godot │ ├── GDExt │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── SConstruct │ │ ├── project │ │ │ ├── Hack-Bold.ttf │ │ │ ├── Hack-Bold.ttf.import │ │ │ ├── Hack-Italic.ttf │ │ │ ├── Hack-Italic.ttf.import │ │ │ ├── Hack-Regular.ttf │ │ │ ├── Hack-Regular.ttf.import │ │ │ ├── addons.json │ │ │ ├── example.gdextension │ │ │ ├── icon.svg │ │ │ ├── icon.svg.import │ │ │ ├── imgui_config.tres │ │ │ ├── main.tscn │ │ │ ├── project.godot │ │ │ └── robot_eye.tres │ │ └── src │ │ │ ├── example.cpp │ │ │ ├── example.h │ │ │ ├── gdmarkdown.cpp │ │ │ ├── gdmarkdown.h │ │ │ ├── register_types.cpp │ │ │ └── register_types.h │ ├── GdsDemo │ │ ├── README.md │ │ ├── addons.json │ │ ├── demo.gd │ │ ├── icon.svg │ │ ├── icon.svg.import │ │ ├── main.tscn │ │ └── project.godot │ ├── GdsGameProject │ │ ├── README.md │ │ ├── addons.json │ │ ├── export │ │ │ └── .gdignore │ │ ├── export_presets.cfg │ │ ├── icon.svg │ │ ├── icon.svg.import │ │ ├── main.gd │ │ ├── main.tscn │ │ ├── project.godot │ │ └── sprite.gd │ ├── Module │ │ ├── README.md │ │ ├── modules │ │ │ └── mymod │ │ │ │ ├── SCsub │ │ │ │ ├── config.py │ │ │ │ ├── mynode.cpp │ │ │ │ ├── mynode.h │ │ │ │ ├── register_types.cpp │ │ │ │ └── register_types.h │ │ └── project │ │ │ ├── addons.json │ │ │ ├── icon.svg │ │ │ ├── icon.svg.import │ │ │ ├── main.tscn │ │ │ └── project.godot │ ├── ToolCSharp │ │ ├── README.md │ │ ├── SpriteTool.cs │ │ ├── ToolCSharp.csproj │ │ ├── ToolCSharp.sln │ │ ├── addons.json │ │ ├── icon.svg │ │ ├── icon.svg.import │ │ ├── main.tscn │ │ └── project.godot │ └── ToolScript │ │ ├── README.md │ │ ├── addons.json │ │ ├── icon.svg │ │ ├── icon.svg.import │ │ ├── main.tscn │ │ ├── project.godot │ │ └── sprite_tool.gd ├── icon.png ├── screenshot.png └── test │ ├── addons │ └── TestData │ │ └── config_scale2x.tres │ ├── csbench │ ├── BenchCanvas.cs │ ├── BenchRid.cs │ ├── Program.cs │ ├── csbench.csproj │ └── csbench.sln │ ├── csharp │ ├── Main.cs │ ├── addons.json │ ├── export │ │ └── .gdignore │ ├── export_presets.cfg │ ├── icon.svg │ ├── icon.svg.import │ ├── main.tscn │ ├── project.godot │ ├── test.csproj │ └── test.sln │ └── gdscript │ ├── addons.json │ ├── export │ └── .gdignore │ ├── export_presets.cfg │ ├── icon.svg │ ├── icon.svg.import │ ├── main.gd │ ├── main.tscn │ ├── project.godot │ └── test_base.gd ├── export_presets.cfg ├── gdext ├── .gdignore ├── CMakeLists.txt ├── SConstruct ├── imgui-godot-native.gdextension ├── include │ ├── .gdignore │ ├── imconfig-godot.h │ └── imgui-godot.h ├── scripts │ ├── gds_bindings.py │ └── vcpkg-macos.sh ├── src │ ├── CMakeLists.txt │ ├── CanvasRenderer.cpp │ ├── CanvasRenderer.h │ ├── Context.cpp │ ├── Context.h │ ├── DummyRenderer.h │ ├── Fonts.cpp │ ├── Fonts.h │ ├── GdsCache.cpp │ ├── GdsCache.h │ ├── ImGuiAPI.cpp │ ├── ImGuiAPI.h │ ├── ImGuiController.cpp │ ├── ImGuiController.h │ ├── ImGuiControllerHelper.cpp │ ├── ImGuiControllerHelper.h │ ├── ImGuiGD.cpp │ ├── ImGuiGD.h │ ├── ImGuiLayer.cpp │ ├── ImGuiLayer.h │ ├── ImGuiSync.cpp │ ├── ImGuiSync.h │ ├── Input.cpp │ ├── Input.h │ ├── InputLocal.cpp │ ├── InputLocal.h │ ├── RdRenderer.cpp │ ├── RdRenderer.h │ ├── RdRendererThreadSafe.cpp │ ├── RdRendererThreadSafe.h │ ├── Renderer.h │ ├── Viewports.cpp │ ├── Viewports.h │ ├── common.h │ └── main.cpp └── vcpkg.json ├── project.godot └── src ├── MyNode.cs ├── MySecondNode.cs ├── ThirdNode.cs ├── ViewportArea.cs └── gui_3d.gd /.clang-format: -------------------------------------------------------------------------------- 1 | Language: Cpp 2 | BasedOnStyle: Microsoft 3 | AccessModifierOffset: -4 4 | AllowAllArgumentsOnNextLine: false 5 | AlignEscapedNewlines: Left 6 | AlwaysBreakTemplateDeclarations: Yes 7 | BinPackArguments: false 8 | BinPackParameters: true 9 | PointerAlignment: Left 10 | AllowShortFunctionsOnASingleLine: InlineOnly 11 | 12 | BreakBeforeBraces: Custom 13 | BraceWrapping: 14 | AfterNamespace: false 15 | AfterExternBlock: false 16 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | end_of_line = lf 9 | charset = utf-8 10 | 11 | [*.cs] 12 | csharp_style_var_when_type_is_apparent = true 13 | csharp_prefer_braces = when_multiline 14 | csharp_style_namespace_declarations = file_scoped 15 | dotnet_style_allow_multiple_blank_lines_experimental = false 16 | csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false 17 | 18 | dotnet_analyzer_diagnostic.severity = warning 19 | 20 | # don't add _ discards for return values 21 | dotnet_diagnostic.IDE0058.severity = none 22 | 23 | # don't change var to explicit type 24 | dotnet_diagnostic.IDE0008.severity = none 25 | 26 | # use expression bodies for methods: when i feel like it 27 | dotnet_diagnostic.IDE0022.severity = none 28 | 29 | # incomplete switch statements are fine 30 | dotnet_diagnostic.IDE0010.severity = none 31 | dotnet_diagnostic.IDE0072.severity = none 32 | 33 | dotnet_diagnostic.CA1805.severity = none 34 | dotnet_diagnostic.CA1051.severity = none 35 | dotnet_diagnostic.CA1001.severity = none 36 | dotnet_diagnostic.CA1725.severity = none 37 | dotnet_diagnostic.CA1707.severity = none 38 | dotnet_diagnostic.CA1711.severity = none 39 | 40 | # Roslynator 41 | dotnet_diagnostic.rcs0056.severity = warning 42 | roslynator_max_line_length = 100 43 | 44 | dotnet_diagnostic.rcs1194.severity = none 45 | dotnet_diagnostic.rcs1129.severity = none 46 | dotnet_diagnostic.rcs1061.severity = none 47 | dotnet_diagnostic.rcs1006.severity = none 48 | dotnet_diagnostic.rcs1141.severity = none 49 | dotnet_diagnostic.rcs1161.severity = none 50 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/actions/import/action.yml: -------------------------------------------------------------------------------- 1 | name: Import 2 | description: Import 3 | inputs: 4 | path: 5 | description: Path 6 | required: true 7 | 8 | runs: 9 | using: composite 10 | steps: 11 | - uses: actions/setup-dotnet@v4 12 | with: 13 | dotnet-version: 8.0.x 14 | 15 | - name: Install GodotEnv 16 | shell: bash 17 | run: | 18 | dotnet tool install --global Chickensoft.GodotEnv 19 | 20 | - name: Prep 21 | shell: bash 22 | run: | 23 | cd imgui-godot-* || true 24 | cd ${{ inputs.path }} 25 | godotenv addons install 26 | if [[ -f addons/imgui-godot/imgui-godot-native.gdextension ]]; then 27 | mkdir .godot 28 | echo "res://addons/imgui-godot/imgui-godot-native.gdextension" > .godot/extension_list.cfg 29 | fi 30 | $GODOT --headless --import || true 31 | echo "GAMEDIR=$(pwd)" >> $GITHUB_ENV 32 | -------------------------------------------------------------------------------- /.github/actions/run-test-project/action.yml: -------------------------------------------------------------------------------- 1 | name: Run test project 2 | description: Run test project 3 | inputs: 4 | exe: 5 | description: Executable 6 | required: true 7 | 8 | runs: 9 | using: composite 10 | steps: 11 | - name: Run tests 12 | shell: bash 13 | run: | 14 | cd $GAMEDIR 15 | $GODOT --headless --debug 16 | 17 | - name: Export debug 18 | shell: bash 19 | run: | 20 | cd $GAMEDIR 21 | $GODOT --headless --export-debug $RUNNER_OS 22 | cd export 23 | ./${{ inputs.exe }} --headless 24 | rm -rf * 25 | 26 | - name: Export release 27 | shell: bash 28 | run: | 29 | cd $GAMEDIR 30 | $GODOT --headless --export-release $RUNNER_OS 31 | cd export 32 | ./${{ inputs.exe }} --headless 33 | rm -rf * 34 | -------------------------------------------------------------------------------- /.github/workflows/dotnet.yml: -------------------------------------------------------------------------------- 1 | name: 🦖 .NET Checks 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - godot3 7 | pull_request: 8 | branches-ignore: 9 | - godot3 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | strategy: 15 | matrix: 16 | dotnet: ["8.0.x", "9.0.x"] 17 | 18 | name: .NET ${{ matrix.dotnet }} 19 | 20 | env: 21 | DemoProj: Dear ImGui for Godot Demo.csproj 22 | 23 | steps: 24 | - uses: actions/checkout@v4 25 | 26 | - name: Setup .NET 27 | uses: actions/setup-dotnet@v4 28 | with: 29 | dotnet-version: ${{ matrix.dotnet }} 30 | 31 | - name: Modify .editorconfig 32 | run: | 33 | sed -i "s:dotnet_analyzer_diagnostic.severity = warning:dotnet_analyzer_diagnostic.severity = error:" .editorconfig 34 | 35 | - name: Restore dependencies 36 | run: dotnet restore 37 | 38 | - name: Format 39 | run: dotnet format --no-restore --verify-no-changes --verbosity detailed "${{ env.DemoProj }}" || (dotnet format --no-restore "${{ env.DemoProj }}" && git diff --color && exit 1) 40 | 41 | - name: Build 42 | run: dotnet build --no-restore 43 | 44 | - name: Test 45 | run: dotnet test --no-build --verbosity normal 46 | -------------------------------------------------------------------------------- /.github/workflows/godot.yml: -------------------------------------------------------------------------------- 1 | name: 🤖 Godot Checks 2 | 3 | on: 4 | - push 5 | - pull_request 6 | 7 | jobs: 8 | test_csharp_only: 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | os: [ubuntu-latest, macos-latest, windows-latest] 13 | gdver: ["4.2.2", "4.3.0", "4.4.1", "4.5.0-dev.2"] 14 | include: 15 | - os: ubuntu-latest 16 | name: 🐧🧪C# Only 17 | exe: test.x86_64 18 | - os: macos-latest 19 | name: 🍎🧪C# Only 20 | exe: test.app/Contents/MacOS/test 21 | - os: windows-latest 22 | name: 🪟🧪C# Only 23 | exe: test.exe 24 | 25 | name: ${{ matrix.name }} (${{ matrix.gdver }}) 26 | runs-on: ${{ matrix.os }} 27 | steps: 28 | - uses: actions/checkout@v4 29 | 30 | - uses: chickensoft-games/setup-godot@v2 31 | with: 32 | version: ${{ matrix.gdver }} 33 | use-dotnet: true 34 | include-templates: true 35 | cache: false 36 | 37 | - name: Import 38 | uses: ./.github/actions/import 39 | with: 40 | path: doc/test/csharp 41 | 42 | - name: Build 43 | shell: bash 44 | run: | 45 | cd $GAMEDIR 46 | dotnet build 47 | 48 | - name: Run tests 49 | uses: ./.github/actions/run-test-project 50 | with: 51 | exe: ${{ matrix.exe }} 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .import/ 2 | .mono/ 3 | .vs/ 4 | .vscode/ 5 | *.old 6 | imgui.ini 7 | .godot/ 8 | *.user 9 | Properties/ 10 | build/ 11 | build.*/ 12 | msvc.*/ 13 | *.so 14 | *.dylib 15 | *.framework 16 | *.dll 17 | *.pdb 18 | doc/cpp-demo/MyGame/addons 19 | *.old.* 20 | gdext/vcpkg_installed/ 21 | .sconsign.dblite 22 | gdext/x64/ 23 | *.exp 24 | *.obj 25 | *.lib 26 | *.os 27 | gdext/proj/addons/imgui-godot-native/include/*.h 28 | gdext/gen/ 29 | *.o 30 | *.pyc 31 | gdext/proj/doc/ 32 | gdext/proj/modules/ 33 | gdext/proj/platform/ 34 | 35 | addons/imgui-godot-native/ 36 | gdext/proj/addons/imgui-godot/ 37 | gdext/samples/project/addons/ 38 | addons/imgui-godot/imgui-godot-native.gdextension 39 | addons/imgui-godot/include/ 40 | scons_cache 41 | doc/**/addons/ 42 | addons/imgui-godot/include/imgui-version.txt 43 | export/ 44 | **/bin/Debug/ 45 | **/bin/Release/ 46 | **/obj/ 47 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "gdext/dear_bindings"] 2 | path = gdext/dear_bindings 3 | url = https://github.com/dearimgui/dear_bindings 4 | [submodule "gdext/imgui"] 5 | path = gdext/imgui 6 | url = https://github.com/ocornut/imgui 7 | [submodule "gdext/godot-cpp"] 8 | path = gdext/godot-cpp 9 | url = https://github.com/godotengine/godot-cpp 10 | -------------------------------------------------------------------------------- /Dear ImGui for Godot Demo.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net8.0 4 | true 5 | DemoProject 6 | True 7 | enable 8 | 9 | 10 | True 11 | True 12 | 13 | 14 | True 15 | True 16 | 17 | 18 | True 19 | True 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | all 31 | runtime; build; native; contentfiles; analyzers; buildtransitive 32 | 33 | 34 | all 35 | runtime; build; native; contentfiles; analyzers; buildtransitive 36 | 37 | 38 | all 39 | runtime; build; native; contentfiles; analyzers; buildtransitive 40 | 41 | 42 | all 43 | runtime; build; native; contentfiles; analyzers; buildtransitive 44 | 45 | 46 | -------------------------------------------------------------------------------- /Dear ImGui for Godot Demo.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2012 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dear ImGui for Godot Demo", "Dear ImGui for Godot Demo.csproj", "{D939DAF9-46BC-4305-9D69-D920E185BDC7}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Any CPU = Debug|Any CPU 8 | ExportDebug|Any CPU = ExportDebug|Any CPU 9 | ExportRelease|Any CPU = ExportRelease|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {D939DAF9-46BC-4305-9D69-D920E185BDC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {D939DAF9-46BC-4305-9D69-D920E185BDC7}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {D939DAF9-46BC-4305-9D69-D920E185BDC7}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU 15 | {D939DAF9-46BC-4305-9D69-D920E185BDC7}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU 16 | {D939DAF9-46BC-4305-9D69-D920E185BDC7}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU 17 | {D939DAF9-46BC-4305-9D69-D920E185BDC7}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Patrick Dawson and contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /addons/imgui-godot/ImGuiGodot/ImGuiController.cs: -------------------------------------------------------------------------------- 1 | #if GODOT_PC 2 | #nullable enable 3 | using Godot; 4 | using ImGuiNET; 5 | 6 | namespace ImGuiGodot; 7 | 8 | public partial class ImGuiController : Node 9 | { 10 | private Window _window = null!; 11 | public static ImGuiController Instance { get; private set; } = null!; 12 | private ImGuiControllerHelper _helper = null!; 13 | public Node Signaler { get; private set; } = null!; 14 | private readonly StringName _signalName = "imgui_layout"; 15 | 16 | private sealed partial class ImGuiControllerHelper : Node 17 | { 18 | public override void _Ready() 19 | { 20 | Name = "ImGuiControllerHelper"; 21 | ProcessPriority = int.MinValue; 22 | ProcessMode = ProcessModeEnum.Always; 23 | } 24 | 25 | public override void _Process(double delta) 26 | { 27 | Internal.State.Instance.InProcessFrame = true; 28 | var vpSize = Internal.State.Instance.Layer.UpdateViewport(); 29 | Internal.State.Instance.Update(delta, new(vpSize.X, vpSize.Y)); 30 | } 31 | } 32 | 33 | public override void _EnterTree() 34 | { 35 | Instance = this; 36 | _window = GetWindow(); 37 | 38 | CheckContentScale(); 39 | 40 | string cfgPath = (string)ProjectSettings.GetSetting("addons/imgui/config", ""); 41 | Resource? cfg = null; 42 | if (ResourceLoader.Exists(cfgPath)) 43 | { 44 | cfg = ResourceLoader.Load(cfgPath); 45 | float scale = (float)cfg.Get("Scale"); 46 | bool cfgok = scale > 0.0f; 47 | 48 | if (!cfgok) 49 | { 50 | GD.PushError($"imgui-godot: config not a valid ImGuiConfig resource: {cfgPath}"); 51 | cfg = null; 52 | } 53 | } 54 | else if (cfgPath.Length > 0) 55 | { 56 | GD.PushError($"imgui-godot: config does not exist: {cfgPath}"); 57 | } 58 | 59 | Internal.State.Init(cfg ?? (Resource)((GDScript)GD.Load( 60 | "res://addons/imgui-godot/scripts/ImGuiConfig.gd")).New()); 61 | 62 | _helper = new ImGuiControllerHelper(); 63 | AddChild(_helper); 64 | 65 | Signaler = GetParent(); 66 | SetMainViewport(_window); 67 | } 68 | 69 | public override void _Ready() 70 | { 71 | ProcessPriority = int.MaxValue; 72 | ProcessMode = ProcessModeEnum.Always; 73 | } 74 | 75 | public override void _ExitTree() 76 | { 77 | Internal.State.Instance.Dispose(); 78 | } 79 | 80 | public override void _Process(double delta) 81 | { 82 | Signaler.EmitSignal(_signalName); 83 | Internal.State.Instance.Render(); 84 | Internal.State.Instance.InProcessFrame = false; 85 | } 86 | 87 | public override void _Notification(int what) 88 | { 89 | Internal.Input.ProcessNotification(what); 90 | } 91 | 92 | public void OnLayerExiting() 93 | { 94 | // an ImGuiLayer is being destroyed without calling SetMainViewport 95 | if (Internal.State.Instance.Layer.GetViewport() != _window) 96 | { 97 | // revert to main window 98 | SetMainViewport(_window); 99 | } 100 | } 101 | 102 | public void SetMainViewport(Viewport vp) 103 | { 104 | ImGuiLayer? oldLayer = Internal.State.Instance.Layer; 105 | if (oldLayer != null) 106 | { 107 | oldLayer.TreeExiting -= OnLayerExiting; 108 | oldLayer.QueueFree(); 109 | } 110 | 111 | var newLayer = new ImGuiLayer(); 112 | newLayer.TreeExiting += OnLayerExiting; 113 | 114 | if (vp is Window window) 115 | { 116 | Internal.State.Instance.Input = new Internal.Input(); 117 | if (window == _window) 118 | AddChild(newLayer); 119 | else 120 | window.AddChild(newLayer); 121 | ImGui.GetIO().BackendFlags |= ImGuiBackendFlags.PlatformHasViewports 122 | | ImGuiBackendFlags.HasMouseHoveredViewport; 123 | } 124 | else if (vp is SubViewport svp) 125 | { 126 | Internal.State.Instance.Input = new Internal.InputLocal(); 127 | svp.AddChild(newLayer); 128 | ImGui.GetIO().BackendFlags &= ~ImGuiBackendFlags.PlatformHasViewports; 129 | ImGui.GetIO().BackendFlags &= ~ImGuiBackendFlags.HasMouseHoveredViewport; 130 | } 131 | else 132 | { 133 | throw new System.ArgumentException("secret third kind of viewport??", nameof(vp)); 134 | } 135 | Internal.State.Instance.Layer = newLayer; 136 | } 137 | 138 | private void CheckContentScale() 139 | { 140 | if (_window.ContentScaleMode == Window.ContentScaleModeEnum.Viewport) 141 | { 142 | GD.PrintErr("imgui-godot: scale mode `viewport` is unsupported"); 143 | } 144 | } 145 | 146 | public static void WindowInputCallback(InputEvent evt) 147 | { 148 | Internal.State.Instance.Input.ProcessInput(evt); 149 | } 150 | } 151 | #endif 152 | -------------------------------------------------------------------------------- /addons/imgui-godot/ImGuiGodot/ImGuiExtensions.cs: -------------------------------------------------------------------------------- 1 | #if GODOT_PC 2 | using Godot; 3 | using ImGuiNET; 4 | using Vector3 = System.Numerics.Vector3; 5 | using Vector4 = System.Numerics.Vector4; 6 | 7 | namespace ImGuiGodot; 8 | 9 | public static class ImGuiExtensions 10 | { 11 | /// 12 | /// Extension method to translate between and 13 | /// 14 | public static ImGuiKey ToImGuiKey(this Key key) 15 | { 16 | return Internal.Input.ConvertKey(key); 17 | } 18 | 19 | /// 20 | /// Extension method to translate between and 21 | /// 22 | public static ImGuiKey ToImGuiKey(this JoyButton button) 23 | { 24 | return Internal.Input.ConvertJoyButton(button); 25 | } 26 | 27 | /// 28 | /// Convert to ImGui color RGBA 29 | /// 30 | public static Vector4 ToVector4(this Color color) 31 | { 32 | return new Vector4(color.R, color.G, color.B, color.A); 33 | } 34 | 35 | /// 36 | /// Convert to ImGui color RGB 37 | /// 38 | public static Vector3 ToVector3(this Color color) 39 | { 40 | return new Vector3(color.R, color.G, color.B); 41 | } 42 | 43 | /// 44 | /// Convert RGB to 45 | /// 46 | public static Color ToColor(this Vector3 vec) 47 | { 48 | return new Color(vec.X, vec.Y, vec.Z); 49 | } 50 | 51 | /// 52 | /// Convert RGBA to 53 | /// 54 | public static Color ToColor(this Vector4 vec) 55 | { 56 | return new Color(vec.X, vec.Y, vec.Z, vec.W); 57 | } 58 | 59 | /// 60 | /// Set IniFilename, converting Godot path to native 61 | /// 62 | public static void SetIniFilename(this ImGuiIOPtr io, string fileName) 63 | { 64 | _ = io; 65 | ImGuiGD.SetIniFilename(fileName); 66 | } 67 | } 68 | #endif 69 | -------------------------------------------------------------------------------- /addons/imgui-godot/ImGuiGodot/ImGuiGD.cs: -------------------------------------------------------------------------------- 1 | #if GODOT_PC 2 | #nullable enable 3 | using Godot; 4 | using System; 5 | 6 | namespace ImGuiGodot; 7 | 8 | public static partial class ImGuiGD 9 | { 10 | private static readonly Internal.IBackend _backend; 11 | 12 | /// 13 | /// Deadzone for all axes 14 | /// 15 | public static float JoyAxisDeadZone 16 | { 17 | get => _backend.JoyAxisDeadZone; 18 | set => _backend.JoyAxisDeadZone = value; 19 | } 20 | 21 | /// 22 | /// Setting this property will reload fonts and modify the ImGuiStyle. 23 | /// Can only be set outside of a process frame (eg, use CallDeferred) 24 | /// 25 | public static float Scale 26 | { 27 | get => _backend.Scale; 28 | set 29 | { 30 | if (_backend.Scale != value && value >= 0.25f) 31 | { 32 | _backend.Scale = value; 33 | RebuildFontAtlas(); 34 | } 35 | } 36 | } 37 | 38 | public static bool Visible 39 | { 40 | get => _backend.Visible; 41 | set => _backend.Visible = value; 42 | } 43 | 44 | static ImGuiGD() 45 | { 46 | _backend = ClassDB.ClassExists("ImGuiGD") 47 | ? new Internal.BackendNative() 48 | : new Internal.BackendNet(); 49 | } 50 | 51 | public static IntPtr BindTexture(Texture2D tex) 52 | { 53 | return (IntPtr)tex.GetRid().Id; 54 | } 55 | 56 | public static void ResetFonts() 57 | { 58 | _backend.ResetFonts(); 59 | } 60 | 61 | public static void AddFont( 62 | FontFile fontData, 63 | int fontSize, 64 | bool merge = false, 65 | ushort[]? glyphRanges = null) 66 | { 67 | _backend.AddFont(fontData, fontSize, merge, glyphRanges); 68 | } 69 | 70 | /// 71 | /// Add a font using glyph ranges from ImGui.GetIO().Fonts.GetGlyphRanges*() 72 | /// 73 | /// pointer to an array of ushorts terminated by 0 74 | public static unsafe void AddFont(FontFile fontData, int fontSize, bool merge, nint glyphRanges) 75 | { 76 | ushort* p = (ushort*)glyphRanges; 77 | int len = 1; 78 | while (p[len++] != 0) ; 79 | ushort[] gr = new ushort[len]; 80 | for (int i = 0; i < len; ++i) 81 | gr[i] = p[i]; 82 | _backend.AddFont(fontData, fontSize, merge, gr); 83 | } 84 | 85 | public static void AddFontDefault() 86 | { 87 | _backend.AddFontDefault(); 88 | } 89 | 90 | public static void RebuildFontAtlas() 91 | { 92 | _backend.RebuildFontAtlas(); 93 | } 94 | 95 | public static void Connect(Callable callable) 96 | { 97 | _backend.Connect(callable); 98 | } 99 | 100 | public static void Connect(Action action) 101 | { 102 | Connect(Callable.From(action)); 103 | } 104 | 105 | /// 106 | /// Changes the main viewport to either a new 107 | /// or a . 108 | /// 109 | public static void SetMainViewport(Viewport vp) 110 | { 111 | _backend.SetMainViewport(vp); 112 | } 113 | 114 | /// 115 | /// Must call from a tool script before doing anything else 116 | /// 117 | public static bool ToolInit() 118 | { 119 | if (_backend is Internal.BackendNative nbe) 120 | { 121 | nbe.ToolInit(); 122 | return true; 123 | } 124 | 125 | return false; 126 | } 127 | 128 | public static void SetIniFilename(string filename) 129 | { 130 | _backend.SetIniFilename(filename); 131 | } 132 | } 133 | #endif 134 | -------------------------------------------------------------------------------- /addons/imgui-godot/ImGuiGodot/ImGuiLayer.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | #if GODOT_PC 3 | #nullable enable 4 | 5 | namespace ImGuiGodot; 6 | 7 | public partial class ImGuiLayer : CanvasLayer 8 | { 9 | private Rid _subViewportRid; 10 | private Vector2I _subViewportSize = Vector2I.Zero; 11 | private Rid _canvasItem; 12 | private Transform2D _finalTransform = Transform2D.Identity; 13 | private bool _visible = true; 14 | private Viewport _parentViewport = null!; 15 | 16 | public override void _EnterTree() 17 | { 18 | Name = "ImGuiLayer"; 19 | Layer = Internal.State.Instance.LayerNum; 20 | 21 | _parentViewport = GetViewport(); 22 | _subViewportRid = AddLayerSubViewport(this); 23 | _canvasItem = RenderingServer.CanvasItemCreate(); 24 | RenderingServer.CanvasItemSetParent(_canvasItem, GetCanvas()); 25 | 26 | Internal.State.Instance.Renderer.InitViewport(_subViewportRid); 27 | Internal.State.Instance.Viewports.SetMainWindow(GetWindow(), _subViewportRid); 28 | } 29 | 30 | public override void _Ready() 31 | { 32 | VisibilityChanged += OnChangeVisibility; 33 | OnChangeVisibility(); 34 | } 35 | 36 | public override void _ExitTree() 37 | { 38 | RenderingServer.FreeRid(_canvasItem); 39 | RenderingServer.FreeRid(_subViewportRid); 40 | } 41 | 42 | private void OnChangeVisibility() 43 | { 44 | _visible = Visible; 45 | if (_visible) 46 | { 47 | SetProcessInput(true); 48 | } 49 | else 50 | { 51 | SetProcessInput(false); 52 | Internal.State.Instance.Renderer.OnHide(); 53 | _subViewportSize = Vector2I.Zero; 54 | RenderingServer.CanvasItemClear(_canvasItem); 55 | } 56 | } 57 | 58 | public override void _Input(InputEvent @event) 59 | { 60 | if (Internal.State.Instance.Input.ProcessInput(@event)) 61 | { 62 | _parentViewport.SetInputAsHandled(); 63 | } 64 | } 65 | 66 | public Vector2I UpdateViewport() 67 | { 68 | Vector2I vpSize = _parentViewport is Window w ? w.Size 69 | : (_parentViewport as SubViewport)?.Size 70 | ?? throw new System.InvalidOperationException(); 71 | 72 | if (_visible) 73 | { 74 | var ft = _parentViewport.GetFinalTransform(); 75 | if (_subViewportSize != vpSize || _finalTransform != ft) 76 | { 77 | // this is more or less how SubViewportContainer works 78 | _subViewportSize = vpSize; 79 | _finalTransform = ft; 80 | RenderingServer.ViewportSetSize( 81 | _subViewportRid, 82 | _subViewportSize.X, 83 | _subViewportSize.Y); 84 | Rid vptex = RenderingServer.ViewportGetTexture(_subViewportRid); 85 | RenderingServer.CanvasItemClear(_canvasItem); 86 | RenderingServer.CanvasItemSetTransform(_canvasItem, ft.AffineInverse()); 87 | RenderingServer.CanvasItemAddTextureRect( 88 | _canvasItem, 89 | new(0, 0, _subViewportSize.X, _subViewportSize.Y), 90 | vptex); 91 | } 92 | } 93 | 94 | return vpSize; 95 | } 96 | 97 | private static Rid AddLayerSubViewport(Node parent) 98 | { 99 | Rid svp = RenderingServer.ViewportCreate(); 100 | RenderingServer.ViewportSetTransparentBackground(svp, true); 101 | RenderingServer.ViewportSetUpdateMode(svp, RenderingServer.ViewportUpdateMode.Always); 102 | RenderingServer.ViewportSetClearMode(svp, RenderingServer.ViewportClearMode.Always); 103 | RenderingServer.ViewportSetActive(svp, true); 104 | RenderingServer.ViewportSetParentViewport(svp, parent.GetWindow().GetViewportRid()); 105 | return svp; 106 | } 107 | } 108 | #else 109 | namespace ImGuiNET 110 | { 111 | } 112 | 113 | namespace ImGuiGodot 114 | { 115 | } 116 | #endif 117 | -------------------------------------------------------------------------------- /addons/imgui-godot/ImGuiGodot/ImGuiSync.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | #if GODOT_PC 3 | using ImGuiNET; 4 | using System.Runtime.InteropServices; 5 | using System; 6 | 7 | namespace ImGuiGodot; 8 | 9 | public partial class ImGuiSync : GodotObject 10 | { 11 | public static readonly StringName GetImGuiPtrs = "GetImGuiPtrs"; 12 | 13 | public static void SyncPtrs() 14 | { 15 | GodotObject gd = Engine.GetSingleton("ImGuiGD"); 16 | long[] ptrs = (long[])gd.Call(GetImGuiPtrs, 17 | ImGui.GetVersion(), 18 | Marshal.SizeOf(), 19 | Marshal.SizeOf(), 20 | sizeof(ushort), 21 | sizeof(ushort) 22 | ); 23 | 24 | if (ptrs.Length != 3) 25 | { 26 | throw new NotSupportedException("ImGui version mismatch"); 27 | } 28 | 29 | checked 30 | { 31 | ImGui.SetCurrentContext((IntPtr)ptrs[0]); 32 | ImGui.SetAllocatorFunctions((IntPtr)ptrs[1], (IntPtr)ptrs[2]); 33 | } 34 | } 35 | } 36 | #endif 37 | -------------------------------------------------------------------------------- /addons/imgui-godot/ImGuiGodot/Internal/BackendNative.cs: -------------------------------------------------------------------------------- 1 | #if GODOT_PC 2 | #nullable enable 3 | using Godot; 4 | 5 | namespace ImGuiGodot.Internal; 6 | 7 | internal sealed class BackendNative : IBackend 8 | { 9 | private readonly GodotObject _gd = Engine.GetSingleton("ImGuiGD"); 10 | 11 | private sealed class MethodName 12 | { 13 | public static readonly StringName AddFont = "AddFont"; 14 | public static readonly StringName AddFontDefault = "AddFontDefault"; 15 | public static readonly StringName Connect = "Connect"; 16 | public static readonly StringName RebuildFontAtlas = "RebuildFontAtlas"; 17 | public static readonly StringName ResetFonts = "ResetFonts"; 18 | public static readonly StringName SetMainViewport = "SetMainViewport"; 19 | public static readonly StringName SubViewport = "SubViewport"; 20 | public static readonly StringName ToolInit = "ToolInit"; 21 | public static readonly StringName SetIniFilename = "SetIniFilename"; 22 | } 23 | 24 | private sealed class PropertyName 25 | { 26 | public static readonly StringName JoyAxisDeadZone = "JoyAxisDeadZone"; 27 | public static readonly StringName Scale = "Scale"; 28 | public static readonly StringName Visible = "Visible"; 29 | } 30 | 31 | public float JoyAxisDeadZone 32 | { 33 | get => (float)_gd.Get(PropertyName.JoyAxisDeadZone); 34 | set => _gd.Set(PropertyName.JoyAxisDeadZone, value); 35 | } 36 | 37 | public float Scale 38 | { 39 | get => (float)_gd.Get(PropertyName.Scale); 40 | set => _gd.Set(PropertyName.Scale, value); 41 | } 42 | 43 | public bool Visible 44 | { 45 | get => (bool)_gd.Get(PropertyName.Visible); 46 | set => _gd.Set(PropertyName.Visible, value); 47 | } 48 | 49 | public void AddFont(FontFile fontData, int fontSize, bool merge, ushort[]? glyphRanges) 50 | { 51 | if (glyphRanges != null) 52 | { 53 | int[] gr = new int[glyphRanges.Length]; 54 | for (int i = 0; i < glyphRanges.Length; ++i) 55 | gr[i] = glyphRanges[i]; 56 | _gd.Call(MethodName.AddFont, fontData, fontSize, merge, gr); 57 | } 58 | else 59 | { 60 | _gd.Call(MethodName.AddFont, fontData, fontSize, merge); 61 | } 62 | } 63 | 64 | public void AddFontDefault() 65 | { 66 | _gd.Call(MethodName.AddFontDefault); 67 | } 68 | 69 | public void Connect(Callable callable) 70 | { 71 | _gd.Call(MethodName.Connect, callable); 72 | } 73 | 74 | public void RebuildFontAtlas() 75 | { 76 | _gd.Call(MethodName.RebuildFontAtlas); 77 | } 78 | 79 | public void ResetFonts() 80 | { 81 | _gd.Call(MethodName.ResetFonts); 82 | } 83 | public void SetMainViewport(Viewport vp) 84 | { 85 | _gd.Call(MethodName.SetMainViewport, vp); 86 | } 87 | 88 | public bool SubViewportWidget(SubViewport svp) 89 | { 90 | return (bool)_gd.Call(MethodName.SubViewport, svp); 91 | } 92 | 93 | public void ToolInit() 94 | { 95 | _gd.Call(MethodName.ToolInit); 96 | ImGuiSync.SyncPtrs(); 97 | } 98 | 99 | public void SetIniFilename(string filename) 100 | { 101 | _gd.Call(MethodName.SetIniFilename, filename); 102 | } 103 | } 104 | #endif 105 | -------------------------------------------------------------------------------- /addons/imgui-godot/ImGuiGodot/Internal/BackendNet.cs: -------------------------------------------------------------------------------- 1 | #if GODOT_PC 2 | #nullable enable 3 | using Godot; 4 | using ImGuiNET; 5 | using System; 6 | using Vector2 = System.Numerics.Vector2; 7 | 8 | namespace ImGuiGodot.Internal; 9 | 10 | internal sealed class BackendNet : IBackend 11 | { 12 | public float JoyAxisDeadZone 13 | { 14 | get => State.Instance.JoyAxisDeadZone; 15 | set => State.Instance.JoyAxisDeadZone = value; 16 | } 17 | 18 | public float Scale 19 | { 20 | get => State.Instance.Scale; 21 | set => State.Instance.Scale = value; 22 | } 23 | 24 | public bool Visible 25 | { 26 | get => State.Instance.Layer.Visible; 27 | set => State.Instance.Layer.Visible = value; 28 | } 29 | 30 | public void AddFont(FontFile fontData, int fontSize, bool merge, ushort[]? glyphRanges) 31 | { 32 | State.Instance.Fonts.AddFont(fontData, fontSize, merge, glyphRanges); 33 | } 34 | 35 | public void AddFontDefault() 36 | { 37 | State.Instance.Fonts.AddFont(null, 13, false, null); 38 | } 39 | 40 | public void Connect(Callable callable) 41 | { 42 | ImGuiController.Instance?.Signaler.Connect("imgui_layout", callable); 43 | } 44 | 45 | public void RebuildFontAtlas() 46 | { 47 | if (State.Instance.InProcessFrame) 48 | throw new InvalidOperationException("fonts can't be changed during process"); 49 | 50 | bool scaleToDpi = (bool)ProjectSettings.GetSetting("display/window/dpi/allow_hidpi"); 51 | int dpiFactor = Math.Max(1, DisplayServer.ScreenGetDpi() / 96); 52 | State.Instance.Fonts.RebuildFontAtlas(scaleToDpi ? dpiFactor * Scale : Scale); 53 | } 54 | 55 | public void ResetFonts() 56 | { 57 | State.Instance.Fonts.ResetFonts(); 58 | } 59 | 60 | public void SetIniFilename(string filename) 61 | { 62 | State.Instance.SetIniFilename(filename); 63 | } 64 | 65 | public void SetMainViewport(Viewport vp) 66 | { 67 | ImGuiController.Instance.SetMainViewport(vp); 68 | } 69 | 70 | public bool SubViewportWidget(SubViewport svp) 71 | { 72 | Vector2 vpSize = new(svp.Size.X, svp.Size.Y); 73 | var pos = ImGui.GetCursorScreenPos(); 74 | var pos_max = new Vector2(pos.X + vpSize.X, pos.Y + vpSize.Y); 75 | ImGui.GetWindowDrawList().AddImage((IntPtr)svp.GetTexture().GetRid().Id, pos, pos_max); 76 | 77 | ImGui.PushID(svp.NativeInstance); 78 | ImGui.InvisibleButton("godot_subviewport", vpSize); 79 | ImGui.PopID(); 80 | 81 | if (ImGui.IsItemHovered()) 82 | { 83 | State.Instance.Input.CurrentSubViewport = svp; 84 | State.Instance.Input.CurrentSubViewportPos = pos; 85 | return true; 86 | } 87 | return false; 88 | } 89 | } 90 | #endif 91 | -------------------------------------------------------------------------------- /addons/imgui-godot/ImGuiGodot/Internal/DummyRenderer.cs: -------------------------------------------------------------------------------- 1 | #if GODOT_PC 2 | using Godot; 3 | 4 | namespace ImGuiGodot.Internal; 5 | 6 | internal sealed class DummyRenderer : IRenderer 7 | { 8 | public string Name => "godot4_net_dummy"; 9 | 10 | public void InitViewport(Rid vprid) 11 | { 12 | } 13 | 14 | public void CloseViewport(Rid vprid) 15 | { 16 | } 17 | 18 | public void OnHide() 19 | { 20 | } 21 | 22 | public void Render() 23 | { 24 | } 25 | 26 | public void Dispose() 27 | { 28 | } 29 | } 30 | #endif 31 | -------------------------------------------------------------------------------- /addons/imgui-godot/ImGuiGodot/Internal/IBackend.cs: -------------------------------------------------------------------------------- 1 | #if GODOT_PC 2 | #nullable enable 3 | using Godot; 4 | 5 | namespace ImGuiGodot.Internal; 6 | 7 | internal interface IBackend 8 | { 9 | bool Visible { get; set; } 10 | float JoyAxisDeadZone { get; set; } 11 | float Scale { get; set; } 12 | void ResetFonts(); 13 | void AddFont(FontFile fontData, int fontSize, bool merge, ushort[]? glyphRanges); 14 | void AddFontDefault(); 15 | void RebuildFontAtlas(); 16 | void Connect(Callable callable); 17 | void SetMainViewport(Viewport vp); 18 | bool SubViewportWidget(SubViewport svp); 19 | void SetIniFilename(string filename); 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /addons/imgui-godot/ImGuiGodot/Internal/IRenderer.cs: -------------------------------------------------------------------------------- 1 | #if GODOT_PC 2 | using Godot; 3 | using System; 4 | 5 | namespace ImGuiGodot.Internal; 6 | 7 | internal interface IRenderer : IDisposable 8 | { 9 | string Name { get; } 10 | void InitViewport(Rid vprid); 11 | void CloseViewport(Rid vprid); 12 | void Render(); 13 | void OnHide(); 14 | } 15 | #endif 16 | -------------------------------------------------------------------------------- /addons/imgui-godot/ImGuiGodot/Internal/InputLocal.cs: -------------------------------------------------------------------------------- 1 | #if GODOT_PC 2 | using Godot; 3 | using ImGuiNET; 4 | 5 | namespace ImGuiGodot.Internal; 6 | 7 | internal sealed class InputLocal : Input 8 | { 9 | protected override void UpdateMousePos(ImGuiIOPtr io) 10 | { 11 | // do not use global mouse position 12 | } 13 | 14 | public override bool ProcessInput(InputEvent evt) 15 | { 16 | // no support for SubViewport widgets 17 | 18 | if (evt is InputEventMouseMotion mm) 19 | { 20 | var io = ImGui.GetIO(); 21 | var mousePos = mm.Position; 22 | #pragma warning disable IDE0004 // Remove Unnecessary Cast 23 | io.AddMousePosEvent((float)mousePos.X, (float)mousePos.Y); 24 | #pragma warning restore IDE0004 // Remove Unnecessary Cast 25 | mm.Dispose(); 26 | return io.WantCaptureMouse; 27 | } 28 | return HandleEvent(evt); 29 | } 30 | } 31 | #endif 32 | -------------------------------------------------------------------------------- /addons/imgui-godot/ImGuiGodot/Internal/Util.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace ImGuiGodot.Internal; 5 | 6 | internal static class Util 7 | { 8 | [UnsafeAccessor(UnsafeAccessorKind.Constructor)] 9 | public static extern Rid ConstructRid(ulong id); 10 | } 11 | -------------------------------------------------------------------------------- /addons/imgui-godot/data/ImGuiRoot.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://dugmpnsxaagba"] 2 | 3 | [ext_resource type="Script" path="res://addons/imgui-godot/scripts/ImGuiRoot.gd" id="1_lney5"] 4 | 5 | [node name="ImGuiRoot" type="Node"] 6 | script = ExtResource("1_lney5") 7 | -------------------------------------------------------------------------------- /addons/imgui-godot/data/ImGuiShader.glsl: -------------------------------------------------------------------------------- 1 | // shader source borrowed from imgui_impl_vulkan.cpp 2 | 3 | #[vertex] 4 | #version 450 core 5 | layout(location = 0) in vec2 aPos; 6 | layout(location = 1) in vec2 aUV; 7 | layout(location = 2) in vec4 aColor; 8 | layout(push_constant) uniform uPushConstant { vec2 uScale; vec2 uTranslate; } pc; 9 | 10 | out gl_PerVertex { vec4 gl_Position; }; 11 | layout(location = 0) out struct { vec4 Color; vec2 UV; } Out; 12 | 13 | void main() 14 | { 15 | Out.Color = aColor; 16 | Out.UV = aUV; 17 | gl_Position = vec4(aPos * pc.uScale + pc.uTranslate, 0, 1); 18 | } 19 | 20 | #[fragment] 21 | #version 450 core 22 | layout(location = 0) out vec4 fColor; 23 | layout(set=0, binding=0) uniform sampler2D sTexture; 24 | layout(location = 0) in struct { vec4 Color; vec2 UV; } In; 25 | 26 | void main() 27 | { 28 | fColor = In.Color * texture(sTexture, In.UV.st); 29 | } 30 | -------------------------------------------------------------------------------- /addons/imgui-godot/data/ImGuiShader.glsl.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="glsl" 4 | type="RDShaderFile" 5 | uid="uid://belucuvjtb04o" 6 | path="res://.godot/imported/ImGuiShader.glsl-2f8c9595e5031ef8022ed7e6f565729e.res" 7 | 8 | [deps] 9 | 10 | source_file="res://addons/imgui-godot/data/ImGuiShader.glsl" 11 | dest_files=["res://.godot/imported/ImGuiShader.glsl-2f8c9595e5031ef8022ed7e6f565729e.res"] 12 | 13 | [params] 14 | 15 | -------------------------------------------------------------------------------- /addons/imgui-godot/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="imgui-godot" 4 | description="Dear ImGui for Godot" 5 | author="Patrick Dawson" 6 | version="6.3.2" 7 | script="scripts/ImGuiPlugin.gd" 8 | -------------------------------------------------------------------------------- /addons/imgui-godot/scripts/ImGuiConfig.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | class_name ImGuiConfig extends Resource 3 | 4 | @export_range(0.25, 4.0, 0.001, "or_greater") var Scale: float = 1.0 5 | @export var IniFilename: String = "user://imgui.ini" 6 | @export_enum("RenderingDevice", "Canvas", "Dummy") var Renderer: String = "RenderingDevice" 7 | @export_range(-128, 128) var Layer: int = 128 8 | 9 | @export_category("Font Settings") 10 | #@export var Fonts: Array[ImGuiFont] 11 | @export var AddDefaultFont: bool = true 12 | 13 | # HACK: workaround for intermittent Godot bug 14 | var _fonts: Array 15 | 16 | func _get_property_list() -> Array[Dictionary]: 17 | return [ 18 | { 19 | "name": "Fonts", 20 | "class_name": &"", 21 | "type": TYPE_ARRAY, 22 | "hint": PROPERTY_HINT_TYPE_STRING, 23 | "hint_string": "24/17:ImGuiFont", 24 | "usage": PROPERTY_USAGE_SCRIPT_VARIABLE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE 25 | } 26 | ] 27 | 28 | func _get(property: StringName) -> Variant: 29 | if property == &"Fonts": 30 | return _fonts 31 | return null 32 | 33 | func _set(property: StringName, value: Variant) -> bool: 34 | if property == &"Fonts": 35 | _fonts = value 36 | return true 37 | return false 38 | -------------------------------------------------------------------------------- /addons/imgui-godot/scripts/ImGuiFont.gd: -------------------------------------------------------------------------------- 1 | class_name ImGuiFont extends Resource 2 | 3 | @export var FontData: FontFile 4 | @export var FontSize: int = 16 5 | @export var Merge: bool = true 6 | -------------------------------------------------------------------------------- /addons/imgui-godot/scripts/ImGuiRoot.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | signal imgui_layout 4 | 5 | const csharp_controller := "res://addons/imgui-godot/ImGuiGodot/ImGuiController.cs" 6 | const csharp_sync := "res://addons/imgui-godot/ImGuiGodot/ImGuiSync.cs" 7 | 8 | func _enter_tree(): 9 | var has_csharp := false 10 | if ClassDB.class_exists("CSharpScript"): 11 | var script := load(csharp_sync) 12 | has_csharp = script.get_instance_base_type() == "Object" 13 | 14 | if ClassDB.class_exists("ImGuiController"): 15 | # native 16 | add_child(ClassDB.instantiate("ImGuiController")) 17 | if has_csharp: 18 | var obj: Object = load(csharp_sync).new() 19 | obj.SyncPtrs() 20 | obj.free() 21 | else: 22 | # C# only 23 | if has_csharp: 24 | add_child(load(csharp_controller).new()) 25 | -------------------------------------------------------------------------------- /data/Hack-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkdawson/imgui-godot/8a9f0c423533e22a8fa156c5f7c79877c01f437d/data/Hack-Regular.ttf -------------------------------------------------------------------------------- /data/Hack-Regular.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://c2o4vx2jik43e" 6 | path="res://.godot/imported/Hack-Regular.ttf-3d6007156cf38336f0685ad871feaf05.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://data/Hack-Regular.ttf" 11 | dest_files=["res://.godot/imported/Hack-Regular.ttf-3d6007156cf38336f0685ad871feaf05.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /data/MPLUS2-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkdawson/imgui-godot/8a9f0c423533e22a8fa156c5f7c79877c01f437d/data/MPLUS2-Regular.ttf -------------------------------------------------------------------------------- /data/MPLUS2-Regular.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://bk0s2hduow46m" 6 | path="res://.godot/imported/MPLUS2-Regular.ttf-7fe86ccd65e167ffa0da418b024bf3c5.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://data/MPLUS2-Regular.ttf" 11 | dest_files=["res://.godot/imported/MPLUS2-Regular.ttf-7fe86ccd65e167ffa0da418b024bf3c5.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /data/buttongroup.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="ButtonGroup" format=3 uid="uid://ucf261yyiwkq"] 2 | 3 | [resource] 4 | -------------------------------------------------------------------------------- /data/default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=2] 2 | 3 | [sub_resource type="Sky" id=1] 4 | 5 | [resource] 6 | background_mode = 2 7 | background_sky = SubResource( 1 ) 8 | -------------------------------------------------------------------------------- /data/demo.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://sdgew7sm2686"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://2cvgmt2fmpao" path="res://data/icon.svg" id="1_c7hdb"] 4 | [ext_resource type="FontFile" uid="uid://c2o4vx2jik43e" path="res://data/Hack-Regular.ttf" id="3_fjiyg"] 5 | [ext_resource type="Script" path="res://src/MyNode.cs" id="3_qvd0t"] 6 | [ext_resource type="ButtonGroup" uid="uid://ucf261yyiwkq" path="res://data/buttongroup.tres" id="4_7oj01"] 7 | 8 | [node name="Control" type="Control"] 9 | layout_mode = 3 10 | anchors_preset = 15 11 | anchor_right = 1.0 12 | anchor_bottom = 1.0 13 | grow_horizontal = 2 14 | grow_vertical = 2 15 | 16 | [node name="MyNode" type="Node" parent="."] 17 | script = ExtResource("3_qvd0t") 18 | 19 | [node name="TextureRect" type="TextureRect" parent="."] 20 | layout_mode = 1 21 | anchors_preset = 8 22 | anchor_left = 0.5 23 | anchor_top = 0.5 24 | anchor_right = 0.5 25 | anchor_bottom = 0.5 26 | offset_left = -128.0 27 | offset_top = -128.0 28 | offset_right = 128.0 29 | offset_bottom = 128.0 30 | grow_horizontal = 2 31 | grow_vertical = 2 32 | texture = ExtResource("1_c7hdb") 33 | 34 | [node name="PanelContainer" type="PanelContainer" parent="."] 35 | layout_mode = 1 36 | anchors_preset = 2 37 | anchor_top = 1.0 38 | anchor_bottom = 1.0 39 | offset_top = -143.0 40 | offset_right = 256.0 41 | grow_vertical = 0 42 | 43 | [node name="CenterContainer" type="CenterContainer" parent="PanelContainer"] 44 | layout_mode = 2 45 | 46 | [node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/CenterContainer"] 47 | layout_mode = 2 48 | 49 | [node name="Label" type="Label" parent="PanelContainer/CenterContainer/VBoxContainer"] 50 | layout_mode = 2 51 | text = "Content scale mode" 52 | horizontal_alignment = 1 53 | 54 | [node name="ButtonCIE" type="Button" parent="PanelContainer/CenterContainer/VBoxContainer"] 55 | layout_mode = 2 56 | focus_mode = 0 57 | toggle_mode = true 58 | button_pressed = true 59 | button_group = ExtResource("4_7oj01") 60 | text = "canvas_items/expand" 61 | 62 | [node name="ButtonD" type="Button" parent="PanelContainer/CenterContainer/VBoxContainer"] 63 | layout_mode = 2 64 | focus_mode = 0 65 | toggle_mode = true 66 | button_group = ExtResource("4_7oj01") 67 | text = "disabled" 68 | 69 | [node name="CanvasLayer" type="CanvasLayer" parent="."] 70 | layer = 120 71 | 72 | [node name="TextureRect2" type="TextureRect" parent="CanvasLayer"] 73 | anchors_preset = 3 74 | anchor_left = 1.0 75 | anchor_top = 1.0 76 | anchor_right = 1.0 77 | anchor_bottom = 1.0 78 | offset_left = -64.0 79 | offset_top = -64.0 80 | grow_horizontal = 0 81 | grow_vertical = 0 82 | texture = ExtResource("1_c7hdb") 83 | expand_mode = 1 84 | 85 | [node name="CenterContainer" type="CenterContainer" parent="."] 86 | layout_mode = 0 87 | offset_right = 209.0 88 | offset_bottom = 173.0 89 | 90 | [node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"] 91 | custom_minimum_size = Vector2(180, 0) 92 | layout_mode = 2 93 | 94 | [node name="Button1" type="Button" parent="CenterContainer/VBoxContainer"] 95 | unique_name_in_owner = true 96 | layout_mode = 2 97 | focus_mode = 0 98 | theme_override_fonts/font = ExtResource("3_fjiyg") 99 | theme_override_font_sizes/font_size = 24 100 | text = "Widgets" 101 | 102 | [node name="Button2" type="Button" parent="CenterContainer/VBoxContainer"] 103 | unique_name_in_owner = true 104 | layout_mode = 2 105 | focus_mode = 0 106 | theme_override_fonts/font = ExtResource("3_fjiyg") 107 | theme_override_font_sizes/font_size = 24 108 | text = "New Window" 109 | 110 | [node name="Button3" type="Button" parent="CenterContainer/VBoxContainer"] 111 | unique_name_in_owner = true 112 | layout_mode = 2 113 | focus_mode = 0 114 | theme_override_fonts/font = ExtResource("3_fjiyg") 115 | theme_override_font_sizes/font_size = 24 116 | text = "3D Scene" 117 | 118 | [node name="CheckBox" type="CheckBox" parent="CenterContainer/VBoxContainer"] 119 | unique_name_in_owner = true 120 | layout_mode = 2 121 | focus_mode = 0 122 | text = "ImGui Viewports" 123 | 124 | [connection signal="pressed" from="PanelContainer/CenterContainer/VBoxContainer/ButtonCIE" to="MyNode" method="OnContentScaleCIE"] 125 | [connection signal="pressed" from="PanelContainer/CenterContainer/VBoxContainer/ButtonD" to="MyNode" method="OnContentScaleDisabled"] 126 | -------------------------------------------------------------------------------- /data/demo2.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=3 uid="uid://dr8hy6iu5hk8a"] 2 | 3 | [ext_resource type="Script" path="res://src/ViewportArea.cs" id="2_btjlu"] 4 | [ext_resource type="Script" path="res://src/MySecondNode.cs" id="2_gnjei"] 5 | 6 | [sub_resource type="PlaneMesh" id="PlaneMesh_dsg5q"] 7 | size = Vector2(250, 250) 8 | 9 | [sub_resource type="CylinderMesh" id="CylinderMesh_kek8d"] 10 | top_radius = 2.0 11 | bottom_radius = 10.0 12 | height = 30.0 13 | 14 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_eanfn"] 15 | albedo_color = Color(0.615686, 0.556863, 0.968627, 1) 16 | 17 | [sub_resource type="BoxShape3D" id="BoxShape3D_6s853"] 18 | size = Vector3(230, 1, 230) 19 | 20 | [node name="Background" type="ColorRect"] 21 | anchors_preset = 15 22 | anchor_right = 1.0 23 | anchor_bottom = 1.0 24 | grow_horizontal = 2 25 | grow_vertical = 2 26 | color = Color(0.0784314, 0, 0.117647, 1) 27 | 28 | [node name="MySecondNode" type="Node" parent="."] 29 | script = ExtResource("2_gnjei") 30 | 31 | [node name="ShowHideButton" type="Button" parent="."] 32 | unique_name_in_owner = true 33 | layout_mode = 1 34 | anchors_preset = 3 35 | anchor_left = 1.0 36 | anchor_top = 1.0 37 | anchor_right = 1.0 38 | anchor_bottom = 1.0 39 | offset_left = -96.0 40 | offset_top = -48.0 41 | offset_right = -7.0 42 | offset_bottom = -8.0 43 | grow_horizontal = 0 44 | grow_vertical = 0 45 | focus_mode = 0 46 | toggle_mode = true 47 | text = "hide" 48 | 49 | [node name="SubViewport" type="SubViewport" parent="."] 50 | unique_name_in_owner = true 51 | physics_object_picking = true 52 | render_target_update_mode = 4 53 | 54 | [node name="Board" type="MeshInstance3D" parent="SubViewport"] 55 | unique_name_in_owner = true 56 | mesh = SubResource("PlaneMesh_dsg5q") 57 | 58 | [node name="Piece" type="MeshInstance3D" parent="SubViewport"] 59 | unique_name_in_owner = true 60 | layers = 2 61 | mesh = SubResource("CylinderMesh_kek8d") 62 | surface_material_override/0 = SubResource("StandardMaterial3D_eanfn") 63 | 64 | [node name="Camera3d" type="Camera3D" parent="SubViewport"] 65 | transform = Transform3D(1, 0, 0, 0, 0.422618, 0.906308, 0, -0.906308, 0.422618, 0, 150, 100) 66 | current = true 67 | 68 | [node name="Area3d" type="Area3D" parent="SubViewport"] 69 | script = ExtResource("2_btjlu") 70 | 71 | [node name="CollisionShape3d" type="CollisionShape3D" parent="SubViewport/Area3d"] 72 | shape = SubResource("BoxShape3D_6s853") 73 | -------------------------------------------------------------------------------- /data/gui_in_3d.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=12 format=3 uid="uid://0iek6ri88gkb"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://dvl383ispakmn" path="res://data/gui_panel_3d.tscn" id="1"] 4 | [ext_resource type="Script" path="res://src/ThirdNode.cs" id="2_xsiun"] 5 | 6 | [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_1lgdv"] 7 | sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) 8 | ground_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) 9 | 10 | [sub_resource type="Sky" id="Sky_pq42j"] 11 | sky_material = SubResource("ProceduralSkyMaterial_1lgdv") 12 | 13 | [sub_resource type="Environment" id="Environment_niyks"] 14 | background_mode = 2 15 | sky = SubResource("Sky_pq42j") 16 | tonemap_mode = 2 17 | tonemap_white = 2.0 18 | 19 | [sub_resource type="Animation" id="1"] 20 | length = 6.0 21 | loop_mode = 1 22 | tracks/0/type = "value" 23 | tracks/0/imported = false 24 | tracks/0/enabled = true 25 | tracks/0/path = NodePath("Camera3D:transform") 26 | tracks/0/interp = 1 27 | tracks/0/loop_wrap = true 28 | tracks/0/keys = { 29 | "times": PackedFloat32Array(0, 2, 4, 6), 30 | "transitions": PackedFloat32Array(-2, -2, -2, -2), 31 | "update": 0, 32 | "values": [Transform3D(0.994592, 0, 0.103856, 0, 1, 0, -0.103856, 0, 0.994592, 0.465682, 0, 1.78523), Transform3D(0.962984, 0, -0.269557, 0, 1, 0, 0.269557, 0, 0.962984, -0.462237, 0, 2.41934), Transform3D(0.806599, 0, -0.591098, 0, 1, 0, 0.591098, 0, 0.806599, -1.59502, 0, 2.05358), Transform3D(0.994592, 0, 0.103856, 0, 1, 0, -0.103856, 0, 0.994592, 0.465682, 0, 1.78523)] 33 | } 34 | 35 | [sub_resource type="AnimationLibrary" id="AnimationLibrary_uw4n0"] 36 | _data = { 37 | "Move_camera": SubResource("1") 38 | } 39 | 40 | [sub_resource type="PlaneMesh" id="2"] 41 | 42 | [sub_resource type="BoxMesh" id="3"] 43 | 44 | [sub_resource type="StandardMaterial3D" id="4"] 45 | albedo_color = Color(0.722656, 0.791992, 1, 1) 46 | roughness = 0.0 47 | 48 | [sub_resource type="SphereMesh" id="SphereMesh_ecs3k"] 49 | 50 | [node name="GUIin3D" type="Node3D"] 51 | 52 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] 53 | transform = Transform3D(-0.866023, -0.433016, 0.250001, 0, 0.499998, 0.866027, -0.500003, 0.749999, -0.43301, 0, 0, 0) 54 | visible = false 55 | shadow_enabled = true 56 | 57 | [node name="WorldEnvironment" type="WorldEnvironment" parent="."] 58 | environment = SubResource("Environment_niyks") 59 | 60 | [node name="GUIPanel3D" parent="." instance=ExtResource("1")] 61 | 62 | [node name="Camera3D" type="Camera3D" parent="."] 63 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 0.999999, 0, 0, 3) 64 | fov = 74.0 65 | near = 0.1 66 | 67 | [node name="OmniLight3D" type="OmniLight3D" parent="."] 68 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.38866, 1.2413, 2.72141) 69 | shadow_enabled = true 70 | shadow_blur = 3.0 71 | omni_range = 10.0 72 | 73 | [node name="Camera_Move" type="AnimationPlayer" parent="."] 74 | libraries = { 75 | "": SubResource("AnimationLibrary_uw4n0") 76 | } 77 | autoplay = "Move_camera" 78 | 79 | [node name="Background" type="Node3D" parent="."] 80 | 81 | [node name="Wall" type="MeshInstance3D" parent="Background"] 82 | transform = Transform3D(4, 0, 0, 0, -1.74846e-07, -4, 0, 4, -1.74846e-07, -2.60819, 0.589247, -2.08943) 83 | mesh = SubResource("2") 84 | 85 | [node name="Wall2" type="MeshInstance3D" parent="Background"] 86 | transform = Transform3D(4, 0, 0, 0, -1.74846e-07, -4, 0, 4, -1.74846e-07, 5.08055, 0.589247, -2.08943) 87 | mesh = SubResource("2") 88 | 89 | [node name="Wall3" type="MeshInstance3D" parent="Background"] 90 | transform = Transform3D(-1.74846e-07, -4, 0, -1.74846e-07, 7.64274e-15, -4, 4, -1.74846e-07, -1.74846e-07, 9.04446, 0.589247, 1.62058) 91 | mesh = SubResource("2") 92 | 93 | [node name="Floor" type="MeshInstance3D" parent="Background"] 94 | transform = Transform3D(4, 0, 0, 0, 4, 0, 0, 0, 4, -2.60819, -2.68765, 1.46502) 95 | mesh = SubResource("2") 96 | 97 | [node name="Floor2" type="MeshInstance3D" parent="Background"] 98 | transform = Transform3D(4, 0, 0, 0, 4, 0, 0, 0, 4, 5.08055, -2.68765, 1.46502) 99 | mesh = SubResource("2") 100 | 101 | [node name="Cube" type="MeshInstance3D" parent="Background"] 102 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.25901, -0.598608, 0.374871) 103 | mesh = SubResource("3") 104 | surface_material_override/0 = SubResource("4") 105 | 106 | [node name="Sphere" type="MeshInstance3D" parent="Background"] 107 | transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 2.88761, 2.01326, 0.374871) 108 | mesh = SubResource("SphereMesh_ecs3k") 109 | surface_material_override/0 = SubResource("4") 110 | 111 | [node name="ThirdNode" type="Node" parent="."] 112 | script = ExtResource("2_xsiun") 113 | -------------------------------------------------------------------------------- /data/gui_panel_3d.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://dvl383ispakmn"] 2 | 3 | [ext_resource type="Script" path="res://src/gui_3d.gd" id="1_lsoqm"] 4 | 5 | [sub_resource type="QuadMesh" id="1"] 6 | size = Vector2(3, 2) 7 | 8 | [sub_resource type="ViewportTexture" id="2"] 9 | viewport_path = NodePath("SubViewport") 10 | 11 | [sub_resource type="StandardMaterial3D" id="3"] 12 | resource_local_to_scene = true 13 | transparency = 1 14 | shading_mode = 0 15 | albedo_texture = SubResource("2") 16 | 17 | [sub_resource type="BoxShape3D" id="4"] 18 | size = Vector3(3, 2, 0.1) 19 | 20 | [node name="GUIPanel3D" type="Node3D"] 21 | process_mode = 3 22 | script = ExtResource("1_lsoqm") 23 | 24 | [node name="SubViewport" type="SubViewport" parent="."] 25 | gui_embed_subwindows = true 26 | size = Vector2i(560, 360) 27 | render_target_update_mode = 4 28 | 29 | [node name="GUI" type="Control" parent="SubViewport"] 30 | layout_mode = 3 31 | anchors_preset = 0 32 | offset_right = 560.0 33 | offset_bottom = 360.0 34 | mouse_filter = 1 35 | 36 | [node name="Panel" type="Panel" parent="SubViewport/GUI"] 37 | layout_mode = 0 38 | anchor_right = 1.0 39 | anchor_bottom = 1.0 40 | 41 | [node name="VBoxContainer" type="VBoxContainer" parent="SubViewport/GUI/Panel"] 42 | layout_mode = 1 43 | anchors_preset = 9 44 | anchor_bottom = 1.0 45 | offset_left = 20.0 46 | offset_top = 20.0 47 | offset_right = 319.0 48 | offset_bottom = -20.0 49 | grow_vertical = 2 50 | theme_override_constants/separation = 13 51 | 52 | [node name="Label" type="Label" parent="SubViewport/GUI/Panel/VBoxContainer"] 53 | layout_mode = 2 54 | text = "Hello world!" 55 | horizontal_alignment = 1 56 | 57 | [node name="Quad" type="MeshInstance3D" parent="."] 58 | mesh = SubResource("1") 59 | surface_material_override/0 = SubResource("3") 60 | 61 | [node name="Area3D" type="Area3D" parent="Quad"] 62 | collision_layer = 2 63 | input_capture_on_drag = true 64 | 65 | [node name="CollisionShape3D" type="CollisionShape3D" parent="Quad/Area3D"] 66 | shape = SubResource("4") 67 | -------------------------------------------------------------------------------- /data/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /data/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://2cvgmt2fmpao" 6 | path="res://.godot/imported/icon.svg-7967cc08d22e46b525e9855c7e0ca0ca.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://data/icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-7967cc08d22e46b525e9855c7e0ca0ca.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=true 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=4.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /data/robot_eye.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://cqelg04ohkgm5"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://2cvgmt2fmpao" path="res://data/icon.svg" id="1_ofydq"] 4 | 5 | [resource] 6 | atlas = ExtResource("1_ofydq") 7 | region = Rect2(142, 228, 64, 64) 8 | -------------------------------------------------------------------------------- /data/sample_config.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="ImGuiConfig" load_steps=7 format=3 uid="uid://bm0qxspuntbpl"] 2 | 3 | [ext_resource type="FontFile" uid="uid://c2o4vx2jik43e" path="res://data/Hack-Regular.ttf" id="1_0g12f"] 4 | [ext_resource type="Script" path="res://addons/imgui-godot/scripts/ImGuiConfig.gd" id="1_n8f18"] 5 | [ext_resource type="Script" path="res://addons/imgui-godot/scripts/ImGuiFont.gd" id="2_etwwr"] 6 | [ext_resource type="FontFile" uid="uid://bk0s2hduow46m" path="res://data/MPLUS2-Regular.ttf" id="3_qqkxo"] 7 | 8 | [sub_resource type="Resource" id="Resource_df4vj"] 9 | script = ExtResource("2_etwwr") 10 | FontData = ExtResource("1_0g12f") 11 | FontSize = 18 12 | Merge = true 13 | 14 | [sub_resource type="Resource" id="Resource_kiahq"] 15 | script = ExtResource("2_etwwr") 16 | FontData = ExtResource("3_qqkxo") 17 | FontSize = 22 18 | Merge = true 19 | 20 | [resource] 21 | script = ExtResource("1_n8f18") 22 | Fonts = Array[ExtResource("2_etwwr")]([SubResource("Resource_df4vj"), SubResource("Resource_kiahq")]) 23 | AddDefaultFont = true 24 | Scale = 1.0 25 | IniFilename = "user://imgui.ini" 26 | Renderer = "RenderingDevice" 27 | Layer = 100 28 | -------------------------------------------------------------------------------- /doc/.gdignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkdawson/imgui-godot/8a9f0c423533e22a8fa156c5f7c79877c01f437d/doc/.gdignore -------------------------------------------------------------------------------- /doc/examples/CSharpGameProject/CSharpGameProject.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | true 5 | True 6 | enable 7 | 8 | 9 | $(DefineConstants);IMGUI 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /doc/examples/CSharpGameProject/CSharpGameProject.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2012 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpGameProject", "CSharpGameProject.csproj", "{86EC619D-62C6-466E-9415-95CB700470B1}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Any CPU = Debug|Any CPU 8 | ExportDebug|Any CPU = ExportDebug|Any CPU 9 | ExportRelease|Any CPU = ExportRelease|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {86EC619D-62C6-466E-9415-95CB700470B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {86EC619D-62C6-466E-9415-95CB700470B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {86EC619D-62C6-466E-9415-95CB700470B1}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU 15 | {86EC619D-62C6-466E-9415-95CB700470B1}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU 16 | {86EC619D-62C6-466E-9415-95CB700470B1}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU 17 | {86EC619D-62C6-466E-9415-95CB700470B1}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /doc/examples/CSharpGameProject/Globals.cs: -------------------------------------------------------------------------------- 1 | #if !IMGUI 2 | namespace ImGuiNET { } 3 | namespace ImGuiGodot { } 4 | #endif 5 | -------------------------------------------------------------------------------- /doc/examples/CSharpGameProject/Main.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using ImGuiNET; 3 | 4 | namespace CSharpGameProject; 5 | 6 | public partial class Main : Node 7 | { 8 | public override void _Ready() 9 | { 10 | if (DisplayServer.WindowGetVsyncMode() == DisplayServer.VSyncMode.Disabled) 11 | { 12 | int refreshRate = (int)DisplayServer.ScreenGetRefreshRate(); 13 | Engine.MaxFps = refreshRate > 0 ? refreshRate : 60; 14 | } 15 | 16 | #if IMGUI 17 | var io = ImGui.GetIO(); 18 | io.ConfigFlags |= ImGuiConfigFlags.ViewportsEnable; 19 | #endif 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /doc/examples/CSharpGameProject/README.md: -------------------------------------------------------------------------------- 1 | # C# Game Project 2 | 3 | Run: 4 | 5 | ``` 6 | godotenv addons install 7 | ``` 8 | 9 | (or install from AssetLib) 10 | 11 | See the .csproj and Globals.cs for recommended changes to support exports with ImGui disabled. 12 | -------------------------------------------------------------------------------- /doc/examples/CSharpGameProject/Sprite.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using ImGuiNET; 3 | 4 | namespace CSharpGameProject; 5 | 6 | public partial class Sprite : Sprite2D 7 | { 8 | public override void _Process(double delta) 9 | { 10 | Position = new((float)(Position.X + (delta * 10.0)), Position.Y); 11 | 12 | #if IMGUI 13 | ImGui.Begin($"SpriteTool: {Name}", ImGuiWindowFlags.AlwaysAutoResize); 14 | int[] pos = [(int)Position.X, (int)Position.Y]; 15 | if (ImGui.DragInt2("position", ref pos[0])) 16 | { 17 | Position = new(pos[0], pos[1]); 18 | } 19 | ImGui.End(); 20 | #endif 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /doc/examples/CSharpGameProject/addons.json: -------------------------------------------------------------------------------- 1 | { 2 | "addons": { 3 | "imgui-godot": { 4 | "url": "../../../addons/imgui-godot", 5 | "source": "symlink" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /doc/examples/CSharpGameProject/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/examples/CSharpGameProject/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cq5t7s1jnaiuj" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /doc/examples/CSharpGameProject/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://cyqi1opwbrjvr"] 2 | 3 | [ext_resource type="Script" path="res://Main.cs" id="1_taldx"] 4 | [ext_resource type="Texture2D" uid="uid://cq5t7s1jnaiuj" path="res://icon.svg" id="2_e48e3"] 5 | [ext_resource type="Script" path="res://Sprite.cs" id="3_wp2si"] 6 | 7 | [node name="Node2D" type="Node2D"] 8 | script = ExtResource("1_taldx") 9 | 10 | [node name="Icon" type="Sprite2D" parent="."] 11 | position = Vector2(450, 244) 12 | texture = ExtResource("2_e48e3") 13 | script = ExtResource("3_wp2si") 14 | -------------------------------------------------------------------------------- /doc/examples/CSharpGameProject/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="CSharpGameProject" 14 | run/main_scene="res://main.tscn" 15 | config/features=PackedStringArray("4.2", "C#", "Forward Plus") 16 | config/icon="res://icon.svg" 17 | 18 | [autoload] 19 | 20 | ImGuiRoot="*res://addons/imgui-godot/data/ImGuiRoot.tscn" 21 | 22 | [display] 23 | 24 | window/subwindows/embed_subwindows=false 25 | window/vsync/vsync_mode=0 26 | 27 | [dotnet] 28 | 29 | project/assembly_name="CSharpGameProject" 30 | 31 | [editor_plugins] 32 | 33 | enabled=PackedStringArray("res://addons/imgui-godot/plugin.cfg") 34 | -------------------------------------------------------------------------------- /doc/examples/GDExt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.26) 2 | 3 | # Windows only 4 | 5 | set(IMGUI_GODOT_INCLUDE "../../../addons/imgui-godot/include") 6 | 7 | project(gdexample CXX) 8 | 9 | include(FetchContent) 10 | FetchContent_Declare( 11 | godot-cpp 12 | GIT_REPOSITORY https://github.com/godotengine/godot-cpp 13 | GIT_TAG 4.2 14 | ) 15 | FetchContent_MakeAvailable(godot-cpp) 16 | 17 | FetchContent_Declare( 18 | imgui 19 | GIT_REPOSITORY https://github.com/ocornut/imgui 20 | GIT_TAG v1.91.6-docking 21 | ) 22 | FetchContent_MakeAvailable(imgui) 23 | 24 | FetchContent_Declare( 25 | implot 26 | GIT_REPOSITORY https://github.com/epezent/implot 27 | GIT_TAG master 28 | ) 29 | FetchContent_MakeAvailable(implot) 30 | 31 | FetchContent_Declare( 32 | imgui_markdown 33 | GIT_REPOSITORY https://github.com/enkisoftware/imgui_markdown 34 | GIT_TAG main 35 | ) 36 | FetchContent_MakeAvailable(imgui_markdown) 37 | 38 | add_library(gdexample SHARED) 39 | target_compile_features(gdexample PRIVATE cxx_std_20) 40 | target_compile_definitions(gdexample PUBLIC 41 | IMGUI_USER_CONFIG="imconfig-godot.h" 42 | ) 43 | if (MSVC) 44 | target_compile_options(godot-cpp PRIVATE "/MP") 45 | target_compile_options(gdexample PRIVATE "/MP") 46 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD ON) 47 | endif() 48 | 49 | target_sources(gdexample PRIVATE 50 | ${imgui_SOURCE_DIR}/imgui.cpp 51 | ${imgui_SOURCE_DIR}/imgui_demo.cpp 52 | ${imgui_SOURCE_DIR}/imgui_draw.cpp 53 | ${imgui_SOURCE_DIR}/imgui_tables.cpp 54 | ${imgui_SOURCE_DIR}/imgui_widgets.cpp 55 | ${imgui_SOURCE_DIR}/imgui.h 56 | ${implot_SOURCE_DIR}/implot.cpp 57 | ${implot_SOURCE_DIR}/implot_demo.cpp 58 | ${implot_SOURCE_DIR}/implot_items.cpp 59 | ${implot_SOURCE_DIR}/implot.h 60 | ${imgui_markdown_SOURCE_DIR}/imgui_markdown.h 61 | src/example.cpp 62 | src/example.h 63 | src/register_types.cpp 64 | src/register_types.h 65 | src/gdmarkdown.cpp 66 | src/gdmarkdown.h 67 | ) 68 | 69 | target_link_libraries(gdexample PUBLIC godot-cpp) 70 | 71 | target_include_directories(gdexample PRIVATE 72 | src 73 | ${IMGUI_GODOT_INCLUDE} 74 | ${imgui_SOURCE_DIR} 75 | ${implot_SOURCE_DIR} 76 | ${imgui_markdown_SOURCE_DIR} 77 | ) 78 | 79 | set_property(TARGET gdexample 80 | PROPERTY OUTPUT_NAME "libgdexample.windows.template_$,debug,release>.x86_64") 81 | 82 | set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/project") 83 | 84 | install(TARGETS gdexample 85 | RUNTIME DESTINATION bin 86 | ) 87 | -------------------------------------------------------------------------------- /doc/examples/GDExt/README.md: -------------------------------------------------------------------------------- 1 | Run: 2 | 3 | ``` 4 | scons 5 | cd project 6 | godotenv addons install 7 | ``` 8 | -------------------------------------------------------------------------------- /doc/examples/GDExt/SConstruct: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | IMGUI_GODOT_INCLUDE = "../../../addons/imgui-godot/include" 4 | IMGUI_TAG = "v1.91.6-docking" 5 | 6 | import os 7 | import subprocess 8 | 9 | if not os.path.exists("godot-cpp"): 10 | subprocess.call( 11 | "git clone -b 4.2 https://github.com/godotengine/godot-cpp", shell=True 12 | ) 13 | 14 | if not os.path.exists("imgui"): 15 | subprocess.call("git clone -b docking https://github.com/ocornut/imgui", shell=True) 16 | subprocess.call(f"git -C imgui checkout {IMGUI_TAG}", shell=True) 17 | 18 | if not os.path.exists("implot"): 19 | subprocess.call("git clone https://github.com/epezent/implot", shell=True) 20 | 21 | if not os.path.exists("imgui_markdown"): 22 | subprocess.call( 23 | "git clone https://github.com/enkisoftware/imgui_markdown", shell=True 24 | ) 25 | 26 | env = SConscript("godot-cpp/SConstruct") 27 | env = env.Clone() 28 | 29 | env.Append(CPPPATH=["src/"]) 30 | sources = Glob("src/*.cpp") 31 | 32 | # Dear ImGui 33 | sources += Glob(f"imgui/*.cpp") 34 | env.Append(CPPDEFINES=['IMGUI_USER_CONFIG="\\"imconfig-godot.h\\""']) 35 | env.Append(CPPPATH=["imgui", IMGUI_GODOT_INCLUDE]) 36 | 37 | # ImPlot 38 | sources += Glob(f"implot/*.cpp") 39 | env.Append(CPPPATH=["implot"]) 40 | 41 | # imgui_markdown 42 | env.Append(CPPPATH=["imgui_markdown"]) 43 | 44 | if env["platform"] == "macos": 45 | library = env.SharedLibrary( 46 | "project/bin/libgdexample.{}.{}.framework/libgdexample.{}.{}".format( 47 | env["platform"], env["target"], env["platform"], env["target"] 48 | ), 49 | source=sources, 50 | ) 51 | else: 52 | library = env.SharedLibrary( 53 | "project/bin/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]), 54 | source=sources, 55 | ) 56 | 57 | Default(library) 58 | -------------------------------------------------------------------------------- /doc/examples/GDExt/project/Hack-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkdawson/imgui-godot/8a9f0c423533e22a8fa156c5f7c79877c01f437d/doc/examples/GDExt/project/Hack-Bold.ttf -------------------------------------------------------------------------------- /doc/examples/GDExt/project/Hack-Bold.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://geey1pyskdev" 6 | path="res://.godot/imported/Hack-Bold.ttf-691cdc24fdde9142fc0f47c007a581d0.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://Hack-Bold.ttf" 11 | dest_files=["res://.godot/imported/Hack-Bold.ttf-691cdc24fdde9142fc0f47c007a581d0.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | multichannel_signed_distance_field=false 19 | msdf_pixel_range=8 20 | msdf_size=48 21 | allow_system_fallback=true 22 | force_autohinter=false 23 | hinting=1 24 | subpixel_positioning=1 25 | oversampling=0.0 26 | Fallbacks=null 27 | fallbacks=[] 28 | Compress=null 29 | compress=true 30 | preload=[] 31 | language_support={} 32 | script_support={} 33 | opentype_features={} 34 | -------------------------------------------------------------------------------- /doc/examples/GDExt/project/Hack-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkdawson/imgui-godot/8a9f0c423533e22a8fa156c5f7c79877c01f437d/doc/examples/GDExt/project/Hack-Italic.ttf -------------------------------------------------------------------------------- /doc/examples/GDExt/project/Hack-Italic.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://ccn210ltcrs6i" 6 | path="res://.godot/imported/Hack-Italic.ttf-da10696e2f4be4192574d1c950d4085f.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://Hack-Italic.ttf" 11 | dest_files=["res://.godot/imported/Hack-Italic.ttf-da10696e2f4be4192574d1c950d4085f.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | multichannel_signed_distance_field=false 19 | msdf_pixel_range=8 20 | msdf_size=48 21 | allow_system_fallback=true 22 | force_autohinter=false 23 | hinting=1 24 | subpixel_positioning=1 25 | oversampling=0.0 26 | Fallbacks=null 27 | fallbacks=[] 28 | Compress=null 29 | compress=true 30 | preload=[] 31 | language_support={} 32 | script_support={} 33 | opentype_features={} 34 | -------------------------------------------------------------------------------- /doc/examples/GDExt/project/Hack-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkdawson/imgui-godot/8a9f0c423533e22a8fa156c5f7c79877c01f437d/doc/examples/GDExt/project/Hack-Regular.ttf -------------------------------------------------------------------------------- /doc/examples/GDExt/project/Hack-Regular.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://2se0brkpdxhs" 6 | path="res://.godot/imported/Hack-Regular.ttf-4957220eed9c50075bb4de8b4fadc317.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://Hack-Regular.ttf" 11 | dest_files=["res://.godot/imported/Hack-Regular.ttf-4957220eed9c50075bb4de8b4fadc317.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | multichannel_signed_distance_field=false 19 | msdf_pixel_range=8 20 | msdf_size=48 21 | allow_system_fallback=true 22 | force_autohinter=false 23 | hinting=1 24 | subpixel_positioning=1 25 | oversampling=0.0 26 | Fallbacks=null 27 | fallbacks=[] 28 | Compress=null 29 | compress=true 30 | preload=[] 31 | language_support={} 32 | script_support={} 33 | opentype_features={} 34 | -------------------------------------------------------------------------------- /doc/examples/GDExt/project/addons.json: -------------------------------------------------------------------------------- 1 | { 2 | "addons": { 3 | "imgui-godot": { 4 | "url": "../../../../addons/imgui-godot", 5 | "source": "symlink" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /doc/examples/GDExt/project/example.gdextension: -------------------------------------------------------------------------------- 1 | [configuration] 2 | 3 | entry_symbol = "example_library_init" 4 | compatibility_minimum = "4.2" 5 | 6 | [libraries] 7 | 8 | macos.debug = "res://bin/libgdexample.macos.template_debug.framework" 9 | macos.release = "res://bin/libgdexample.macos.template_release.framework" 10 | windows.debug.x86_64 = "res://bin/libgdexample.windows.template_debug.x86_64.dll" 11 | windows.release.x86_64 = "res://bin/libgdexample.windows.template_release.x86_64.dll" 12 | linux.debug.x86_64 = "res://bin/libgdexample.linux.template_debug.x86_64.so" 13 | linux.release.x86_64 = "res://bin/libgdexample.linux.template_release.x86_64.so" 14 | -------------------------------------------------------------------------------- /doc/examples/GDExt/project/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/examples/GDExt/project/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cr045l23wjmqc" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=true 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=4.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /doc/examples/GDExt/project/imgui_config.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="ImGuiConfig" load_steps=11 format=3 uid="uid://c58buectmbwmf"] 2 | 3 | [ext_resource type="Script" path="res://addons/imgui-godot/scripts/ImGuiFont.gd" id="1_0saup"] 4 | [ext_resource type="FontFile" uid="uid://2se0brkpdxhs" path="res://Hack-Regular.ttf" id="1_7tey3"] 5 | [ext_resource type="Script" path="res://addons/imgui-godot/scripts/ImGuiConfig.gd" id="1_nq4e5"] 6 | [ext_resource type="FontFile" uid="uid://geey1pyskdev" path="res://Hack-Bold.ttf" id="3_5fv0r"] 7 | [ext_resource type="FontFile" uid="uid://ccn210ltcrs6i" path="res://Hack-Italic.ttf" id="4_34el5"] 8 | 9 | [sub_resource type="Resource" id="Resource_57j4v"] 10 | script = ExtResource("1_0saup") 11 | FontData = ExtResource("1_7tey3") 12 | FontSize = 16 13 | Merge = false 14 | 15 | [sub_resource type="Resource" id="Resource_4trot"] 16 | script = ExtResource("1_0saup") 17 | FontData = ExtResource("3_5fv0r") 18 | FontSize = 32 19 | Merge = false 20 | 21 | [sub_resource type="Resource" id="Resource_okot8"] 22 | script = ExtResource("1_0saup") 23 | FontData = ExtResource("3_5fv0r") 24 | FontSize = 24 25 | Merge = false 26 | 27 | [sub_resource type="Resource" id="Resource_3knfi"] 28 | script = ExtResource("1_0saup") 29 | FontData = ExtResource("3_5fv0r") 30 | FontSize = 16 31 | Merge = false 32 | 33 | [sub_resource type="Resource" id="Resource_2wpqv"] 34 | script = ExtResource("1_0saup") 35 | FontData = ExtResource("4_34el5") 36 | FontSize = 16 37 | Merge = false 38 | 39 | [resource] 40 | script = ExtResource("1_nq4e5") 41 | Fonts = Array[ExtResource("1_0saup")]([SubResource("Resource_57j4v"), SubResource("Resource_4trot"), SubResource("Resource_okot8"), SubResource("Resource_3knfi"), SubResource("Resource_2wpqv")]) 42 | AddDefaultFont = false 43 | Scale = 1.0 44 | IniFilename = "user://imgui.ini" 45 | Renderer = "RenderingDevice" 46 | Layer = 128 47 | -------------------------------------------------------------------------------- /doc/examples/GDExt/project/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene format=3 uid="uid://c08lt0b17jqog"] 2 | 3 | [node name="Node2D" type="Node2D"] 4 | 5 | [node name="Example" type="Example" parent="."] 6 | -------------------------------------------------------------------------------- /doc/examples/GDExt/project/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [addons] 12 | 13 | imgui/config="res://imgui_config.tres" 14 | 15 | [application] 16 | 17 | config/name="GDExt" 18 | run/main_scene="res://main.tscn" 19 | config/features=PackedStringArray("4.2", "Forward Plus") 20 | run/max_fps=144 21 | config/icon="res://icon.svg" 22 | 23 | [autoload] 24 | 25 | ImGuiRoot="*res://addons/imgui-godot/data/ImGuiRoot.tscn" 26 | 27 | [display] 28 | 29 | window/subwindows/embed_subwindows=false 30 | window/vsync/vsync_mode=0 31 | 32 | [editor_plugins] 33 | 34 | enabled=PackedStringArray("res://addons/imgui-godot/plugin.cfg") 35 | -------------------------------------------------------------------------------- /doc/examples/GDExt/project/robot_eye.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://cqelg04ohkgm5"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://cr045l23wjmqc" path="res://icon.svg" id="1_d7u5w"] 4 | 5 | [resource] 6 | atlas = ExtResource("1_d7u5w") 7 | region = Rect2(142, 228, 64, 64) 8 | -------------------------------------------------------------------------------- /doc/examples/GDExt/src/example.cpp: -------------------------------------------------------------------------------- 1 | #include "example.h" 2 | #include "gdmarkdown.h" 3 | #include 4 | #include 5 | #include 6 | 7 | using godot::Engine; 8 | using godot::ResourceLoader; 9 | 10 | static const std::string markdownText = R"(# H1 Header 11 | 12 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 13 | 14 | ## H2 Header 15 | 16 | Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 17 | 18 | ### H3 Header 19 | 20 | * Item 1 21 | * Item 2 22 | * Item 3 23 | 24 | *Emphasis* and **strong emphasis** change the appearance of the text. 25 | 26 | Link: [Godot Engine](https://godotengine.org) 27 | 28 | robot eye ![an atlas texture](res://robot_eye.tres) 29 | 30 | ___ 31 | 32 | big robot 33 | ![](res://icon.svg) 34 | )"; 35 | 36 | void Example::_bind_methods() 37 | { 38 | } 39 | 40 | Example::Example() 41 | { 42 | } 43 | 44 | Example::~Example() 45 | { 46 | } 47 | 48 | void Example::_ready() 49 | { 50 | #ifdef DEBUG_ENABLED 51 | if (Engine::get_singleton()->is_editor_hint()) 52 | return; 53 | #endif 54 | 55 | _img = ResourceLoader::get_singleton()->load("res://robot_eye.tres"); 56 | ImGui::InitMarkdown(); 57 | } 58 | 59 | void Example::_process(double delta) 60 | { 61 | #ifdef DEBUG_ENABLED 62 | if (Engine::get_singleton()->is_editor_hint()) 63 | return; 64 | #endif 65 | 66 | static int x = 0; 67 | 68 | ImGui::SetNextWindowSize({200, 200}, ImGuiCond_Once); 69 | ImGui::Begin("GDExtension Example"); 70 | ImGui::DragInt("x", &x); 71 | ImGui::Text("x = %d", x); 72 | ImGui::Separator(); 73 | ImGui::Image(_img, {64, 64}); 74 | ImGui::End(); 75 | 76 | ImGui::ShowDemoWindow(); 77 | 78 | ImPlot::ShowDemoWindow(); 79 | 80 | ImGui::Begin("Markdown example"); 81 | ImGui::Markdown(markdownText); 82 | ImGui::End(); 83 | } 84 | -------------------------------------------------------------------------------- /doc/examples/GDExt/src/example.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | using godot::Node; 6 | using godot::Ref; 7 | using godot::AtlasTexture; 8 | 9 | class Example : public Node 10 | { 11 | GDCLASS(Example, Node); 12 | 13 | protected: 14 | static void _bind_methods(); 15 | 16 | public: 17 | Example(); 18 | ~Example(); 19 | 20 | void _ready() override; 21 | void _process(double delta) override; 22 | 23 | private: 24 | Ref _img; 25 | }; 26 | -------------------------------------------------------------------------------- /doc/examples/GDExt/src/gdmarkdown.cpp: -------------------------------------------------------------------------------- 1 | #include "gdmarkdown.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace { 10 | using godot::AtlasTexture; 11 | using godot::OS; 12 | using godot::Ref; 13 | using godot::ResourceLoader; 14 | using godot::String; 15 | using godot::Texture2D; 16 | 17 | ImGui::MarkdownConfig mdConfig; 18 | ImFont* italicFont = nullptr; 19 | 20 | void MdLinkCallback(ImGui::MarkdownLinkCallbackData data) 21 | { 22 | if (!data.isImage) 23 | { 24 | String link = String::utf8(data.link, data.linkLength); 25 | OS::get_singleton()->shell_open(link); 26 | } 27 | } 28 | 29 | ImGui::MarkdownImageData MdImageCallback(ImGui::MarkdownLinkCallbackData data) 30 | { 31 | ImGui::MarkdownImageData imageData; 32 | 33 | String link = String::utf8(data.link, data.linkLength); 34 | Ref tex = ResourceLoader::get_singleton()->load(link); 35 | 36 | if (tex.is_valid()) 37 | { 38 | imageData.isValid = true; 39 | imageData.useLinkCallback = false; 40 | imageData.user_texture_id = (ImTextureID)tex->get_rid().get_id(); 41 | 42 | if (Ref atex = tex; atex.is_valid()) 43 | { 44 | imageData.size = atex->get_size(); 45 | 46 | Vector2 atlasSize = atex->get_atlas()->get_size(); 47 | imageData.uv0 = atex->get_region().get_position() / atlasSize; 48 | imageData.uv1 = atex->get_region().get_end() / atlasSize; 49 | } 50 | else 51 | { 52 | imageData.size = tex->get_size(); 53 | } 54 | } 55 | 56 | return imageData; 57 | } 58 | 59 | void MdFormatCallback(const ImGui::MarkdownFormatInfo& fmt, bool start) 60 | { 61 | if (fmt.type == ImGui::MarkdownFormatType::EMPHASIS && fmt.level == 1) 62 | { 63 | if (start) 64 | ImGui::PushFont(italicFont); 65 | else 66 | ImGui::PopFont(); 67 | } 68 | else if (fmt.type == ImGui::MarkdownFormatType::HEADING) 69 | { 70 | // default has excessive whitespace 71 | 72 | int32_t level = std::min(fmt.level, ImGui::MarkdownConfig::NUMHEADINGS); 73 | ImGui::MarkdownHeadingFormat hfmt = fmt.config->headingFormats[level - 1]; 74 | 75 | if (start) 76 | { 77 | ImGui::NewLine(); 78 | if (hfmt.font) 79 | ImGui::PushFont(hfmt.font); 80 | } 81 | else 82 | { 83 | if (hfmt.separator) 84 | ImGui::Separator(); 85 | if (hfmt.font) 86 | ImGui::PopFont(); 87 | } 88 | } 89 | else 90 | { 91 | ImGui::defaultMarkdownFormatCallback(fmt, start); 92 | } 93 | } 94 | 95 | void MdTooltipCallback(ImGui::MarkdownTooltipCallbackData data) 96 | { 97 | if (data.linkData.isImage) 98 | { 99 | if (data.linkData.textLength > 0) 100 | { 101 | ImGui::SetTooltip("%.*s", data.linkData.textLength, data.linkData.text); 102 | } 103 | } 104 | else 105 | { 106 | ImGui::SetTooltip("%s Open in browser\n%.*s", data.linkIcon, data.linkData.linkLength, data.linkData.link); 107 | } 108 | } 109 | } // namespace 110 | 111 | void ImGui::InitMarkdown() 112 | { 113 | const auto& io = ImGui::GetIO(); 114 | const auto& fonts = io.Fonts->Fonts; 115 | 116 | mdConfig.linkCallback = MdLinkCallback; 117 | mdConfig.tooltipCallback = MdTooltipCallback; 118 | mdConfig.imageCallback = MdImageCallback; 119 | mdConfig.formatCallback = MdFormatCallback; 120 | mdConfig.headingFormats[0] = {fonts[1], true}; 121 | mdConfig.headingFormats[1] = {fonts[2], true}; 122 | mdConfig.headingFormats[2] = {fonts[3], false}; 123 | 124 | italicFont = fonts[4]; 125 | } 126 | 127 | void ImGui::Markdown(std::string_view text) 128 | { 129 | ImGui::Markdown(text.data(), text.length(), mdConfig); 130 | } 131 | -------------------------------------------------------------------------------- /doc/examples/GDExt/src/gdmarkdown.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace ImGui { 4 | void InitMarkdown(); 5 | void Markdown(std::string_view text); 6 | } // namespace ImGui 7 | -------------------------------------------------------------------------------- /doc/examples/GDExt/src/register_types.cpp: -------------------------------------------------------------------------------- 1 | #include "register_types.h" 2 | #include "example.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using godot::MODULE_INITIALIZATION_LEVEL_SCENE; 12 | 13 | void initialize_example_module(ModuleInitializationLevel p_level) 14 | { 15 | if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) 16 | return; 17 | 18 | ImGui::Godot::SyncImGuiPtrs(); 19 | ImPlot::CreateContext(); 20 | 21 | godot::ClassDB::register_class(); 22 | } 23 | 24 | void uninitialize_example_module(ModuleInitializationLevel p_level) 25 | { 26 | if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) 27 | return; 28 | 29 | ImPlot::DestroyContext(); 30 | } 31 | 32 | extern "C" { 33 | GDExtensionBool GDE_EXPORT example_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, 34 | GDExtensionClassLibraryPtr p_library, 35 | GDExtensionInitialization* r_initialization) 36 | { 37 | godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization); 38 | 39 | init_obj.register_initializer(initialize_example_module); 40 | init_obj.register_terminator(uninitialize_example_module); 41 | init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE); 42 | 43 | return init_obj.init(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /doc/examples/GDExt/src/register_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | using godot::ModuleInitializationLevel; 5 | 6 | void initialize_example_module(ModuleInitializationLevel p_level); 7 | void uninitialize_example_module(ModuleInitializationLevel p_level); 8 | -------------------------------------------------------------------------------- /doc/examples/GdsDemo/README.md: -------------------------------------------------------------------------------- 1 | Run: 2 | 3 | ``` 4 | godotenv addons install 5 | ``` 6 | -------------------------------------------------------------------------------- /doc/examples/GdsDemo/addons.json: -------------------------------------------------------------------------------- 1 | { 2 | "addons": { 3 | "imgui-godot": { 4 | "url": "../../../addons/imgui-godot", 5 | "source": "symlink" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /doc/examples/GdsDemo/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/examples/GdsDemo/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://p5eschom80xn" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /doc/examples/GdsDemo/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://dcv44scldjibq"] 2 | 3 | [ext_resource type="Script" path="res://demo.gd" id="1_dqw6r"] 4 | 5 | [node name="Control" type="Control"] 6 | layout_mode = 3 7 | anchors_preset = 15 8 | anchor_right = 1.0 9 | anchor_bottom = 1.0 10 | grow_horizontal = 2 11 | grow_vertical = 2 12 | script = ExtResource("1_dqw6r") 13 | -------------------------------------------------------------------------------- /doc/examples/GdsDemo/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="GdsDemo" 14 | run/main_scene="res://main.tscn" 15 | config/features=PackedStringArray("4.3", "Forward Plus") 16 | config/icon="res://icon.svg" 17 | 18 | [autoload] 19 | 20 | ImGuiRoot="*res://addons/imgui-godot/data/ImGuiRoot.tscn" 21 | 22 | [display] 23 | 24 | window/subwindows/embed_subwindows=false 25 | window/vsync/vsync_mode=0 26 | 27 | [editor_plugins] 28 | 29 | enabled=PackedStringArray("res://addons/imgui-godot/plugin.cfg") 30 | -------------------------------------------------------------------------------- /doc/examples/GdsGameProject/README.md: -------------------------------------------------------------------------------- 1 | # GDScript Game Project 2 | 3 | Run: 4 | 5 | ``` 6 | godotenv addons install 7 | ``` 8 | 9 | (or install from AssetLib) 10 | 11 | This project demonstrates how to use ImGui in a way that makes it safe to export your project with 12 | imgui-godot disabled. 13 | -------------------------------------------------------------------------------- /doc/examples/GdsGameProject/addons.json: -------------------------------------------------------------------------------- 1 | { 2 | "addons": { 3 | "imgui-godot": { 4 | "url": "../../../addons/imgui-godot", 5 | "source": "symlink" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /doc/examples/GdsGameProject/export/.gdignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkdawson/imgui-godot/8a9f0c423533e22a8fa156c5f7c79877c01f437d/doc/examples/GdsGameProject/export/.gdignore -------------------------------------------------------------------------------- /doc/examples/GdsGameProject/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/examples/GdsGameProject/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bwwgygwkoe4ei" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /doc/examples/GdsGameProject/main.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | func _ready() -> void: 4 | # disabling vsync reduces input lag 5 | if DisplayServer.window_get_vsync_mode() == DisplayServer.VSYNC_DISABLED: 6 | var refreshRate := DisplayServer.screen_get_refresh_rate() 7 | Engine.max_fps = int(refreshRate) if refreshRate > 0.0 else 60 8 | 9 | if Engine.has_singleton("ImGuiAPI"): 10 | var ImGui: Object = Engine.get_singleton("ImGuiAPI") 11 | var io: Object = ImGui.GetIO() 12 | io.ConfigFlags |= ImGui.ConfigFlags_ViewportsEnable 13 | 14 | func _process(_delta: float) -> void: 15 | pass 16 | -------------------------------------------------------------------------------- /doc/examples/GdsGameProject/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://cmvrg5mco0rv7"] 2 | 3 | [ext_resource type="Script" path="res://main.gd" id="1_a75q1"] 4 | [ext_resource type="Texture2D" uid="uid://bwwgygwkoe4ei" path="res://icon.svg" id="1_v7ads"] 5 | [ext_resource type="Script" path="res://sprite.gd" id="3_ngin8"] 6 | 7 | [node name="Node2D" type="Node2D"] 8 | script = ExtResource("1_a75q1") 9 | 10 | [node name="Sprite1" type="Sprite2D" parent="."] 11 | position = Vector2(275, 236) 12 | texture = ExtResource("1_v7ads") 13 | script = ExtResource("3_ngin8") 14 | -------------------------------------------------------------------------------- /doc/examples/GdsGameProject/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="GdsGameProject" 14 | run/main_scene="res://main.tscn" 15 | config/features=PackedStringArray("4.2", "Forward Plus") 16 | config/icon="res://icon.svg" 17 | 18 | [autoload] 19 | 20 | ImGuiRoot="*res://addons/imgui-godot/data/ImGuiRoot.tscn" 21 | 22 | [debug] 23 | 24 | gdscript/warnings/shadowed_global_identifier=0 25 | gdscript/warnings/untyped_declaration=1 26 | 27 | [display] 28 | 29 | window/subwindows/embed_subwindows=false 30 | window/vsync/vsync_mode=0 31 | 32 | [editor_plugins] 33 | 34 | enabled=PackedStringArray("res://addons/imgui-godot/plugin.cfg") 35 | 36 | [rendering] 37 | 38 | textures/vram_compression/import_etc2_astc=true 39 | -------------------------------------------------------------------------------- /doc/examples/GdsGameProject/sprite.gd: -------------------------------------------------------------------------------- 1 | extends Sprite2D 2 | 3 | func _ready() -> void: 4 | pass 5 | 6 | func _process(delta: float) -> void: 7 | position.x += delta * 10.0 8 | 9 | if Engine.has_singleton("ImGuiAPI"): 10 | var ImGui: Object = Engine.get_singleton("ImGuiAPI") 11 | ImGui.Begin("SpriteTool: %s" % name, [], ImGui.WindowFlags_AlwaysAutoResize) 12 | var pos: Array = [position.x, position.y] 13 | if ImGui.DragInt2("position", pos): 14 | position = Vector2(pos[0], pos[1]) 15 | ImGui.End() 16 | -------------------------------------------------------------------------------- /doc/examples/Module/README.md: -------------------------------------------------------------------------------- 1 | Run, for example: 2 | 3 | ``` 4 | git clone https://github.com/ocornut/imgui 5 | git -C imgui checkout v1.91.6-docking 6 | git clone https://github.com/godotengine/godot 7 | cd godot 8 | scons custom_modules=../modules 9 | cd ../project 10 | godotenv addons install 11 | ../godot/bin/godot.* -e 12 | ``` 13 | -------------------------------------------------------------------------------- /doc/examples/Module/modules/mymod/SCsub: -------------------------------------------------------------------------------- 1 | Import('env') 2 | 3 | IMGUI_PATH = "../../imgui" 4 | IMGUI_GODOT_INCLUDE = "../../../../../addons/imgui-godot/include" 5 | 6 | env.Append(CPPPATH=[IMGUI_PATH, IMGUI_GODOT_INCLUDE]) 7 | env.Append(CPPDEFINES=['IMGUI_USER_CONFIG="\\"imconfig-godot.h\\""']) 8 | env.add_source_files(env.modules_sources, f"{IMGUI_PATH}/*.cpp") 9 | 10 | env.add_source_files(env.modules_sources, "*.cpp") 11 | -------------------------------------------------------------------------------- /doc/examples/Module/modules/mymod/config.py: -------------------------------------------------------------------------------- 1 | def can_build(env, platform): 2 | return True 3 | 4 | def configure(env): 5 | pass 6 | -------------------------------------------------------------------------------- /doc/examples/Module/modules/mymod/mynode.cpp: -------------------------------------------------------------------------------- 1 | #include "mynode.h" 2 | #include "core/config/engine.h" 3 | #include "core/io/resource_loader.h" 4 | #include 5 | 6 | MyNode::MyNode() 7 | { 8 | #ifdef DEBUG_ENABLED 9 | if (Engine::get_singleton()->is_editor_hint()) 10 | return; 11 | #endif 12 | set_process(true); 13 | } 14 | 15 | MyNode::~MyNode() 16 | { 17 | } 18 | 19 | void MyNode::_bind_methods() 20 | { 21 | } 22 | 23 | void MyNode::_notification(int what) 24 | { 25 | #ifdef DEBUG_ENABLED 26 | if (Engine::get_singleton()->is_editor_hint()) 27 | return; 28 | #endif 29 | 30 | switch (what) 31 | { 32 | case NOTIFICATION_PROCESS: 33 | ImGui::Begin("C++ module", nullptr, ImGuiWindowFlags_AlwaysAutoResize); 34 | ImGui::Text("hello"); 35 | ImGui::Image(_img, {_iconSize, _iconSize}); 36 | ImGui::DragFloat("size", &_iconSize, 1.f, 32.f, 512.f); 37 | ImGui::End(); 38 | break; 39 | 40 | case NOTIFICATION_READY: 41 | _img = ResourceLoader::load("res://icon.svg"); 42 | break; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /doc/examples/Module/modules/mymod/mynode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "scene/main/node.h" 3 | #include "scene/resources/texture.h" 4 | 5 | class MyNode : public Node 6 | { 7 | GDCLASS(MyNode, Node); 8 | 9 | protected: 10 | static void _bind_methods(); 11 | 12 | void _notification(int what); 13 | 14 | public: 15 | MyNode(); 16 | ~MyNode(); 17 | 18 | private: 19 | Ref _img; 20 | float _iconSize = 64.f; 21 | }; 22 | -------------------------------------------------------------------------------- /doc/examples/Module/modules/mymod/register_types.cpp: -------------------------------------------------------------------------------- 1 | #include "register_types.h" 2 | #include "core/object/class_db.h" 3 | #include "mynode.h" 4 | #include 5 | 6 | // use this macro once in any module 7 | IMGUI_GODOT_MODULE_INIT() 8 | 9 | void initialize_mymod_module(ModuleInitializationLevel p_level) 10 | { 11 | if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) 12 | return; 13 | ClassDB::register_class(); 14 | } 15 | 16 | void uninitialize_mymod_module(ModuleInitializationLevel p_level) 17 | { 18 | if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) 19 | return; 20 | } 21 | -------------------------------------------------------------------------------- /doc/examples/Module/modules/mymod/register_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "modules/register_module_types.h" 4 | 5 | void initialize_mymod_module(ModuleInitializationLevel p_level); 6 | void uninitialize_mymod_module(ModuleInitializationLevel p_level); 7 | -------------------------------------------------------------------------------- /doc/examples/Module/project/addons.json: -------------------------------------------------------------------------------- 1 | { 2 | "addons": { 3 | "imgui-godot": { 4 | "url": "../../../../addons/imgui-godot", 5 | "source": "symlink" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /doc/examples/Module/project/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/examples/Module/project/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://c4q3xqtrta6bs" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=true 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=4.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /doc/examples/Module/project/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene format=3 uid="uid://bgkdofvtxk6qx"] 2 | 3 | [node name="Node2D" type="Node2D"] 4 | 5 | [node name="MyNode" type="MyNode" parent="."] 6 | -------------------------------------------------------------------------------- /doc/examples/Module/project/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="Module" 14 | run/main_scene="res://main.tscn" 15 | config/features=PackedStringArray("4.2", "Forward Plus") 16 | config/icon="res://icon.svg" 17 | 18 | [autoload] 19 | 20 | ImGuiRoot="*res://addons/imgui-godot/data/ImGuiRoot.tscn" 21 | 22 | [editor_plugins] 23 | 24 | enabled=PackedStringArray("res://addons/imgui-godot/plugin.cfg") 25 | -------------------------------------------------------------------------------- /doc/examples/ToolCSharp/README.md: -------------------------------------------------------------------------------- 1 | Run: 2 | 3 | ``` 4 | godotenv addons install 5 | ``` 6 | 7 | Open the project, then restart the editor. 8 | -------------------------------------------------------------------------------- /doc/examples/ToolCSharp/SpriteTool.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using ImGuiNET; 3 | using ImGuiGodot; 4 | 5 | [Tool] 6 | public partial class SpriteTool : Sprite2D 7 | { 8 | private bool _showImGui = false; 9 | 10 | public override void _Ready() 11 | { 12 | if (Engine.IsEditorHint()) 13 | { 14 | _showImGui = ImGuiGD.ToolInit(); 15 | var io = ImGui.GetIO(); 16 | io.ConfigFlags |= ImGuiConfigFlags.ViewportsEnable; 17 | io.ConfigViewportsNoAutoMerge = true; 18 | } 19 | } 20 | 21 | public override void _Process(double delta) 22 | { 23 | if (_showImGui) 24 | { 25 | ImGui.Begin($"SpriteTool: {Name}"); 26 | float scale = Scale.X; 27 | if (ImGui.DragFloat("scale", ref scale, 0.1f)) 28 | { 29 | Scale = new(scale, scale); 30 | } 31 | ImGui.End(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /doc/examples/ToolCSharp/ToolCSharp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | true 5 | True 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /doc/examples/ToolCSharp/ToolCSharp.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2012 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ToolCSharp", "ToolCSharp.csproj", "{E08468D9-B6AE-4EBA-BE2B-B18B0194FEAF}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Any CPU = Debug|Any CPU 8 | ExportDebug|Any CPU = ExportDebug|Any CPU 9 | ExportRelease|Any CPU = ExportRelease|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {E08468D9-B6AE-4EBA-BE2B-B18B0194FEAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {E08468D9-B6AE-4EBA-BE2B-B18B0194FEAF}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {E08468D9-B6AE-4EBA-BE2B-B18B0194FEAF}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU 15 | {E08468D9-B6AE-4EBA-BE2B-B18B0194FEAF}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU 16 | {E08468D9-B6AE-4EBA-BE2B-B18B0194FEAF}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU 17 | {E08468D9-B6AE-4EBA-BE2B-B18B0194FEAF}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /doc/examples/ToolCSharp/addons.json: -------------------------------------------------------------------------------- 1 | { 2 | "addons": { 3 | "imgui-godot": { 4 | "url": "../../../addons/imgui-godot", 5 | "source": "symlink" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /doc/examples/ToolCSharp/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/examples/ToolCSharp/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://g0surar1un43" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /doc/examples/ToolCSharp/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://ceybxiw6agvb2"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://g0surar1un43" path="res://icon.svg" id="1_vsk0a"] 4 | [ext_resource type="Script" path="res://SpriteTool.cs" id="2_a7b6t"] 5 | 6 | [node name="Node2D" type="Node2D"] 7 | 8 | [node name="Icon" type="Sprite2D" parent="."] 9 | position = Vector2(470, 223) 10 | texture = ExtResource("1_vsk0a") 11 | script = ExtResource("2_a7b6t") 12 | -------------------------------------------------------------------------------- /doc/examples/ToolCSharp/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="ToolCSharp" 14 | run/main_scene="res://main.tscn" 15 | config/features=PackedStringArray("4.2", "C#", "Forward Plus") 16 | config/icon="res://icon.svg" 17 | 18 | [autoload] 19 | 20 | ImGuiRoot="*res://addons/imgui-godot/data/ImGuiRoot.tscn" 21 | 22 | [dotnet] 23 | 24 | project/assembly_name="ToolCSharp" 25 | 26 | [editor_plugins] 27 | 28 | enabled=PackedStringArray("res://addons/imgui-godot/plugin.cfg") 29 | -------------------------------------------------------------------------------- /doc/examples/ToolScript/README.md: -------------------------------------------------------------------------------- 1 | Run: 2 | 3 | ``` 4 | godotenv addons install 5 | ``` 6 | 7 | Open the project, then restart the editor. 8 | -------------------------------------------------------------------------------- /doc/examples/ToolScript/addons.json: -------------------------------------------------------------------------------- 1 | { 2 | "addons": { 3 | "imgui-godot": { 4 | "url": "../../../addons/imgui-godot", 5 | "source": "symlink" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /doc/examples/ToolScript/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/examples/ToolScript/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://nhty36dbhwyw" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /doc/examples/ToolScript/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://cc1o2vsbuo1u8"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://nhty36dbhwyw" path="res://icon.svg" id="1_refmf"] 4 | [ext_resource type="Script" path="res://sprite_tool.gd" id="2_e8mp5"] 5 | 6 | [node name="Node2D" type="Node2D"] 7 | 8 | [node name="Sprite 1" type="Sprite2D" parent="."] 9 | position = Vector2(264, 176) 10 | texture = ExtResource("1_refmf") 11 | script = ExtResource("2_e8mp5") 12 | 13 | [node name="Sprite 2" type="Sprite2D" parent="."] 14 | position = Vector2(790, 348) 15 | rotation = 0.785398 16 | scale = Vector2(2, 2) 17 | texture = ExtResource("1_refmf") 18 | script = ExtResource("2_e8mp5") 19 | -------------------------------------------------------------------------------- /doc/examples/ToolScript/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="ToolScript" 14 | run/main_scene="res://main.tscn" 15 | config/features=PackedStringArray("4.2", "Forward Plus") 16 | config/icon="res://icon.svg" 17 | 18 | [autoload] 19 | 20 | ImGuiRoot="*res://addons/imgui-godot/data/ImGuiRoot.tscn" 21 | 22 | [editor_plugins] 23 | 24 | enabled=PackedStringArray("res://addons/imgui-godot/plugin.cfg") 25 | -------------------------------------------------------------------------------- /doc/examples/ToolScript/sprite_tool.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Node2D 3 | 4 | var show_tool_gui := ImGuiGD.ToolInit() 5 | var myscale := [scale.x] 6 | var myrot := [0] 7 | var auto_rotate := [false] 8 | 9 | func _ready(): 10 | if show_tool_gui: 11 | var io = ImGui.GetIO() 12 | io.ConfigFlags |= ImGui.ConfigFlags_ViewportsEnable 13 | io.ConfigViewportsNoAutoMerge = true 14 | 15 | 16 | func _process(_delta): 17 | if show_tool_gui: 18 | ImGui.Begin("tool: " + name) 19 | if ImGui.DragFloatEx("scale", myscale, 0.1, 0.25, 8.0): 20 | scale.x = myscale[0] 21 | scale.y = myscale[0] 22 | 23 | myrot[0] = rad_to_deg(rotation) 24 | if ImGui.DragInt("rotation", myrot): 25 | rotation = deg_to_rad(myrot[0]) 26 | 27 | ImGui.Checkbox("auto rotate", auto_rotate) 28 | if auto_rotate[0]: 29 | if rotation >= 2 * PI: 30 | rotation = 0 31 | rotation += deg_to_rad(1) 32 | ImGui.End() 33 | -------------------------------------------------------------------------------- /doc/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkdawson/imgui-godot/8a9f0c423533e22a8fa156c5f7c79877c01f437d/doc/icon.png -------------------------------------------------------------------------------- /doc/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkdawson/imgui-godot/8a9f0c423533e22a8fa156c5f7c79877c01f437d/doc/screenshot.png -------------------------------------------------------------------------------- /doc/test/addons/TestData/config_scale2x.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="ImGuiConfig" load_steps=2 format=3 uid="uid://su0bdciskixm"] 2 | 3 | [ext_resource type="Script" path="res://addons/imgui-godot/scripts/ImGuiConfig.gd" id="1_o27t7"] 4 | 5 | [resource] 6 | script = ExtResource("1_o27t7") 7 | Fonts = Array[Resource("res://addons/imgui-godot/scripts/ImGuiFont.gd")]([]) 8 | AddDefaultFont = true 9 | Scale = 2.0 10 | IniFilename = "user://imgui.ini" 11 | Renderer = "RenderingDevice" 12 | Layer = 128 13 | -------------------------------------------------------------------------------- /doc/test/csbench/BenchCanvas.cs: -------------------------------------------------------------------------------- 1 | using ImGuiNET; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace csbench; 5 | 6 | [MemoryDiagnoser] 7 | public class BenchCanvas 8 | { 9 | private readonly ImDrawVertPtr v; 10 | private readonly Godot.Vector2[] points = new Godot.Vector2[1]; 11 | private readonly Godot.Color[] colors = new Godot.Color[1]; 12 | private readonly Godot.Vector2[] uvs = new Godot.Vector2[1]; 13 | 14 | public unsafe BenchCanvas() 15 | { 16 | nint ptr = Marshal.AllocHGlobal(sizeof(ImDrawVert)); 17 | v = new(ptr) 18 | { 19 | col = 0x12345678, 20 | uv = new(0.1f, 0.2f), 21 | pos = new(0.3f, 0.4f) 22 | }; 23 | } 24 | 25 | [Benchmark(Baseline = true)] 26 | public void ConvertVertex1() 27 | { 28 | points[0] = new(v.pos.X, v.pos.Y); 29 | uint rgba = v.col; 30 | float r = (rgba & 0xFFu) / 255f; 31 | rgba >>= 8; 32 | float g = (rgba & 0xFFu) / 255f; 33 | rgba >>= 8; 34 | float b = (rgba & 0xFFu) / 255f; 35 | rgba >>= 8; 36 | float a = (rgba & 0xFFu) / 255f; 37 | colors[0] = new(r, g, b, a); 38 | uvs[0] = new(v.uv.X, v.uv.Y); 39 | } 40 | 41 | // same as #1 42 | [Benchmark] 43 | public void ConvertVertex2() 44 | { 45 | ref var out_pos = ref points[0]; 46 | ref var out_color = ref colors[0]; 47 | ref var out_uv = ref uvs[0]; 48 | 49 | out_pos.X = v.pos.X; 50 | out_pos.Y = v.pos.Y; 51 | uint rgba = v.col; 52 | out_color.R = (rgba & 0xFFu) / 255f; 53 | rgba >>= 8; 54 | out_color.G = (rgba & 0xFFu) / 255f; 55 | rgba >>= 8; 56 | out_color.B = (rgba & 0xFFu) / 255f; 57 | rgba >>= 8; 58 | out_color.A = (rgba & 0xFFu) / 255f; 59 | out_uv.X = v.uv.X; 60 | out_uv.Y = v.uv.Y; 61 | } 62 | 63 | // this is a bit faster 64 | [Benchmark] 65 | public unsafe void ConvertVertex3() 66 | { 67 | ref var out_pos = ref points[0]; 68 | ref var out_color = ref colors[0]; 69 | ref var out_uv = ref uvs[0]; 70 | 71 | ImDrawVert* p = v; 72 | 73 | out_pos.X = p->pos.X; 74 | out_pos.Y = p->pos.Y; 75 | uint rgba = p->col; 76 | out_color.R = (rgba & 0xFFu) / 255f; 77 | rgba >>= 8; 78 | out_color.G = (rgba & 0xFFu) / 255f; 79 | rgba >>= 8; 80 | out_color.B = (rgba & 0xFFu) / 255f; 81 | rgba >>= 8; 82 | out_color.A = (rgba & 0xFFu) / 255f; 83 | out_uv.X = p->uv.X; 84 | out_uv.Y = p->uv.Y; 85 | } 86 | 87 | // same as #3 88 | [Benchmark] 89 | public unsafe void ConvertVertex4() 90 | { 91 | ImDrawVert* p = v; 92 | 93 | points[0] = new(p->pos.X, p->pos.Y); 94 | uint rgba = p->col; 95 | float r = (rgba & 0xFFu) / 255f; 96 | rgba >>= 8; 97 | float g = (rgba & 0xFFu) / 255f; 98 | rgba >>= 8; 99 | float b = (rgba & 0xFFu) / 255f; 100 | rgba >>= 8; 101 | float a = (rgba & 0xFFu) / 255f; 102 | colors[0] = new(r, g, b, a); 103 | uvs[0] = new(p->uv.X, p->uv.Y); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /doc/test/csbench/BenchRid.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System.Reflection.Emit; 3 | using System.Reflection; 4 | using System.Runtime.InteropServices; 5 | using System.Runtime.CompilerServices; 6 | 7 | namespace csbench; 8 | 9 | [MemoryDiagnoser] 10 | public class BenchRid 11 | { 12 | private readonly Func _constructRid; 13 | private readonly ulong _id = 12345; 14 | 15 | public BenchRid() 16 | { 17 | ConstructorInfo cinfo = typeof(Rid).GetConstructor( 18 | BindingFlags.NonPublic | BindingFlags.Instance, 19 | [typeof(ulong)]) ?? 20 | throw new PlatformNotSupportedException("failed to get Rid constructor"); 21 | DynamicMethod dm = new("ConstructRid", typeof(Rid), [typeof(ulong)]); 22 | ILGenerator il = dm.GetILGenerator(); 23 | il.Emit(OpCodes.Ldarg_0); 24 | il.Emit(OpCodes.Newobj, cinfo); 25 | il.Emit(OpCodes.Ret); 26 | _constructRid = dm.CreateDelegate>(); 27 | } 28 | 29 | [Benchmark] 30 | public Rid ConstructRid_Emitted() 31 | { 32 | return _constructRid(_id); 33 | } 34 | 35 | [Benchmark] 36 | public Rid ConstructRid_Marshal() 37 | { 38 | nint ptr = Marshal.AllocHGlobal(Marshal.SizeOf()); 39 | byte[] bytes = BitConverter.GetBytes(_id); 40 | Marshal.Copy(bytes, 0, ptr, bytes.Length); 41 | Rid rv = Marshal.PtrToStructure(ptr); 42 | Marshal.FreeHGlobal(ptr); 43 | return rv; 44 | } 45 | 46 | [Benchmark] 47 | public Rid ConstructRid_MemoryMarshal_WriteRead() 48 | { 49 | Span bytes = stackalloc byte[sizeof(ulong)]; 50 | MemoryMarshal.TryWrite(bytes, in _id); 51 | return MemoryMarshal.Read(bytes); 52 | } 53 | 54 | [Benchmark] 55 | public Rid ConstructRid_MemoryMarshal_SpanCast() 56 | { 57 | ReadOnlySpan uspan = new(in _id); 58 | ReadOnlySpan bytes = MemoryMarshal.Cast(uspan); 59 | return MemoryMarshal.Read(bytes); 60 | } 61 | 62 | [Benchmark] 63 | public Rid ConstructRid_UnsafeAccessor() 64 | { 65 | return RidConstructor(_id); 66 | } 67 | 68 | [UnsafeAccessor(UnsafeAccessorKind.Constructor)] 69 | private static extern Rid RidConstructor(ulong id); 70 | 71 | [Benchmark(Baseline = true)] 72 | public unsafe Rid ConstructRid_Unsafe_DirectCopy() 73 | { 74 | Rid rv; 75 | fixed (ulong* p = &_id) 76 | { 77 | Buffer.MemoryCopy(p, &rv, sizeof(Rid), sizeof(ulong)); 78 | } 79 | return rv; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /doc/test/csbench/Program.cs: -------------------------------------------------------------------------------- 1 | using csbench; 2 | 3 | //BenchmarkRunner.Run(); 4 | BenchmarkRunner.Run(); 5 | -------------------------------------------------------------------------------- /doc/test/csbench/csbench.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | True 9 | False 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /doc/test/csbench/csbench.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.11.35222.181 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csbench", "csbench.csproj", "{D37BA677-C36A-4F7A-9E87-72D5CF034A7B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {D37BA677-C36A-4F7A-9E87-72D5CF034A7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {D37BA677-C36A-4F7A-9E87-72D5CF034A7B}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {D37BA677-C36A-4F7A-9E87-72D5CF034A7B}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {D37BA677-C36A-4F7A-9E87-72D5CF034A7B}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {21D11FF2-8E04-4538-B85D-36C1B5758C37} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /doc/test/csharp/Main.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System; 3 | using Xunit; 4 | using ImGuiGodot; 5 | using ImGuiNET; 6 | 7 | namespace test; 8 | 9 | public partial class Main : Node 10 | { 11 | [Signal] 12 | public delegate void WithinProcessEventHandler(); 13 | 14 | public override async void _Ready() 15 | { 16 | try 17 | { 18 | var io = ImGui.GetIO(); 19 | io.SetIniFilename(""); 20 | 21 | await ToSignal(this, SignalName.WithinProcess); 22 | 23 | Assert.Equal(ImGuiGD.Scale, 2); 24 | Assert.Equal(ImGui.GetFontSize(), 26.0f); 25 | 26 | // just for comparison with GDScript test 27 | Assert.Equal(ImGui.GetID("test_id"), 3584119329u); 28 | 29 | CallDeferred(nameof(ChangeScale)); 30 | 31 | await ToSignal(this, SignalName.WithinProcess); 32 | 33 | Assert.Equal(ImGuiGD.Scale, 4); 34 | Assert.Equal(ImGui.GetFontSize(), 52.0f); 35 | 36 | // IniSavingRate 37 | GetTree().CreateTimer(5.1).Timeout += OnTimeout; 38 | } 39 | catch (Exception e) 40 | { 41 | GD.Print(e); 42 | GetTree().Quit(1); 43 | } 44 | } 45 | 46 | public async void OnTimeout() 47 | { 48 | try 49 | { 50 | await ToSignal(this, SignalName.WithinProcess); 51 | 52 | Assert.False(FileAccess.FileExists("user://imgui.ini")); 53 | 54 | GD.Print("All tests passed."); 55 | GetTree().Quit(0); 56 | } 57 | catch (Exception e) 58 | { 59 | GD.Print(e); 60 | GetTree().Quit(1); 61 | } 62 | } 63 | 64 | public override void _Process(double delta) 65 | { 66 | EmitSignal(SignalName.WithinProcess); 67 | } 68 | 69 | private static void ChangeScale() 70 | { 71 | ImGuiGD.Scale = 4; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /doc/test/csharp/addons.json: -------------------------------------------------------------------------------- 1 | { 2 | "addons": { 3 | "imgui-godot": { 4 | "url": "../../../addons/imgui-godot", 5 | "source": "symlink" 6 | }, 7 | "TestData": { 8 | "url": "../addons/TestData", 9 | "source": "symlink" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /doc/test/csharp/export/.gdignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkdawson/imgui-godot/8a9f0c423533e22a8fa156c5f7c79877c01f437d/doc/test/csharp/export/.gdignore -------------------------------------------------------------------------------- /doc/test/csharp/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/test/csharp/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://kfs316jt1ha0" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /doc/test/csharp/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://b4sq25vkasfoy"] 2 | 3 | [ext_resource type="Script" path="res://Main.cs" id="1_sm0lr"] 4 | 5 | [node name="Node2D" type="Node2D"] 6 | script = ExtResource("1_sm0lr") 7 | -------------------------------------------------------------------------------- /doc/test/csharp/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [addons] 12 | 13 | imgui/config="res://addons/TestData/config_scale2x.tres" 14 | 15 | [application] 16 | 17 | config/name="test" 18 | run/main_scene="res://main.tscn" 19 | config/features=PackedStringArray("4.3", "C#", "Forward Plus") 20 | config/icon="res://icon.svg" 21 | 22 | [autoload] 23 | 24 | ImGuiRoot="*res://addons/imgui-godot/data/ImGuiRoot.tscn" 25 | 26 | [dotnet] 27 | 28 | project/assembly_name="test" 29 | 30 | [editor_plugins] 31 | 32 | enabled=PackedStringArray("res://addons/imgui-godot/plugin.cfg") 33 | 34 | [rendering] 35 | 36 | textures/vram_compression/import_etc2_astc=true 37 | -------------------------------------------------------------------------------- /doc/test/csharp/test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | net7.0 5 | net8.0 6 | true 7 | True 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /doc/test/csharp/test.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2012 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "test.csproj", "{67604B9A-7DDB-4C26-8C73-5ACE0DD01BFD}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Any CPU = Debug|Any CPU 8 | ExportDebug|Any CPU = ExportDebug|Any CPU 9 | ExportRelease|Any CPU = ExportRelease|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {67604B9A-7DDB-4C26-8C73-5ACE0DD01BFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {67604B9A-7DDB-4C26-8C73-5ACE0DD01BFD}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {67604B9A-7DDB-4C26-8C73-5ACE0DD01BFD}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU 15 | {67604B9A-7DDB-4C26-8C73-5ACE0DD01BFD}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU 16 | {67604B9A-7DDB-4C26-8C73-5ACE0DD01BFD}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU 17 | {67604B9A-7DDB-4C26-8C73-5ACE0DD01BFD}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /doc/test/gdscript/addons.json: -------------------------------------------------------------------------------- 1 | { 2 | "addons": { 3 | "imgui-godot": { 4 | "url": "../../../addons/imgui-godot", 5 | "source": "symlink" 6 | }, 7 | "TestData": { 8 | "url": "../addons/TestData", 9 | "source": "symlink" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /doc/test/gdscript/export/.gdignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkdawson/imgui-godot/8a9f0c423533e22a8fa156c5f7c79877c01f437d/doc/test/gdscript/export/.gdignore -------------------------------------------------------------------------------- /doc/test/gdscript/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/test/gdscript/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://kfs316jt1ha0" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /doc/test/gdscript/main.gd: -------------------------------------------------------------------------------- 1 | extends "res://test_base.gd" 2 | 3 | signal within_process 4 | 5 | func _ready() -> void: 6 | ImGuiGD.SetIniFilename("") 7 | 8 | await within_process 9 | 10 | # ImGuiConfig loads properly 11 | assert_equal(ImGuiGD.Scale, 2) 12 | assert_equal(ImGui.GetFontSize(), 26) 13 | 14 | # StringName conversion 15 | assert_equal(ImGui.GetID("test_id"), 3584119329) 16 | 17 | # rescale 18 | call_deferred("change_scale") 19 | 20 | await within_process 21 | 22 | assert_equal(ImGuiGD.Scale, 4) 23 | assert_equal(ImGui.GetFontSize(), 52) 24 | 25 | # IniSavingRate 26 | get_tree().create_timer(5.1).timeout.connect(on_timeout) 27 | 28 | func on_timeout(): 29 | await within_process 30 | 31 | assert_false(FileAccess.file_exists("user://imgui.ini")) 32 | 33 | exit_with_status() 34 | 35 | func _process(_delta: float) -> void: 36 | within_process.emit() 37 | 38 | func change_scale() -> void: 39 | ImGuiGD.Scale = 4 40 | ImGuiGD.RebuildFontAtlas() 41 | -------------------------------------------------------------------------------- /doc/test/gdscript/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://b4sq25vkasfoy"] 2 | 3 | [ext_resource type="Script" path="res://main.gd" id="1_4lpr7"] 4 | 5 | [node name="Node2D" type="Node2D"] 6 | script = ExtResource("1_4lpr7") 7 | -------------------------------------------------------------------------------- /doc/test/gdscript/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [addons] 12 | 13 | imgui/config="res://addons/TestData/config_scale2x.tres" 14 | 15 | [application] 16 | 17 | config/name="test" 18 | run/main_scene="res://main.tscn" 19 | config/features=PackedStringArray("4.3", "Forward Plus") 20 | config/icon="res://icon.svg" 21 | 22 | [autoload] 23 | 24 | ImGuiRoot="*res://addons/imgui-godot/data/ImGuiRoot.tscn" 25 | 26 | [editor_plugins] 27 | 28 | enabled=PackedStringArray("res://addons/imgui-godot/plugin.cfg") 29 | 30 | [rendering] 31 | 32 | textures/vram_compression/import_etc2_astc=true 33 | -------------------------------------------------------------------------------- /doc/test/gdscript/test_base.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | var test_passes := 0 4 | var test_failures := 0 5 | 6 | func __get_stack_frame(): 7 | var me = get_script() 8 | for s in get_stack(): 9 | if s.source == me.resource_path: 10 | return s 11 | return null 12 | 13 | func __assert_pass(): 14 | test_passes += 1 15 | 16 | func __assert_fail(): 17 | test_failures += 1 18 | var s = __get_stack_frame() 19 | if s != null: 20 | print_rich ("[color=red] == FAILURE: In function %s() from '%s' on line %s[/color]" % [s.function, s.source, s.line]) 21 | else: 22 | print_rich ("[color=red] == FAILURE (run with --debug to get more information!) ==[/color]") 23 | 24 | func assert_equal(actual, expected): 25 | if actual == expected: 26 | __assert_pass() 27 | else: 28 | __assert_fail() 29 | print (" |-> Expected '%s' but got '%s'" % [expected, actual]) 30 | 31 | func assert_true(v): 32 | assert_equal(v, true) 33 | 34 | func assert_false(v): 35 | assert_equal(v, false) 36 | 37 | func assert_not_equal(actual, expected): 38 | if actual != expected: 39 | __assert_pass() 40 | else: 41 | __assert_fail() 42 | print (" |-> Expected '%s' NOT to equal '%s'" % [expected, actual]) 43 | 44 | func exit_with_status() -> void: 45 | var success: bool = (test_failures == 0) 46 | print ("") 47 | print_rich ("[color=%s] ==== TESTS FINISHED ==== [/color]" % ("green" if success else "red")) 48 | print ("") 49 | print_rich (" PASSES: [color=green]%s[/color]" % test_passes) 50 | print_rich (" FAILURES: [color=red]%s[/color]" % test_failures) 51 | print ("") 52 | 53 | if success: 54 | print_rich("[color=green] ******** PASSED ******** [/color]") 55 | else: 56 | print_rich("[color=red] ******** FAILED ********[/color]") 57 | print("") 58 | 59 | get_tree().quit(0 if success else 1) 60 | -------------------------------------------------------------------------------- /export_presets.cfg: -------------------------------------------------------------------------------- 1 | [preset.0] 2 | 3 | name="Linux" 4 | platform="Linux/X11" 5 | runnable=true 6 | dedicated_server=false 7 | custom_features="" 8 | export_filter="all_resources" 9 | include_filter="" 10 | exclude_filter="" 11 | export_path="export/demo" 12 | encryption_include_filters="" 13 | encryption_exclude_filters="" 14 | encrypt_pck=false 15 | encrypt_directory=false 16 | 17 | [preset.0.options] 18 | 19 | custom_template/debug="" 20 | custom_template/release="" 21 | debug/export_console_wrapper=1 22 | binary_format/embed_pck=false 23 | texture_format/bptc=false 24 | texture_format/s3tc=true 25 | texture_format/etc=false 26 | texture_format/etc2=false 27 | binary_format/architecture="x86_64" 28 | ssh_remote_deploy/enabled=false 29 | ssh_remote_deploy/host="user@host_ip" 30 | ssh_remote_deploy/port="22" 31 | ssh_remote_deploy/extra_args_ssh="" 32 | ssh_remote_deploy/extra_args_scp="" 33 | ssh_remote_deploy/run_script="#!/usr/bin/env bash 34 | export DISPLAY=:0 35 | unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\" 36 | \"{temp_dir}/{exe_name}\" {cmd_args}" 37 | ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash 38 | kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\") 39 | rm -rf \"{temp_dir}\"" 40 | dotnet/include_scripts_content=false 41 | dotnet/include_debug_symbols=true 42 | dotnet/embed_build_outputs=false 43 | texture_format/s3tc_bptc=true 44 | texture_format/etc2_astc=false 45 | debug/export_console_script=1 46 | texture_format/no_bptc_fallbacks=true 47 | imgui/debug=true 48 | imgui/release=true 49 | -------------------------------------------------------------------------------- /gdext/.gdignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkdawson/imgui-godot/8a9f0c423533e22a8fa156c5f7c79877c01f437d/gdext/.gdignore -------------------------------------------------------------------------------- /gdext/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.26) 2 | 3 | # using cmake for dev on Windows, scons for production builds 4 | 5 | # set up vcpkg 6 | if (WIN32) 7 | set(VCPKG_TARGET_TRIPLET x64-windows-static-md) 8 | endif() 9 | file(TO_CMAKE_PATH "$ENV{VCPKG_ROOT}" VCPKG_ROOT) 10 | set(CMAKE_TOOLCHAIN_FILE "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake") 11 | 12 | project(imgui-godot-native CXX) 13 | 14 | if (NOT TARGET godot-cpp) 15 | include(FetchContent) 16 | FetchContent_Declare( 17 | godot-cpp 18 | GIT_REPOSITORY https://github.com/godotengine/godot-cpp 19 | GIT_TAG 4.2 20 | ) 21 | FetchContent_MakeAvailable(godot-cpp) 22 | endif() 23 | 24 | find_package(freetype CONFIG REQUIRED) 25 | #find_package(unofficial-lunasvg CONFIG REQUIRED) 26 | 27 | add_library(imgui-godot-native SHARED) 28 | target_compile_features(imgui-godot-native PRIVATE cxx_std_20) 29 | target_compile_definitions(imgui-godot-native PUBLIC 30 | IMGUI_USER_CONFIG="imconfig-godot.h" 31 | IMGUI_ENABLE_FREETYPE 32 | # IMGUI_ENABLE_FREETYPE_LUNASVG 33 | IGN_EXPORT 34 | # REAL_T_IS_DOUBLE 35 | ) 36 | 37 | # target_compile_definitions(godot-cpp PUBLIC 38 | # REAL_T_IS_DOUBLE 39 | # ) 40 | 41 | if (MSVC) 42 | target_compile_options(godot-cpp PRIVATE "/MP") 43 | target_compile_options(imgui-godot-native PRIVATE "/MP") 44 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD ON) 45 | endif() 46 | 47 | add_subdirectory(src) 48 | 49 | target_sources(imgui-godot-native PRIVATE 50 | imgui/imgui.cpp 51 | imgui/imgui_demo.cpp 52 | imgui/imgui_draw.cpp 53 | imgui/imgui_tables.cpp 54 | imgui/imgui_widgets.cpp 55 | imgui/imgui.h 56 | imgui/misc/freetype/imgui_freetype.cpp 57 | imgui/misc/freetype/imgui_freetype.h 58 | include/imconfig-godot.h 59 | include/imgui-godot.h 60 | gen/imgui_bindings.gen.h 61 | gen/cimgui.cpp 62 | gen/cimgui.h 63 | ) 64 | 65 | target_link_libraries(imgui-godot-native PUBLIC 66 | godot-cpp 67 | freetype 68 | # unofficial::lunasvg::lunasvg 69 | ) 70 | 71 | target_include_directories(imgui-godot-native PRIVATE src imgui gen PUBLIC include) 72 | set_target_properties(imgui-godot-native PROPERTIES PUBLIC_HEADER "include/imconfig-godot.h;include/imgui-godot.h") 73 | 74 | if(WIN32) 75 | set_property(TARGET imgui-godot-native 76 | PROPERTY OUTPUT_NAME "libimgui-godot-native.windows.$,debug,release>.x86_64") 77 | elseif(APPLE) 78 | set_property(TARGET imgui-godot-native 79 | PROPERTY OUTPUT_NAME "imgui-godot-native.macos.$,debug,release>") 80 | set_target_properties(imgui-godot-native PROPERTIES SUFFIX "") 81 | endif() 82 | 83 | set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/../addons/imgui-godot") 84 | 85 | if(WIN32) 86 | install(TARGETS imgui-godot-native 87 | RUNTIME DESTINATION bin 88 | PUBLIC_HEADER DESTINATION include 89 | ) 90 | elseif(APPLE) 91 | install(TARGETS imgui-godot-native 92 | DESTINATION bin/libimgui-godot-native.macos.$,debug,release>.framework 93 | PUBLIC_HEADER DESTINATION include 94 | ) 95 | endif() 96 | install(FILES "${CMAKE_SOURCE_DIR}/imgui-godot-native.gdextension" 97 | DESTINATION . 98 | ) 99 | -------------------------------------------------------------------------------- /gdext/SConstruct: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from glob import glob 3 | from pathlib import Path 4 | import os 5 | import shutil 6 | import subprocess 7 | import SCons 8 | import sys 9 | 10 | 11 | class CustomCacheDir(SCons.CacheDir.CacheDir): 12 | @classmethod 13 | def copy_to_cache(cls, env, src, dst) -> str: 14 | fn = str(src) 15 | if fn.startswith("godot-cpp"): 16 | if os.path.splitext(fn)[1] not in [".lib", ".dll", ".exp", ".a", ".so"]: 17 | return super().copy_to_cache(env, src, dst) 18 | return None 19 | 20 | 21 | env = SConscript("godot-cpp/SConstruct") 22 | env.CacheDir("scons_cache", CustomCacheDir) 23 | env.Append(CPPDEFINES=['IMGUI_USER_CONFIG="\\"imconfig-godot.h\\""', "IGN_EXPORT"]) 24 | env.Append(CPPPATH=["src/", "imgui/", "include/", "gen/"]) 25 | env.Replace(CXXFLAGS=str(env["CXXFLAGS"]).replace("c++17", "c++20")) 26 | 27 | windows = env["platform"] == "windows" 28 | linux = env["platform"] == "linux" 29 | config = "release" if env["target"] == "template_release" else "debug" 30 | 31 | if config == "release": 32 | if windows: 33 | env.Append(CPPDEFINES=["NDEBUG"]) 34 | 35 | if windows: 36 | if env["arch"] == "arm64": 37 | triplet = "arm64-windows-static" 38 | else: 39 | triplet = "x64-windows-static" 40 | if not os.path.exists(f"vcpkg_installed/{triplet}"): 41 | subprocess.call(f'"%VCPKG_ROOT%/vcpkg" install --triplet {triplet}', shell=True) 42 | elif linux: 43 | triplet = "x64-linux" 44 | if not os.path.exists("vcpkg_installed"): 45 | subprocess.call("$VCPKG_ROOT/vcpkg install", shell=True) 46 | else: 47 | triplet = "arm64-osx" 48 | if not os.path.exists("vcpkg_installed"): 49 | if subprocess.call("zsh scripts/vcpkg-macos.sh", shell=True) != 0: 50 | sys.exit(1) 51 | 52 | if not os.path.exists("gen/imgui_bindings.gen.h"): 53 | subprocess.call("python scripts/gds_bindings.py", shell=True) 54 | 55 | shutil.copy("imgui-godot-native.gdextension", "../addons/imgui-godot/") 56 | shutil.copytree("include", "../addons/imgui-godot/include", dirs_exist_ok=True) 57 | 58 | sources = Glob("src/*.cpp") + Glob("imgui/*.cpp") + Glob("gen/*.cpp") 59 | 60 | (extension_path,) = glob("../addons/imgui-godot/*.gdextension") 61 | addon_path = Path(extension_path).parent 62 | project_name = Path(extension_path).stem 63 | 64 | libpath = env.get("LIBPATH", []) 65 | libs = [env["LIBS"]] 66 | 67 | env.Append(CPPPATH=["imgui/misc/freetype/"]) 68 | env.Append(CPPPATH=[f"vcpkg_installed/{triplet}/include"]) 69 | env.Append(CPPDEFINES=["IMGUI_ENABLE_FREETYPE"]) 70 | # env.Append(CPPDEFINES=["IMGUI_ENABLE_FREETYPE_LUNASVG"]) 71 | sources += Glob("imgui/misc/freetype/*.cpp") 72 | libpath += [f"vcpkg_installed/{triplet}/lib"] 73 | libs += [ 74 | "freetype", 75 | # "lunasvg", 76 | "bz2", 77 | "libpng16" if windows else "png16", 78 | "zlib" if windows else "z", 79 | "brotlidec", 80 | "brotlicommon", 81 | ] 82 | 83 | if env["platform"] == "macos": 84 | library = env.SharedLibrary( 85 | "{0}/bin/lib{1}.{2}.{3}.framework/{1}.{2}.{3}".format( 86 | addon_path, 87 | project_name, 88 | env["platform"], 89 | config, 90 | ), 91 | source=sources, 92 | LIBPATH=libpath, 93 | LIBS=libs, 94 | ) 95 | else: 96 | library = env.SharedLibrary( 97 | "{}/bin/lib{}.{}.{}.{}{}".format( 98 | addon_path, 99 | project_name, 100 | env["platform"], 101 | config, 102 | env["arch"], 103 | env["SHLIBSUFFIX"], 104 | ), 105 | source=sources, 106 | LIBPATH=libpath, 107 | LIBS=libs, 108 | ) 109 | 110 | Default(library) 111 | -------------------------------------------------------------------------------- /gdext/imgui-godot-native.gdextension: -------------------------------------------------------------------------------- 1 | [configuration] 2 | 3 | entry_symbol = "ign_init" 4 | compatibility_minimum = 4.2 5 | 6 | [libraries] 7 | 8 | macos.debug = "bin/libimgui-godot-native.macos.debug.framework" 9 | macos.release = "bin/libimgui-godot-native.macos.release.framework" 10 | windows.debug.x86_64 = "bin/libimgui-godot-native.windows.debug.x86_64.dll" 11 | windows.release.x86_64 = "bin/libimgui-godot-native.windows.release.x86_64.dll" 12 | linux.debug.x86_64 = "bin/libimgui-godot-native.linux.debug.x86_64.so" 13 | linux.release.x86_64 = "bin/libimgui-godot-native.linux.release.x86_64.so" 14 | -------------------------------------------------------------------------------- /gdext/include/.gdignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkdawson/imgui-godot/8a9f0c423533e22a8fa156c5f7c79877c01f437d/gdext/include/.gdignore -------------------------------------------------------------------------------- /gdext/include/imconfig-godot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define IMGUI_DISABLE_OBSOLETE_FUNCTIONS // match ImGui.NET 4 | 5 | #if __has_include("godot_cpp/godot.hpp") // GDExtension 6 | #include 7 | #include 8 | #include 9 | #include 10 | using godot::Color; 11 | using godot::Vector2; 12 | using godot::Vector2i; 13 | using godot::Vector4; 14 | 15 | #if defined(DEBUG_ENABLED) && defined(IGN_EXPORT) 16 | #ifndef IM_ASSERT 17 | #include 18 | #define IM_ASSERT(_EXPR) \ 19 | do \ 20 | { \ 21 | if (!(_EXPR)) \ 22 | godot::UtilityFunctions::push_error(godot::vformat("IM_ASSERT %s (%s:%d)", #_EXPR, __FILE__, __LINE__)); \ 23 | } while (0) 24 | #endif 25 | #endif 26 | #else // module 27 | #include "core/math/color.h" 28 | #include "core/math/vector2.h" 29 | #include "core/math/vector2i.h" 30 | #include "core/math/vector4.h" 31 | #endif 32 | 33 | #define IM_VEC2_CLASS_EXTRA \ 34 | constexpr ImVec2(const Vector2& f) : x(f.x), y(f.y) \ 35 | { \ 36 | } \ 37 | operator Vector2() const \ 38 | { \ 39 | return Vector2(x, y); \ 40 | } \ 41 | constexpr ImVec2(const Vector2i& f) : x(static_cast(f.x)), y(static_cast(f.y)) \ 42 | { \ 43 | } \ 44 | operator Vector2i() const \ 45 | { \ 46 | return Vector2i(static_cast(x), static_cast(y)); \ 47 | } 48 | 49 | #define IM_VEC4_CLASS_EXTRA \ 50 | constexpr ImVec4(const Vector4& f) : x(f.x), y(f.y), z(f.z), w(f.w) \ 51 | { \ 52 | } \ 53 | operator Vector4() const \ 54 | { \ 55 | return Vector4(x, y, z, w); \ 56 | } \ 57 | constexpr ImVec4(const Color& c) : x(c.r), y(c.g), z(c.b), w(c.a) \ 58 | { \ 59 | } \ 60 | operator Color() const \ 61 | { \ 62 | return Color(x, y, z, w); \ 63 | } 64 | -------------------------------------------------------------------------------- /gdext/scripts/vcpkg-macos.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | vcpkg_x64=$(pwd)/vcpkg_installed.x64 4 | 5 | $VCPKG_ROOT/vcpkg install --triplet x64-osx 6 | mv vcpkg_installed $vcpkg_x64 7 | $VCPKG_ROOT/vcpkg install --triplet arm64-osx 8 | 9 | for libpath in "lib" "debug/lib" 10 | do 11 | pushd vcpkg_installed/arm64-osx/$libpath 12 | for x in *.a 13 | do 14 | echo "$libpath/$x" 15 | lipo -create -output $x $x $vcpkg_x64/x64-osx/$libpath/$x 16 | done 17 | popd 18 | done 19 | 20 | rm -r $vcpkg_x64 21 | -------------------------------------------------------------------------------- /gdext/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(imgui-godot-native PRIVATE 2 | CanvasRenderer.cpp 3 | CanvasRenderer.h 4 | common.h 5 | Context.cpp 6 | Context.h 7 | DummyRenderer.h 8 | Fonts.cpp 9 | Fonts.h 10 | GdsCache.cpp 11 | GdsCache.h 12 | ImGuiAPI.cpp 13 | ImGuiAPI.h 14 | ImGuiController.cpp 15 | ImGuiController.h 16 | ImGuiControllerHelper.cpp 17 | ImGuiControllerHelper.h 18 | ImGuiGD.cpp 19 | ImGuiGD.h 20 | ImGuiLayer.cpp 21 | ImGuiLayer.h 22 | ImGuiSync.cpp 23 | ImGuiSync.h 24 | Input.cpp 25 | Input.h 26 | InputLocal.cpp 27 | InputLocal.h 28 | main.cpp 29 | RdRenderer.cpp 30 | RdRenderer.h 31 | RdRendererThreadSafe.cpp 32 | RdRendererThreadSafe.h 33 | Renderer.h 34 | Viewports.cpp 35 | Viewports.h 36 | ) 37 | -------------------------------------------------------------------------------- /gdext/src/CanvasRenderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Renderer.h" 3 | #include 4 | #include 5 | #include 6 | 7 | using godot::RID; 8 | 9 | namespace ImGui::Godot { 10 | 11 | class CanvasRenderer : public Renderer 12 | { 13 | public: 14 | CanvasRenderer(); 15 | virtual ~CanvasRenderer(); 16 | 17 | virtual const char* Name() override { return "godot4_canvas"; } 18 | 19 | bool Init() override; 20 | void InitViewport(RID vprid) override; 21 | void CloseViewport(RID vprid) override; 22 | void Render() override; 23 | void OnHide() override; 24 | 25 | private: 26 | struct Impl; 27 | std::unique_ptr impl; 28 | }; 29 | 30 | } // namespace ImGui::Godot 31 | -------------------------------------------------------------------------------- /gdext/src/Context.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "DummyRenderer.h" 22 | #include "Fonts.h" 23 | #include "GdsCache.h" 24 | #include "ImGuiGD.h" 25 | #include "ImGuiLayer.h" 26 | #include "Input.h" 27 | #include "RdRenderer.h" 28 | #include "RdRendererThreadSafe.h" 29 | #include "Renderer.h" 30 | #include "Viewports.h" 31 | 32 | using namespace godot; 33 | 34 | namespace ImGui::Godot { 35 | 36 | enum class RendererType 37 | { 38 | Dummy, 39 | Canvas, 40 | RenderingDevice, 41 | }; 42 | 43 | struct Context 44 | { 45 | std::unique_ptr viewports; 46 | std::unique_ptr fonts; 47 | std::unique_ptr input; 48 | std::unique_ptr renderer; 49 | 50 | float scale = 1.0f; 51 | float joyAxisDeadZone = 0.15f; 52 | int layerNum = 128; 53 | ImGuiLayer* layer = nullptr; 54 | bool inProcessFrame = false; 55 | std::vector iniFilename; 56 | 57 | Context(std::unique_ptr r); 58 | ~Context(); 59 | 60 | void Render(); 61 | void Update(double delta, Vector2 displaySize); 62 | }; 63 | 64 | Context* GetContext(); 65 | 66 | void Init(const Ref& config); 67 | void Shutdown(); 68 | void Connect(const Callable& callable); 69 | void ResetFonts(); 70 | void AddFont(const Ref& fontFile, int fontSize, bool merge = false, 71 | const ImVector& glyphRanges = {}); 72 | void AddFontDefault(); 73 | void RebuildFontAtlas(); 74 | void SetIniFilename(const String& fn); 75 | void SetVisible(bool visible); 76 | 77 | bool SubViewportWidget(SubViewport* svp); 78 | } // namespace ImGui::Godot 79 | -------------------------------------------------------------------------------- /gdext/src/DummyRenderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Renderer.h" 3 | 4 | namespace ImGui::Godot { 5 | 6 | class DummyRenderer : public Renderer 7 | { 8 | public: 9 | DummyRenderer() {} 10 | ~DummyRenderer() {} 11 | 12 | const char* Name() override { return "godot4_dummy"; } 13 | 14 | bool Init() override { return true; } 15 | void InitViewport(RID vprid) override {} 16 | void CloseViewport(RID vprid) override {} 17 | void Render() override {} 18 | void OnHide() override {} 19 | }; 20 | 21 | } // namespace ImGui::Godot 22 | -------------------------------------------------------------------------------- /gdext/src/Fonts.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | using namespace godot; 6 | 7 | namespace ImGui::Godot { 8 | 9 | class Fonts 10 | { 11 | public: 12 | Fonts(); 13 | ~Fonts(); 14 | 15 | void Reset(); 16 | void Add(Ref fontData, int fontSize, bool merge = false, const ImVector& glyphRanges = {}); 17 | void RebuildFontAtlas(float scale); 18 | 19 | private: 20 | struct Impl; 21 | std::unique_ptr impl; 22 | }; 23 | 24 | } // namespace ImGui::Godot 25 | -------------------------------------------------------------------------------- /gdext/src/GdsCache.cpp: -------------------------------------------------------------------------------- 1 | #include "GdsCache.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace godot; 9 | 10 | namespace ImGui::Godot { 11 | 12 | std::unique_ptr gdscache = std::make_unique(); 13 | 14 | struct GdsCache::Impl 15 | { 16 | std::unordered_map> bufs; 17 | std::unordered_map used; 18 | 19 | static void CopyInput(std::vector& buf, const Array& a) 20 | { 21 | CharString cs = String(a[0]).utf8(); 22 | const std::string_view sv = cs.get_data(); 23 | if (sv.size() >= buf.size()) 24 | return; 25 | std::copy(sv.begin(), sv.end(), buf.begin()); 26 | buf[sv.size()] = '\0'; 27 | } 28 | }; 29 | 30 | GdsCache::GdsCache() : impl(std::make_unique()) 31 | { 32 | } 33 | 34 | GdsCache::~GdsCache() 35 | { 36 | } 37 | 38 | void GdsCache::OnNewFrame() 39 | { 40 | for (auto it = impl->used.begin(); it != impl->used.end();) 41 | { 42 | if (!it->second) 43 | { 44 | impl->bufs.erase(it->first); 45 | it = impl->used.erase(it); 46 | } 47 | else 48 | { 49 | it->second = false; 50 | ++it; 51 | } 52 | } 53 | } 54 | 55 | std::vector& GdsCache::GetTextBuf(const StringName& label, size_t size, const Array& a) 56 | { 57 | const int64_t hash = ImGui::GetID((void*)label.hash()); 58 | impl->used[hash] = true; 59 | auto it = impl->bufs.find(hash); 60 | if (it == impl->bufs.end()) 61 | { 62 | impl->bufs[hash] = std::vector(size); 63 | std::vector& buf = impl->bufs[hash]; 64 | Impl::CopyInput(buf, a); 65 | return buf; 66 | } 67 | else 68 | { 69 | std::vector& buf = it->second; 70 | buf.resize(size); 71 | Impl::CopyInput(buf, a); 72 | return buf; 73 | } 74 | } 75 | 76 | const std::vector& GdsCache::GetZeroArray(const Array& a) 77 | { 78 | const int64_t hash = a.hash(); 79 | impl->used[hash] = true; 80 | if (auto it = impl->bufs.find(hash); it != impl->bufs.end()) 81 | { 82 | return it->second; 83 | } 84 | 85 | impl->bufs[hash] = {}; 86 | std::vector& buf = impl->bufs[hash]; 87 | for (int i = 0; i < a.size(); ++i) 88 | { 89 | CharString cs = String(a[i]).utf8(); 90 | const std::string_view sv = cs.get_data(); 91 | std::copy(sv.begin(), sv.end(), std::back_inserter(buf)); 92 | buf.push_back('\0'); 93 | } 94 | buf.push_back('\0'); 95 | return buf; 96 | } 97 | 98 | } // namespace ImGui::Godot 99 | -------------------------------------------------------------------------------- /gdext/src/GdsCache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace godot; 7 | 8 | namespace ImGui::Godot { 9 | 10 | class GdsCache 11 | { 12 | public: 13 | GdsCache(); 14 | ~GdsCache(); 15 | 16 | void OnNewFrame(); 17 | std::vector& GetTextBuf(const StringName& label, size_t size, const Array& a); 18 | const std::vector& GetZeroArray(const Array& a); 19 | 20 | private: 21 | struct Impl; 22 | std::unique_ptr impl; 23 | }; 24 | 25 | extern std::unique_ptr gdscache; 26 | 27 | } // namespace ImGui::Godot 28 | -------------------------------------------------------------------------------- /gdext/src/ImGuiAPI.cpp: -------------------------------------------------------------------------------- 1 | #include "ImGuiAPI.h" 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace godot; 7 | 8 | namespace { 9 | inline Vector2 ToVector2(ImVec2 v) 10 | { 11 | return Vector2(v.x, v.y); 12 | } 13 | 14 | inline Color ToColor(const ImVec4& v) 15 | { 16 | return Color(v.x, v.y, v.z, v.w); 17 | } 18 | 19 | inline ImVec4 FromColor(const Color& c) 20 | { 21 | return {c.r, c.g, c.b, c.a}; 22 | } 23 | 24 | inline PackedColorArray ToPackedColorArray(ImVec4* colors, int size) 25 | { 26 | PackedColorArray rv; 27 | rv.resize(size); 28 | for (int i = 0; i < size; ++i) 29 | rv[i] = ToColor(colors[i]); 30 | return rv; 31 | } 32 | 33 | inline void FromPackedColorArray(const PackedColorArray& in, ImVec4* out) 34 | { 35 | for (int i = 0; i < in.size(); ++i) 36 | out[i] = FromColor(in[i]); 37 | } 38 | 39 | inline Array FromImVector(const ImVector_ImGuiSelectionRequest& in) 40 | { 41 | Array rv; 42 | for (int i = 0; i < in.Size; ++i) 43 | { 44 | Ref req; 45 | req.instantiate(); 46 | req->_SetPtr(&in.Data[i]); 47 | rv.append(req); 48 | } 49 | return rv; 50 | } 51 | 52 | inline ImVector_ImGuiSelectionRequest ToImVector(const Array& in) 53 | { 54 | ERR_FAIL_V_MSG({}, "ToImVector not implemented"); 55 | return {}; 56 | } 57 | 58 | inline Array SpecsToArray(const ImGuiTableSortSpecs* p) 59 | { 60 | ERR_FAIL_COND_V(!p, {}); 61 | 62 | Array rv; 63 | for (int i = 0; i < p->SpecsCount; ++i) 64 | { 65 | Ref col; 66 | col.instantiate(); 67 | col->_SetPtr(const_cast(&p->Specs[i])); 68 | rv.append(col); 69 | } 70 | return rv; 71 | } 72 | 73 | const char* sn_to_cstr(const StringName& sn) 74 | { 75 | static std::unordered_map stringname_cache; 76 | const int64_t hash = sn.hash(); 77 | if (!stringname_cache.contains(hash)) 78 | { 79 | stringname_cache[hash] = std::string(String(sn).utf8().get_data()); 80 | } 81 | return stringname_cache[hash].c_str(); 82 | } 83 | } // namespace 84 | 85 | namespace ImGui::Godot { 86 | 87 | void register_imgui_api() 88 | { 89 | ClassDB::register_class<::ImGui::Godot::ImGui>(); 90 | 91 | Engine::get_singleton()->register_singleton("ImGuiAPI", memnew(::ImGui::Godot::ImGui)); 92 | } 93 | 94 | void unregister_imgui_api() 95 | { 96 | ::ImGui::Godot::ImGui* api = (::ImGui::Godot::ImGui*)Engine::get_singleton()->get_singleton("ImGuiAPI"); 97 | Engine::get_singleton()->unregister_singleton("ImGuiAPI"); 98 | memdelete(api); 99 | } 100 | 101 | #include "imgui_bindings_impl.gen.h" 102 | 103 | } // namespace ImGui::Godot 104 | -------------------------------------------------------------------------------- /gdext/src/ImGuiAPI.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GdsCache.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | using namespace godot; 14 | 15 | namespace ImGui::Godot { 16 | 17 | template 18 | struct GdsPtr 19 | { 20 | // TypedArray& arr; 21 | Array& arr; 22 | T val; 23 | 24 | GdsPtr(Array& x) : arr(x) 25 | { 26 | // safety for tool script reload, and programming errors 27 | if (arr.size() == 0) [[unlikely]] 28 | arr.append(T()); 29 | val = arr[0]; 30 | } 31 | 32 | ~GdsPtr() { arr[0] = val; } 33 | 34 | operator T*() { return &val; } 35 | }; 36 | 37 | template <> 38 | struct GdsPtr 39 | { 40 | Array& arr; 41 | std::vector& buf; 42 | int64_t bufhash; 43 | 44 | GdsPtr(Array& x, size_t s, const StringName& label) : arr(x), buf(gdscache->GetTextBuf(label, s, x)) 45 | { 46 | bufhash = std::hash{}({buf.begin(), buf.end()}); 47 | } 48 | 49 | ~GdsPtr() 50 | { 51 | if (bufhash != std::hash{}({buf.begin(), buf.end()})) 52 | { 53 | arr[0] = String::utf8(buf.data()); 54 | } 55 | } 56 | 57 | operator char*() { return buf.data(); } 58 | }; 59 | 60 | template 61 | struct GdsArray 62 | { 63 | Array& arr; 64 | std::vector buf; 65 | 66 | GdsArray(Array& a) : arr(a), buf(a.size()) 67 | { 68 | for (int i = 0; i < arr.size(); ++i) 69 | { 70 | buf[i] = arr[i]; 71 | } 72 | } 73 | 74 | ~GdsArray() 75 | { 76 | for (int i = 0; i < arr.size(); ++i) 77 | { 78 | arr[i] = buf[i]; 79 | } 80 | } 81 | 82 | operator T*() { return buf.data(); } 83 | }; 84 | 85 | // TODO: take PackedFloat32Array parameters instead 86 | template <> 87 | struct GdsArray 88 | { 89 | std::vector buf; 90 | 91 | GdsArray(Array& arr) : buf(arr.size()) 92 | { 93 | for (int i = 0; i < arr.size(); ++i) 94 | { 95 | buf[i] = arr[i]; 96 | } 97 | } 98 | 99 | operator const float*() { return buf.data(); } 100 | }; 101 | 102 | template <> 103 | struct GdsArray 104 | { 105 | std::vector buf; 106 | std::vector ptrs; 107 | 108 | GdsArray(Array& arr) : buf(arr.size()), ptrs(arr.size()) 109 | { 110 | for (int i = 0; i < arr.size(); ++i) 111 | { 112 | buf[i] = String(arr[i]).utf8(); 113 | ptrs[i] = buf[i].get_data(); 114 | } 115 | } 116 | 117 | operator const char* const*() { return ptrs.data(); } 118 | }; 119 | 120 | struct GdsZeroArray 121 | { 122 | const std::vector& buf; 123 | 124 | GdsZeroArray(const Array& a) : buf(gdscache->GetZeroArray(a)) {} 125 | 126 | operator const char*() { return buf.data(); } 127 | }; 128 | 129 | #define VARIANT_CSTR(v) v.get_type() == Variant::STRING ? static_cast(v).utf8().get_data() : nullptr 130 | 131 | #define GDS_PTR(T, a) a.size() == 0 ? nullptr : (T*)GdsPtr(a) 132 | // #define GDS_PTR_STR(a, len, label) a.size() == 0 ? nullptr : (char*)GdsPtr(a, len, label) 133 | 134 | } // namespace ImGui::Godot 135 | 136 | #include "imgui_bindings.gen.h" 137 | -------------------------------------------------------------------------------- /gdext/src/ImGuiController.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | using namespace godot; 6 | 7 | namespace ImGui::Godot { 8 | 9 | class ImGuiController : public Node 10 | { 11 | GDCLASS(ImGuiController, Node); 12 | 13 | protected: 14 | static void _bind_methods(); 15 | 16 | public: 17 | static ImGuiController* Instance(); 18 | 19 | ImGuiController(); 20 | ~ImGuiController(); 21 | 22 | void _ready() override; 23 | void _enter_tree() override; 24 | void _exit_tree() override; 25 | void _process(double delta) override; 26 | void _notification(int p_what); 27 | void SetMainViewport(Viewport* vp); 28 | 29 | void OnLayerExiting(); 30 | void on_frame_pre_draw(); 31 | void window_input_callback(Ref evt); 32 | 33 | private: 34 | struct Impl; 35 | std::unique_ptr impl; 36 | }; 37 | 38 | } // namespace ImGui::Godot 39 | -------------------------------------------------------------------------------- /gdext/src/ImGuiControllerHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "ImGuiControllerHelper.h" 2 | #include "Context.h" 3 | using namespace godot; 4 | 5 | namespace ImGui::Godot { 6 | 7 | ImGuiControllerHelper::ImGuiControllerHelper() 8 | { 9 | } 10 | 11 | ImGuiControllerHelper::~ImGuiControllerHelper() 12 | { 13 | } 14 | 15 | void ImGuiControllerHelper::_bind_methods() 16 | { 17 | } 18 | 19 | void ImGuiControllerHelper::_enter_tree() 20 | { 21 | } 22 | 23 | void ImGuiControllerHelper::_ready() 24 | { 25 | set_name("ImGuiControllerHelper"); 26 | set_process_priority(std::numeric_limits::min()); 27 | set_process_mode(Node::PROCESS_MODE_ALWAYS); 28 | } 29 | 30 | void ImGuiControllerHelper::_exit_tree() 31 | { 32 | } 33 | 34 | void ImGuiControllerHelper::_process(double delta) 35 | { 36 | Context* ctx = GetContext(); 37 | ctx->inProcessFrame = true; 38 | ctx->Update(delta, ctx->layer->UpdateViewport()); 39 | } 40 | 41 | } // namespace ImGui::Godot 42 | -------------------------------------------------------------------------------- /gdext/src/ImGuiControllerHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | using godot::Node; 5 | 6 | namespace ImGui::Godot { 7 | 8 | class ImGuiControllerHelper : public Node 9 | { 10 | GDCLASS(ImGuiControllerHelper, Node); 11 | 12 | protected: 13 | static void _bind_methods(); 14 | 15 | public: 16 | void _ready() override; 17 | void _enter_tree() override; 18 | void _exit_tree() override; 19 | void _process(double delta) override; 20 | 21 | ImGuiControllerHelper(); 22 | ~ImGuiControllerHelper(); 23 | }; 24 | 25 | } // namespace ImGui::Godot 26 | -------------------------------------------------------------------------------- /gdext/src/ImGuiGD.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace godot; 10 | 11 | namespace ImGui::Godot { 12 | 13 | class ImGuiGD : public Object 14 | { 15 | GDCLASS(ImGuiGD, Object); 16 | 17 | protected: 18 | static void _bind_methods(); 19 | 20 | public: 21 | bool ToolInit(); 22 | 23 | void Connect(const Callable& cb); 24 | 25 | void ResetFonts(); 26 | void AddFont(const Ref& fontFile, int fontSize, bool merge = false, 27 | const PackedInt32Array& glyphRanges = {}); 28 | void AddFontDefault(); 29 | void RebuildFontAtlas(); 30 | 31 | void _SetJoyAxisDeadZone(real_t zone); 32 | real_t _GetJoyAxisDeadZone(); 33 | 34 | void _SetVisible(bool visible); 35 | bool _GetVisible(); 36 | 37 | void _SetScale(real_t scale); 38 | real_t _GetScale(); 39 | 40 | void SetMainViewport(Viewport* vp); 41 | void SetIniFilename(String fn); 42 | 43 | PackedInt64Array GetFontPtrs(); 44 | PackedInt64Array GetImGuiPtrs(String version, int ioSize, int vertSize, int idxSize, int charSize); 45 | 46 | bool SubViewport(godot::SubViewport* svp); 47 | }; 48 | 49 | } // namespace ImGui::Godot 50 | -------------------------------------------------------------------------------- /gdext/src/ImGuiLayer.cpp: -------------------------------------------------------------------------------- 1 | #include "ImGuiLayer.h" 2 | #include "Context.h" 3 | #include "ImGuiControllerHelper.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace godot; 17 | 18 | namespace ImGui::Godot { 19 | 20 | struct ImGuiLayer::Impl 21 | { 22 | RID subViewportRid; 23 | Vector2i subViewportSize{0, 0}; 24 | RID canvasItem; 25 | Transform2D finalTransform{1.f, 0.f, 0.f, 1.f, 0.f, 0.f}; // identity 26 | bool visible = true; 27 | Viewport* parentViewport = nullptr; 28 | 29 | static RID AddLayerSubViewport(Node* parent); 30 | }; 31 | 32 | RID ImGuiLayer::Impl::AddLayerSubViewport(Node* parent) 33 | { 34 | RenderingServer* RS = RenderingServer::get_singleton(); 35 | RID svp = RS->viewport_create(); 36 | RS->viewport_set_transparent_background(svp, true); 37 | RS->viewport_set_update_mode(svp, RenderingServer::VIEWPORT_UPDATE_ALWAYS); 38 | RS->viewport_set_clear_mode(svp, RenderingServer::VIEWPORT_CLEAR_ALWAYS); 39 | RS->viewport_set_active(svp, true); 40 | RS->viewport_set_parent_viewport(svp, parent->get_window()->get_viewport_rid()); 41 | return svp; 42 | } 43 | 44 | ImGuiLayer::ImGuiLayer() : impl(std::make_unique()) 45 | { 46 | } 47 | 48 | ImGuiLayer::~ImGuiLayer() 49 | { 50 | } 51 | 52 | void ImGuiLayer::_bind_methods() 53 | { 54 | ClassDB::bind_method(D_METHOD("on_visibility_changed"), &ImGuiLayer::on_visibility_changed); 55 | } 56 | 57 | void ImGuiLayer::_enter_tree() 58 | { 59 | Context* ctx = GetContext(); 60 | set_name("ImGuiLayer"); 61 | set_layer(ctx->layerNum); 62 | 63 | impl->parentViewport = get_viewport(); 64 | impl->subViewportRid = Impl::AddLayerSubViewport(this); 65 | 66 | RenderingServer* RS = RenderingServer::get_singleton(); 67 | impl->canvasItem = RS->canvas_item_create(); 68 | RS->canvas_item_set_parent(impl->canvasItem, get_canvas()); 69 | 70 | ctx->renderer->InitViewport(impl->subViewportRid); 71 | ctx->viewports->SetMainWindow(get_window(), impl->subViewportRid); 72 | } 73 | 74 | void ImGuiLayer::_ready() 75 | { 76 | connect("visibility_changed", Callable(this, "on_visibility_changed")); 77 | } 78 | 79 | void ImGuiLayer::_exit_tree() 80 | { 81 | RenderingServer::get_singleton()->free_rid(impl->canvasItem); 82 | RenderingServer::get_singleton()->free_rid(impl->subViewportRid); 83 | } 84 | 85 | void ImGuiLayer::on_visibility_changed() 86 | { 87 | impl->visible = is_visible(); 88 | if (impl->visible) 89 | { 90 | set_process_input(true); 91 | } 92 | else 93 | { 94 | set_process_input(false); 95 | ImGui::Godot::GetContext()->renderer->OnHide(); 96 | impl->subViewportSize = {0, 0}; 97 | RenderingServer::get_singleton()->canvas_item_clear(impl->canvasItem); 98 | } 99 | } 100 | 101 | void ImGuiLayer::_input(const Ref& event) 102 | { 103 | if (GetContext()->input->ProcessInput(event)) 104 | { 105 | impl->parentViewport->set_input_as_handled(); 106 | } 107 | } 108 | 109 | Vector2i ImGuiLayer::UpdateViewport() 110 | { 111 | Vector2i vpSize; 112 | if (Window* w = Object::cast_to(impl->parentViewport)) 113 | vpSize = w->get_size(); 114 | else 115 | vpSize = Object::cast_to(impl->parentViewport)->get_size(); 116 | 117 | if (impl->visible) 118 | { 119 | const Transform2D ft = impl->parentViewport->get_final_transform(); 120 | 121 | if (impl->subViewportSize != vpSize || 122 | impl->finalTransform != ft 123 | #ifdef DEBUG_ENABLED 124 | // force redraw on every frame in editor 125 | || Engine::get_singleton()->is_editor_hint() 126 | #endif 127 | ) 128 | { 129 | // this is more or less how SubViewportContainer works 130 | impl->subViewportSize = vpSize; 131 | impl->finalTransform = ft; 132 | 133 | RenderingServer* RS = RenderingServer::get_singleton(); 134 | RS->viewport_set_size(impl->subViewportRid, impl->subViewportSize.x, impl->subViewportSize.y); 135 | const RID vptex = RS->viewport_get_texture(impl->subViewportRid); 136 | RS->canvas_item_clear(impl->canvasItem); 137 | RS->canvas_item_set_transform(impl->canvasItem, ft.affine_inverse()); 138 | RS->canvas_item_add_texture_rect(impl->canvasItem, 139 | Rect2(0, 0, impl->subViewportSize.x, impl->subViewportSize.y), 140 | vptex); 141 | } 142 | } 143 | 144 | return vpSize; 145 | } 146 | 147 | } // namespace ImGui::Godot 148 | -------------------------------------------------------------------------------- /gdext/src/ImGuiLayer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace godot; 7 | 8 | namespace ImGui::Godot { 9 | 10 | class ImGuiLayer : public CanvasLayer 11 | { 12 | GDCLASS(ImGuiLayer, CanvasLayer); 13 | 14 | protected: 15 | static void _bind_methods(); 16 | 17 | public: 18 | ImGuiLayer(); 19 | ~ImGuiLayer(); 20 | 21 | void _ready() override; 22 | void _enter_tree() override; 23 | void _exit_tree() override; 24 | void _input(const Ref& event) override; 25 | 26 | void on_visibility_changed(); 27 | 28 | Vector2i UpdateViewport(); 29 | 30 | private: 31 | struct Impl; 32 | std::unique_ptr impl; 33 | }; 34 | 35 | } // namespace ImGui::Godot 36 | -------------------------------------------------------------------------------- /gdext/src/ImGuiSync.cpp: -------------------------------------------------------------------------------- 1 | #include "ImGuiSync.h" 2 | #include 3 | #include 4 | #include 5 | 6 | namespace ImGui::Godot { 7 | 8 | void ImGuiSync::_bind_methods() 9 | { 10 | ClassDB::bind_static_method("ImGuiSync", D_METHOD("GetImGuiPtrs"), &ImGuiSync::GetImGuiPtrs); 11 | } 12 | 13 | PackedInt64Array ImGuiSync::GetImGuiPtrs(String version, int ioSize, int vertSize, int idxSize, int charSize) 14 | { 15 | if (version != String(ImGui::GetVersion()) || ioSize != sizeof(ImGuiIO) || vertSize != sizeof(ImDrawVert) || 16 | idxSize != sizeof(ImDrawIdx) || charSize != sizeof(ImWchar)) 17 | { 18 | UtilityFunctions::push_error("ImGui version mismatch, use v", ImGui::GetVersion(), "-docking"); 19 | return {}; 20 | } 21 | 22 | ImGuiMemAllocFunc alloc_func = nullptr; 23 | ImGuiMemFreeFunc free_func = nullptr; 24 | void* user_data = nullptr; 25 | 26 | ImGui::GetAllocatorFunctions(&alloc_func, &free_func, &user_data); 27 | 28 | PackedInt64Array rv; 29 | rv.resize(3); 30 | rv[0] = reinterpret_cast(ImGui::GetCurrentContext()); 31 | rv[1] = reinterpret_cast(alloc_func); 32 | rv[2] = reinterpret_cast(free_func); 33 | return rv; 34 | } 35 | 36 | } // namespace ImGui::Godot 37 | -------------------------------------------------------------------------------- /gdext/src/ImGuiSync.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | using namespace godot; 5 | 6 | namespace ImGui::Godot { 7 | 8 | class ImGuiSync : public Object 9 | { 10 | GDCLASS(ImGuiSync, Object); 11 | 12 | protected: 13 | static void _bind_methods(); 14 | 15 | public: 16 | static PackedInt64Array GetImGuiPtrs(String version, int ioSize, int vertSize, int idxSize, int charSize); 17 | }; 18 | 19 | } // namespace ImGui::Godot 20 | -------------------------------------------------------------------------------- /gdext/src/Input.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace godot; 10 | 11 | namespace ImGui::Godot { 12 | class Input 13 | { 14 | public: 15 | Input(); 16 | virtual ~Input(); 17 | 18 | void Update(); 19 | virtual bool ProcessInput(const Ref& evt); 20 | void ProcessNotification(int what); 21 | void SetActiveSubViewport(godot::SubViewport* svp, Vector2 pos); 22 | 23 | protected: 24 | virtual void UpdateMousePos(); 25 | void ProcessSubViewportWidget(const Ref& evt); 26 | bool HandleEvent(const Ref& evt); 27 | 28 | private: 29 | void UpdateMouse(); 30 | 31 | struct Impl; 32 | std::unique_ptr impl; 33 | }; 34 | } // namespace ImGui::Godot 35 | -------------------------------------------------------------------------------- /gdext/src/InputLocal.cpp: -------------------------------------------------------------------------------- 1 | #include "InputLocal.h" 2 | #include 3 | #include 4 | 5 | namespace ImGui::Godot { 6 | 7 | void InputLocal::UpdateMousePos() 8 | { 9 | // do not use global mouse position 10 | } 11 | 12 | bool InputLocal::ProcessInput(const Ref& evt) 13 | { 14 | // no support for SubViewport widgets 15 | 16 | if (Ref mm = evt; mm.is_valid()) 17 | { 18 | ImGuiIO& io = ImGui::GetIO(); 19 | Vector2 mousePos = mm->get_position(); 20 | io.AddMousePosEvent(mousePos.x, mousePos.y); 21 | return io.WantCaptureMouse; 22 | } 23 | return HandleEvent(evt); 24 | } 25 | 26 | } // namespace ImGui::Godot 27 | -------------------------------------------------------------------------------- /gdext/src/InputLocal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Input.h" 3 | 4 | using namespace godot; 5 | 6 | namespace ImGui::Godot { 7 | 8 | class InputLocal : public Input 9 | { 10 | protected: 11 | void UpdateMousePos() override; 12 | bool ProcessInput(const Ref& evt) override; 13 | }; 14 | 15 | } // namespace ImGui::Godot 16 | -------------------------------------------------------------------------------- /gdext/src/RdRenderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Renderer.h" 3 | #include 4 | #include 5 | #include 6 | 7 | using godot::RID; 8 | 9 | namespace ImGui::Godot { 10 | 11 | class RdRenderer : public Renderer 12 | { 13 | public: 14 | RdRenderer(); 15 | virtual ~RdRenderer(); 16 | 17 | virtual const char* Name() override { return "godot4_rd"; } 18 | 19 | bool Init() override; 20 | void InitViewport(RID vprid) override; 21 | void CloseViewport(RID vprid) override {} 22 | virtual void Render() override; 23 | void OnHide() override {} 24 | 25 | protected: 26 | void Render(RID fb, ImDrawData* drawData); 27 | static void ReplaceTextureRIDs(ImDrawData* drawData); 28 | RID GetFramebuffer(RID vprid); 29 | void FreeUnusedTextures(); 30 | 31 | private: 32 | struct Impl; 33 | std::unique_ptr impl; 34 | }; 35 | 36 | } // namespace ImGui::Godot 37 | -------------------------------------------------------------------------------- /gdext/src/RdRendererThreadSafe.cpp: -------------------------------------------------------------------------------- 1 | #include "RdRendererThreadSafe.h" 2 | #include "common.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace godot; 10 | 11 | namespace ImGui::Godot { 12 | 13 | struct RdRendererThreadSafe::Impl 14 | { 15 | struct ClonedDrawData 16 | { 17 | ClonedDrawData(ImDrawData* drawData) 18 | { 19 | static_assert(sizeof(ImDrawData) == 64); 20 | data = IM_NEW(ImDrawData); 21 | data->Valid = drawData->Valid; 22 | data->CmdListsCount = drawData->CmdListsCount; 23 | data->TotalIdxCount = drawData->TotalIdxCount; 24 | data->TotalVtxCount = drawData->TotalVtxCount; 25 | data->CmdLists = {}; 26 | data->DisplayPos = drawData->DisplayPos; 27 | data->DisplaySize = drawData->DisplaySize; 28 | data->FramebufferScale = drawData->FramebufferScale; 29 | data->OwnerViewport = drawData->OwnerViewport; 30 | 31 | for (int i = 0; i < drawData->CmdLists.Size; ++i) 32 | { 33 | data->CmdLists.push_back(drawData->CmdLists[i]->CloneOutput()); 34 | } 35 | } 36 | 37 | ~ClonedDrawData() 38 | { 39 | for (int i = 0; i < data->CmdLists.Size; ++i) 40 | { 41 | IM_DELETE(data->CmdLists[i]); 42 | } 43 | IM_DELETE(data); 44 | } 45 | 46 | ImDrawData* data; 47 | }; 48 | 49 | bool isGodot42 = false; 50 | 51 | using SharedData = std::pair>; 52 | 53 | // mutex overhead should be minimal (near-zero contention), and refactoring to atomic is ugly 54 | std::mutex sharedDataMutex; 55 | std::vector dataToDraw; 56 | }; 57 | 58 | RdRendererThreadSafe::RdRendererThreadSafe() : impl(std::make_unique()) 59 | { 60 | // TODO: remove 4.2 compatibility when 4.4 is released 61 | Dictionary vinfo = Engine::get_singleton()->get_version_info(); 62 | impl->isGodot42 = (int)vinfo["hex"] < 0x040300; 63 | 64 | if (impl->isGodot42) 65 | { 66 | RenderingServer* RS = RenderingServer::get_singleton(); 67 | RS->connect("frame_pre_draw", 68 | Callable(Engine::get_singleton()->get_singleton("ImGuiController"), "on_frame_pre_draw")); 69 | } 70 | 71 | if (DisplayServer::get_singleton()->window_get_vsync_mode() == DisplayServer::VSYNC_DISABLED) 72 | { 73 | UtilityFunctions::push_warning("[imgui-godot] Multi-threaded renderer with vsync disabled will probably crash"); 74 | } 75 | } 76 | 77 | RdRendererThreadSafe::~RdRendererThreadSafe() 78 | { 79 | } 80 | 81 | void RdRendererThreadSafe::Render() 82 | { 83 | auto& pio = ImGui::GetPlatformIO(); 84 | std::vector newData(pio.Viewports.size()); 85 | 86 | for (int i = 0; i < pio.Viewports.size(); ++i) 87 | { 88 | ImGuiViewport* vp = pio.Viewports[i]; 89 | if (vp->Flags & ImGuiViewportFlags_IsMinimized) 90 | continue; 91 | 92 | RID vprid = make_rid(vp->RendererUserData); 93 | if (impl->isGodot42) 94 | { 95 | ReplaceTextureRIDs(vp->DrawData); 96 | newData[i].first = GetFramebuffer(vprid); 97 | } 98 | else 99 | { 100 | newData[i].first = vprid; 101 | } 102 | newData[i].second = std::make_unique(vp->DrawData); 103 | } 104 | 105 | { 106 | std::unique_lock lock(impl->sharedDataMutex); 107 | impl->dataToDraw = std::move(newData); 108 | } 109 | 110 | if (!impl->isGodot42) 111 | { 112 | RenderingServer::get_singleton()->call_on_render_thread( 113 | Callable(Engine::get_singleton()->get_singleton("ImGuiController"), "on_frame_pre_draw")); 114 | } 115 | } 116 | 117 | void RdRendererThreadSafe::OnFramePreDraw() 118 | { 119 | std::vector dataArray; 120 | 121 | { 122 | std::unique_lock lock(impl->sharedDataMutex); 123 | // take ownership of shared data 124 | dataArray = std::move(impl->dataToDraw); 125 | } 126 | 127 | RenderingDevice* RD = RenderingServer::get_singleton()->get_rendering_device(); 128 | for (const auto& kv : dataArray) 129 | { 130 | RID fb = kv.first; 131 | ImDrawData* drawData = kv.second->data; 132 | 133 | if (!impl->isGodot42) 134 | { 135 | fb = GetFramebuffer(fb); 136 | ReplaceTextureRIDs(drawData); 137 | } 138 | 139 | if (RD->framebuffer_is_valid(fb)) 140 | { 141 | RdRenderer::Render(fb, drawData); 142 | } 143 | } 144 | 145 | FreeUnusedTextures(); 146 | } 147 | 148 | } // namespace ImGui::Godot 149 | -------------------------------------------------------------------------------- /gdext/src/RdRendererThreadSafe.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "RdRenderer.h" 3 | #include 4 | #include 5 | #include 6 | 7 | using godot::RID; 8 | 9 | namespace ImGui::Godot { 10 | 11 | class RdRendererThreadSafe : public RdRenderer 12 | { 13 | public: 14 | RdRendererThreadSafe(); 15 | virtual ~RdRendererThreadSafe(); 16 | 17 | const char* Name() override { return "godot4_rd_mt"; } 18 | 19 | void Render() override; 20 | void OnFramePreDraw() override; 21 | 22 | private: 23 | struct Impl; 24 | std::unique_ptr impl; 25 | }; 26 | 27 | } // namespace ImGui::Godot 28 | -------------------------------------------------------------------------------- /gdext/src/Renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | using godot::RID; 7 | 8 | namespace ImGui::Godot { 9 | 10 | class Renderer 11 | { 12 | public: 13 | Renderer() {} 14 | virtual ~Renderer() {} 15 | 16 | virtual const char* Name() = 0; 17 | 18 | virtual bool Init() = 0; 19 | virtual void InitViewport(RID vprid) = 0; 20 | virtual void CloseViewport(RID vprid) = 0; 21 | virtual void Render() = 0; 22 | virtual void OnHide() = 0; 23 | virtual void OnFramePreDraw() {} 24 | }; 25 | 26 | } // namespace ImGui::Godot 27 | -------------------------------------------------------------------------------- /gdext/src/Viewports.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace godot; 8 | 9 | namespace ImGui::Godot { 10 | 11 | class ImGuiWindow : public Window 12 | { 13 | GDCLASS(ImGuiWindow, Window); 14 | 15 | protected: 16 | static void _bind_methods() 17 | { 18 | ClassDB::bind_method(D_METHOD("_close_requested"), &ImGuiWindow::_close_requested); 19 | ClassDB::bind_method(D_METHOD("_size_changed"), &ImGuiWindow::_size_changed); 20 | } 21 | 22 | public: 23 | void init(ImGuiViewport* vp) 24 | { 25 | _vp = vp; 26 | connect("close_requested", Callable(this, "_close_requested")); 27 | connect("size_changed", Callable(this, "_size_changed")); 28 | } 29 | 30 | void _close_requested() { _vp->PlatformRequestClose = true; } 31 | 32 | void _size_changed() { _vp->PlatformRequestResize = true; } 33 | 34 | private: 35 | ImGuiViewport* _vp = nullptr; 36 | }; 37 | 38 | class Viewports 39 | { 40 | public: 41 | Viewports(); 42 | ~Viewports(); 43 | 44 | void SetMainWindow(Window* mainWindow, RID mainSubViewport); 45 | 46 | private: 47 | struct Impl; 48 | std::unique_ptr impl; 49 | }; 50 | 51 | } // namespace ImGui::Godot 52 | -------------------------------------------------------------------------------- /gdext/src/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | using godot::RID; 6 | 7 | namespace ImGui::Godot { 8 | 9 | inline RID make_rid(int64_t id) 10 | { 11 | // HACK: only way to set a RID value 12 | RID rv; 13 | memcpy(rv._native_ptr(), &id, sizeof(int64_t)); 14 | return rv; 15 | } 16 | 17 | inline RID make_rid(void* p) 18 | { 19 | return make_rid(reinterpret_cast(p)); 20 | } 21 | 22 | } // namespace ImGui::Godot 23 | 24 | template <> 25 | struct std::hash 26 | { 27 | std::size_t operator()(const RID& rid) const noexcept { return rid.get_id(); } 28 | }; 29 | -------------------------------------------------------------------------------- /gdext/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | static_assert(GODOT_VERSION_MAJOR == 4 && GODOT_VERSION_MINOR >= 2); 13 | 14 | #include 15 | 16 | #include "ImGuiController.h" 17 | #include "ImGuiControllerHelper.h" 18 | #include "ImGuiGD.h" 19 | #include "ImGuiLayer.h" 20 | #include "ImGuiSync.h" 21 | #include "Viewports.h" 22 | 23 | // avoid including cimgui.h elsewhere 24 | 25 | namespace ImGui::Godot { 26 | void register_imgui_api(); 27 | void unregister_imgui_api(); 28 | } // namespace ImGui::Godot 29 | 30 | using namespace godot; 31 | using namespace ImGui::Godot; 32 | 33 | ImGuiGD* gd = nullptr; 34 | 35 | #ifdef _WIN32 36 | #define WIN32_LEAN_AND_MEAN 37 | #include 38 | #else 39 | #include 40 | #endif 41 | 42 | void sync_modules() 43 | { 44 | typedef void (*pmodinit)(uint32_t, ImGuiContext*, ImGuiMemAllocFunc, ImGuiMemFreeFunc); 45 | #ifdef _WIN32 46 | pmodinit mod_init = (pmodinit)GetProcAddress(GetModuleHandle(nullptr), "imgui_godot_module_init"); 47 | #else 48 | pmodinit mod_init = (pmodinit)dlsym(dlopen(nullptr, RTLD_LAZY), "imgui_godot_module_init"); 49 | #endif 50 | if (mod_init) 51 | { 52 | ImGuiMemAllocFunc afunc; 53 | ImGuiMemFreeFunc ffunc; 54 | void* ud; 55 | ImGui::GetAllocatorFunctions(&afunc, &ffunc, &ud); 56 | mod_init(IMGUI_VERSION_NUM, ImGui::GetCurrentContext(), afunc, ffunc); 57 | } 58 | } 59 | 60 | void initialize_ign_module(ModuleInitializationLevel p_level) 61 | { 62 | if (p_level == MODULE_INITIALIZATION_LEVEL_SERVERS) 63 | { 64 | ImGui::CreateContext(); 65 | ClassDB::register_internal_class(); 66 | } 67 | 68 | if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) 69 | return; 70 | 71 | ClassDB::register_internal_class(); 72 | ClassDB::register_internal_class(); 73 | ClassDB::register_class(); 74 | ClassDB::register_class(); 75 | ClassDB::register_internal_class(); 76 | register_imgui_api(); 77 | 78 | gd = memnew(ImGuiGD); 79 | Engine::get_singleton()->register_singleton("ImGuiGD", gd); 80 | sync_modules(); 81 | 82 | if (!ProjectSettings::get_singleton()->has_setting("autoload/ImGuiRoot")) 83 | { 84 | UtilityFunctions::push_warning( 85 | "[imgui-godot] Plugin is not enabled. If you call ImGui methods, your project will crash!"); 86 | } 87 | } 88 | 89 | void uninitialize_ign_module(ModuleInitializationLevel p_level) 90 | { 91 | if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) 92 | return; 93 | 94 | Engine::get_singleton()->unregister_singleton("ImGuiGD"); 95 | memdelete(gd); 96 | unregister_imgui_api(); 97 | } 98 | 99 | extern "C" { 100 | GDExtensionBool GDE_EXPORT ign_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, 101 | GDExtensionClassLibraryPtr p_library, GDExtensionInitialization* r_initialization) 102 | { 103 | GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization); 104 | 105 | init_obj.register_initializer(initialize_ign_module); 106 | init_obj.register_terminator(uninitialize_ign_module); 107 | init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SERVERS); 108 | 109 | return init_obj.init(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /gdext/vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | "freetype" 4 | ], 5 | "builtin-baseline": "6f29f12e82a8293156836ad81cc9bf5af41fe836" 6 | } -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="Dear ImGui for Godot Demo" 14 | run/main_scene="res://data/demo.tscn" 15 | config/features=PackedStringArray("4.3", "C#") 16 | run/max_fps=60 17 | config/icon="res://data/icon.svg" 18 | 19 | [autoload] 20 | 21 | ImGuiRoot="*res://addons/imgui-godot/data/ImGuiRoot.tscn" 22 | 23 | [display] 24 | 25 | window/size/viewport_width=1280 26 | window/size/viewport_height=720 27 | window/subwindows/embed_subwindows=false 28 | window/stretch/mode="canvas_items" 29 | window/stretch/aspect="expand" 30 | window/vsync/vsync_mode=0 31 | 32 | [dotnet] 33 | 34 | project/assembly_name="Dear ImGui for Godot Demo" 35 | 36 | [editor_plugins] 37 | 38 | enabled=PackedStringArray("res://addons/imgui-godot/plugin.cfg") 39 | -------------------------------------------------------------------------------- /src/MyNode.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using ImGuiGodot; 3 | using ImGuiNET; 4 | 5 | namespace DemoProject; 6 | 7 | public partial class MyNode : Node 8 | { 9 | private Window _window = null!; 10 | private CheckBox _checkBox = null!; 11 | 12 | public override void _Ready() 13 | { 14 | _window = GetWindow(); 15 | GetNode