├── .github └── workflows │ └── build.yml ├── .gitignore ├── .idea ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── inspectionProfiles │ └── Project_Default.xml ├── kotlinc.xml ├── misc.xml ├── php.xml ├── runConfigurations │ ├── Opengl3Kt.xml │ ├── VulkanKt.xml │ └── Vulkan_Vanilla_Kt.xml └── vcs.xml ├── .travis.yml ├── LICENSE ├── README.md ├── bgfx ├── build.gradle.kts └── src │ ├── main │ ├── java │ │ └── module-info.java │ └── kotlin │ │ └── imgui │ │ └── impl │ │ └── bgfx │ │ ├── ImplBgfx.kt │ │ ├── fs_imgui_image.kt │ │ ├── fs_ocornut_imgui.kt │ │ ├── vs_imgui_image.kt │ │ └── vs_ocornut_imgui.kt │ └── test │ ├── java │ └── imgui │ │ ├── BgfxDemoUtil.java │ │ ├── Cubes.java │ │ └── Demo.java │ └── resources │ ├── Roboto-Regular.ttf │ ├── RobotoMono-Regular.ttf │ └── shaders │ ├── dx11 │ ├── fs_cubes.bin │ └── vs_cubes.bin │ └── glsl │ ├── fs_cubes.bin │ └── vs_cubes.bin ├── build.gradle.kts ├── core ├── core.gradle.kts └── src │ ├── main │ ├── java │ │ └── imgui │ │ │ └── Jdsl.java │ ├── kotlin │ │ ├── imgui │ │ │ ├── api │ │ │ │ ├── backgroundForegroundDrawLists.kt │ │ │ │ ├── childWindows.kt │ │ │ │ ├── clipboardUtilities.kt │ │ │ │ ├── clipping.kt │ │ │ │ ├── colorUtilities.kt │ │ │ │ ├── columns.kt │ │ │ │ ├── contentRegion.kt │ │ │ │ ├── context.kt │ │ │ │ ├── cursorLayout.kt │ │ │ │ ├── debugUtilities.kt │ │ │ │ ├── demoDebugInformations.kt │ │ │ │ ├── dragAndDrop.kt │ │ │ │ ├── focusActivation.kt │ │ │ │ ├── idStackScopes.kt │ │ │ │ ├── inputUtilitiesMouse.kt │ │ │ │ ├── inputsUtilitiesKeyboardMouseGamepad.kt │ │ │ │ ├── inputsUtilitiesShortcutRouting.kt │ │ │ │ ├── itemWidgetsUtilities.kt │ │ │ │ ├── loggingCapture.kt │ │ │ │ ├── main.kt │ │ │ │ ├── miscellaneousUtilities.kt │ │ │ │ ├── overlappingMode.kt │ │ │ │ ├── parametersStacks.kt │ │ │ │ ├── popupsModals.kt │ │ │ │ ├── settingsIniUtilities.kt │ │ │ │ ├── styleReadAccess.kt │ │ │ │ ├── styles.kt │ │ │ │ ├── tabBarsTabs.kt │ │ │ │ ├── tables.kt │ │ │ │ ├── textUtilities.kt │ │ │ │ ├── tooltips.kt │ │ │ │ ├── viewports.kt │ │ │ │ ├── widgetsColorEditorPicker.kt │ │ │ │ ├── widgetsComboBox.kt │ │ │ │ ├── widgetsDataPlotting.kt │ │ │ │ ├── widgetsDrags.kt │ │ │ │ ├── widgetsImages.kt │ │ │ │ ├── widgetsInputWithKeyboard.kt │ │ │ │ ├── widgetsListBoxes.kt │ │ │ │ ├── widgetsMain.kt │ │ │ │ ├── widgetsMenus.kt │ │ │ │ ├── widgetsSelectables.kt │ │ │ │ ├── widgetsSliders.kt │ │ │ │ ├── widgetsText.kt │ │ │ │ ├── widgetsTrees.kt │ │ │ │ ├── windowScrolling.kt │ │ │ │ ├── windows.kt │ │ │ │ └── windowsUtilities.kt │ │ │ ├── classes │ │ │ │ ├── Context.kt │ │ │ │ ├── DrawList.kt │ │ │ │ ├── IO.kt │ │ │ │ ├── InputTextCallbackData.kt │ │ │ │ ├── ListClipper.kt │ │ │ │ ├── Style.kt │ │ │ │ └── misc.kt │ │ │ ├── demo │ │ │ │ ├── DemoWindow.kt │ │ │ │ ├── ShowDemoWindowColumns.kt │ │ │ │ ├── ShowDemoWindowInputs.kt │ │ │ │ ├── ShowDemoWindowLayout.kt │ │ │ │ ├── ShowDemoWindowPopus.kt │ │ │ │ ├── ShowDemoWindowTables.kt │ │ │ │ ├── ShowDemoWindowWidgets.kt │ │ │ │ └── showExampleApp │ │ │ │ │ ├── AutoResize.kt │ │ │ │ │ ├── Console.kt │ │ │ │ │ ├── ConstrainedResize.kt │ │ │ │ │ ├── CustomRendering.kt │ │ │ │ │ ├── Documents.kt │ │ │ │ │ ├── Fullscreen.kt │ │ │ │ │ ├── Layout.kt │ │ │ │ │ ├── Log.kt │ │ │ │ │ ├── LongText.kt │ │ │ │ │ ├── MainMenuBar.kt │ │ │ │ │ ├── MenuFile.kt │ │ │ │ │ ├── PropertyEditor.kt │ │ │ │ │ ├── SimpleOverlay.kt │ │ │ │ │ ├── StyleEditor.kt │ │ │ │ │ └── WindowTitles.kt │ │ │ ├── dsl.kt │ │ │ ├── flags & enumerations.kt │ │ │ ├── font │ │ │ │ ├── Font.kt │ │ │ │ ├── FontAtlas.kt │ │ │ │ ├── FontGlyphRangesBuilder.kt │ │ │ │ ├── misc.kt │ │ │ │ └── test.kt │ │ │ ├── genericMath.kt │ │ │ ├── helpers.kt │ │ │ ├── imgui.kt │ │ │ ├── internal │ │ │ │ ├── api │ │ │ │ │ ├── basicAccessors.kt │ │ │ │ │ ├── basicHelpersForWidgetCode.kt │ │ │ │ │ ├── color.kt │ │ │ │ │ ├── combos.kt │ │ │ │ │ ├── dataTypeHelpers.kt │ │ │ │ │ ├── debugLog.kt │ │ │ │ │ ├── debugTools.kt │ │ │ │ │ ├── disabling.kt │ │ │ │ │ ├── dragAndDrop.kt │ │ │ │ │ ├── focusActivation.kt │ │ │ │ │ ├── focusScope.kt │ │ │ │ │ ├── fontsDrawing.kt │ │ │ │ │ ├── gamepadKeyboardNavigation.kt │ │ │ │ │ ├── garbageCollection.kt │ │ │ │ │ ├── genericContextHooks.kt │ │ │ │ │ ├── inputText.kt │ │ │ │ │ ├── inputs.kt │ │ │ │ │ ├── internalColumnsAPI.kt │ │ │ │ │ ├── localization.kt │ │ │ │ │ ├── loggingCapture.kt │ │ │ │ │ ├── menus.kt │ │ │ │ │ ├── newFrame.kt │ │ │ │ │ ├── parameterStacks.kt │ │ │ │ │ ├── plot.kt │ │ │ │ │ ├── popupsModalsTooltips.kt │ │ │ │ │ ├── renderHelpers.kt │ │ │ │ │ ├── scrolling.kt │ │ │ │ │ ├── settings.kt │ │ │ │ │ ├── settingsWindows.kt │ │ │ │ │ ├── shadeFunctions.kt │ │ │ │ │ ├── tabBars.kt │ │ │ │ │ ├── tableSettings.kt │ │ │ │ │ ├── tablesCandidatesForPublicAPI.kt │ │ │ │ │ ├── tablesInternal.kt │ │ │ │ │ ├── templateFunctions.kt │ │ │ │ │ ├── viewports.kt │ │ │ │ │ ├── widgets.kt │ │ │ │ │ ├── widgetsLowLevelBehaviors.kt │ │ │ │ │ ├── widgetsWindowDecorations.kt │ │ │ │ │ ├── windows.kt │ │ │ │ │ └── windowsDisplayAndFocusOrder.kt │ │ │ │ ├── classes │ │ │ │ │ ├── InputTextState.kt │ │ │ │ │ ├── Rect.kt │ │ │ │ │ ├── TabBar.kt │ │ │ │ │ ├── Table.kt │ │ │ │ │ ├── Window.kt │ │ │ │ │ ├── WindowTempData.kt │ │ │ │ │ ├── misc.kt │ │ │ │ │ └── tables.kt │ │ │ │ ├── draw.kt │ │ │ │ ├── generic helpers.kt │ │ │ │ └── sections │ │ │ │ │ ├── Clipper support.kt │ │ │ │ │ ├── Columns support.kt │ │ │ │ │ ├── Docking support.kt │ │ │ │ │ ├── Input support.kt │ │ │ │ │ ├── Macros.kt │ │ │ │ │ ├── Multi-select support.kt │ │ │ │ │ ├── Navigation support.kt │ │ │ │ │ ├── Settings support.kt │ │ │ │ │ ├── Table support.kt │ │ │ │ │ ├── Viewport support.kt │ │ │ │ │ ├── Widgets support flags, enums, data structures.kt │ │ │ │ │ ├── drawList support.kt │ │ │ │ │ └── test engine specific hooks.kt │ │ │ ├── statics │ │ │ │ ├── errorCheckingAndDebugTools.kt │ │ │ │ ├── forwardDeclarations.kt │ │ │ │ ├── inputs.kt │ │ │ │ ├── misc.kt │ │ │ │ ├── navigation.kt │ │ │ │ ├── tables.kt │ │ │ │ ├── viewports.kt │ │ │ │ ├── widgets.kt │ │ │ │ └── widgetsTabBar.kt │ │ │ ├── stb │ │ │ │ ├── RectPack.kt │ │ │ │ ├── TrueType.kt │ │ │ │ └── textEdit.kt │ │ │ ├── stb_ │ │ │ │ ├── Buf.kt │ │ │ │ ├── Context.kt │ │ │ │ ├── Csctx.kt │ │ │ │ ├── Node.kt │ │ │ │ ├── TrueType.kt │ │ │ │ ├── bitmap rendering.kt │ │ │ │ ├── character.kt │ │ │ │ ├── easyFont.kt │ │ │ │ ├── finding the right font.kt │ │ │ │ ├── font loading.kt │ │ │ │ ├── glyph shapes.kt │ │ │ │ ├── new texture baking api.kt │ │ │ │ ├── rectpack.kt │ │ │ │ ├── sdf rendering.kt │ │ │ │ ├── texture baking api.kt │ │ │ │ └── util.kt │ │ │ ├── tmp.kt │ │ │ ├── viewport.kt │ │ │ └── windowsIme │ │ │ │ ├── imeListener.kt │ │ │ │ └── imm.kt │ │ ├── java │ │ │ └── lang │ │ │ │ ├── helpers.kt │ │ │ │ └── sc.kt │ │ ├── kotlin │ │ │ └── internal │ │ │ │ └── Annotations.kt │ │ └── module-info │ └── resources │ │ └── fonts │ │ ├── ArialUni.TTF │ │ ├── Cousine-Regular.ttf │ │ ├── DroidSans.ttf │ │ ├── Karla-Regular.ttf │ │ ├── ProggyClean.ttf │ │ ├── ProggyTiny.ttf │ │ └── README.txt │ └── test │ └── kotlin │ ├── fontAtlasTest.kt │ └── util.kt ├── gl ├── gl.gradle.kts └── src │ ├── main │ ├── java │ │ └── module-info │ └── kotlin │ │ └── imgui │ │ └── impl │ │ └── gl │ │ ├── GLInterface.kt │ │ ├── ImplBestGL.kt │ │ ├── ImplGL2.kt │ │ ├── ImplGL2_mac.kt │ │ └── ImplGL3.kt │ └── test │ ├── java │ └── imgui │ │ └── examples │ │ └── OpenGL3.java │ ├── kotlin │ └── examples │ │ ├── TestMultipleWindowsLwjgl.kt │ │ ├── opengl2.kt │ │ ├── opengl2_mac.kt │ │ └── opengl3.kt │ └── resources │ └── fonts │ ├── NotoSans-Regular.ttf │ ├── NotoSansMono-Regular.ttf │ ├── Roboto-Medium.ttf │ ├── fa5-regular-400.otf │ ├── fa5-solid-900.otf │ └── fontawesome-webfont.ttf ├── glfw ├── glfw.gradle.kts └── src │ └── main │ ├── java │ └── module-info │ └── kotlin │ └── imgui │ └── impl │ └── glfw │ ├── ImplGlfw.kt │ └── wndProc hook.kt ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── imgui.ini ├── imgui_perflog.csv ├── jogl ├── build.gradle └── src │ ├── main │ ├── java │ │ └── module-info.java │ └── kotlin │ │ └── imgui │ │ └── impl │ │ ├── JoglGL3.kt │ │ ├── JoglVrGL3.kt │ │ └── common.kt │ └── test │ └── kotlin │ └── imgui │ └── test jogl.kt ├── openjfx └── src │ ├── main │ ├── java │ │ └── module-info.java │ └── kotlin │ │ └── imgui │ │ └── impl │ │ ├── ImplJFX.kt │ │ └── OpenJFXDummyMain.kt │ └── test │ └── kotlin │ └── imgui │ └── jfx │ └── test javafx.kt ├── platform └── platform.gradle.kts ├── settings.gradle.kts └── vk └── src ├── main ├── java │ ├── TriangleDemo.java │ ├── VkUtil.java │ └── module-info.java └── kotlin │ └── imgui │ └── impl │ ├── vk │ ├── ImplVulkan.kt │ ├── ImplVulkanH.kt │ ├── anchor.kt │ ├── static functions.kt │ └── tmp.kt │ └── vk_ │ ├── ImplVulkanH_.kt │ ├── ImplVulkan_.kt │ ├── anchor_.kt │ └── static functions_.kt └── test └── kotlin ├── imguiVk ├── helpers.kt └── vulkan.kt └── imguiVk_ ├── helpers_.kt └── vulkan_.kt /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: [push] 4 | 5 | jobs: 6 | linux: 7 | name: 'Linux' 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v3 12 | - name: Set up JDK 1.8 13 | uses: actions/setup-java@v3 14 | with: 15 | distribution: temurin 16 | java-version: 8 17 | - name: Grant execute permission for gradlew 18 | run: chmod +x gradlew 19 | - name: Build with Gradle 20 | run: ./gradlew build 21 | # - name: Build fat jars 22 | # run: ./gradlew shadowJar 23 | # - name: Move jars 24 | ## run: ls -la 25 | # run: mkdir shadowJars && mv build/libs/imgui*.jar shadowJars 26 | # - uses: actions/upload-artifact@v1 27 | # with: 28 | # name: ImGui linux artifacts 29 | # path: 'shadowJars' 30 | 31 | windows: 32 | name: 'Windows' 33 | runs-on: windows-latest 34 | 35 | steps: 36 | - uses: actions/checkout@v3 37 | - name: Set up JDK 1.8 38 | uses: actions/setup-java@v3 39 | with: 40 | distribution: temurin 41 | java-version: 8 42 | - name: Build with Gradle 43 | run: .\gradlew.bat build 44 | # - name: Build fat jars 45 | # run: ./gradlew shadowJar 46 | # - name: Move jars 47 | # run: mkdir shadowJars; mv build/libs/imgui*.jar shadowJars 48 | # - uses: actions/upload-artifact@v1 49 | # with: 50 | # name: ImGui windows artifacts 51 | # path: 'shadowJars' 52 | 53 | mac: 54 | name: 'Mac OS' 55 | runs-on: macos-latest 56 | 57 | steps: 58 | - uses: actions/checkout@v3 59 | - name: Set up JDK 1.8 60 | uses: actions/setup-java@v3 61 | with: 62 | distribution: temurin 63 | java-version: 8 64 | - name: Grant execute permission for gradlew 65 | run: chmod +x gradlew 66 | - name: Build with Gradle 67 | run: ./gradlew build 68 | # - name: Build fat jars 69 | # run: ./gradlew shadowJar 70 | # - name: Move jars 71 | # run: mkdir shadowJars && mv build/libs/imgui*.jar shadowJars 72 | # - uses: actions/upload-artifact@v1 73 | # with: 74 | # name: ImGui macOS artifacts 75 | # path: 'shadowJars' 76 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/java,gradle,intellij,kotlin 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=java,gradle,intellij,kotlin 3 | 4 | ### Intellij ### 5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 6 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 7 | 8 | # User-specific stuff 9 | .idea/**/workspace.xml 10 | .idea/**/tasks.xml 11 | .idea/**/usage.statistics.xml 12 | .idea/**/dictionaries 13 | .idea/**/shelf 14 | 15 | # Generated files 16 | .idea/**/contentModel.xml 17 | 18 | # Sensitive or high-churn files 19 | .idea/**/dataSources/ 20 | .idea/**/dataSources.ids 21 | .idea/**/dataSources.local.xml 22 | .idea/**/sqlDataSources.xml 23 | .idea/**/dynamic.xml 24 | .idea/**/uiDesigner.xml 25 | .idea/**/dbnavigator.xml 26 | 27 | # Gradle 28 | .idea/**/gradle.xml 29 | .idea/**/libraries 30 | 31 | # Gradle and Maven with auto-import 32 | # When using Gradle or Maven with auto-import, you should exclude module files, 33 | # since they will be recreated, and may cause churn. Uncomment if using 34 | # auto-import. 35 | .idea/artifacts 36 | .idea/compiler.xml 37 | .idea/jarRepositories.xml 38 | .idea/modules.xml 39 | .idea/*.iml 40 | .idea/modules 41 | *.iml 42 | *.ipr 43 | 44 | # CMake 45 | cmake-build-*/ 46 | 47 | # Mongo Explorer plugin 48 | .idea/**/mongoSettings.xml 49 | 50 | # File-based project format 51 | *.iws 52 | 53 | # IntelliJ 54 | out/ 55 | 56 | # mpeltonen/sbt-idea plugin 57 | .idea_modules/ 58 | 59 | # JIRA plugin 60 | atlassian-ide-plugin.xml 61 | 62 | # Cursive Clojure plugin 63 | .idea/replstate.xml 64 | 65 | # Crashlytics plugin (for Android Studio and IntelliJ) 66 | com_crashlytics_export_strings.xml 67 | crashlytics.properties 68 | crashlytics-build.properties 69 | fabric.properties 70 | 71 | # Editor-based Rest Client 72 | .idea/httpRequests 73 | 74 | # Android studio 3.1+ serialized cache file 75 | .idea/caches/build_file_checksums.ser 76 | 77 | ### Intellij Patch ### 78 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 79 | 80 | # *.iml 81 | # modules.xml 82 | # .idea/misc.xml 83 | # *.ipr 84 | 85 | # Sonarlint plugin 86 | # https://plugins.jetbrains.com/plugin/7973-sonarlint 87 | .idea/**/sonarlint/ 88 | 89 | # SonarQube Plugin 90 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin 91 | .idea/**/sonarIssues.xml 92 | 93 | # Markdown Navigator plugin 94 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced 95 | .idea/**/markdown-navigator.xml 96 | .idea/**/markdown-navigator-enh.xml 97 | .idea/**/markdown-navigator/ 98 | 99 | # Cache file creation bug 100 | # See https://youtrack.jetbrains.com/issue/JBR-2257 101 | .idea/$CACHE_FILE$ 102 | 103 | # CodeStream plugin 104 | # https://plugins.jetbrains.com/plugin/12206-codestream 105 | .idea/codestream.xml 106 | 107 | ### Java ### 108 | # Compiled class file 109 | *.class 110 | 111 | # Log file 112 | *.log 113 | 114 | # BlueJ files 115 | *.ctxt 116 | 117 | # Mobile Tools for Java (J2ME) 118 | .mtj.tmp/ 119 | 120 | # Package Files # 121 | *.jar 122 | *.war 123 | *.nar 124 | *.ear 125 | *.zip 126 | *.tar.gz 127 | *.rar 128 | 129 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 130 | hs_err_pid* 131 | 132 | ### Kotlin ### 133 | # Compiled class file 134 | 135 | # Log file 136 | 137 | # BlueJ files 138 | 139 | # Mobile Tools for Java (J2ME) 140 | 141 | # Package Files # 142 | 143 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 144 | 145 | ### Gradle ### 146 | .gradle 147 | build/ 148 | 149 | # Ignore Gradle GUI config 150 | gradle-app.setting 151 | 152 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 153 | !gradle-wrapper.jar 154 | 155 | # Cache of project 156 | .gradletasknamecache 157 | 158 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 159 | # gradle/wrapper/gradle-wrapper.properties 160 | 161 | ### Gradle Patch ### 162 | **/build/ 163 | 164 | 165 | # End of https://www.toptal.com/developers/gitignore/api/java,gradle,intellij,kotlin -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /.idea/php.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 12 | -------------------------------------------------------------------------------- /.idea/runConfigurations/Opengl3Kt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | -------------------------------------------------------------------------------- /.idea/runConfigurations/VulkanKt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | -------------------------------------------------------------------------------- /.idea/runConfigurations/Vulkan_Vanilla_Kt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: openjdk11 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 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 | -------------------------------------------------------------------------------- /bgfx/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.gradle.internal.os.OperatingSystem.* 2 | 3 | val moduleName = "$group.${rootProject.name}.bgfx" 4 | 5 | dependencies { 6 | 7 | implementation(project(":core")) 8 | 9 | val kx = "com.github.kotlin-graphics" 10 | implementation("$kx:uno-sdk:${findProperty("unoVersion")}") 11 | implementation("$kx:glm:${findProperty("glmVersion")}") 12 | implementation("$kx:kool:${findProperty("koolVersion")}") 13 | 14 | val lwjglNatives = "natives-" + when (current()) { 15 | WINDOWS -> "windows" 16 | LINUX -> "linux" 17 | else -> "macos" 18 | } 19 | listOf("", "-glfw", "-bgfx", "-stb").forEach { 20 | implementation("org.lwjgl", "lwjgl$it") 21 | runtimeOnly("org.lwjgl", "lwjgl$it", classifier = lwjglNatives) 22 | } 23 | 24 | // testImplementation group: 'junit', name: 'junit', version: '4.12' 25 | } 26 | 27 | tasks.compileJava { 28 | // this is needed because we have a separate compile step in this example with the 'module-info.java' is in 'main/java' and the Kotlin code is in 'main/kotlin' 29 | options.compilerArgs = listOf("--patch-module", "$moduleName=${sourceSets.main.get().output.asPath}") 30 | } -------------------------------------------------------------------------------- /bgfx/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module com.github.kotlin_graphics.imgui.bgfx { 2 | 3 | requires kotlin.stdlib; 4 | 5 | requires com.github.kotlin_graphics.glm; 6 | 7 | requires org.lwjgl.glfw; 8 | 9 | requires com.github.kotlin_graphics.imgui.core; 10 | requires com.github.kotlin_graphics.kool; 11 | requires org.lwjgl.bgfx; 12 | } -------------------------------------------------------------------------------- /bgfx/src/test/resources/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/bgfx/src/test/resources/Roboto-Regular.ttf -------------------------------------------------------------------------------- /bgfx/src/test/resources/RobotoMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/bgfx/src/test/resources/RobotoMono-Regular.ttf -------------------------------------------------------------------------------- /bgfx/src/test/resources/shaders/dx11/fs_cubes.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/bgfx/src/test/resources/shaders/dx11/fs_cubes.bin -------------------------------------------------------------------------------- /bgfx/src/test/resources/shaders/dx11/vs_cubes.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/bgfx/src/test/resources/shaders/dx11/vs_cubes.bin -------------------------------------------------------------------------------- /bgfx/src/test/resources/shaders/glsl/fs_cubes.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/bgfx/src/test/resources/shaders/glsl/fs_cubes.bin -------------------------------------------------------------------------------- /bgfx/src/test/resources/shaders/glsl/vs_cubes.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/bgfx/src/test/resources/shaders/glsl/vs_cubes.bin -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | import magik.createGithubPublication 2 | import magik.github 3 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask 4 | 5 | plugins { 6 | kotlin("jvm") version "1.8.20" 7 | id("org.lwjgl.plugin") version "0.0.34" 8 | id("elect86.magik") version "0.3.2" 9 | `maven-publish` 10 | // id("com.github.johnrengelman.shadow") version "8.1.1" 11 | id("com.google.devtools.ksp") version "1.8.20-1.0.10" apply false 12 | } 13 | 14 | dependencies { 15 | api(projects.core) 16 | api(projects.gl) 17 | api(projects.glfw) 18 | // vk 19 | } 20 | 21 | kotlin.jvmToolchain { languageVersion.set(JavaLanguageVersion.of(8)) } 22 | 23 | tasks { 24 | withType>().configureEach { 25 | compilerOptions.freeCompilerArgs.addAll("-opt-in=kotlin.RequiresOptIn", "-Xallow-kotlin-package") 26 | } 27 | test { useJUnitPlatform() } 28 | } 29 | 30 | publishing { 31 | publications { 32 | createGithubPublication { 33 | from(components["java"]) 34 | suppressAllPomMetadataWarnings() 35 | } 36 | } 37 | repositories.github { domain = "kotlin-graphics/mary" } 38 | } 39 | 40 | java.withSourcesJar() -------------------------------------------------------------------------------- /core/core.gradle.kts: -------------------------------------------------------------------------------- 1 | import magik.createGithubPublication 2 | import magik.github 3 | import org.gradle.nativeplatform.platform.internal.Architectures 4 | import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform 5 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask 6 | import org.lwjgl.Lwjgl.Module.jemalloc 7 | import org.lwjgl.Lwjgl.Module.stb 8 | import org.lwjgl.lwjgl 9 | 10 | plugins { 11 | kotlin("jvm") 12 | id("org.lwjgl.plugin") 13 | id("elect86.magik") 14 | `maven-publish` 15 | id("com.google.devtools.ksp") 16 | } 17 | 18 | group = rootProject.group 19 | version = rootProject.version 20 | 21 | dependencies { 22 | implementation(kotlin("reflect")) 23 | testImplementation(kotlin("test")) 24 | 25 | api("kotlin.graphics:uno-core:0.7.21") 26 | lwjgl { implementation(jemalloc, stb) } 27 | 28 | implementation("com.github.livefront.sealed-enum:runtime:0.7.0") 29 | ksp("com.github.livefront.sealed-enum:ksp:0.7.0") 30 | 31 | val brotliVersion = "1.11.0" 32 | val operatingSystem: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem() 33 | implementation("com.aayushatharva.brotli4j:brotli4j:$brotliVersion") 34 | runtimeOnly("com.aayushatharva.brotli4j:native-${ 35 | if (operatingSystem.isWindows) "windows-x86_64" 36 | else if (operatingSystem.isMacOsX) 37 | if (DefaultNativePlatform.getCurrentArchitecture().isArm()) "osx-aarch64" 38 | else "osx-x86_64" 39 | else if (operatingSystem.isLinux) 40 | if (Architectures.ARM_V7.isAlias(DefaultNativePlatform.getCurrentArchitecture().name)) "linux-armv7" 41 | else if (Architectures.AARCH64.isAlias(DefaultNativePlatform.getCurrentArchitecture().name)) "linux-aarch64" 42 | else if (Architectures.X86_64.isAlias(DefaultNativePlatform.getCurrentArchitecture().name)) "linux-x86_64" 43 | else throw IllegalStateException("Unsupported architecture: ${DefaultNativePlatform.getCurrentArchitecture().name}") 44 | else throw IllegalStateException("Unsupported operating system: $operatingSystem") 45 | }:$brotliVersion") 46 | } 47 | 48 | kotlin.jvmToolchain { languageVersion.set(JavaLanguageVersion.of(8)) } 49 | 50 | tasks { 51 | withType>().configureEach { compilerOptions.freeCompilerArgs.addAll("-opt-in=kotlin.RequiresOptIn", "-Xallow-kotlin-package") } 52 | test { useJUnitPlatform() } 53 | } 54 | 55 | publishing { 56 | publications { 57 | createGithubPublication { 58 | from(components["java"]) 59 | artifactId = "${rootProject.name}-${project.name}" 60 | suppressAllPomMetadataWarnings() 61 | } 62 | } 63 | repositories.github { domain = "kotlin-graphics/mary" } 64 | } 65 | 66 | java.withSourcesJar() -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/backgroundForegroundDrawLists.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import imgui.classes.DrawList 4 | 5 | // Background/Foreground Draw Lists 6 | interface backgroundForegroundDrawLists { 7 | 8 | /** this draw list will be the first rendering one. Useful to quickly draw shapes/text behind dear imgui contents. */ 9 | val backgroundDrawList: DrawList 10 | get() = g.viewports[0].backgroundDrawList 11 | 12 | /** this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents. 13 | * ~GetForegroundDrawList */ 14 | val foregroundDrawList: DrawList 15 | get() = g.viewports[0].foregroundDrawList 16 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/childWindows.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import glm_.glm 4 | import glm_.has 5 | import glm_.vec2.Vec2 6 | import imgui.* 7 | import imgui.ImGui.beginChildEx 8 | import imgui.ImGui.currentWindow 9 | import imgui.ImGui.end 10 | import imgui.ImGui.itemAdd 11 | import imgui.ImGui.itemSize 12 | import imgui.ImGui.renderNavHighlight 13 | import imgui.internal.classes.Rect 14 | import imgui.internal.sections.Axis 15 | import imgui.internal.sections.ItemStatusFlag 16 | import imgui.internal.sections.NavHighlightFlag 17 | import imgui.internal.sections.shl 18 | import imgui.WindowFlag as Wf 19 | 20 | 21 | interface childWindows { 22 | 23 | // Child Windows 24 | 25 | /** - Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window. Child windows can embed their own child. 26 | * - For each independent axis of 'size': ==0.0f: use remaining host window size / >0.0f: fixed size 27 | * / <0.0f: use remaining window size minus abs(size) / Each axis can use a different mode, e.g. ImVec2(0,400). 28 | * - BeginChild() returns false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting anything to the window. 29 | * Always call a matching EndChild() for each BeginChild() call, regardless of its return value. 30 | * [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu, 31 | * BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function 32 | * returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.] */ 33 | fun beginChild(strId: String, size: Vec2 = Vec2(), border: Boolean = false, flags: WindowFlags = none): Boolean = 34 | beginChildEx(strId, currentWindow.getID(strId), size, border, flags) 35 | 36 | /** begin a scrolling region. 37 | * size == 0f: use remaining window size 38 | * size < 0f: use remaining window size minus abs(size) 39 | * size > 0f: fixed size. each axis can use a different mode, e.g. Vec2(0, 400). */ 40 | fun beginChild(id: ID, sizeArg: Vec2 = Vec2(), border: Boolean = false, flags: WindowFlags = none): Boolean { 41 | assert(id != 0) 42 | return beginChildEx("", id, sizeArg, border, flags) 43 | } 44 | 45 | /** Always call even if BeginChild() return false (which indicates a collapsed or clipping child window) */ 46 | fun endChild() { 47 | 48 | val window = currentWindow 49 | 50 | assert(!g.withinEndChild) 51 | assert(window.flags has Wf._ChildWindow) { "Mismatched BeginChild()/EndChild() callss" } 52 | 53 | g.withinEndChild = true 54 | if (window.beginCount > 1) 55 | end() 56 | else { 57 | val sz = Vec2(window.size) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f 58 | if (window.autoFitChildAxes has (1 shl Axis.X)) 59 | sz.x = glm.max(4f, sz.x) 60 | if (window.autoFitChildAxes has (1 shl Axis.Y)) 61 | sz.y = glm.max(4f, sz.y) 62 | end() 63 | 64 | val parentWindow = currentWindow 65 | val bb = Rect(parentWindow.dc.cursorPos, parentWindow.dc.cursorPos + sz) 66 | itemSize(sz) 67 | if ((window.dc.navLayersActiveMask != 0 || window.dc.navWindowHasScrollY) && window.flags hasnt Wf._NavFlattened) { 68 | itemAdd(bb, window.childId) 69 | renderNavHighlight(bb, window.childId) 70 | 71 | // When browsing a window that has no activable items (scroll only) we keep a highlight on the child (pass g.NavId to trick into always displaying) 72 | if (window.dc.navLayersActiveMask == 0 && window === g.navWindow) 73 | renderNavHighlight(Rect(bb.min - 2, bb.max + 2), g.navId, NavHighlightFlag.TypeThin) 74 | } else { 75 | // Not navigable into 76 | itemAdd(bb, 0) 77 | 78 | // But when flattened we directly reach items, adjust active layer mask accordingly 79 | if (window.flags has Wf._NavFlattened) 80 | parentWindow.dc.navLayersActiveMaskNext = parentWindow.dc.navLayersActiveMaskNext or window.dc.navLayersActiveMaskNext 81 | } 82 | if (g.hoveredWindow === window) 83 | g.lastItemData.statusFlags = g.lastItemData.statusFlags or ItemStatusFlag.HoveredWindow 84 | } 85 | g.withinEndChild = false 86 | g.logLinePosY = -Float.MAX_VALUE // To enforce a carriage return 87 | } 88 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/clipboardUtilities.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import imgui.ImGui.io 4 | import imgui.classes.Context 5 | 6 | /** Clipboard Utilities 7 | * - Also see the LogToClipboard() function to capture GUI into clipboard, or easily output text data to the clipboard. */ 8 | interface clipboardUtilities { 9 | 10 | var clipboardText: String 11 | /** ~GetClipboardText */ 12 | get() = io.getClipboardTextFn?.invoke(io.clipboardUserData) ?: "" 13 | /** ~SetClipboardText */ 14 | set(value) { 15 | io.setClipboardTextFn?.invoke(io.clipboardUserData, value) 16 | } 17 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/clipping.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import glm_.vec2.Vec2 4 | import imgui.ImGui.currentWindow 5 | 6 | // Clipping 7 | // - Mouse hovering is affected by ImGui::PushClipRect() calls, unlike direct calls to ImDrawList::PushClipRect() which are render only. 8 | interface clipping { 9 | 10 | /** Push a clipping rectangle for both ImGui logic (hit-testing etc.) and low-level ImDrawList rendering. 11 | * - When using this function it is sane to ensure that float are perfectly rounded to integer values, 12 | * so that e.g. (int)(max.x-min.x) in user's render produce correct result. 13 | * - If the code here changes, may need to update code of functions like NextColumn() and PushColumnClipRect(): 14 | * some frequently called functions which to modify both channels and clipping simultaneously tend to use the 15 | * more specialized SetWindowClipRectBeforeSetChannel() to avoid extraneous updates of underlying ImDrawCmds. */ 16 | fun pushClipRect(clipRectMin: Vec2, clipRectMax: Vec2, intersectWithCurrentClipRect: Boolean) { 17 | currentWindow.apply { 18 | drawList.pushClipRect(clipRectMin, clipRectMax, intersectWithCurrentClipRect) 19 | clipRect put drawList._clipRectStack.last() 20 | } 21 | } 22 | 23 | fun popClipRect() { 24 | with(currentWindow) { 25 | drawList.popClipRect() 26 | clipRect put drawList._clipRectStack.last() 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/colorUtilities.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import glm_.f 4 | import glm_.glm 5 | import glm_.i 6 | import glm_.vec3.Vec3 7 | import glm_.vec4.Vec4 8 | import imgui.Vec3Setter 9 | import imgui.put 10 | 11 | 12 | /** Color Utilities */ 13 | interface colorUtilities { 14 | 15 | /** Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592 16 | * Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv */ 17 | fun colorConvertRGBtoHSV(rgb: Vec3, hsv: Vec3 = Vec3()): Vec3 = colorConvertRGBtoHSV(rgb.r, rgb.g, rgb.b, hsv) 18 | fun colorConvertRGBtoHSV(rgb: Vec4, hsv: Vec4 = Vec4()): Vec4 = colorConvertRGBtoHSV(rgb.r, rgb.g, rgb.b, hsv) 19 | fun colorConvertRGBtoHSV(r: Float, g: Float, b: Float, hsv: Vec3) = hsv.apply { 20 | colorConvertRGBtoHSV(r, g, b, ::put) 21 | } 22 | 23 | fun colorConvertRGBtoHSV(r: Float, g: Float, b: Float, hsv: Vec4) = hsv.apply { 24 | colorConvertRGBtoHSV(r, g, b, ::put) 25 | } 26 | 27 | fun Vec3.rgbToHSV() = colorConvertRGBtoHSV(this, this) 28 | fun Vec4.rgbToHSV() = colorConvertRGBtoHSV(this, this) 29 | 30 | /** Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593 31 | * also http://en.wikipedia.org/wiki/HSL_and_HSV */ 32 | fun colorConvertHSVtoRGB(hsv: Vec3, rgb: Vec3 = Vec3()): Vec3 = colorConvertHSVtoRGB(hsv.x, hsv.y, hsv.z, rgb) 33 | 34 | fun colorConvertHSVtoRGB(hsv: Vec4, rgb: Vec4 = Vec4()): Vec4 = colorConvertHSVtoRGB(hsv.x, hsv.y, hsv.z, rgb) 35 | 36 | fun colorConvertHSVtoRGB(h: Float, s: Float, v: Float, rgb: Vec3 = Vec3()): Vec3 = rgb.apply { 37 | colorConvertHSVtoRGB(h, s, v, ::put) 38 | } 39 | 40 | fun colorConvertHSVtoRGB(h: Float, s: Float, v: Float, rgb: Vec4 = Vec4(), unit: Unit = Unit): Vec4 = rgb.apply { 41 | colorConvertHSVtoRGB(h, s, v, ::put) 42 | } 43 | 44 | fun Vec3.hsvToRGB() = colorConvertHSVtoRGB(this, this) 45 | fun Vec4.hsvToRGB() = colorConvertHSVtoRGB(this, this) 46 | } 47 | 48 | inline fun colorConvertRGBtoHSV(rgb: Vec3, hsvSetter: Vec3Setter) { 49 | colorConvertRGBtoHSV(rgb.x, rgb.y, rgb.z, hsvSetter) 50 | } 51 | 52 | inline fun colorConvertRGBtoHSV(rgb: Vec4, hsvSetter: Vec3Setter) { 53 | colorConvertRGBtoHSV(rgb.x, rgb.y, rgb.z, hsvSetter) 54 | } 55 | 56 | inline fun colorConvertRGBtoHSV(r_: Float, g_: Float, b_: Float, hsvSetter: Vec3Setter) { 57 | var k = 0f 58 | var r = r_ 59 | var g = g_ 60 | var b = b_ 61 | if (g < b) { 62 | val tmp = g; g = b; b = tmp 63 | k = -1f 64 | } 65 | if (r < g) { 66 | val tmp = r; r = g; g = tmp 67 | k = -2f / 6f - k 68 | } 69 | 70 | val chroma = r - (if (g < b) g else b) 71 | hsvSetter(glm.abs(k + (g - b) / (6f * chroma + 1e-20f)), chroma / (r + 1e-20f), r) 72 | } 73 | 74 | inline fun colorConvertHSVtoRGB(hsv: Vec3, rgbSetter: Vec3Setter) { 75 | colorConvertHSVtoRGB(hsv.x, hsv.y, hsv.z, rgbSetter) 76 | } 77 | 78 | inline fun colorConvertHSVtoRGB(hsv: Vec4, rgbSetter: Vec3Setter) { 79 | colorConvertHSVtoRGB(hsv.x, hsv.y, hsv.z, rgbSetter) 80 | } 81 | 82 | inline fun colorConvertHSVtoRGB(h_: Float, s: Float, v: Float, rgbSetter: Vec3Setter) { 83 | if (s == 0f) { 84 | // gray 85 | return rgbSetter(v, v, v) 86 | } 87 | 88 | val h = glm.mod(h_, 1f) / (60f / 360f) 89 | val i = h.i 90 | val f = h - i.f 91 | val p = v * (1f - s) 92 | val q = v * (1f - s * f) 93 | val t = v * (1f - s * (1f - f)) 94 | 95 | when (i) { 96 | 0 -> rgbSetter(v, t, p) 97 | 1 -> rgbSetter(q, v, p) 98 | 2 -> rgbSetter(p, v, t) 99 | 3 -> rgbSetter(p, q, v) 100 | 4 -> rgbSetter(t, p, v) 101 | else -> rgbSetter(v, p, q) 102 | } 103 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/contentRegion.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import glm_.vec2.Vec2 4 | import imgui.ImGui.contentRegionMaxAbs 5 | 6 | // Content region 7 | // - Retrieve available space from a given point. GetContentRegionAvail() is frequently useful. 8 | // - Those functions are bound to be redesigned (they are confusing, incomplete and the Min/Max return values are in local window coordinates which increases confusion) 9 | interface contentRegion { 10 | 11 | /** == GetContentRegionMax() - GetCursorPos() 12 | * 13 | * ~GetContentRegionAvail */ 14 | val contentRegionAvail: Vec2 15 | get() = g.currentWindow!!.run { contentRegionMaxAbs - dc.cursorPos } 16 | 17 | /** current content boundaries (typically window boundaries including scrolling, or current column boundaries), in 18 | * windows coordinates 19 | * FIXME: This is in window space (not screen space!). We should try to obsolete all those functions. 20 | * ~GetContentRegionMax */ 21 | val contentRegionMax: Vec2 22 | /** ~GetContentRegionMax */ 23 | get() { 24 | val window = g.currentWindow!! 25 | val mx = window.contentRegionRect.max - window.pos 26 | if (window.dc.currentColumns != null || g.currentTable != null) 27 | mx.x = window.workRect.max.x - window.pos.x 28 | return mx 29 | } 30 | 31 | /** content boundaries min for the full window (roughly (0,0)-Scroll), in window coordinates 32 | * ~GetWindowContentRegionMin */ 33 | val windowContentRegionMin: Vec2 34 | get() = g.currentWindow!!.run { contentRegionRect.min - pos } 35 | 36 | /** content boundaries max for the full window (roughly (0,0)+Size-Scroll) where Size can be overridden with SetNextWindowContentSize(), 37 | * in window coordinates 38 | * ~GetWindowContentRegionMax */ 39 | val windowContentRegionMax: Vec2 40 | get() = g.currentWindow!!.run { contentRegionRect.max - pos } 41 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/context.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import imgui.classes.Context 4 | 5 | 6 | /** ----------------------------------------------------------------------------- 7 | * Context 8 | * ----------------------------------------------------------------------------- 9 | * 10 | * Current context pointer. Implicitly used by all ImGui functions. Always assumed to be != null. 11 | * ImGui::CreateContext() will automatically set this pointer if it is NULL. Change to a different context by calling ImGui::SetCurrentContext(). 12 | * 1) Important: globals are not shared across DLL boundaries! If you use DLLs or any form of hot-reloading: you will need to call 13 | * SetCurrentContext() (with the pointer you got from CreateContext) from each unique static/DLL boundary, and after each hot-reloading. 14 | * In your debugger, add GImGui to your watch window and notice how its value changes depending on which location you are currently stepping into. 15 | * 2) Important: Dear ImGui functions are not thread-safe because of this pointer. 16 | * If you want thread-safety to allow N threads to access N different contexts, you can: 17 | * - Change this variable to use thread local storage so each thread can refer to a different context, in imconfig.h: 18 | * struct ImGuiContext; 19 | * extern thread_local ImGuiContext* MyImGuiTLS; 20 | * #define GImGui MyImGuiTLS 21 | * And then define MyImGuiTLS in one of your cpp file. Note that thread_local is a C++11 keyword, earlier C++ uses compiler-specific keyword. 22 | * - Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586 23 | * - If you need a finite number of contexts, you may compile and use multiple instances of the ImGui code from different namespace. */ 24 | val g: Context 25 | get() = gImGui 26 | 27 | /** ~GetCurrentContext/SetCurrentContext */ 28 | var gImGui: Context 29 | get() = gImGuiNullable!! 30 | set(value) { 31 | gImGuiNullable = value 32 | } 33 | var gImGuiNullable: Context? = null 34 | 35 | 36 | -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/debugUtilities.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import glm_.b 4 | import imgui.ImGui 5 | import imgui.ImGui.sameLine 6 | import imgui.ImGui.tableHeadersRow 7 | import imgui.ImGui.tableNextColumn 8 | import imgui.ImGui.tableSetupColumn 9 | import imgui.ImGui.text 10 | import imgui.ImGui.textUnformatted 11 | import imgui.TableFlag 12 | import imgui.div 13 | import imgui.dsl.table 14 | import imgui.internal.textCharFromUtf8 15 | import imgui.or 16 | import uno.kotlin.NUL 17 | 18 | // Debug Utilities 19 | interface debugUtilities { 20 | 21 | /** Helper tool to diagnose between text encoding issues and font loading issues. Pass your UTF-8 string and verify that there are correct. */ 22 | fun debugTextEncoding(str: ByteArray) { 23 | text("Text: \"$str\"") 24 | table("##DebugTextEncoding", 4, TableFlag.Borders / TableFlag.RowBg / TableFlag.SizingFixedFit / TableFlag.Resizable) { 25 | tableSetupColumn("Offset") 26 | tableSetupColumn("UTF-8") 27 | tableSetupColumn("Glyph") 28 | tableSetupColumn("Codepoint") 29 | tableHeadersRow() 30 | var p = 0 31 | while (p < str.size && str[p] != 0.b) { 32 | val (c, cUtf8Len) = textCharFromUtf8(str, p, -1) 33 | tableNextColumn() 34 | text("$p") 35 | tableNextColumn() 36 | for (byteIndex in 0 until cUtf8Len) { 37 | if (byteIndex > 0) 38 | sameLine() 39 | text("0x%02X", str[p + byteIndex]) 40 | } 41 | tableNextColumn() 42 | if (ImGui.font.findGlyphNoFallback(Char(c)) != null) 43 | textUnformatted(str.copyOfRange(p, p + cUtf8Len), cUtf8Len) 44 | else 45 | textUnformatted("[missing]") 46 | tableNextColumn() 47 | text("U+%04X", c) 48 | p += cUtf8Len 49 | } 50 | } 51 | } 52 | //IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro. 53 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/focusActivation.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import imgui.Dir 4 | import imgui.ImGui.navMoveRequestResolveWithLastItem 5 | import imgui.ImGui.navMoveRequestSubmit 6 | import imgui.ImGui.scrollToRectEx 7 | import imgui.ImGui.setNavWindow 8 | import imgui.div 9 | import imgui.internal.sections.IMGUI_DEBUG_LOG_FOCUS 10 | import imgui.internal.sections.NavMoveFlag 11 | import imgui.internal.sections.ScrollFlag 12 | import imgui.statics.navApplyItemToResult 13 | import imgui.statics.navUpdateAnyRequestFlag 14 | 15 | 16 | /** Focus, Activation 17 | * - Prefer using "SetItemDefaultFocus()" over "if (IsWindowAppearing()) SetScrollHereY()" when applicable to signify "this is the default item" */ 18 | interface focusActivation { 19 | 20 | // (Prefer using "SetItemDefaultFocus()" over "if (IsWindowAppearing()) SetScrollHereY()" when applicable to signify "this is the default item") 21 | 22 | /** make last item the default focused item of a window. */ 23 | fun setItemDefaultFocus() { 24 | val window = g.currentWindow!! 25 | if (!window.appearing) 26 | return 27 | if (g.navWindow !== window.rootWindowForNav || (!g.navInitRequest && g.navInitResult.id == 0) || g.navLayer != window.dc.navLayerCurrent) 28 | return 29 | 30 | g.navInitRequest = false 31 | navApplyItemToResult(g.navInitResult) 32 | navUpdateAnyRequestFlag() 33 | 34 | // Scroll could be done in NavInitRequestApplyResult() via an opt-in flag (we however don't want regular init requests to scroll) 35 | if (g.lastItemData.rect !in window.clipRect) 36 | scrollToRectEx(window, g.lastItemData.rect) 37 | } 38 | 39 | /** focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. 40 | * Use -1 to access previous widget. 41 | * 42 | * Note: this will likely be called ActivateItem() once we rework our Focus/Activation system! 43 | * But ActivateItem() should function without altering scroll/focus? */ 44 | fun setKeyboardFocusHere(offset: Int = 0) { 45 | val window = g.currentWindow!! 46 | assert(offset >= -1) { "-1 is allowed but not below" } 47 | IMGUI_DEBUG_LOG_FOCUS("SetKeyboardFocusHere($offset) in window \"${window.name}\"") 48 | 49 | // It makes sense in the vast majority of cases to never interrupt a drag and drop. 50 | // When we refactor this function into ActivateItem() we may want to make this an option. 51 | // MovingWindow is protected from most user inputs using SetActiveIdUsingNavAndKeys(), but 52 | // is also automatically dropped in the event g.ActiveId is stolen. 53 | if (g.dragDropActive || g.movingWindow != null) { 54 | IMGUI_DEBUG_LOG_FOCUS("SetKeyboardFocusHere() ignored while DragDropActive!") 55 | return 56 | } 57 | 58 | setNavWindow(window) 59 | 60 | val moveFlags = NavMoveFlag.Tabbing / NavMoveFlag.Activate / NavMoveFlag.FocusApi 61 | val scrollFlags = if (window.appearing) ScrollFlag.KeepVisibleEdgeX / ScrollFlag.AlwaysCenterY else ScrollFlag.KeepVisibleEdgeX / ScrollFlag.KeepVisibleEdgeY 62 | navMoveRequestSubmit(Dir.None, if (offset < 0) Dir.Up else Dir.Down, moveFlags, scrollFlags) // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable. 63 | if (offset == -1) 64 | navMoveRequestResolveWithLastItem(g.navMoveResultLocal) 65 | else { 66 | g.navTabbingDir = 1 67 | g.navTabbingCounter = offset + 1 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/idStackScopes.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import imgui.ID 4 | 5 | // ID stack/scopes 6 | // Read the FAQ (docs/FAQ.md or http://dearimgui.org/faq) for more details about how ID are handled in dear imgui. 7 | // - Those questions are answered and impacted by understanding of the ID stack system: 8 | // - "Q: Why is my widget not reacting when I click on it?" 9 | // - "Q: How can I have widgets with an empty label?" 10 | // - "Q: How can I have multiple widgets with the same label?" 11 | // - Short version: ID are hashes of the entire ID stack. If you are creating widgets in a loop you most likely 12 | // want to push a unique identifier (e.g. object pointer, loop index) to uniquely differentiate them. 13 | // - You can also use the "Label##foobar" syntax within widget label to distinguish them from each others. 14 | // - In this header file we use the "label"/"name" terminology to denote a string that will be displayed + used as an ID, 15 | // whereas "str_id" denote a string that is only used as an ID and not normally displayed. 16 | interface idStackScopes { 17 | 18 | /** [JVM] */ 19 | fun pushID(ptrID: Any) = with(g.currentWindow!!) { idStack += getID(ptrID) } 20 | 21 | /** push string into the ID stack (will hash string). */ 22 | fun pushID(strID: String) = with(g.currentWindow!!) { idStack += getID(strID) } 23 | 24 | /** push string into the ID stack (will hash string). */ 25 | fun pushID(strID: String, strIdEnd: Int) = with(g.currentWindow!!) { idStack += getID(strID, strIdEnd) } 26 | 27 | /** push pointer into the ID stack (will hash pointer). */ 28 | fun pushID(intPtr: Long) = with(g.currentWindow!!) { idStack += getID(intPtr) } 29 | 30 | /** push integer into the ID stack (will hash integer). */ 31 | fun pushID(intId: Int) = with(g.currentWindow!!) { idStack += getID(intId) } 32 | 33 | /** pop from the ID stack. */ 34 | fun popID() { 35 | val window = g.currentWindow!! 36 | assert(window.idStack.size > 1) { "Too many PopID(), or could be popping in a wrong/different window?" } 37 | window.idStack.pop() 38 | } 39 | 40 | /** calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage 41 | * yourself. otherwise rarely needed */ 42 | fun getID(strID: String) = g.currentWindow!!.getID(strID) 43 | 44 | fun getID(ptrID: Any): ID = g.currentWindow!!.getID(ptrID) 45 | 46 | /** ~ImGui::GetID((void*)(intptr_t)i) */ 47 | fun getID(intPtr: Long): ID = g.currentWindow!!.getID(intPtr) 48 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/inputsUtilitiesKeyboardMouseGamepad.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import glm_.i 4 | import imgui.ImGui 5 | import imgui.ImGui.data 6 | import imgui.ImGui.isDown 7 | import imgui.ImGui.isPressed 8 | import imgui.ImGui.isReleased 9 | import imgui.Key 10 | import imgui.none 11 | import imgui.internal.classes.InputFlag 12 | import imgui.internal.sections.KeyOwner_Any 13 | 14 | 15 | // Inputs Utilities: Keyboard/Mouse/Gamepad 16 | // - the ImGuiKey enum contains all possible keyboard, mouse and gamepad inputs (e.g. ImGuiKey_A, ImGuiKey_MouseLeft, ImGuiKey_GamepadDpadUp...). 17 | // - before v1.87, we used ImGuiKey to carry native/user indices as defined by each backends. About use of those legacy ImGuiKey values: 18 | // - without IMGUI_DISABLE_OBSOLETE_KEYIO (legacy support): you can still use your legacy native/user indices (< 512) according to how your backend/engine stored them in io.KeysDown[], but need to cast them to ImGuiKey. 19 | // - with IMGUI_DISABLE_OBSOLETE_KEYIO (this is the way forward): any use of ImGuiKey will assert with key < 512. GetKeyIndex() is pass-through and therefore deprecated (gone if IMGUI_DISABLE_OBSOLETE_KEYIO is defined). 20 | interface inputsUtilitiesKeyboardMouseGamepad { 21 | 22 | /** ~IsKeyDown 23 | * 24 | * is key being held. 25 | * 26 | * Note that Dear ImGui doesn't know the meaning/semantic of ImGuiKey from 0..511: they are legacy native keycodes. 27 | * Consider transitioning from 'IsKeyDown(MY_ENGINE_KEY_A)' (<1.87) to IsKeyDown(A) (>= 1.87) */ 28 | val Key.isDown: Boolean 29 | get() = isDown(KeyOwner_Any) 30 | 31 | /** [JVM] ~IsKeyPressed 32 | * 33 | * uses user's key indices as stored in the keys_down[] array. if repeat=true. 34 | * uses io.KeyRepeatDelay / KeyRepeatRate 35 | * 36 | * was key pressed (went from !Down to Down)? if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate */ 37 | infix fun Key.isPressed(repeat: Boolean): Boolean = isPressed(KeyOwner_Any, if (repeat) InputFlag.Repeat else none) 38 | 39 | /** ~IsKeyPressed() */ 40 | val Key.isPressed: Boolean 41 | get() = isPressed(true) 42 | 43 | /** ~IsKeyReleased 44 | * 45 | * was key released (went from Down to !Down)? */ 46 | val Key.isReleased: Boolean 47 | get() = isReleased(KeyOwner_Any) 48 | 49 | /** ~getKeyPressedAmount 50 | * 51 | * Uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough 52 | * that DeltaTime > RepeatRate 53 | * 54 | * Return value representing the number of presses in the last time period, for the given repeat rate 55 | * (most often returns 0 or 1. The result is generally only >1 when RepeatRate is smaller than DeltaTime, aka large DeltaTime or fast RepeatRate) */ 56 | fun Key.getPressedAmount(repeatDelay: Float, repeatRate: Float): Int { 57 | if (!data.down) // In theory this should already be encoded as (DownDuration < 0.0f), but testing this facilitates eating mechanism (until we finish work on key ownership) 58 | return 0 59 | val t = ImGui.io.keysData[index].downDuration 60 | return ImGui.calcTypematicRepeatAmount(t - ImGui.io.deltaTime, t, repeatDelay, repeatRate) 61 | } 62 | 63 | /** Override io.WantCaptureKeyboard flag next frame (said flag is left for your application to handle, typically when true it instructs your app to ignore inputs). e.g. force capture keyboard when your widget is being hovered. This is equivalent to setting "io.WantCaptureKeyboard = want_capture_keyboard"; after the next NewFrame() call. */ 64 | fun setNextFrameWantCaptureKeyboard(wantCaptureKeyboard: Boolean = true) { 65 | g.wantCaptureKeyboardNextFrame = wantCaptureKeyboard.i 66 | } 67 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/loggingCapture.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import imgui.ImGui.button 4 | import imgui.ImGui.clipboardText 5 | import imgui.ImGui.logBegin 6 | import imgui.ImGui.popTabStop 7 | import imgui.ImGui.popID 8 | import imgui.ImGui.pushTabStop 9 | import imgui.ImGui.pushID 10 | import imgui.ImGui.sameLine 11 | import imgui.ImGui.setNextItemWidth 12 | import imgui.classes.Context 13 | import imgui.internal.sections.LogType 14 | import java.io.File 15 | import java.io.FileWriter 16 | 17 | /** Logging/Capture 18 | * - All text output from the interface can be captured into tty/file/clipboard. 19 | * By default, tree nodes are automatically opened during logging. */ 20 | interface loggingCapture { 21 | 22 | /** Start logging/capturing text output to TTY */ 23 | fun logToTTY(autoOpenDepth: Int = -1): Nothing = TODO() 24 | 25 | /** Start logging/capturing text output to given file */ 26 | fun logToFile(maxDepth: Int = -1, file_: File? = null) { 27 | if (g.logEnabled) 28 | return 29 | val window = g.currentWindow!! 30 | 31 | g.logFile = file_ ?: g.logFile ?: return 32 | 33 | g.logEnabled = true 34 | g.logDepthRef = window.dc.treeDepth 35 | if (maxDepth >= 0) 36 | g.logDepthToExpandDefault = maxDepth 37 | } 38 | 39 | /** start logging ImGui output to OS clipboard */ 40 | fun logToClipboard(autoOpenDepth: Int = -1) { 41 | 42 | if (g.logEnabled) return 43 | 44 | logBegin(LogType.Clipboard, autoOpenDepth) 45 | } 46 | 47 | /** stop logging (close file, etc.) */ 48 | fun logFinish() { 49 | 50 | if (!g.logEnabled) 51 | return 52 | 53 | logText("\n") 54 | 55 | when (g.logType) { 56 | LogType.TTY -> TODO() //fflush(g.LogFile) 57 | LogType.File -> TODO() //fclose(g.LogFile) 58 | LogType.Buffer -> Unit 59 | LogType.Clipboard -> { 60 | if (g.logBuffer.length > 1) { // TODO 1? maybe 0? 61 | clipboardText = g.logBuffer.toString() 62 | g.logBuffer.clear() 63 | } 64 | } 65 | else -> error("Invalid log type") 66 | } 67 | 68 | g.logEnabled = false 69 | g.logType = LogType.None 70 | g.logFile = null 71 | g.logBuffer.clear() 72 | } 73 | 74 | /** Helper to display buttons for logging to tty/file/clipboard 75 | * FIXME-OBSOLETE: We should probably obsolete this and let the user have their own helper (this is one of the oldest function alive!) */ 76 | fun logButtons() { 77 | pushID("LogButtons") 78 | val logToTty = button("Log To TTY"); sameLine() 79 | val logToFile = button("Log To File"); sameLine() 80 | val logToClipboard = button("Log To Clipboard"); sameLine() 81 | pushTabStop(false) 82 | setNextItemWidth(80f) 83 | slider("Default Depth", g::logDepthToExpandDefault, 0, 9) 84 | popTabStop() 85 | popID() 86 | 87 | // Start logging at the end of the function so that the buttons don't appear in the log 88 | if (logToTty) logToTTY() 89 | if (logToFile) logToFile() 90 | if (logToClipboard) logToClipboard() 91 | } 92 | 93 | /** pass text data straight to log (without being displayed) */ 94 | fun logTextV(g: Context, fmt: String, vararg args: Any) { 95 | val text = if (args.isEmpty()) fmt else fmt.format(*args) 96 | g.logFile?.appendText(text) ?: g.logBuffer.append(text) 97 | } 98 | 99 | fun logText(fmt: String, vararg args: Any) { 100 | if (!g.logEnabled) 101 | return 102 | 103 | logTextV(g, fmt, *args) 104 | } 105 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/miscellaneousUtilities.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import glm_.vec2.Vec2 4 | import imgui.* 5 | import imgui.ImGui.beginChild 6 | import imgui.ImGui.currentWindowRead 7 | import imgui.ImGui.endChild 8 | import imgui.ImGui.popStyleColor 9 | import imgui.ImGui.popStyleVar 10 | import imgui.ImGui.pushStyleColor 11 | import imgui.ImGui.pushStyleVar 12 | import imgui.ImGui.style 13 | import imgui.internal.classes.Rect 14 | import imgui.internal.sections.DrawListSharedData 15 | import imgui.WindowFlag as Wf 16 | 17 | /** Miscellaneous Utilities */ 18 | interface miscellaneousUtilities { 19 | 20 | /** test if rectangle (of given size, starting from cursor position) is visible / not clipped. */ 21 | fun isRectVisible(size: Vec2): Boolean = with(currentWindowRead!!) { clipRect overlaps Rect(dc.cursorPos, dc.cursorPos + size) } 22 | 23 | /** [JVM] */ 24 | fun isRectVisible(rect: Rect): Boolean = isRectVisible(rect.min, rect.max) 25 | 26 | /** test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. */ 27 | fun isRectVisible(rectMin: Vec2, rectMax: Vec2): Boolean = currentWindowRead!!.clipRect overlaps Rect(rectMin, rectMax) 28 | 29 | /** ~GetTime */ 30 | val time: Double 31 | get() = g.time 32 | 33 | /** ~GetFrameCount */ 34 | val frameCount: Int 35 | get() = g.frameCount 36 | 37 | /** you may use this when creating your own ImDrawList instances. 38 | * ~GetDrawListSharedData */ 39 | val drawListSharedData: DrawListSharedData 40 | get() = g.drawListSharedData 41 | 42 | /** Useless on JVM with Enums */ 43 | //IMGUI_API const char* GetStyleColorName(ImGuiCol idx); 44 | 45 | var stateStorage: HashMap? 46 | /** ~GetStateStorage */ 47 | get() = g.currentWindow!!.dc.stateStorage 48 | /** ~SetStateStorage */ 49 | set(value) { 50 | val window = g.currentWindow!! 51 | window.dc.stateStorage = value ?: window.stateStorage 52 | } 53 | 54 | 55 | /** helper to create a child window / scrolling region that looks like a normal widget frame */ 56 | fun beginChildFrame(id: ID, size: Vec2, extraFlags: WindowFlags = none): Boolean { 57 | pushStyleColor(Col.ChildBg, style.colors[Col.FrameBg]) 58 | pushStyleVar(StyleVar.ChildRounding, style.frameRounding) 59 | pushStyleVar(StyleVar.ChildBorderSize, style.frameBorderSize) 60 | pushStyleVar(StyleVar.WindowPadding, style.framePadding) 61 | return beginChild(id, size, true, Wf.NoMove or Wf.AlwaysUseWindowPadding or extraFlags).also { 62 | popStyleVar(3) 63 | popStyleColor() 64 | } 65 | } 66 | 67 | /** Always call EndChildFrame() regardless of BeginChildFrame() return values (which indicates a collapsed/clipped window) */ 68 | fun endChildFrame() = endChild() 69 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/overlappingMode.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import imgui.div 4 | import imgui.internal.sections.ItemFlag 5 | 6 | // Overlapping mode 7 | interface overlappingMode { 8 | 9 | // Allow next item to be overlapped by subsequent items. 10 | // This works by requiring HoveredId to match for two subsequent frames, 11 | // so if a following items overwrite it our interactions will naturally be disabled. 12 | fun setNextItemAllowOverlap() { 13 | val g = gImGui 14 | g.nextItemData.itemFlags /= ItemFlag.AllowOverlap 15 | } 16 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/settingsIniUtilities.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import imgui.ImGui.findSettingsHandler 4 | import imgui.internal.sections.SettingsHandler 5 | import java.io.File 6 | import java.nio.file.Paths 7 | 8 | 9 | // Settings/.Ini Utilities 10 | // - The disk functions are automatically called if io.IniFilename != NULL (default is "imgui.ini"). 11 | // - Set io.IniFilename to NULL to load/save manually. Read io.WantSaveIniSettings description about handling .ini saving manually. 12 | // - Important: default value "imgui.ini" is relative to current working dir! Most apps will want to lock this to an absolute path (e.g. same path as executables). 13 | interface settingsIniUtilities { 14 | 15 | /** call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename). */ 16 | fun loadIniSettingsFromDisk(iniFilename: String?) { 17 | if (iniFilename == null) 18 | return 19 | val file = File(Paths.get(iniFilename).toUri()) 20 | if (file.exists() && file.canRead()) 21 | loadIniSettingsFromMemory(file.readLines()) 22 | } 23 | 24 | /** call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source. 25 | * 26 | * Zero-tolerance, no error reporting, cheap .ini parsing 27 | * Set ini_size==0 to let us use strlen(ini_data). Do not call this function with a 0 if your buffer is actually empty! */ 28 | fun loadIniSettingsFromMemory(lines: List) { 29 | 30 | assert(g.initialized) 31 | //IM_ASSERT(!g.WithinFrameScope && "Cannot be called between NewFrame() and EndFrame()"); 32 | // assert(!g.settingsLoaded && g.frameCount == 0) 33 | 34 | // For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter). 35 | // For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy.. 36 | 37 | // Call pre-read handlers 38 | // Some types will clear their data (e.g. dock information) some types will allow merge/override (window) 39 | for (handler in g.settingsHandlers) 40 | handler.readInitFn?.invoke(g, handler) 41 | 42 | var entryHandler: SettingsHandler? = null 43 | var entryData: Any? = null 44 | for (i in lines.indices) { 45 | val line = lines[i].trim() 46 | if (line.isNotEmpty() && line.isNotBlank()) { 47 | // Skip new lines markers, then find end of the line 48 | if (line[0] == '[' && line.last() == ']') { 49 | // Parse "[Type][Name]". Note that 'Name' can itself contains [] characters, which is acceptable with the current format and parsing code. 50 | val firstCloseBracket = line.indexOf(']') 51 | if (firstCloseBracket != -1 && line[firstCloseBracket + 1] == '[') { 52 | val type = line.substring(1, firstCloseBracket) 53 | val name = line.substring(firstCloseBracket + 2, line.lastIndex) 54 | entryHandler = findSettingsHandler(type) 55 | entryData = entryHandler?.readOpenFn?.invoke(g, entryHandler, name) 56 | } 57 | } else if (entryHandler != null && entryData != null) 58 | // Let type handler parse the line 59 | entryHandler.readLineFn!!(g, entryHandler, entryData, line) 60 | } 61 | } 62 | g.settingsLoaded = true 63 | 64 | // Call post-read handlers 65 | for (handler in g.settingsHandlers) 66 | handler.applyAllFn?.invoke(g, handler) 67 | } 68 | 69 | /** this is automatically called (if io.IniFilename is not empty) a few seconds after any modification that should be reflected in the .ini file (and also by DestroyContext). */ 70 | fun saveIniSettingsToDisk(iniFilename: String?) { 71 | 72 | g.settingsDirtyTimer = 0f 73 | if (iniFilename == null) 74 | return 75 | 76 | val file = File(Paths.get(iniFilename).toUri()) 77 | if (file.exists() && file.canWrite()) 78 | file.writeText(saveIniSettingsToMemory()) 79 | } 80 | 81 | /** Call registered handlers (e.g. SettingsHandlerWindow_WriteAll() + custom handlers) to write their stuff into a text buffer */ 82 | fun saveIniSettingsToMemory(): String { 83 | g.settingsDirtyTimer = 0f 84 | val buf = StringBuilder() 85 | for (handler in g.settingsHandlers) 86 | handler.writeAllFn!!(g, handler, buf) 87 | g.settingsIniData = buf.toString() 88 | return g.settingsIniData 89 | } 90 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/styleReadAccess.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import glm_.f 4 | import glm_.i 5 | import glm_.vec2.Vec2 6 | import glm_.vec4.Vec4 7 | import imgui.* 8 | import imgui.font.Font 9 | 10 | // Style read access 11 | // - Use the ShowStyleEditor() function to interactively see/edit the colors. 12 | interface styleReadAccess { 13 | 14 | /** get current font 15 | * ~GetFont */ 16 | val font: Font 17 | get() = g.font 18 | 19 | /** get current font size (= height in pixels) of current font with current scale applied 20 | * ~GetFontSize */ 21 | val fontSize: Float 22 | get() = g.fontSize 23 | 24 | /** get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API 25 | * ~GetFontTexUvWhitePixel */ 26 | val fontTexUvWhitePixel: Vec2 27 | get() = g.drawListSharedData.texUvWhitePixel 28 | 29 | /** retrieve given style color with style alpha applied and optional extra alpha multiplier */ 30 | fun getColorU32(idx: Col, alphaMul: Float = 1f): Int = getColorU32(idx.i, alphaMul) 31 | 32 | fun getColorU32(idx: Int, alphaMul: Float = 1f): Int { 33 | val c = Vec4(ImGui.style.colors[idx]) 34 | c.w *= ImGui.style.alpha * alphaMul 35 | return c.u32 36 | } 37 | 38 | /** retrieve given color with style alpha applied */ 39 | fun getColorU32(col: Vec4): Int { 40 | val c = Vec4(col) 41 | c.w *= ImGui.style.alpha 42 | return c.u32 43 | } 44 | 45 | /** retrieve given color with style alpha applied */ 46 | fun getColorU32(col: Int): Int { 47 | val styleAlpha = ImGui.style.alpha 48 | if (styleAlpha >= 1f) return col 49 | var a = (col and COL32_A_MASK) ushr COL32_A_SHIFT 50 | a = (a * styleAlpha).i // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range. 51 | return (col and COL32_A_MASK.inv()) or (a shl COL32_A_SHIFT) 52 | } 53 | 54 | fun getColorU32(r: Int, g: Int, b: Int, a: Int): Int { 55 | val c = Vec4(r.f / 255.0, g.f / 255.0, b.f / 255.0, a.f / 255.0) 56 | c.w *= ImGui.style.alpha 57 | return c.u32 58 | } 59 | 60 | /** retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwise use 61 | * GetColorU32() to get style color + style alpha. */ 62 | fun getStyleColorVec4(idx: Col): Vec4 = Vec4(ImGui.style.colors[idx]) 63 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/textUtilities.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import glm_.vec2.Vec2 4 | import imgui.ImGui 5 | import imgui.internal.floor 6 | 7 | // Text Utilities 8 | interface textUtilities { 9 | 10 | /** Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. 11 | * CalcTextSize("") should return ImVec2(0.0f, g.FontSize) */ 12 | fun calcTextSize(text: String, hideTextAfterDoubleHash: Boolean = false, wrapWidth: Float = -1f): Vec2 { 13 | val bytes = text.toByteArray() 14 | return calcTextSize(bytes, 0, bytes.size, hideTextAfterDoubleHash, wrapWidth) 15 | } 16 | 17 | /** Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. 18 | * CalcTextSize("") should return ImVec2(0.0f, g.FontSize) */ 19 | fun calcTextSize(text: ByteArray, textBegin: Int, textEnd: Int = text.size, hideTextAfterDoubleHash: Boolean = false, wrapWidth: Float = -1f): Vec2 { 20 | 21 | val textDisplayEnd = when { 22 | hideTextAfterDoubleHash -> ImGui.findRenderedTextEnd(text, 0, textEnd) // Hide anything after a '##' string 23 | else -> textEnd 24 | } 25 | 26 | val font = g.font 27 | val fontSize = g.fontSize 28 | return when (textDisplayEnd) { 29 | 0 -> Vec2(0f, fontSize) 30 | else -> font.calcTextSizeA(fontSize, Float.MAX_VALUE, wrapWidth, text, textEnd = textDisplayEnd).apply { 31 | // Round 32 | // FIXME: This has been here since Dec 2015 (7b0bf230) but down the line we want this out. 33 | // FIXME: Investigate using ceilf or e.g. 34 | // - https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c 35 | // - https://embarkstudios.github.io/rust-gpu/api/src/libm/math/ceilf.rs.html 36 | x = floor(x + 0.99999f) 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/tooltips.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import imgui.HoveredFlag 4 | import imgui.ImGui.beginTooltipEx 5 | import imgui.ImGui.currentWindowRead 6 | import imgui.ImGui.end 7 | import imgui.ImGui.isItemHovered 8 | import imgui.ImGui.text 9 | import imgui.has 10 | import imgui.internal.sections.TooltipFlag 11 | import imgui.none 12 | import imgui.WindowFlag as Wf 13 | 14 | // Tooltips 15 | // - Tooltips are windows following the mouse. They do not take focus away. 16 | // - A tooltip window can contain items of any types. SetTooltip() is a shortcut for the 'if (BeginTooltip()) { Text(...); EndTooltip(); }' idiom. 17 | interface tooltips { 18 | 19 | /** begin/append a tooltip window. */ 20 | fun beginTooltip(): Boolean = beginTooltipEx() 21 | 22 | /** only call EndTooltip() if BeginTooltip()/BeginItemTooltip() returns true! */ 23 | fun endTooltip() { 24 | assert(currentWindowRead!!.flags has Wf._Tooltip) { "Mismatched BeginTooltip()/EndTooltip() calls" } 25 | end() 26 | } 27 | 28 | /** set a text-only tooltip. Often used after a ImGui::IsItemHovered() check. Override any previous call to SetTooltip(). */ 29 | fun setTooltip(fmt: String, vararg args: Any) { 30 | if (!beginTooltipEx(TooltipFlag.OverridePrevious)) 31 | return 32 | text(fmt, *args) 33 | endTooltip() 34 | } 35 | 36 | // Tooltips: helpers for showing a tooltip when hovering an item 37 | // - BeginItemTooltip() is a shortcut for the 'if (IsItemHovered(ImGuiHoveredFlags_Tooltip) && BeginTooltip())' idiom. 38 | // - SetItemTooltip() is a shortcut for the 'if (IsItemHovered(ImGuiHoveredFlags_Tooltip)) { SetTooltip(...); }' idiom. 39 | // - Where 'ImGuiHoveredFlags_Tooltip' itself is a shortcut to use 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on active input type. For mouse it defaults to 'ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort'. 40 | 41 | /** begin/append a tooltip window if preceding item was hovered. */ 42 | fun beginItemTooltip(): Boolean { 43 | if (!isItemHovered(HoveredFlag.ForTooltip)) 44 | return false 45 | return beginTooltipEx(none, none) 46 | } 47 | 48 | /** Shortcut to use 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav'. 49 | * Defaults to == ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort when using the mouse. 50 | * 51 | * set a text-only tooltip if preceeding item was hovered. override any previous call to SetTooltip(). 52 | */ 53 | fun setItemTooltip(fmt: String, vararg args: String) { 54 | if (isItemHovered(HoveredFlag.ForTooltip)) 55 | setTooltip(fmt, *args) 56 | } 57 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/viewports.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import imgui.Viewport 4 | 5 | // Viewports 6 | // - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows. 7 | // - In 'docking' branch with multi-viewport enabled, we extend this concept to have multiple active viewports. 8 | // - In the future we will extend this concept further to also represent Platform Monitor and support a "no main platform window" operation mode. 9 | interface viewports { 10 | 11 | /** return primary/default viewport. This can never be NULL. */ 12 | val mainViewport: Viewport 13 | get() = g.viewports[0] 14 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/widgetsDataPlotting.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import glm_.vec2.Vec2 4 | import imgui.internal.api.plotEx 5 | import imgui.internal.sections.PlotType 6 | 7 | // Widgets: Data Plotting 8 | // - Consider using ImPlot (https://github.com/epezent/implot) which is much better! 9 | interface widgetsDataPlotting { 10 | fun plotLines(label: String, 11 | values: FloatArray, 12 | valuesOffset: Int = 0, 13 | overlayText: String = "", 14 | scaleMin: Float = Float.MAX_VALUE, 15 | scaleMax: Float = Float.MAX_VALUE, 16 | graphSize: Vec2 = Vec2(), 17 | stride: Int = 1): Int = 18 | plotEx(PlotType.Lines, label, values.size, valuesOffset, overlayText, scaleMin, scaleMax, graphSize) { 19 | values[it * stride] 20 | } 21 | 22 | fun plotHistogram(label: String, 23 | values: FloatArray, 24 | valuesOffset: Int = 0, 25 | overlayText: String = "", 26 | scaleMin: Float = Float.MAX_VALUE, 27 | scaleMax: Float = Float.MAX_VALUE, 28 | graphSize: Vec2 = Vec2(), 29 | stride: Int = 1): Int = 30 | plotEx(PlotType.Histogram, label, values.size, valuesOffset, overlayText, scaleMin, scaleMax, graphSize) { 31 | values[it * stride] 32 | } 33 | } 34 | 35 | inline fun plotLines(label: String, 36 | valuesCount: Int, 37 | valuesOffset: Int = 0, 38 | overlayText: String = "", 39 | scaleMin: Float = Float.MAX_VALUE, 40 | scaleMax: Float = Float.MAX_VALUE, 41 | graphSize: Vec2 = Vec2(), 42 | valuesGetter: (idx: Int) -> Float) = plotEx(PlotType.Lines, label, valuesCount, valuesOffset, overlayText, scaleMin, scaleMax, graphSize, valuesGetter) 43 | 44 | inline fun plotHistogram(label: String, 45 | valuesCount: Int, 46 | valuesOffset: Int = 0, 47 | overlayText: String = "", 48 | scaleMin: Float = Float.MAX_VALUE, 49 | scaleMax: Float = Float.MAX_VALUE, 50 | graphSize: Vec2 = Vec2(), 51 | valuesGetter: (idx: Int) -> Float) = plotEx(PlotType.Histogram, label, valuesCount, valuesOffset, overlayText, scaleMin, scaleMax, graphSize, valuesGetter) -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/widgetsImages.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import glm_.L 4 | import glm_.vec2.Vec2 5 | import glm_.vec4.Vec4 6 | import imgui.ImGui 7 | import imgui.ImGui.imageButtonEx 8 | import imgui.TextureID 9 | import imgui.internal.classes.Rect 10 | 11 | // Widgets: Images 12 | // - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples 13 | interface widgetsImages { 14 | 15 | fun image(userTextureId: TextureID, size: Vec2, uv0: Vec2 = Vec2(), uv1: Vec2 = Vec2(1), tintCol: Vec4 = Vec4(1), 16 | borderCol: Vec4 = Vec4()) { 17 | 18 | val window = ImGui.currentWindow 19 | if (window.skipItems) return 20 | 21 | val bb = Rect(window.dc.cursorPos, window.dc.cursorPos + size) 22 | if (borderCol.w > 0f) bb.max plusAssign 2 23 | ImGui.itemSize(bb) 24 | if (!ImGui.itemAdd(bb, 0)) return 25 | 26 | if (borderCol.w > 0f) { 27 | window.drawList.addRect(bb.min, bb.max, ImGui.getColorU32(borderCol), 0f) 28 | window.drawList.addImage(userTextureId, bb.min + 1, bb.max - 1, uv0, uv1, ImGui.getColorU32(tintCol)) 29 | } else 30 | window.drawList.addImage(userTextureId, bb.min, bb.max, uv0, uv1, ImGui.getColorU32(tintCol)) 31 | } 32 | 33 | /** frame_padding < 0: uses FramePadding from style (default) 34 | * frame_padding = 0: no framing/padding 35 | * frame_padding > 0: set framing size 36 | * The color used are the button colors. */ 37 | fun imageButton(strId: String, userTextureId: TextureID, size: Vec2, uv0: Vec2 = Vec2(), uv1: Vec2 = Vec2(), 38 | bgCol: Vec4 = Vec4(), tintCol: Vec4 = Vec4(1)): Boolean { 39 | 40 | val window = ImGui.currentWindow 41 | if (window.skipItems) 42 | return false 43 | 44 | return imageButtonEx(window.getID(strId), userTextureId, size, uv0, uv1, bgCol, tintCol) 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/api/windowScrolling.kt: -------------------------------------------------------------------------------- 1 | package imgui.api 2 | 3 | import glm_.max 4 | import imgui.ImGui.currentWindow 5 | import imgui.ImGui.setScrollFromPosX 6 | import imgui.ImGui.setScrollFromPosY 7 | import imgui.ImGui.setScrollX 8 | import imgui.ImGui.setScrollY 9 | import imgui.ImGui.style 10 | import imgui.internal.lerp 11 | 12 | // Windows Scrolling 13 | // - Any change of Scroll will be applied at the beginning of next frame in the first call to Begin(). 14 | // - You may instead use SetNextWindowScroll() prior to calling Begin() to avoid this delay, as an alternative to using SetScrollX()/SetScrollY(). 15 | interface windowScrolling { 16 | 17 | /** Scrolling amount [0..GetScrollMaxX()] */ 18 | var scrollX: Float 19 | /** ~GetScrollX */ 20 | get() = currentWindow.scroll.x 21 | /** ~SetScrollX */ 22 | set(value) = currentWindow.setScrollX(value) 23 | 24 | /** scrolling amount [0..GetScrollMaxY()] */ 25 | var scrollY: Float 26 | /** ~GetScrollY */ 27 | get() = currentWindow.scroll.y 28 | /** ~SetScrollY */ 29 | set(value) = currentWindow.setScrollY(value) 30 | 31 | /** get maximum scrolling amount ~~ ContentSize.x - WindowSize.x 32 | * ~GetScrollMaxX */ 33 | val scrollMaxX: Float 34 | get() = currentWindow.scrollMax.x 35 | 36 | /** get maximum scrolling amount ~~ ContentSize.y - WindowSize.y 37 | * ~GetScrollMaxY */ 38 | val scrollMaxY: Float 39 | get() = currentWindow.scrollMax.y 40 | 41 | /** center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item. 42 | * 43 | * adjust scrolling amount to make current cursor position visible. center_x_ratio=0.0: left, 0.5: center, 1.0: right. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead. */ 44 | fun setScrollHereX(centerXRatio: Float = 0.5f) { 45 | val window = g.currentWindow!! 46 | val spacingX = window.windowPadding.x max style.itemSpacing.x 47 | val targetPosX = lerp(g.lastItemData.rect.min.x - spacingX, g.lastItemData.rect.max.x + spacingX, centerXRatio) 48 | window.setScrollFromPosX(targetPosX - window.pos.x, centerXRatio) // Convert from absolute to local pos 49 | 50 | // Tweak: snap on edges when aiming at an item very close to the edge 51 | window.scrollTargetEdgeSnapDist.x = 0f max (window.windowPadding.x - spacingX) 52 | } 53 | 54 | /** adjust scrolling amount to make current cursor position visible. 55 | * centerYRatio = 0.0: top, 0.5: center, 1.0: bottom. 56 | * When using to make a "default/current item" visible, consider using setItemDefaultFocus() instead.*/ 57 | fun setScrollHereY(centerYRatio: Float = 0.5f) { 58 | val window = g.currentWindow!! 59 | val spacingY = window.windowPadding.y max style.itemSpacing.y 60 | val targetPosY = lerp(window.dc.cursorPosPrevLine.y - spacingY, window.dc.cursorPosPrevLine.y + window.dc.prevLineSize.y + spacingY, centerYRatio) 61 | window.setScrollFromPosY(targetPosY - window.pos.y, centerYRatio) // Convert from absolute to local pos 62 | 63 | // Tweak: snap on edges when aiming at an item very close to the edge 64 | window.scrollTargetEdgeSnapDist.y = 0f max (window.windowPadding.y - spacingY) 65 | } 66 | 67 | fun setScrollFromPosX(localX: Float, centerXratio: Float = 0.5f) = g.currentWindow!!.setScrollFromPosX(localX, centerXratio) 68 | 69 | fun setScrollFromPosY(localY: Float, centerYratio: Float = 0.5f) = g.currentWindow!!.setScrollFromPosY(localY, centerYratio) 70 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/demo/showExampleApp/AutoResize.kt: -------------------------------------------------------------------------------- 1 | package imgui.demo.showExampleApp 2 | 3 | import imgui.ImGui.begin 4 | import imgui.ImGui.end 5 | import imgui.ImGui.text 6 | import imgui.api.slider 7 | import imgui.mutablePropertyAt 8 | import kotlin.reflect.KMutableProperty0 9 | import imgui.WindowFlag as Wf 10 | 11 | object AutoResize { 12 | 13 | val lines = intArrayOf(10) 14 | 15 | /** Demonstrate creating a window which gets auto-resized according to its content. */ 16 | operator fun invoke(open: KMutableProperty0) { 17 | 18 | if (!begin("Example: Auto-resizing window", open, Wf.AlwaysAutoResize)) { 19 | end() 20 | return 21 | } 22 | 23 | text(""" 24 | Window will resize every-frame to the size of its content. 25 | Note that you probably don't want to query the window size to 26 | output your content because that would create a feedback loop.""".trimIndent()) 27 | slider("Number of lines", lines mutablePropertyAt 0, 1, 20) 28 | for (i in 0 until lines[0]) 29 | text(" ".repeat(i * 4) + "This is line $i") // Pad with space to extend size horizontally 30 | end() 31 | } 32 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/demo/showExampleApp/Fullscreen.kt: -------------------------------------------------------------------------------- 1 | package imgui.demo.showExampleApp 2 | 3 | import imgui.ImGui.button 4 | import imgui.ImGui.checkbox 5 | import imgui.ImGui.checkboxFlags 6 | import imgui.ImGui.mainViewport 7 | import imgui.ImGui.sameLine 8 | import imgui.ImGui.setNextWindowPos 9 | import imgui.ImGui.setNextWindowSize 10 | import imgui.api.demoDebugInformations.Companion.helpMarker 11 | import imgui.dsl.indent 12 | import imgui.dsl.window 13 | import imgui.or 14 | import kotlin.reflect.KMutableProperty0 15 | import imgui.WindowFlag as Wf 16 | 17 | //----------------------------------------------------------------------------- 18 | // [SECTION] Example App: Fullscreen window / ShowExampleAppFullscreen() 19 | //----------------------------------------------------------------------------- 20 | 21 | // Demonstrate creating a window covering the entire screen/viewport 22 | object Fullscreen { 23 | 24 | var useWorkArea = true 25 | var flags = Wf.NoDecoration or Wf.NoMove or Wf.NoSavedSettings 26 | operator fun invoke(pOpen: KMutableProperty0?) { 27 | 28 | // We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.) 29 | // Based on your use case you may want one or the other. 30 | val viewport = mainViewport 31 | setNextWindowPos(if(useWorkArea) viewport.workPos else viewport.pos) 32 | setNextWindowSize(if(useWorkArea) viewport.workSize else viewport.size) 33 | 34 | window("Example: Fullscreen window", pOpen, flags) { 35 | 36 | checkbox("Use work area instead of main area", ::useWorkArea) 37 | sameLine() 38 | helpMarker("Main Area = entire viewport,\nWork Area = entire viewport minus sections used by the main menu bars, task bars etc.\n\nEnable the main-menu bar in Examples menu to see the difference.") 39 | 40 | checkboxFlags("ImGuiWindowFlags_NoBackground", ::flags, Wf.NoBackground) 41 | checkboxFlags("ImGuiWindowFlags_NoDecoration", ::flags, Wf.NoDecoration) 42 | indent { 43 | checkboxFlags("ImGuiWindowFlags_NoTitleBar", ::flags, Wf.NoTitleBar) 44 | checkboxFlags("ImGuiWindowFlags_NoCollapse", ::flags, Wf.NoCollapse) 45 | checkboxFlags("ImGuiWindowFlags_NoScrollbar", ::flags, Wf.NoScrollbar) 46 | } 47 | 48 | if (pOpen != null && button("Close this window")) 49 | pOpen.set(false) 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/demo/showExampleApp/Layout.kt: -------------------------------------------------------------------------------- 1 | package imgui.demo.showExampleApp 2 | 3 | import glm_.vec2.Vec2 4 | import imgui.Cond 5 | import imgui.ImGui.begin 6 | import imgui.ImGui.beginChild 7 | import imgui.ImGui.beginTabBar 8 | import imgui.ImGui.beginTabItem 9 | import imgui.ImGui.end 10 | import imgui.ImGui.endChild 11 | import imgui.ImGui.endTabBar 12 | import imgui.ImGui.endTabItem 13 | import imgui.ImGui.frameHeightWithSpacing 14 | import imgui.ImGui.sameLine 15 | import imgui.ImGui.selectable 16 | import imgui.ImGui.separator 17 | import imgui.ImGui.setNextWindowSize 18 | import imgui.ImGui.text 19 | import imgui.ImGui.textWrapped 20 | import imgui.dsl.button 21 | import imgui.dsl.child 22 | import imgui.dsl.group 23 | import imgui.dsl.menu 24 | import imgui.dsl.menuBar 25 | import imgui.dsl.menuItem 26 | import kool.getValue 27 | import kool.setValue 28 | import kotlin.reflect.KMutableProperty0 29 | import imgui.WindowFlag as Wf 30 | 31 | object Layout { 32 | 33 | var selected = 0 34 | 35 | /** Demonstrate create a window with multiple child windows. */ 36 | operator fun invoke(pOpen: KMutableProperty0) { 37 | 38 | var open by pOpen 39 | 40 | setNextWindowSize(Vec2(500, 440), Cond.FirstUseEver) 41 | if (begin("Example: Simple layout", pOpen, Wf.MenuBar)) { 42 | menuBar { 43 | menu("File") { 44 | menuItem("Close", "Ctrl+W") { open = false } 45 | } 46 | } 47 | 48 | // Left 49 | child("left pane", Vec2(150, 0), true) { 50 | for (i in 0..99) { 51 | // FIXME: Good candidate to use ImGuiSelectableFlags_SelectOnNav 52 | val label = "MyObject $i" 53 | if (selectable(label, selected == i)) 54 | selected = i 55 | } 56 | } 57 | sameLine() 58 | 59 | // Right 60 | group { 61 | beginChild("item view", Vec2(0, -frameHeightWithSpacing)) // Leave room for 1 line below us 62 | text("MyObject: $selected") 63 | separator() 64 | if (beginTabBar("##Tabs")) { 65 | if (beginTabItem("Description")) { 66 | textWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ") 67 | endTabItem() 68 | } 69 | if (beginTabItem("Details")) { 70 | text("ID: 0123456789") 71 | endTabItem() 72 | } 73 | endTabBar() 74 | } 75 | endChild() 76 | button("Revert") {} 77 | sameLine() 78 | button("Save") {} 79 | } 80 | } 81 | end() 82 | } 83 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/demo/showExampleApp/LongText.kt: -------------------------------------------------------------------------------- 1 | package imgui.demo.showExampleApp 2 | 3 | import glm_.vec2.Vec2 4 | import imgui.Cond 5 | import imgui.ImGui.begin 6 | import imgui.ImGui.beginChild 7 | import imgui.ImGui.button 8 | import imgui.ImGui.combo 9 | import imgui.ImGui.end 10 | import imgui.ImGui.endChild 11 | import imgui.ImGui.popStyleVar 12 | import imgui.ImGui.pushStyleVar 13 | import imgui.ImGui.sameLine 14 | import imgui.ImGui.setNextWindowSize 15 | import imgui.ImGui.text 16 | import imgui.ImGui.textEx 17 | import imgui.StyleVar 18 | import imgui.classes.ListClipper 19 | import imgui.classes.listClipper 20 | import uno.kotlin.NUL 21 | import kotlin.reflect.KMutableProperty0 22 | 23 | object LongText { 24 | 25 | var testType = 0 26 | val log = StringBuilder() 27 | var lines = 0 28 | 29 | /** Demonstrate/test rendering huge amount of text, and the incidence of clipping. */ 30 | operator fun invoke(open: KMutableProperty0) { 31 | 32 | setNextWindowSize(Vec2(520, 600), Cond.FirstUseEver) 33 | if (!begin("Example: Long text display", open)) { 34 | end() 35 | return 36 | } 37 | 38 | text("Printing unusually long amount of text.") 39 | combo("Test type", ::testType, 40 | "Single call to TextUnformatted()" + NUL + 41 | "Multiple calls to Text(), clipped" + NUL + 42 | "Multiple calls to Text(), not clipped (slow)" + NUL) 43 | text("Buffer contents: %d lines, %d bytes", lines, log.length) 44 | if (button("Clear")) log.clear().also { lines = 0 } 45 | sameLine() 46 | if (button("Add 1000 lines")) { 47 | for (i in 0..999) 48 | log.append("${lines + i} The quick brown fox jumps over the lazy dog\n") 49 | lines += 1000 50 | } 51 | beginChild("Log") 52 | 53 | when (testType) { 54 | // Single call to TextUnformatted() with a big buffer 55 | 0 -> textEx(log.toString()) 56 | // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper. 57 | 1 -> { 58 | pushStyleVar(StyleVar.ItemSpacing, Vec2(0)) 59 | listClipper(lines) { 60 | for (i in it.display) 61 | text("$i The quick brown fox jumps over the lazy dog") 62 | } 63 | popStyleVar() 64 | } 65 | 2 -> { 66 | pushStyleVar(StyleVar.ItemSpacing, Vec2(0, 1)) 67 | for (i in 0 until lines) 68 | text("%d The quick brown fox jumps over the lazy dog".format(i)) 69 | popStyleVar() 70 | } 71 | } 72 | 73 | endChild() 74 | end() 75 | } 76 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/demo/showExampleApp/MainMenuBar.kt: -------------------------------------------------------------------------------- 1 | package imgui.demo.showExampleApp 2 | 3 | import imgui.ImGui.menuItem 4 | import imgui.ImGui.separator 5 | import imgui.dsl.mainMenuBar 6 | import imgui.dsl.menu 7 | 8 | /** Demonstrate creating a "main" fullscreen menu bar and populating it. 9 | * Note the difference between BeginMainMenuBar() and BeginMenuBar(): 10 | * - BeginMenuBar() = menu-bar inside current window (which needs the ImGuiWindowFlags_MenuBar flag!) 11 | * - BeginMainMenuBar() = helper to create menu-bar-sized window at the top of the main viewport + call BeginMenuBar() into it. */ 12 | object MainMenuBar { 13 | 14 | operator fun invoke() = mainMenuBar { 15 | menu("File") { MenuFile() } 16 | menu("Edit") { 17 | menuItem("Undo", "CTRL+Z") 18 | menuItem("Redo", "CTRL+Y", false, false) // Disabled item 19 | separator() 20 | menuItem("Cut", "CTRL+X") 21 | menuItem("Copy", "CTRL+C") 22 | menuItem("Paste", "CTRL+V") 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/demo/showExampleApp/MenuFile.kt: -------------------------------------------------------------------------------- 1 | package imgui.demo.showExampleApp 2 | 3 | import glm_.vec2.Vec2 4 | import imgui.Col 5 | import imgui.ImGui.beginChild 6 | import imgui.ImGui.checkbox 7 | import imgui.ImGui.combo 8 | import imgui.ImGui.cursorScreenPos 9 | import imgui.ImGui.dummy 10 | import imgui.ImGui.endChild 11 | import imgui.ImGui.input 12 | import imgui.ImGui.menuItem 13 | import imgui.ImGui.sameLine 14 | import imgui.ImGui.separator 15 | import imgui.ImGui.text 16 | import imgui.ImGui.textLineHeight 17 | import imgui.ImGui.windowDrawList 18 | import imgui.api.slider 19 | import imgui.dsl.menu 20 | 21 | object MenuFile { 22 | 23 | var enabled = true 24 | var float = 0.5f 25 | var combo = 0 26 | var check = true 27 | 28 | // Note that shortcuts are currently provided for display only 29 | // (future version will add explicit flags to BeginMenu() to request processing shortcuts) 30 | operator fun invoke() { 31 | 32 | menuItem("(demo menu)", "", false, false) 33 | menuItem("New") 34 | menuItem("Open", "Ctrl+O") 35 | menu("Open Recent") { 36 | menuItem("fish_hat.c") 37 | menuItem("fish_hat.inl") 38 | menuItem("fish_hat.h") 39 | menu("More..") { 40 | menuItem("Hello") 41 | menuItem("Sailor") 42 | menu("Recurse..") { MenuFile() } 43 | } 44 | } 45 | menuItem("Save", "Ctrl+S") 46 | menuItem("Save As..") 47 | 48 | separator() 49 | menu("Options") { 50 | menuItem("Enabled", "", ::enabled) 51 | beginChild("child", Vec2(0, 60), true) 52 | for (i in 0 until 10) text("Scrolling Text $i") 53 | endChild() 54 | slider("Value", ::float, 0f, 1f) 55 | input("Input", ::float, 0.1f) 56 | combo("Combo", ::combo, "Yes\u0000No\u0000Maybe\u0000\u0000") 57 | } 58 | 59 | menu("Colors") { 60 | val sz = textLineHeight 61 | for (col in Col.values()) { 62 | val name = col.name 63 | val p = Vec2(cursorScreenPos) 64 | windowDrawList.addRectFilled(p, Vec2(p.x + sz, p.y + sz), col.u32) 65 | dummy(Vec2(sz)) 66 | sameLine() 67 | menuItem(name) 68 | } 69 | } 70 | 71 | // Here we demonstrate appending again to the "Options" menu (which we already created above) 72 | // Of course in this demo it is a little bit silly that this function calls BeginMenu("Options") twice. 73 | // In a real code-base using it would make senses to use this feature from very different code locations. 74 | menu("Options") { // <-- Append! 75 | checkbox("SomeOption", ::check) 76 | } 77 | 78 | menu("Disabled", false) { assert(false) { "Disabled" } } 79 | menuItem("Checked", selected = true) 80 | separator() 81 | menuItem("Quit", "Alt+F4") 82 | } 83 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/demo/showExampleApp/PropertyEditor.kt: -------------------------------------------------------------------------------- 1 | package imgui.demo.showExampleApp 2 | 3 | import glm_.vec2.Vec2 4 | import imgui.* 5 | import imgui.ImGui.alignTextToFramePadding 6 | import imgui.ImGui.begin 7 | import imgui.ImGui.drag 8 | import imgui.ImGui.end 9 | import imgui.ImGui.input 10 | import imgui.ImGui.nextColumn 11 | import imgui.ImGui.popID 12 | import imgui.ImGui.popItemWidth 13 | import imgui.ImGui.popStyleVar 14 | import imgui.ImGui.pushID 15 | import imgui.ImGui.pushItemWidth 16 | import imgui.ImGui.pushStyleVar 17 | import imgui.ImGui.setNextWindowSize 18 | import imgui.ImGui.tableNextRow 19 | import imgui.ImGui.tableSetColumnIndex 20 | import imgui.ImGui.text 21 | import imgui.ImGui.treeNode 22 | import imgui.ImGui.treeNodeEx 23 | import imgui.ImGui.treePop 24 | import imgui.api.demoDebugInformations.Companion.helpMarker 25 | import imgui.api.drag 26 | import imgui.dsl.table 27 | import kotlin.reflect.KMutableProperty0 28 | import imgui.TreeNodeFlag as Tnf 29 | 30 | object PropertyEditor { 31 | 32 | /** Demonstrate create a simple property editor. */ 33 | operator fun invoke(open: KMutableProperty0) { 34 | 35 | setNextWindowSize(Vec2(430, 450), Cond.FirstUseEver) 36 | if (!begin("Example: Property editor", open)) { 37 | end() 38 | return 39 | } 40 | 41 | helpMarker(""" 42 | This example shows how you may implement a property editor using two columns. 43 | All objects/fields data are dummies here. 44 | Remember that in many simple cases, you can use ImGui::SameLine(xxx) to position 45 | your cursor horizontally instead of using the Columns() API.""".trimIndent()) 46 | 47 | pushStyleVar(StyleVar.FramePadding, Vec2(2)) 48 | table("split", 2, TableFlag.BordersOuter or TableFlag.Resizable) { 49 | // Iterate placeholder objects (all the same data) 50 | for (objI in 0..3) { 51 | showPlaceholderObject("Object", objI) 52 | //ImGui::Separator(); 53 | } 54 | } 55 | popStyleVar() 56 | end() 57 | } 58 | 59 | fun showPlaceholderObject(prefix: String, uid: Int) { 60 | // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID. 61 | pushID(uid) 62 | 63 | // Text and Tree nodes are less high than framed widgets, using AlignTextToFramePadding() we add vertical spacing to make the tree lines equal high. 64 | tableNextRow() 65 | tableSetColumnIndex(0) 66 | alignTextToFramePadding() 67 | val nodeOpen = treeNode("Object", "${prefix}_$uid") 68 | tableSetColumnIndex(1) 69 | text("my sailor is rich") 70 | 71 | if (nodeOpen) { 72 | for (i in 0..7) { 73 | pushID(i) // Use field index as identifier. 74 | if (i < 2) 75 | showPlaceholderObject("Child", 424242) 76 | else { 77 | // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well) 78 | tableNextRow() 79 | tableSetColumnIndex(0) 80 | alignTextToFramePadding() 81 | val flags = Tnf.Leaf or Tnf.NoTreePushOnOpen or Tnf.Bullet 82 | treeNodeEx("Field", flags, "Field_$i") 83 | 84 | tableSetColumnIndex(1) 85 | pushItemWidth(-Float.MIN_VALUE) 86 | if (i >= 5) 87 | input("##value", placeholderMembers mutablePropertyAt i, 1f) 88 | else 89 | drag("##value", placeholderMembers mutablePropertyAt i, 0.01f) 90 | popItemWidth() 91 | nextColumn() 92 | } 93 | popID() 94 | } 95 | treePop() 96 | } 97 | popID() 98 | } 99 | 100 | val placeholderMembers = floatArrayOf(0f, 0f, 1f, 3.1416f, 100f, 999f) 101 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/demo/showExampleApp/SimpleOverlay.kt: -------------------------------------------------------------------------------- 1 | package imgui.demo.showExampleApp 2 | 3 | import glm_.has 4 | import glm_.vec2.Vec2 5 | import imgui.* 6 | import imgui.ImGui.io 7 | import imgui.ImGui.isMousePosValid 8 | import imgui.ImGui.mainViewport 9 | import imgui.ImGui.menuItem 10 | import imgui.ImGui.separator 11 | import imgui.ImGui.setNextWindowBgAlpha 12 | import imgui.ImGui.setNextWindowPos 13 | import imgui.ImGui.text 14 | import imgui.dsl.menuItem 15 | import imgui.dsl.popupContextWindow 16 | import imgui.dsl.window 17 | import kotlin.reflect.KMutableProperty0 18 | import imgui.WindowFlag as Wf 19 | 20 | 21 | //----------------------------------------------------------------------------- 22 | // [SECTION] Example App: Simple overlay / ShowExampleAppSimpleOverlay() 23 | //----------------------------------------------------------------------------- 24 | 25 | // Demonstrate creating a simple static window with no decoration 26 | // + a context-menu to choose which corner of the screen to use. 27 | object SimpleOverlay { 28 | 29 | var location = 0 30 | 31 | // Demonstrate creating a simple static window with no decoration 32 | // + a context-menu to choose which corner of the screen to use. 33 | operator fun invoke(open: KMutableProperty0) { 34 | 35 | var windowFlags = Wf.NoDecoration or Wf.AlwaysAutoResize or Wf.NoSavedSettings or Wf.NoFocusOnAppearing or Wf.NoNav 36 | if (location >= 0) { 37 | val PAD = 10f 38 | val viewport = mainViewport 39 | val workPos = viewport.workPos // Use work area to avoid menu-bar/task-bar, if any! 40 | val workSize = viewport.workSize 41 | val windowPos = Vec2(workPos.x + if (location has 1) workSize.x - PAD else PAD, 42 | workPos.y + if (location has 2) workSize.y - PAD else PAD) 43 | val windowPosPivot = Vec2(if (location has 1) 1f else 0f, 44 | if (location has 2) 1f else 0f) 45 | setNextWindowPos(windowPos, Cond.Always, windowPosPivot) 46 | windowFlags = windowFlags or Wf.NoMove 47 | } else if (location == -2) { 48 | // Center window 49 | setNextWindowPos(ImGui.mainViewport.center, Cond.Always, Vec2( 0.5f)) 50 | windowFlags /= Wf.NoMove 51 | } 52 | setNextWindowBgAlpha(0.35f) // Transparent background 53 | window("Example: Simple overlay", open, windowFlags) { 54 | text("Simple overlay\n(right-click to change position)") 55 | separator() 56 | text("Mouse Position: " + when { 57 | isMousePosValid() -> "(%.1f,%.1f)".format(io.mousePos.x, io.mousePos.y) 58 | else -> "" 59 | }) 60 | popupContextWindow { 61 | menuItem("Custom", "", location == -1) { location = -1 } 62 | menuItem("Center", "", location == -2) { location = -2 } 63 | menuItem("Top-left", "", location == 0) { location = 0 } 64 | menuItem("Top-right", "", location == 1) { location = 1 } 65 | menuItem("Bottom-left", "", location == 2) { location = 2 } 66 | menuItem("Bottom-right", "", location == 3) { location = 3 } 67 | if (open() && menuItem("Close")) open.set(false) 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/demo/showExampleApp/WindowTitles.kt: -------------------------------------------------------------------------------- 1 | package imgui.demo.showExampleApp 2 | 3 | import glm_.i 4 | import glm_.vec2.Vec2 5 | import imgui.Cond 6 | import imgui.ImGui.frameCount 7 | import imgui.ImGui.mainViewport 8 | import imgui.ImGui.setNextWindowPos 9 | import imgui.ImGui.text 10 | import imgui.ImGui.time 11 | import imgui.dsl.window 12 | 13 | 14 | //----------------------------------------------------------------------------- 15 | // [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles() 16 | //----------------------------------------------------------------------------- 17 | // Demonstrate the use of "##" and "###" in identifiers to manipulate ID generation. 18 | // This applies to all regular items as well. 19 | // Read FAQ section "How can I have multiple widgets with the same label?" for details. 20 | object WindowTitles { 21 | 22 | operator fun invoke() { 23 | 24 | val viewport = mainViewport 25 | val basePos = viewport.pos 26 | 27 | // By default, Windows are uniquely identified by their title. 28 | // You can use the "##" and "###" markers to manipulate the display/ID. 29 | 30 | setNextWindowPos(Vec2(basePos + 100), Cond.FirstUseEver) 31 | window("Same title as another window##1") { 32 | text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.") 33 | } 34 | 35 | setNextWindowPos(Vec2(basePos.x + 100, basePos.y + 200), Cond.FirstUseEver) 36 | window("Same title as another window##2") { 37 | text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.") 38 | } 39 | 40 | // Using "###" to display a changing title but keep a static identifier "AnimatedTitle" 41 | val title = "Animated title ${"|/-\\"[(time / 0.25f).i and 3]} $frameCount###AnimatedTitle" 42 | setNextWindowPos(Vec2(basePos.x + 100, basePos.y + 300), Cond.FirstUseEver) 43 | window(title) { text("This window has a changing title.") } 44 | } 45 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/font/FontGlyphRangesBuilder.kt: -------------------------------------------------------------------------------- 1 | package imgui.font 2 | 3 | import imgui.UNICODE_CODEPOINT_MAX 4 | import imgui.internal.textCharFromUtf8 5 | import uno.kotlin.NUL 6 | 7 | class FontGlyphRangesBuilder { 8 | 9 | /** Store 1-bit per Unicode code point (0=unused, 1=used) */ 10 | val usedChars = ArrayList() 11 | 12 | init { 13 | clear() 14 | } 15 | 16 | fun clear() { 17 | val sizeInBytes = (UNICODE_CODEPOINT_MAX + 1) / 8 18 | usedChars.clear() 19 | for (i in 0 until sizeInBytes / UInt.SIZE_BYTES) 20 | usedChars += 0u 21 | } 22 | 23 | /** Get bit n in the array */ 24 | fun getBit(n: Int): Boolean { 25 | val off = n shr 5 26 | val mask = 1u shl (n and 31) 27 | return (usedChars[off] and mask) != 0u 28 | } 29 | 30 | /** Set bit n in the array */ 31 | fun setBit(n: Int) { 32 | val off = n shr 5 33 | val mask = 1u shl (n and 31) 34 | usedChars[off] = usedChars[off] or mask 35 | } 36 | 37 | /** Add character */ 38 | fun addChar(c: Char) = setBit(c.code) 39 | 40 | /** Add string (each character of the UTF-8 string are added) */ 41 | fun addText(text: ByteArray, textEnd: Int? = null) { 42 | var p = 0 43 | while (p < (textEnd ?: text.size)) { 44 | val (c, cLen) = textCharFromUtf8(text, p, textEnd ?: -1) 45 | p += cLen 46 | if (cLen == 0) 47 | break 48 | addChar(Char(c)) 49 | } 50 | } 51 | 52 | /** Add ranges, e.g. builder.AddRanges(ImFontAtlas::GetGlyphRangesDefault()) to force add all of ASCII/Latin+Ext */ 53 | fun addRanges(ranges: ArrayList) { 54 | for (i in ranges.indices step 2) { 55 | var c = ranges[i] 56 | while (c <= ranges[i + 1] && c.code <= UNICODE_CODEPOINT_MAX) //-V560 57 | addChar(c++) 58 | } 59 | } 60 | 61 | /** Output new ranges */ 62 | infix fun buildRanges(outRanges: ArrayList) { 63 | val maxCodepoint = UNICODE_CODEPOINT_MAX 64 | var n = 0 65 | while (n <= maxCodepoint) { 66 | if (getBit(n)) { 67 | outRanges += Char(n) 68 | while (n < maxCodepoint && getBit(n + 1)) 69 | n++ 70 | outRanges += Char(n) 71 | } 72 | n++ 73 | } 74 | outRanges += NUL 75 | } 76 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/font/test.kt: -------------------------------------------------------------------------------- 1 | package imgui.font 2 | 3 | import com.aayushatharva.brotli4j.Brotli4jLoader 4 | import com.aayushatharva.brotli4j.encoder.Encoder 5 | import glm_.asHexString 6 | import glm_.i 7 | import glm_.minus 8 | import java.io.File 9 | import java.math.BigInteger 10 | 11 | 12 | fun main() { 13 | val ini = File("core/src/main/resources/fonts/ProggyClean.ttf") 14 | val array = ini.readBytes().asUByteArray() 15 | // encode(ubyteArrayOf(0u, 1u, 2u, 3u)) 16 | 17 | // Load the native library 18 | Brotli4jLoader.ensureAvailability() 19 | 20 | // Compress data and get output in byte array 21 | val compressed = ini.readBytes()// Encoder.compress(ini.readBytes(), Encoder.Parameters().setQuality(11))//.take(4).toByteArray() 22 | 23 | println() 24 | 25 | // val n = stb.compress(CharArray(compressed.size) { compressed[it].toChar() }) 26 | 27 | val range = (0xD7FF + 1 - 0x0000) + (0xFFFF + 1 - 0xE000) + (Char.MAX_HIGH_SURROGATE.i + 1 - Char.MIN_SURROGATE.i) * (Char.MAX_SURROGATE.i + 1 - Char.MIN_LOW_SURROGATE.i) 28 | 29 | for (i in 0 until range) { 30 | val code = encode(i) 31 | val plain = decode(code) 32 | if (i != plain) 33 | error("$i != $plain") 34 | } 35 | 36 | 37 | val bigInteger = BigInteger(compressed) 38 | var div = bigInteger 39 | val res = StringBuilder() 40 | while (div > BigInteger.ZERO) { 41 | val (d, r) = div.divideAndRemainder(range.toBigInteger()) 42 | div = d 43 | val rem = r.toInt() 44 | res.insert(0, encode(rem)) 45 | } 46 | 47 | var value = BigInteger.ZERO 48 | var i = 0 49 | while (i < res.length) { 50 | val s = when (val c = res[i++]) { 51 | in Char.MIN_SURROGATE..Char.MAX_SURROGATE -> c.toString() + res[i++] 52 | else -> c.toString() 53 | } 54 | value = value * range.toBigInteger() + decode(s).toBigInteger() 55 | } 56 | 57 | val equal = bigInteger == value 58 | println(equal) 59 | } 60 | 61 | fun encode(int: Int): String = when { 62 | int <= 0xD7FF -> int.toChar().toString() 63 | int <= 0xD7FF + (0xFFFF + 1 - 0xE000) -> (int + (0xE000 - Char.MIN_SURROGATE.i)).toChar().toString() 64 | int <= 0xD7FF + (0xFFFF + 1 - 0xE000) + (Char.MAX_HIGH_SURROGATE.i + 1 - Char.MIN_SURROGATE.i) * (Char.MAX_SURROGATE.i + 1 - Char.MIN_LOW_SURROGATE.i) -> { 65 | val i = int - (0xD7FF + (0xFFFF + 1 - 0xE000)) 66 | val chunk = Char.MAX_SURROGATE.i + 1 - Char.MIN_LOW_SURROGATE.i 67 | charArrayOf(Char.MIN_SURROGATE + i / chunk, Char.MIN_LOW_SURROGATE + i % chunk).concatToString() 68 | } 69 | 70 | else -> error("int = $int") 71 | } 72 | 73 | fun decode(string: String): Int = when (string.length) { 74 | 1 -> { 75 | val code = string[0].code 76 | when { 77 | code <= 0xD7FF -> code 78 | code in 0xE000..0xFFFF -> code - (0xE000 - Char.MIN_SURROGATE.i) 79 | else -> error("") 80 | } 81 | } 82 | 83 | 2 -> { 84 | val a = string[0].code - Char.MIN_SURROGATE 85 | val b = string[1].code - Char.MIN_LOW_SURROGATE 86 | val chunk = Char.MAX_SURROGATE.i + 1 - Char.MIN_LOW_SURROGATE.i 87 | val code = a * chunk + b 88 | check(code <= (Char.MAX_HIGH_SURROGATE.i + 1 - Char.MIN_SURROGATE.i) * (Char.MAX_SURROGATE.i + 1 - Char.MIN_LOW_SURROGATE.i)) 89 | code + 0xD7FF + (0xFFFF + 1 - 0xE000) 90 | } 91 | 92 | else -> error("") 93 | } 94 | 95 | val codepoints = Char.MIN_SURROGATE.i..Char.MAX_HIGH_SURROGATE.i to Char.MIN_LOW_SURROGATE.i..Char.MAX_SURROGATE.i -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/dataTypeHelpers.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import glm_.* 4 | import imgui.internal.addClampOverflow 5 | import imgui.internal.subClampOverflow 6 | import unsigned.Ubyte 7 | import unsigned.Uint 8 | import unsigned.Ulong 9 | import unsigned.Ushort 10 | 11 | // Data type helpers 12 | 13 | /* ~DataTypeApplyOp */ 14 | 15 | infix fun Byte.addOp(arg: Byte): Byte = addClampOverflow(this.i, arg.i, Byte.MIN_VALUE.i, Byte.MAX_VALUE.i).b 16 | infix fun Byte.subOp(arg: Byte): Byte = subClampOverflow(this.i, arg.i, Byte.MIN_VALUE.i, Byte.MAX_VALUE.i).b 17 | infix fun Ubyte.addOp(arg: Ubyte): Ubyte = addClampOverflow(this.i, arg.i, Ubyte.MIN_VALUE, Ubyte.MAX_VALUE).ub 18 | infix fun Ubyte.subOp(arg: Ubyte): Ubyte = subClampOverflow(this.i, arg.i, Ubyte.MIN_VALUE, Ubyte.MAX_VALUE).ub 19 | infix fun Short.addOp(arg: Short): Short = addClampOverflow(this.i, arg.i, Short.MIN_VALUE.i, Short.MAX_VALUE.i).s 20 | infix fun Short.subOp(arg: Short): Short = subClampOverflow(this.i, arg.i, Short.MIN_VALUE.i, Short.MAX_VALUE.i).s 21 | infix fun Ushort.addOp(arg: Ushort): Ushort = addClampOverflow(this.i, arg.i, Ushort.MIN_VALUE, Ushort.MAX_VALUE).us 22 | infix fun Ushort.subOp(arg: Ushort): Ushort = subClampOverflow(this.i, arg.i, Ushort.MIN_VALUE, Ushort.MAX_VALUE).us 23 | infix fun Int.addOp(arg: Int): Int = addClampOverflow(this, arg, Int.MIN_VALUE, Int.MAX_VALUE) 24 | infix fun Int.subOp(arg: Int): Int = subClampOverflow(this, arg, Int.MIN_VALUE, Int.MAX_VALUE) 25 | infix fun Uint.addOp(arg: Uint): Uint = addClampOverflow(this.L, arg.L, Uint.MIN_VALUE, Uint.MAX_VALUE).ui 26 | infix fun Uint.subOp(arg: Uint): Uint = subClampOverflow(this.L, arg.L, Uint.MIN_VALUE, Uint.MAX_VALUE).ui 27 | infix fun Long.addOp(arg: Long): Long = addClampOverflow(this, arg, Long.MIN_VALUE, Long.MAX_VALUE) 28 | infix fun Long.subOp(arg: Long): Long = subClampOverflow(this, arg, Long.MIN_VALUE, Long.MAX_VALUE) 29 | infix fun Ulong.addOp(arg: Ulong): Ulong = addClampOverflow(this.toBigInt(), arg.toBigInt(), Ulong.MIN_VALUE, Ulong.MAX_VALUE).ul 30 | infix fun Ulong.subOp(arg: Ulong): Ulong = subClampOverflow(this.toBigInt(), arg.toBigInt(), Ulong.MIN_VALUE, Ulong.MAX_VALUE).ul -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/debugLog.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import imgui.api.g 4 | import imgui.has 5 | import imgui.internal.classes.DebugLogFlag 6 | import imgui.internal.sections.IMGUI_DEBUG_PRINTF 7 | 8 | // Debug Log 9 | 10 | //----------------------------------------------------------------------------- 11 | // [SECTION] DEBUG LOG WINDOW 12 | //----------------------------------------------------------------------------- 13 | 14 | internal interface debugLog { 15 | 16 | fun debugLog(fmt: String, vararg args: Any) { 17 | val oldSize = g.debugLogBuf.length 18 | g.debugLogBuf.append("[%05d] ".format(g.frameCount)) 19 | g.debugLogBuf.append(fmt.format(*args)) 20 | if (g.debugLogFlags has DebugLogFlag.OutputToTTY) 21 | IMGUI_DEBUG_PRINTF(g.debugLogBuf.drop(oldSize).toString()) 22 | // g.DebugLogIndex.append(g.DebugLogBuf.c_str(), old_size, g.DebugLogBuf.size()); 23 | } 24 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/disabling.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import imgui.api.g 4 | import imgui.div 5 | import imgui.has 6 | import imgui.hasnt 7 | import imgui.internal.sections.ItemFlag 8 | 9 | // Disabling [BETA API] 10 | // - Disable all user interactions and dim items visuals (applying style.DisabledAlpha over current colors) 11 | // - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled) 12 | // - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it. 13 | internal interface disabling { 14 | 15 | /** BeginDisabled()/EndDisabled() 16 | * - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled) 17 | * - Visually this is currently altering alpha, but it is expected that in a future styling system this would work differently. 18 | * - Feedback welcome at https://github.com/ocornut/imgui/issues/211 19 | * - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it. 20 | * - Optimized shortcuts instead of PushStyleVar() + PushItemFlag() */ 21 | fun beginDisabled(disabled: Boolean = true) { 22 | val wasDisabled = g.currentItemFlags has ItemFlag.Disabled 23 | if (!wasDisabled && disabled) { 24 | g.disabledAlphaBackup = g.style.alpha 25 | g.style.alpha *= g.style.disabledAlpha // PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * g.Style.DisabledAlpha); 26 | } 27 | if (wasDisabled || disabled) 28 | g.currentItemFlags /= ItemFlag.Disabled 29 | g.itemFlagsStack += g.currentItemFlags 30 | g.disabledStackSize++ 31 | } 32 | 33 | fun endDisabled() { 34 | assert(g.disabledStackSize > 0) 35 | g.disabledStackSize-- 36 | val wasDisabled = g.currentItemFlags has ItemFlag.Disabled 37 | //popItemFlag() 38 | g.itemFlagsStack.pop() 39 | g.currentItemFlags = g.itemFlagsStack.last() 40 | if (wasDisabled && g.currentItemFlags hasnt ItemFlag.Disabled) 41 | g.style.alpha = g.disabledAlphaBackup //PopStyleVar(); 42 | } 43 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/dragAndDrop.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import glm_.vec2.Vec2 4 | import imgui.Col 5 | import imgui.ID 6 | import imgui.ImGui 7 | import imgui.ImGui.isMouseHoveringRect 8 | import imgui.api.g 9 | import imgui.none 10 | import imgui.internal.classes.Rect 11 | import kool.fill 12 | import java.nio.ByteBuffer 13 | 14 | internal interface dragAndDrop { 15 | 16 | val isDragDropActive: Boolean 17 | get() = g.dragDropActive 18 | fun beginDragDropTargetCustom(bb: Rect, id: ID): Boolean { 19 | if (!g.dragDropActive) return false 20 | 21 | assert(!g.dragDropWithinTarget) 22 | 23 | val window = g.currentWindow!! 24 | val hoveredWindow = g.hoveredWindowUnderMovingWindow 25 | if (hoveredWindow == null || window.rootWindow !== hoveredWindow.rootWindow) 26 | return false 27 | assert(id != 0) 28 | if (!isMouseHoveringRect(bb) || id == g.dragDropPayload.sourceId) 29 | return false 30 | if (window.skipItems) return false 31 | 32 | assert(!g.dragDropWithinTarget) 33 | g.dragDropTargetRect put bb 34 | g.dragDropTargetId = id 35 | g.dragDropWithinTarget = true 36 | return true 37 | } 38 | 39 | fun clearDragDrop() = with(g) { 40 | dragDropActive = false 41 | dragDropPayload.clear() 42 | dragDropAcceptFlags = none 43 | dragDropAcceptIdPrev = 0 44 | dragDropAcceptIdCurr = 0 45 | dragDropAcceptIdCurrRectSurface = Float.MAX_VALUE 46 | dragDropAcceptFrameCount = -1 47 | 48 | g.dragDropPayloadBufHeap = ByteBuffer.allocate(0) 49 | g.dragDropPayloadBufLocal.fill(0) 50 | } 51 | 52 | val isDragDropPayloadBeingAccepted: Boolean 53 | get() = g.dragDropActive && g.dragDropAcceptIdPrev != 0 54 | 55 | /** FIXME-DRAGDROP: Settle on a proper default visuals for drop target. */ 56 | fun renderDragDropTargetRect(bb: Rect) = 57 | ImGui.windowDrawList.addRect(bb.min - Vec2(3.5f), bb.max + Vec2(3.5f), Col.DragDropTarget.u32, 0f, thickness = 2f) 58 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/focusActivation.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import imgui.Dir 4 | import imgui.ID 5 | import imgui.ImGui.navMoveRequestResolveWithLastItem 6 | import imgui.ImGui.navMoveRequestSubmit 7 | import imgui.ImGui.setNavWindow 8 | import imgui.api.g 9 | import imgui.api.gImGui 10 | import imgui.div 11 | import imgui.internal.sections.IMGUI_DEBUG_LOG_FOCUS 12 | import imgui.internal.sections.NavMoveFlag 13 | import imgui.internal.sections.ScrollFlag 14 | import imgui.none 15 | 16 | // Focus/Activation 17 | // This should be part of a larger set of API: FocusItem(offset = -1), FocusItemByID(id), ActivateItem(offset = -1), ActivateItemByID(id) etc. which are 18 | // much harder to design and implement than expected. I have a couple of private branches on this matter but it's not simple. For now implementing the easy ones. 19 | interface focusActivation { 20 | 21 | // Focus last item (no selection/activation). 22 | // Focus = move navigation cursor, set scrolling, set focus window. 23 | fun focusItem() { 24 | val g = gImGui 25 | val window = g.currentWindow!! 26 | IMGUI_DEBUG_LOG_FOCUS("FocusItem(0x%08x) in window \"${window.name}\"", g.lastItemData.id) 27 | if (g.dragDropActive || g.movingWindow != null) { // FIXME: Opt-in flags for this? 28 | IMGUI_DEBUG_LOG_FOCUS("FocusItem() ignored while DragDropActive!") 29 | return 30 | } 31 | 32 | val moveFlags = NavMoveFlag.Tabbing / NavMoveFlag.FocusApi / NavMoveFlag.NoSelect 33 | val scrollFlags = ScrollFlag.KeepVisibleEdgeX / if(window.appearing) ScrollFlag.AlwaysCenterY else ScrollFlag.KeepVisibleEdgeY 34 | setNavWindow(window) 35 | navMoveRequestSubmit(Dir.None, Dir.Up, moveFlags, scrollFlags) 36 | navMoveRequestResolveWithLastItem(g.navMoveResultLocal) 37 | } 38 | 39 | /** Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed 40 | * on the next frame when the item is encountered again. 41 | * 42 | * Activate an item by ID (button, checkbox, tree node etc.). Activation is queued and processed on the next frame when the item is encountered again. */ 43 | fun activateItemByID(id: ID) { 44 | g.navNextActivateId = id 45 | g.navNextActivateFlags = none 46 | } 47 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/focusScope.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import imgui.ID 4 | import imgui.api.g 5 | 6 | // [EXPERIMENTAL] Focus Scope 7 | // This is generally used to identify a unique input location (for e.g. a selection set) 8 | // There is one per window (automatically set in Begin), but: 9 | // - Selection patterns generally need to react (e.g. clear a selection) when landing on one item of the set. 10 | // So in order to identify a set multiple lists in same window may each need a focus scope. 11 | // If you imagine an hypothetical BeginSelectionGroup()/EndSelectionGroup() api, it would likely call PushFocusScope()/EndFocusScope() 12 | // - Shortcut routing also use focus scope as a default location identifier if an owner is not provided. 13 | // We don't use the ID Stack for this as it is common to want them separate. 14 | interface focusScope { 15 | 16 | fun pushFocusScope(id: ID) { 17 | g.focusScopeStack += id 18 | g.currentFocusScopeId = id 19 | } 20 | 21 | fun popFocusScope() { 22 | assert(g.focusScopeStack.isNotEmpty()) { "Too many PopFocusScope() ?" } 23 | g.focusScopeStack.pop() 24 | g.currentFocusScopeId = g.focusScopeStack.lastOrNull() ?: 0 25 | } 26 | 27 | /** Focus scope we are outputting into, set by PushFocusScope() */ 28 | val currentFocusScope: ID 29 | get() = g.currentFocusScopeId 30 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/fontsDrawing.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import glm_.func.common.max 4 | import imgui.ImGui 5 | import imgui.ImGui.foregroundDrawList 6 | import imgui.api.g 7 | import imgui.classes.DrawList 8 | import imgui.font.Font 9 | import imgui.internal.classes.Window 10 | 11 | // Fonts, drawing 12 | internal interface fontsDrawing { 13 | 14 | /** Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only. */ 15 | fun setCurrentFont(font: Font) { 16 | assert(font.isLoaded) { "Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?" } 17 | assert(font.scale > 0f) 18 | g.font = font 19 | g.fontBaseSize = 1f max (ImGui.io.fontGlobalScale * g.font.fontSize * g.font.scale) 20 | g.fontSize = g.currentWindow?.calcFontSize() ?: 0f 21 | 22 | val atlas = g.font.containerAtlas 23 | g.drawListSharedData.also { 24 | it.texUvWhitePixel = atlas.texUvWhitePixel 25 | it.texUvLines = atlas.texUvLines 26 | it.font = g.font 27 | it.fontSize = g.fontSize 28 | } 29 | } 30 | 31 | /** ~GetDefaultFont */ 32 | val defaultFont: Font 33 | get() = ImGui.io.fontDefault ?: ImGui.io.fonts.fonts[0] 34 | 35 | fun getForegroundDrawList(window: Window?): DrawList = ImGui.foregroundDrawList // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches. 36 | 37 | // GetBackgroundDrawList(ImGuiViewport* viewport) 38 | // GetForegroundDrawList(ImGuiViewport* viewport); -> Viewport class 39 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/garbageCollection.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import imgui.api.g 4 | import imgui.ImGui.tableGcCompactSettings 5 | import imgui.internal.classes.Window 6 | import imgui.reserve 7 | import kool.cap 8 | 9 | /** Garbage collection */ 10 | interface garbageCollection { 11 | 12 | fun gcCompactTransientMiscBuffers() { 13 | g.itemFlagsStack.clear() 14 | g.groupStack.clear() 15 | tableGcCompactSettings() 16 | } 17 | 18 | /** Free up/compact internal window buffers, we can use this when a window becomes unused. 19 | * Not freed: 20 | * - ImGuiWindow, ImGuiWindowSettings, Name, StateStorage, ColumnsStorage (may hold useful data) 21 | * This should have no noticeable visual effect. When the window reappear however, expect new allocation/buffer growth/copy cost. 22 | * 23 | * ~gcCompactTransientWindowBuffers */ 24 | fun Window.gcCompactTransientBuffers() { 25 | memoryCompacted = true 26 | memoryDrawListIdxCapacity = drawList.idxBuffer.cap 27 | memoryDrawListVtxCapacity = drawList.vtxBuffer.cap 28 | idStack.clear() 29 | drawList._clearFreeMemory() 30 | dc.apply { 31 | childWindows.clear() 32 | itemWidthStack.clear() 33 | textWrapPosStack.clear() 34 | } 35 | } 36 | 37 | /** ~GcAwakeTransientWindowBuffers */ 38 | fun Window.gcAwakeTransientBuffers() { // We stored capacity of the ImDrawList buffer to reduce growth-caused allocation/copy when awakening. 39 | // The other buffers tends to amortize much faster. 40 | memoryCompacted = false 41 | drawList.apply { 42 | idxBuffer = idxBuffer reserve memoryDrawListIdxCapacity 43 | vtxBuffer = vtxBuffer reserve memoryDrawListVtxCapacity 44 | } 45 | memoryDrawListIdxCapacity = 0 46 | memoryDrawListVtxCapacity = 0 47 | } 48 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/genericContextHooks.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import imgui.ID 4 | import imgui.classes.Context 5 | import imgui.classes.ContextHook 6 | import imgui.classes.ContextHookType 7 | 8 | // Generic context hooks 9 | interface genericContextHooks { 10 | 11 | /** No specific ordering/dependency support, will see as needed */ 12 | infix fun Context.addHook(hook: ContextHook): ID { 13 | assert(hook.callback != null && hook.hookId == 0 && hook.type != ContextHookType.PendingRemoval_) 14 | hooks += hook 15 | hook.hookId = ++hookIdNext 16 | return hookIdNext 17 | } 18 | 19 | infix fun Context.removeContextHook(hookId: ID) { 20 | assert(hookId != 0) 21 | for (hook in hooks) 22 | if (hook.hookId == hookId) 23 | hook.type = ContextHookType.PendingRemoval_ 24 | } 25 | 26 | /** Call context hooks (used by e.g. test engine) 27 | * We assume a small number of hooks so all stored in same array */ 28 | infix fun Context.callHooks(hookType: ContextHookType) { 29 | for (hook in hooks) 30 | if (hook.type == hookType) 31 | hook.callback!!.invoke(this, hook) 32 | } 33 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/localization.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import imgui.api.g 4 | import imgui.internal.classes.LocEntry 5 | import imgui.internal.classes.LocKey 6 | 7 | // Localization 8 | internal interface localization { 9 | 10 | fun localizeRegisterEntries(entries: List) { 11 | for (entry in entries) 12 | g.localizationTable[entry.key] = entry.text 13 | } 14 | 15 | /** ~LocalizeGetMsg */ 16 | val LocKey.msg 17 | get() = g.localizationTable[this] ?: "*Missing Text*" 18 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/loggingCapture.kt: -------------------------------------------------------------------------------- 1 | @file:OptIn(ExperimentalStdlibApi::class) 2 | 3 | package imgui.internal.api 4 | 5 | import glm_.vec2.Vec2 6 | import imgui.ImGui 7 | import imgui.ImGui.logText 8 | import imgui.api.g 9 | import imgui.getOrNul 10 | import imgui.internal.eolRange 11 | import imgui.internal.sections.LogType 12 | 13 | /** Logging/Capture */ 14 | internal interface loggingCapture { 15 | 16 | /** -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name. */ 17 | /** Start logging/capturing text output */ 18 | fun logBegin(type: LogType, autoOpenDepth: Int) { 19 | 20 | val window = g.currentWindow!! 21 | 22 | assert(!g.logEnabled && g.logFile == null && g.logBuffer.isEmpty()) 23 | g.logEnabled = true 24 | g.logType = type 25 | // g.logNextPrefix = g.LogNextSuffix = NULL TODO 26 | g.logDepthRef = window.dc.treeDepth 27 | g.logDepthToExpand = autoOpenDepth.takeIf { it >= 0 } ?: g.logDepthToExpandDefault 28 | g.logLinePosY = Float.MAX_VALUE 29 | g.logLineFirstItem = true 30 | } 31 | 32 | /** Start logging/capturing to internal buffer */ 33 | fun logToBuffer(autoOpenDepth: Int = -1) { 34 | if (g.logEnabled) 35 | return 36 | logBegin(LogType.Buffer, autoOpenDepth) 37 | } 38 | 39 | /** Internal version that takes a position to decide on newline placement and pad items according to their depth. 40 | * We split text into individual lines to add current tree level padding 41 | * FIXME: This code is a little complicated perhaps, considering simplifying the whole system. */ 42 | fun logRenderedText(refPos: Vec2?, text: String, textEnd: Int = ImGui.findRenderedTextEnd(text)) { // TODO ByteArray? 43 | 44 | val window = g.currentWindow!! 45 | 46 | val prefix = g.logNextPrefix 47 | val suffix = g.logNextSuffix 48 | g.logNextPrefix = ""; g.logNextSuffix = "" 49 | 50 | // if (!text_end) 51 | // text_end = FindRenderedTextEnd(text, text_end) 52 | 53 | val logNewLine = refPos != null && (refPos.y > g.logLinePosY + g.style.framePadding.y + 1) 54 | if (refPos != null) 55 | g.logLinePosY = refPos.y 56 | if (logNewLine) { 57 | logText("\n") 58 | g.logLineFirstItem = true 59 | } 60 | 61 | if (prefix.isNotEmpty()) 62 | logRenderedText(refPos, prefix, prefix.length) // Calculate end ourself to ensure "##" are included here. 63 | 64 | // Re-adjust padding if we have popped out of our starting depth 65 | if (g.logDepthRef > window.dc.treeDepth) 66 | g.logDepthRef = window.dc.treeDepth 67 | val treeDepth = window.dc.treeDepth - g.logDepthRef 68 | 69 | var textRemaining = 0//text 70 | while (true) { 71 | // Split the string. Each new line (after a '\n') is followed by indentation corresponding to the current depth of our log entry. 72 | // We don't add a trailing \n yet to allow a subsequent item on the same line to be captured. 73 | val lineStart = textRemaining 74 | val lineEnd = text.eolRange(lineStart, textEnd) 75 | val isLastLine = lineEnd == textEnd 76 | if (lineStart != lineEnd || !isLastLine) { 77 | val lineLength = lineEnd - lineStart 78 | val indentation = if (g.logLineFirstItem) treeDepth * 4 else 1 79 | val t = text.encodeToByteArray().sliceArray(lineStart ..< lineStart + lineLength) 80 | logText(" ".repeat(indentation) + t.decodeToString()) 81 | g.logLineFirstItem = false 82 | if (text.getOrNul(lineEnd) == '\n') { 83 | logText("\n") 84 | g.logLineFirstItem = true 85 | } 86 | } 87 | if (isLastLine) 88 | break 89 | textRemaining = lineEnd + 1 90 | } 91 | 92 | if (suffix.isNotEmpty()) 93 | logRenderedText(refPos, suffix, suffix.length) 94 | } 95 | 96 | /** Important: doesn't copy underlying data, use carefully (prefix/suffix must be in scope at the time of the next LogRenderedText) */ 97 | fun logSetNextTextDecoration(prefix: String, suffix: String) { // TODO check where this is called, missed some porting 98 | g.logNextPrefix = prefix 99 | g.logNextSuffix = suffix 100 | } 101 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/parameterStacks.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import imgui.api.g 4 | import imgui.internal.sections.ItemFlags 5 | import imgui.or 6 | import imgui.wo 7 | 8 | // Parameter stacks (shared) 9 | internal interface parameterStacks { 10 | 11 | /** allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets 12 | * @param option = ItemFlag */ 13 | fun pushItemFlag(option: ItemFlags, enabled: Boolean) { 14 | var itemFlags = g.currentItemFlags 15 | assert(itemFlags == g.itemFlagsStack.last()) 16 | itemFlags = when { 17 | enabled -> itemFlags or option 18 | else -> itemFlags wo option 19 | } 20 | g.currentItemFlags = itemFlags 21 | g.itemFlagsStack += itemFlags 22 | } 23 | 24 | fun popItemFlag() { 25 | assert(g.itemFlagsStack.size > 1) { "Too many calls to PopItemFlag() - we always leave a 0 at the bottom of the stack." } 26 | g.itemFlagsStack.pop() 27 | g.currentItemFlags = g.itemFlagsStack.last() 28 | } 29 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/settings.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import imgui.ImGui.io 4 | import imgui.WindowFlag 5 | import imgui.api.g 6 | import imgui.hasnt 7 | import imgui.internal.classes.Window 8 | import imgui.internal.hashStr 9 | import imgui.internal.sections.SettingsHandler 10 | 11 | /** Settings */ 12 | internal interface settings { 13 | 14 | fun markIniSettingsDirty() { 15 | if (g.settingsDirtyTimer <= 0f) 16 | g.settingsDirtyTimer = io.iniSavingRate 17 | } 18 | 19 | fun Window.markIniSettingsDirty() { 20 | if (flags hasnt WindowFlag.NoSavedSettings && g.settingsDirtyTimer <= 0f) 21 | g.settingsDirtyTimer = io.iniSavingRate 22 | } 23 | 24 | // MarkIniSettingsDirty(ImGuiWindow* window) -> Window class 25 | 26 | // Clear all settings (windows, tables, docking etc.) 27 | fun clearIniSettings() { 28 | g.settingsIniData = "" 29 | for (handler in g.settingsHandlers) 30 | handler.clearAllFn?.invoke(g, handler) 31 | g.settingsWindows.clear() 32 | } 33 | 34 | fun addSettingsHandler(handler: SettingsHandler) { 35 | assert(findSettingsHandler(handler.typeName) == null) 36 | g.settingsHandlers += handler 37 | } 38 | 39 | fun removeSettingsHandler(typeName: String) { 40 | findSettingsHandler(typeName)?.let { handler -> 41 | g.settingsHandlers -= handler 42 | } 43 | } 44 | 45 | fun findSettingsHandler(typeName: String): SettingsHandler? { 46 | val typeHash = hashStr(typeName) 47 | return g.settingsHandlers.find { it.typeHash == typeHash } 48 | } 49 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/settingsWindows.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import imgui.ID 4 | import imgui.ImGui.findWindowByName 5 | import imgui.WindowFlag 6 | import imgui.api.g 7 | import imgui.div 8 | import imgui.internal.classes.Window 9 | import imgui.internal.hashStr 10 | import imgui.internal.sections.WindowSettings 11 | import imgui.statics.initOrLoadWindowSettings 12 | 13 | // Settings - Windows 14 | interface settingsWindows { 15 | 16 | fun createNewWindowSettings(name_: String): WindowSettings { 17 | val name = when(g.io.configDebugIniSettings) { 18 | // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() 19 | // Preserve the full string when ConfigDebugVerboseIniSettings is set to make .ini inspection easier. 20 | false -> name_.removePrefix("###") 21 | else -> name_ 22 | } 23 | return WindowSettings(name).also { 24 | g.settingsWindows += it 25 | } 26 | } 27 | 28 | // We don't provide a FindWindowSettingsByName() because Docking system doesn't always hold on names. 29 | // This is called once per window .ini entry + once per newly instanciated window. 30 | fun findWindowSettingsByID(id: ID): WindowSettings? = g.settingsWindows.find { it.id == id && !it.wantDelete } 31 | 32 | // This is faster if you are holding on a Window already as we don't need to perform a search. 33 | fun findWindowSettingsByWindow(window: Window): WindowSettings? { 34 | if (window.settingsOffset != -1) 35 | return g.settingsWindows[window.settingsOffset] 36 | return findWindowSettingsByID(window.id) 37 | } 38 | 39 | // This will revert window to its initial state, including enabling the ImGuiCond_FirstUseEver/ImGuiCond_Once conditions once more. 40 | fun clearWindowSettings(name: String) { 41 | //IMGUI_DEBUG_LOG("ClearWindowSettings('%s')\n", name); 42 | val window = findWindowByName(name) 43 | if (window != null) { 44 | window.flags /= WindowFlag.NoSavedSettings 45 | initOrLoadWindowSettings(window, null) 46 | } 47 | val settings = window?.let { findWindowSettingsByWindow(window) } ?: findWindowSettingsByID(hashStr(name)) 48 | settings?.wantDelete = true 49 | } 50 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/shadeFunctions.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | import glm_.glm 4 | import glm_.i 5 | import glm_.vec2.Vec2 6 | import imgui.COL32_A_MASK 7 | import imgui.COL32_B_SHIFT 8 | import imgui.COL32_G_SHIFT 9 | import imgui.COL32_R_SHIFT 10 | import imgui.classes.DrawList 11 | import imgui.internal.DrawVert 12 | import imgui.internal.lengthSqr 13 | 14 | internal interface shadeFunctions { 15 | 16 | /** Generic linear color gradient, write to RGB fields, leave A untouched. */ 17 | fun DrawList.shadeVertsLinearColorGradientKeepAlpha( 18 | vertStart: Int, vertEnd: Int, gradientP0: Vec2, 19 | gradientP1: Vec2, col0: Int, col1: Int, 20 | ) { 21 | val gradientExtent = gradientP1 - gradientP0 22 | val gradientInvLength2 = 1f / gradientExtent.lengthSqr 23 | val col0R = (col0 ushr COL32_R_SHIFT) and 0xFF 24 | val col0G = (col0 ushr COL32_G_SHIFT) and 0xFF 25 | val col0B = (col0 ushr COL32_B_SHIFT) and 0xFF 26 | val colDeltaR = ((col1 ushr COL32_R_SHIFT) and 0xFF) - col0R 27 | val colDeltaG = ((col1 ushr COL32_G_SHIFT) and 0xFF) - col0G 28 | val colDeltaB = ((col1 ushr COL32_B_SHIFT) and 0xFF) - col0B 29 | for (i in vertStart until vertEnd) { 30 | var offset = i * DrawVert.SIZE 31 | val pos = Vec2(vtxBuffer.data, offset) 32 | val d = pos - gradientP0 dot gradientExtent 33 | val t = glm.clamp(d * gradientInvLength2, 0f, 1f) 34 | val r = (col0R + colDeltaR * t).i 35 | val g = (col0G + colDeltaG * t).i 36 | val b = (col0B + colDeltaB * t).i 37 | offset += Vec2.size * 2 38 | val col = vtxBuffer.data.getInt(offset) 39 | val newCol = (r shl COL32_R_SHIFT) or (g shl COL32_G_SHIFT) or (b shl COL32_B_SHIFT) or (col and COL32_A_MASK) 40 | vtxBuffer.data.putInt(offset, newCol) 41 | } 42 | } 43 | 44 | /** Distribute UV over (a, b) rectangle */ 45 | fun DrawList.shadeVertsLinearUV(vertStart: Int, vertEnd: Int, a: Vec2, b: Vec2, uvA: Vec2, uvB: Vec2, clamp: Boolean) { 46 | val size = b - a 47 | val uvSize = uvB - uvA 48 | val scale = Vec2( 49 | if (size.x != 0f) uvSize.x / size.x else 0f, 50 | if (size.y != 0f) uvSize.y / size.y else 0f) 51 | if (clamp) { 52 | val min = uvA min uvB 53 | val max = uvA max uvB 54 | for (i in vertStart until vertEnd) { 55 | val vertexPos = Vec2(vtxBuffer.data, i * DrawVert.SIZE) 56 | val vertexUV = glm.clamp(uvA + (vertexPos - a) * scale, min, max) 57 | vertexUV.to(vtxBuffer.data, i * DrawVert.SIZE + Vec2.size) 58 | } 59 | } else 60 | for (i in vertStart until vertEnd) { 61 | val vertexPos = Vec2(vtxBuffer.data, i * DrawVert.SIZE) 62 | val vertexUV = uvA + (vertexPos - a) * scale 63 | vertexUV.to(vtxBuffer.data, i * DrawVert.SIZE + Vec2.size) 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/api/viewports.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.api 2 | 3 | // Viewports 4 | internal interface viewports { 5 | 6 | // use direct field access in Window class 7 | // IMGUI_API void SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport) 8 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/classes/TabBar.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.classes 2 | 3 | import glm_.vec2.Vec2 4 | import imgui.ID 5 | import imgui.TabBarFlags 6 | import imgui.none 7 | 8 | class TabBarSection { 9 | /** Number of tabs in this section. */ 10 | var tabCount = 0 11 | 12 | /** Sum of width of tabs in this section (after shrinking down) */ 13 | var width = 0f 14 | 15 | /** Horizontal spacing at the end of the section. */ 16 | var spacing = 0f 17 | } 18 | 19 | /** Storage for a tab bar (sizeof() 152 bytes) */ 20 | class TabBar { 21 | 22 | val tabs = ArrayList() 23 | 24 | var flags: TabBarFlags = none 25 | 26 | /** Zero for tab-bars used by docking */ 27 | var id: ID = 0 28 | 29 | /** Selected tab/window */ 30 | var selectedTabId: ID = 0 31 | 32 | /** Next selected tab/window. Will also trigger a scrolling animation */ 33 | var nextSelectedTabId: ID = 0 34 | 35 | /** Can occasionally be != SelectedTabId (e.g. when previewing contents for CTRL+TAB preview) */ 36 | var visibleTabId: ID = 0 37 | var currFrameVisible = -1 38 | var prevFrameVisible = -1 39 | val barRect = Rect() 40 | 41 | var currTabsContentsHeight = 0f 42 | 43 | /** Record the height of contents submitted below the tab bar */ 44 | var prevTabsContentsHeight = 0f 45 | 46 | /** Actual width of all tabs (locked during layout) */ 47 | var widthAllTabs = 0f 48 | 49 | /** Ideal width if all tabs were visible and not clipped */ 50 | var widthAllTabsIdeal = 0f 51 | 52 | var scrollingAnim = 0f 53 | var scrollingTarget = 0f 54 | var scrollingTargetDistToVisibility = 0f 55 | var scrollingSpeed = 0f 56 | var scrollingRectMinX = 0f 57 | var scrollingRectMaxX = 0f 58 | var reorderRequestTabId: ID = 0 59 | var reorderRequestOffset = 0 60 | var beginCount = 0 61 | 62 | var wantLayout = false 63 | var visibleTabWasSubmitted = false 64 | 65 | /** Set to true when a new tab item or button has been added to the tab bar during last frame */ 66 | var tabsAddedNew = false 67 | 68 | /** Number of tabs submitted this frame. */ 69 | var tabsActiveCount = 0 70 | 71 | /** Index of last BeginTabItem() tab for use by EndTabItem() */ 72 | var lastTabItemIdx = -1 73 | 74 | var itemSpacingY = 0f 75 | 76 | /** style.FramePadding locked at the time of BeginTabBar() */ 77 | var framePadding = Vec2() 78 | 79 | val backupCursorPos = Vec2() 80 | 81 | /** For non-docking tab bar we re-append names in a contiguous buffer. */ 82 | val tabsNames = ArrayList() 83 | 84 | infix fun getTabOrder(tab: TabItem) = tabs.indexOf(tab) 85 | // infix fun getTabName(tab: TabItem): String { 86 | // assert(tab.nameOffset != -1 && tab.nameOffset < tabsNames.size) 87 | // return tabsNames[tab.nameOffset] 88 | // } 89 | 90 | val TabItem.order: Int 91 | get() = tabs.indexOf(this) 92 | 93 | fun getTabName(tab: TabItem): String = tab.name 94 | 95 | /** ~TabBarGetTabName */ 96 | val TabItem.name: String 97 | get() { 98 | if (nameOffset == -1) 99 | return "N/A" 100 | assert(nameOffset in tabsNames.indices) 101 | return tabsNames[nameOffset] 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/sections/Clipper support.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.sections 2 | 3 | import glm_.i 4 | import imgui.classes.ListClipper 5 | 6 | //----------------------------------------------------------------------------- 7 | // [SECTION] Clipper support 8 | //----------------------------------------------------------------------------- 9 | 10 | // Note that Max is exclusive, so perhaps should be using a Begin/End convention. 11 | class ListClipperRange { 12 | var min = 0 13 | var max = 0 14 | var posToIndexConvert = false // Begin/End are absolute position (will be converted to indices later) 15 | var posToIndexOffsetMin = 0 // Add to Min after converting to indices 16 | var posToIndexOffsetMax = 0 // Add to Min after converting to indices 17 | 18 | companion object { 19 | fun fromIndices(min: Int, max: Int) = ListClipperRange().also { it.min = min; it.max = max } 20 | fun fromPositions(y1: Float, y2: Float, offMin: Int, offMax: Int) = 21 | ListClipperRange().also { it.min = y1.i; it.max = y2.i; it.posToIndexConvert = true; it.posToIndexOffsetMin = offMin; it.posToIndexOffsetMax = offMax } 22 | } 23 | } 24 | 25 | // Temporary clipper data, buffers shared/reused between instances 26 | class ListClipperData { 27 | lateinit var listClipper: ListClipper 28 | var lossynessOffset = 0f 29 | var stepNo = 0 30 | var itemsFrozen = 0 31 | val ranges = ArrayList() 32 | fun reset(clipper: ListClipper) { 33 | listClipper = clipper 34 | stepNo = 0 35 | itemsFrozen = 0 36 | ranges.clear() 37 | } 38 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/sections/Columns support.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.sections 2 | 3 | import com.livefront.sealedenum.GenSealedEnum 4 | import imgui.Flag 5 | import imgui.FlagBase 6 | import imgui.ID 7 | import imgui.none 8 | import imgui.internal.DrawListSplitter 9 | import imgui.internal.classes.Rect 10 | 11 | 12 | //----------------------------------------------------------------------------- 13 | // [SECTION] Columns support 14 | //----------------------------------------------------------------------------- 15 | 16 | 17 | typealias OldColumnFlags = Flag 18 | 19 | /** Flags: for Columns(), BeginColumns() */ 20 | sealed class OldColumnsFlag : FlagBase() { 21 | 22 | /** Disable column dividers */ 23 | object NoBorder : OldColumnsFlag() 24 | 25 | /** Disable resizing columns when clicking on the dividers */ 26 | object NoResize : OldColumnsFlag() 27 | 28 | /** Disable column width preservation when adjusting columns */ 29 | object NoPreserveWidths : OldColumnsFlag() 30 | 31 | /** Disable forcing columns to fit within window */ 32 | object NoForceWithinWindow : OldColumnsFlag() 33 | 34 | /** (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns 35 | * width at all_. Will eventually remove. */ 36 | object GrowParentContentsSize : OldColumnsFlag() 37 | 38 | override val i: Int = 1 shl ordinal 39 | 40 | @GenSealedEnum 41 | companion object 42 | } 43 | 44 | /** Storage data for a single column for legacy Columns() api */ 45 | class OldColumnData { 46 | /** Column start offset, normalized 0f (far left) -> 1f (far right) */ 47 | var offsetNorm = 0f 48 | var offsetNormBeforeResize = 0f 49 | 50 | /** Not exposed */ 51 | var flags: OldColumnFlags = none 52 | var clipRect = Rect() 53 | } 54 | 55 | /** Storage data for a columns set for legacy Columns() api */ 56 | class OldColumns { 57 | var id: ID = 0 58 | var flags: OldColumnFlags = none 59 | var isFirstFrame = false 60 | var isBeingResized = false 61 | var current = 0 62 | var count = 1 63 | 64 | /** Offsets from HostWorkRect.Min.x */ 65 | var offMinX = 0f 66 | 67 | /** Offsets from HostWorkRect.Min.x */ 68 | var offMaxX = 0f 69 | 70 | /** Backup of CursorPos at the time of BeginColumns() */ 71 | var hostCursorPosY = 0f 72 | 73 | /** Backup of CursorMaxPos at the time of BeginColumns() */ 74 | var hostCursorMaxPosX = 0f 75 | 76 | /** Backup of ClipRect at the time of BeginColumns() */ 77 | var hostInitialClipRect = Rect() 78 | 79 | /** Backup of ClipRect during PushColumnsBackground()/PopColumnsBackground() */ 80 | var hostBackupClipRect = Rect() 81 | 82 | /** Backup of WorkRect at the time of BeginColumns() */ 83 | var hostBackupParentWorkRect = Rect() 84 | var lineMinY = 0f 85 | var lineMaxY = 0f 86 | val columns = ArrayList() 87 | val splitter = DrawListSplitter() 88 | 89 | fun destroy() = splitter.clearFreeMemory() 90 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/sections/Docking support.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.sections 2 | 3 | //----------------------------------------------------------------------------- 4 | // [SECTION] Docking support 5 | //----------------------------------------------------------------------------- -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/sections/Input support.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.sections 2 | 3 | import imgui.* 4 | 5 | 6 | enum class InputSource { 7 | None, Mouse, // Note: may be Mouse or TouchScreen or Pen. See io.MouseSource to distinguish them. 8 | Keyboard, Gamepad, 9 | 10 | /** Currently only used by InputText() */ 11 | Clipboard 12 | } 13 | 14 | // FIXME: Structures in the union below need to be declared as anonymous unions appears to be an extension? 15 | // Using ImVec2() would fail on Clang 'union member 'MousePos' has a non-trivial default constructor' 16 | 17 | sealed class InputEvent(val eventId: UInt) { // Unique, sequential increasing integer to identify an event (if you need to correlate them to other data). 18 | 19 | abstract val source: InputSource 20 | var addedByTestEngine = false 21 | 22 | class MousePos(val posX: Float, 23 | val posY: Float, 24 | val mouseSource: MouseSource, eventId: UInt) : InputEvent(eventId) { 25 | override val source: InputSource = InputSource.Mouse 26 | } 27 | 28 | class MouseWheel(val wheelX: Float, 29 | val wheelY: Float, 30 | val mouseSource: MouseSource, eventId: UInt) : InputEvent(eventId) { 31 | override val source: InputSource = InputSource.Mouse 32 | } 33 | 34 | class MouseButton(val button: imgui.MouseButton, 35 | val down: Boolean, 36 | val mouseSource: MouseSource, eventId: UInt) : InputEvent(eventId) { 37 | override val source: InputSource = InputSource.Mouse 38 | } 39 | 40 | class Key(val key: imgui.Key, 41 | val down: Boolean, 42 | val analogValue: Float, 43 | override val source: InputSource = InputSource.Keyboard, eventId: UInt) : InputEvent(eventId) 44 | 45 | class Text(val char: Char, eventId: UInt) : InputEvent(eventId) { 46 | override val source: InputSource = InputSource.Keyboard 47 | } 48 | 49 | class AppFocused(val focused: Boolean, eventId: UInt) : InputEvent(eventId) { 50 | override val source: InputSource = InputSource.None 51 | } 52 | } 53 | 54 | // Input function taking an 'ImGuiID owner_id' argument defaults to (ImGuiKeyOwner_Any == 0) aka don't test ownership, which matches legacy behavior. 55 | 56 | /** Accept key that have an owner, UNLESS a call to SetKeyOwner() explicitly used ImGuiInputFlags_LockThisFrame or ImGuiInputFlags_LockUntilRelease. */ 57 | const val KeyOwner_Any: ID = 0 58 | 59 | /** Require key to have no owner. */ 60 | const val KeyOwner_None: ID = -1 61 | 62 | typealias KeyRoutingIndex = Int 63 | 64 | // Routing table entry (sizeof() == 16 bytes) 65 | class KeyRoutingData { 66 | var nextEntryIndex: KeyRoutingIndex = -1 67 | 68 | /** Technically we'd only need 4-bits but for simplify we store ImGuiMod_ values which need 16-bits. ImGuiMod_Shortcut is already translated to Ctrl/Super. */ 69 | var mods: KeyChord = none 70 | var routingNextScore = 255 // Lower is better (0: perfect score) 71 | var routingCurr: ID = KeyOwner_None 72 | var routingNext: ID = KeyOwner_None 73 | } 74 | 75 | // Routing table: maintain a desired owner for each possible key-chord (key + mods), and setup owner in NewFrame() when mods are matching. 76 | // Stored in main context (1 instance) 77 | class KeyRoutingTable { 78 | val index = IntArray(Key.COUNT) { -1 } // Index of first entry in Entries[] 79 | val entries = ArrayList() 80 | val entriesNext = ArrayList() // Double-buffer to avoid reallocation (could use a shared buffer) 81 | 82 | fun clear() { 83 | index.fill(-1) 84 | entries.clear() 85 | entriesNext.clear() 86 | } 87 | } 88 | 89 | /** This extends ImGuiKeyData but only for named keys (legacy keys don't support the new features) 90 | * Stored in main context (1 per named key). In the future it might be merged into ImGuiKeyData. */ 91 | class KeyOwnerData { 92 | var ownerCurr = KeyOwner_None 93 | var ownerNext = KeyOwner_None 94 | 95 | /** Reading this key requires explicit owner id (until end of frame). Set by ImGuiInputFlags_LockThisFrame. */ 96 | var lockThisFrame = false 97 | 98 | /** Reading this key requires explicit owner id (until key is released). Set by ImGuiInputFlags_LockUntilRelease. When this is true LockThisFrame is always true as well. */ 99 | var lockUntilRelease = false 100 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/sections/Macros.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.sections 2 | 3 | import imgui.ImGui 4 | import imgui.api.g 5 | import imgui.has 6 | import imgui.internal.classes.DebugLogFlag 7 | 8 | 9 | // Debug Printing Into TTY 10 | fun IMGUI_DEBUG_PRINTF(fmt: String, vararg args: Any) = println(fmt.format(*args)) 11 | 12 | // Debug Logging for ShowDebugLogWindow(). This is designed for relatively rare events so please don't spam. 13 | fun IMGUI_DEBUG_LOG(fmt: String, vararg args: Any) = ImGui.debugLog(fmt, *args) 14 | 15 | fun IMGUI_DEBUG_LOG_ACTIVEID(fmt: String, vararg args: Any) { 16 | if (g.debugLogFlags has DebugLogFlag.EventActiveId) 17 | IMGUI_DEBUG_LOG(fmt, *args) 18 | } 19 | 20 | fun IMGUI_DEBUG_LOG_FOCUS(fmt: String, vararg args: Any) { 21 | if (g.debugLogFlags has DebugLogFlag.EventFocus) 22 | IMGUI_DEBUG_LOG(fmt, *args) 23 | } 24 | 25 | // Debug Logging for selected systems. Remove the '((void)0) //' to enable. 26 | fun IMGUI_DEBUG_LOG_POPUP(fmt: String, vararg args: Any) { 27 | if (g.debugLogFlags has DebugLogFlag.EventPopup) 28 | IMGUI_DEBUG_LOG(fmt, *args) 29 | } 30 | 31 | fun IMGUI_DEBUG_LOG_NAV(fmt: String, vararg args: Any) { 32 | if (g.debugLogFlags has DebugLogFlag.EventNav) 33 | IMGUI_DEBUG_LOG(fmt, *args) 34 | } 35 | 36 | fun IMGUI_DEBUG_LOG_SELECTION(fmt: String, vararg args: Any) { 37 | if (g.debugLogFlags has DebugLogFlag.EventSelection) 38 | IMGUI_DEBUG_LOG(fmt, *args) 39 | } 40 | 41 | fun IMGUI_DEBUG_LOG_CLIPPER(fmt: String, vararg args: Any) { 42 | if (g.debugLogFlags has DebugLogFlag.EventClipper) 43 | IMGUI_DEBUG_LOG(fmt, *args) 44 | } 45 | 46 | fun IMGUI_DEBUG_LOG_IO(fmt: String, vararg args: Any) { 47 | if (g.debugLogFlags has DebugLogFlag.EventIO) 48 | IMGUI_DEBUG_LOG(fmt, *args) 49 | } 50 | 51 | fun ASSERT_PARANOID(value: Boolean) = assert(value) 52 | fun ASSERT_PARANOID(value: Boolean, lazyMessage: () -> Any) = assert(value, lazyMessage) -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/sections/Multi-select support.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.sections 2 | 3 | //----------------------------------------------------------------------------- 4 | // [SECTION] Multi-select support 5 | //----------------------------------------------------------------------------- -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/sections/Settings support.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.sections 2 | 3 | import glm_.vec2.Vec2 4 | import imgui.ID 5 | import imgui.internal.classes.* 6 | import imgui.internal.hashStr 7 | 8 | /** Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session) 9 | * 10 | * Because we never destroy or rename ImGuiWindowSettings, we can store the names in a separate buffer easily. 11 | * [JVM] We prefer keeping the `name` variable 12 | */ 13 | class WindowSettings(val name: String = "") { 14 | var id: ID = hashStr(name) 15 | var pos = Vec2() 16 | var size = Vec2() 17 | var collapsed = false 18 | var wantApply = false // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context) 19 | var wantDelete = false // Set to invalidate/delete the settings entry 20 | 21 | fun clear() { 22 | id = hashStr(name) 23 | pos put 0f 24 | size put 0f 25 | collapsed = false 26 | wantApply = false 27 | wantDelete = false 28 | } 29 | } 30 | 31 | /** Storage for one type registered in the .ini file */ 32 | class SettingsHandler { 33 | /** Short description stored in .ini file. Disallowed characters: '[' ']' */ 34 | var typeName = "" 35 | /** == ImHashStr(TypeName) */ 36 | var typeHash: ID = 0 37 | 38 | var clearAllFn: ClearAllFn? = null 39 | var readInitFn: ReadInitFn? = null 40 | var readOpenFn: ReadOpenFn? = null 41 | var readLineFn: ReadLineFn? = null 42 | var applyAllFn: ApplyAllFn? = null 43 | var writeAllFn: WriteAllFn? = null 44 | var userData: Any? = null 45 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/sections/Table support.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.sections 2 | 3 | //----------------------------------------------------------------------------- 4 | // [SECTION] Table support 5 | //----------------------------------------------------------------------------- -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/sections/Viewport support.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.sections 2 | 3 | import glm_.max 4 | import glm_.vec2.Vec2 5 | import imgui.ImGui 6 | import imgui.Viewport 7 | import imgui.api.g 8 | import imgui.classes.DrawList 9 | import imgui.internal.DrawData 10 | import imgui.internal.classes.Rect 11 | import kool.lim 12 | 13 | 14 | //----------------------------------------------------------------------------- 15 | // [SECTION] Viewport support 16 | //----------------------------------------------------------------------------- 17 | 18 | /** ImGuiViewport Private/Internals fields (cardinal sin: we are using inheritance!) 19 | * Every instance of ImGuiViewport is in fact a ImGuiViewportP. */ 20 | class ViewportP : Viewport() { 21 | 22 | /** Last frame number the background (0) and foreground (1) draw lists were used */ 23 | val drawListsLastFrame = intArrayOf(-1, -1) 24 | 25 | /** Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays. */ 26 | val drawLists = Array(2) { null } 27 | 28 | val drawDataP = DrawData() 29 | 30 | val drawDataBuilder = DrawDataBuilder() 31 | 32 | /** Work Area: Offset from Pos to top-left corner of Work Area. Generally (0,0) or (0,+main_menu_bar_height). Work Area is Full Area but without menu-bars/status-bars (so WorkArea always fit inside Pos/Size!) */ 33 | val workOffsetMin = Vec2() 34 | 35 | /** Work Area: Offset from Pos+Size to bottom-right corner of Work Area. Generally (0,0) or (0,-status_bar_height). */ 36 | 37 | val workOffsetMax = Vec2() 38 | 39 | /** Work Area: Offset being built during current frame. Generally >= 0.0f. */ 40 | val buildWorkOffsetMin = Vec2() 41 | 42 | /** Work Area: Offset being built during current frame. Generally <= 0.0f. */ 43 | val buildWorkOffsetMax = Vec2() 44 | 45 | // Calculate work rect pos/size given a set of offset (we have 1 pair of offset for rect locked from last frame data, and 1 pair for currently building rect) 46 | fun calcWorkRectPos(offMin: Vec2) = Vec2(pos.x + offMin.x, pos.y + offMin.y) 47 | fun calcWorkRectSize(offMin: Vec2, offMax: Vec2) = Vec2(0f max (size.x - offMin.x + offMax.x), 0f max (size.y - offMin.y + offMax.y)) 48 | fun updateWorkRect() { // Update public fields 49 | workPos put calcWorkRectPos(workOffsetMin) 50 | workSize put calcWorkRectSize(workOffsetMin, workOffsetMax) 51 | } 52 | 53 | // Helpers to retrieve ImRect (we don't need to store BuildWorkRect as every access tend to change it, hence the code asymmetry) 54 | 55 | val mainRect: Rect 56 | get() = Rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y) 57 | 58 | val workRect: Rect 59 | get() = Rect(workPos.x, workPos.y, workPos.x + workSize.x, workPos.y + workSize.y) 60 | 61 | val buildWorkRect: Rect 62 | get() { 63 | val pos = calcWorkRectPos(buildWorkOffsetMin) 64 | val size = calcWorkRectSize(buildWorkOffsetMin, buildWorkOffsetMax) 65 | return Rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y) 66 | } 67 | 68 | /** ~GetViewportDrawList */ 69 | fun getDrawList(drawlistNo: Int, drawlistName: String): DrawList { 70 | // Create the draw list on demand, because they are not frequently used for all viewports 71 | assert(drawlistNo in drawLists.indices) 72 | val drawList = drawLists[drawlistNo] ?: DrawList(g.drawListSharedData).apply { 73 | _ownerName = drawlistName 74 | drawLists[drawlistNo] = this 75 | } 76 | 77 | // Our ImDrawList system requires that there is always a command 78 | if (drawListsLastFrame[drawlistNo] != g.frameCount) { 79 | drawList._resetForNewFrame() 80 | drawList pushTextureID g.io.fonts.texID 81 | drawList.pushClipRect(pos, pos + size, false) 82 | drawListsLastFrame[drawlistNo] = g.frameCount 83 | } 84 | return drawList 85 | } 86 | 87 | /** ~SetupViewportDrawData */ 88 | infix fun setupDrawData(drawLists: ArrayList) { 89 | drawDataP.apply { 90 | valid = true 91 | cmdLists.clear() 92 | if (drawLists.isNotEmpty()) 93 | cmdLists += drawLists 94 | totalIdxCount = 0 95 | totalVtxCount = 0 96 | displayPos put pos 97 | displaySize put size 98 | framebufferScale put ImGui.io.displayFramebufferScale 99 | for (n in 0 until drawLists.size) { 100 | val drawList = drawLists[n] 101 | drawList._popUnusedDrawCmd() 102 | totalVtxCount += drawList.vtxBuffer.lim 103 | totalIdxCount += drawList.idxBuffer.lim 104 | } 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/internal/sections/test engine specific hooks.kt: -------------------------------------------------------------------------------- 1 | package imgui.internal.sections 2 | 3 | import imgui.ID 4 | import imgui.api.g 5 | import imgui.classes.Context 6 | import imgui.internal.classes.LastItemData 7 | import imgui.internal.classes.Rect 8 | 9 | //----------------------------------------------------------------------------- 10 | // [SECTION] Test Engine specific hooks (imgui_test_engine) 11 | //----------------------------------------------------------------------------- 12 | 13 | // In IMGUI_VERSION_NUM >= 18934: changed IMGUI_TEST_ENGINE_ITEM_ADD(bb,id) to IMGUI_TEST_ENGINE_ITEM_ADD(id,bb,item_data); 14 | typealias TestEngineHook_ItemAdd = (ctx: Context, id: ID, bb: Rect, itemData: LastItemData?) -> Unit // item_data may be NULL 15 | typealias TestEngineHook_ItemInfo = (ctx: Context, id: ID, label: String?, flags: ItemStatusFlags) -> Unit 16 | typealias TestEngineHook_Log = (ctx: Context, fmt: String, args: Array) -> Unit 17 | typealias TestEngine_FindItemDebugLabel = (ctx: Context, id: ID) -> String? 18 | 19 | lateinit var testEngineHook_ItemAdd: TestEngineHook_ItemAdd 20 | lateinit var testEngineHook_ItemInfo: TestEngineHook_ItemInfo 21 | 22 | lateinit var testEngineHook_Log: TestEngineHook_Log 23 | lateinit var testEngine_FindItemDebugLabel: TestEngine_FindItemDebugLabel 24 | 25 | /** Register item bounding box */ 26 | fun IMGUI_TEST_ENGINE_ITEM_ADD(id: ID, bb: Rect, itemData: LastItemData?) { 27 | if (g.testEngineHookItems) 28 | testEngineHook_ItemAdd(g, id, bb, itemData) 29 | } 30 | 31 | /** Register item label and status flags (optional)} */ 32 | fun IMGUI_TEST_ENGINE_ITEM_INFO(id: ID, label: String, flags: ItemStatusFlags) { 33 | if (g.testEngineHookItems) 34 | testEngineHook_ItemInfo(g, id, label, flags) 35 | } 36 | 37 | /** Custom log entry from user land into test log */ 38 | fun IMGUI_TEST_ENGINE_LOG(fmt: String, vararg args: Any) { 39 | if (g.testEngineHookItems) 40 | testEngineHook_Log(g, fmt, args) 41 | } 42 | -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/statics/viewports.kt: -------------------------------------------------------------------------------- 1 | package imgui.static 2 | 3 | import imgui.ViewportFlag 4 | import imgui.api.g 5 | import imgui.or 6 | 7 | // Viewports 8 | 9 | /** Update viewports and monitor infos */ 10 | fun updateViewportsNewFrame() { 11 | 12 | assert(g.viewports.size == 1) 13 | 14 | // Update main viewport with current platform position. 15 | // FIXME-VIEWPORT: Size is driven by backend/user code for backward-compatibility but we should aim to make this more consistent. 16 | g.viewports[0].apply { 17 | flags = ViewportFlag.IsPlatformWindow or ViewportFlag.OwnedByApp 18 | pos put 0f 19 | size put g.io.displaySize 20 | } 21 | for (viewport in g.viewports) 22 | viewport.apply { 23 | // Lock down space taken by menu bars and status bars, reset the offset for fucntions like BeginMainMenuBar() to alter them again. 24 | workOffsetMin put buildWorkOffsetMin 25 | workOffsetMax put buildWorkOffsetMax 26 | buildWorkOffsetMin put 0f 27 | buildWorkOffsetMax put 0f 28 | updateWorkRect() 29 | } 30 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/stb_/Buf.kt: -------------------------------------------------------------------------------- 1 | package imgui.stb_ 2 | 3 | import kool.cap 4 | import kool.lim 5 | import kool.pos 6 | import unsigned.toUInt 7 | import java.nio.ByteBuffer 8 | 9 | /** private structure */ 10 | class Buf(var data: UByteArray = UByteArray(0), val ptr: Int = 0) { 11 | 12 | constructor(buf: Buf) : this(buf.data) { 13 | cursor = buf.cursor 14 | } 15 | 16 | init { 17 | assert(data.size < 0x40000000) 18 | } 19 | 20 | var cursor = 0 21 | 22 | // fun hasRemaining() = data.hasRemaining() 23 | 24 | fun isEmpty() = data.isEmpty() 25 | fun isNotEmpty() = data.isNotEmpty() 26 | val size get() = data.size 27 | 28 | ////////////////////////////////////////////////////////////////////////// 29 | // 30 | // stbtt__buf helpers to parse data from file 31 | // 32 | 33 | fun get8(): UByte = when { 34 | cursor >= size -> 0u 35 | else -> data[cursor++] 36 | } 37 | 38 | fun peek8(): UByte = when { 39 | cursor >= size -> 0u 40 | else -> data[cursor] 41 | } 42 | 43 | infix fun seek(o: Int) { 44 | assert(o in data.indices) 45 | cursor = if (o !in data.indices) size else o 46 | } 47 | 48 | infix fun skip(o: Int) = seek(cursor + o) 49 | 50 | fun get(n: Int): UInt { 51 | var v = 0u 52 | assert(n in 1..4) 53 | for (i in 0 until n) 54 | v = (v shl 8) or get8().ui 55 | return v 56 | } 57 | 58 | // stbtt__new_buf -> Buf constructor 59 | 60 | fun get16(): UInt = get(2) 61 | fun get32(): UInt = get(4) 62 | 63 | fun range(o: Int, s: Int): Buf { 64 | TODO() 65 | // val r = Buf() 66 | // if (o < 0 || s < 0 || o > size || s > size - o) return Buf() 67 | // else Buf(data, o 68 | // r.size = s 69 | // return r 70 | // return when { 71 | // o < 0 || s < 0 || o > data.lim || s > data.lim - o -> Buf() 72 | // else -> Buf(data.sliceAt(o, s)) 73 | // } 74 | } 75 | 76 | fun cffGetIndex(): Buf { 77 | TODO() 78 | // val start = pos 79 | // val count = get16() 80 | // if (count != 0) { 81 | // val offsize = get8() 82 | // assert(offsize in 1..4) 83 | // skip(offsize * count) 84 | // skip(get(offsize) - 1) 85 | // } 86 | // return range(start, pos - start) 87 | } 88 | 89 | val cffInt: Int 90 | get() = TODO()/* when (val b0 = get8()) { 91 | in 32..246 -> b0 - 139 92 | in 247..250 -> (b0 - 247) * 256 + get8() + 108 93 | in 251..254 -> -(b0 - 251) * 256 - get8() - 108 94 | 28 -> get16() 95 | 29 -> get32() 96 | else -> error("") 97 | }*/ 98 | 99 | fun cffSkipOperand() { 100 | val b0 = peek8() 101 | TODO() 102 | // assert(b0 >= 28) 103 | // if (b0 == 30) { 104 | // skip(1) 105 | // while (hasRemaining()) { 106 | // val v = get8() 107 | // if ((v and 0xF) == 0xF || (v shl 4) == 0xF) 108 | // break 109 | // } 110 | // } else cffInt 111 | } 112 | 113 | infix fun dictGet(key: Int): Buf { 114 | TODO() 115 | // seek(0) 116 | // while (hasRemaining()) { 117 | // val start = pos//, end, op 118 | // while (peek8() >= 28) 119 | // cffSkipOperand() 120 | // val end = pos 121 | // var op = get8() 122 | // if (op == 12) op = get8() or 0x100 123 | // if (op == key) return range(start, end - start) 124 | // } 125 | // return range(0, 0) 126 | } 127 | 128 | fun dictGetInts(key: Int, out: IntArray) { 129 | val operands = dictGet(key) 130 | var i = 0 131 | TODO() 132 | // while (i < out.size && operands.hasRemaining()) 133 | // out[i++] = operands.cffInt 134 | } 135 | 136 | fun dictGetInt(key: Int, default: Int = 0): Int { 137 | val operands = dictGet(key) 138 | TODO() 139 | // return when { 140 | // operands.hasRemaining() -> operands.cffInt 141 | // else -> default 142 | // } 143 | } 144 | 145 | val cffIndexCount: Int 146 | get() { 147 | TODO() 148 | // seek(0) 149 | // return get16() 150 | } 151 | 152 | infix fun cffIndexGet(i: Int): Buf { 153 | seek(0) 154 | TODO() 155 | // val count = get16() 156 | // val offsize = get8() 157 | // assert(i in 0 until count) 158 | // assert(offsize in 1..4) 159 | // skip(i * offsize) 160 | // val start = get(offsize) 161 | // val end = get(offsize) 162 | // return range(2 + (count + 1) * offsize + start, end - start) 163 | } 164 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/stb_/Csctx.kt: -------------------------------------------------------------------------------- 1 | package imgui.stb_ 2 | 3 | import glm_.i 4 | 5 | class Csctx(val bounds: Boolean) { 6 | var started = false 7 | var firstX = 0f 8 | var firstY = 0f 9 | var x = 0f 10 | var y = 0f 11 | var minX = 0 12 | var maxX = 0 13 | var minY = 0 14 | var maxY = 0 15 | 16 | lateinit var vertices: Array 17 | var numVertices = 0 18 | 19 | fun trackVertex(x: Int, y: Int) { 20 | if (x > maxX || !started) maxX = x 21 | if (y > maxY || !started) maxY = y 22 | if (x < minX || !started) minX = x 23 | if (y < minY || !started) minY = y 24 | started = true 25 | } 26 | 27 | fun v(type: Vertex.Type, x: Int, y: Int, cx: Int, cy: Int, cx1: Int, cy1: Int) { 28 | if (bounds) { 29 | trackVertex(x, y) 30 | if (type == Vertex.Type.cubic) { 31 | trackVertex(cx, cy) 32 | trackVertex(cx1, cy1) 33 | } 34 | } else vertices.last().apply { 35 | set(type, x, y, cx, cy) 36 | cX1 = cx1 37 | cY1 = cy1 38 | } 39 | numVertices++ 40 | } 41 | 42 | fun closeShape() { 43 | if (firstX != x || firstY != y) 44 | v(Vertex.Type.line, firstX.i, firstY.i, 0, 0, 0, 0) 45 | } 46 | 47 | fun rMoveTo(dx: Float, dy: Float) { 48 | closeShape() 49 | x += dx 50 | firstX = x 51 | y += dy 52 | firstY = y 53 | v(Vertex.Type.move, x.i, y.i, 0, 0, 0, 0) 54 | } 55 | 56 | fun rLineTo(dx: Float, dy: Float) { 57 | x += dx 58 | y += dy 59 | v(Vertex.Type.line, x.i, y.i, 0, 0, 0, 0) 60 | } 61 | 62 | fun rcCurveTo(dx1: Float, dy1: Float, dx2: Float, dy2: Float, dx3: Float, dy3: Float) { 63 | val cx1 = x + dx1 64 | val cy1 = y + dy1 65 | val cx2 = cx1 + dx2 66 | val cy2 = cy1 + dy2 67 | x = cx2 + dx3 68 | y = cy2 + dy3 69 | v(Vertex.Type.cubic, x.i, y.i, cx1.i, cy1.i, cx2.i, cy2.i) 70 | } 71 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/stb_/Node.kt: -------------------------------------------------------------------------------- 1 | package imgui.stb_ 2 | 3 | class Node(val i: Int) { 4 | var x = 0 5 | var y = 0 6 | var next: Ptr? = null 7 | override fun toString() = "i = $i, x=$x y=$y next={$next}" 8 | } 9 | 10 | class Ptr(var value: N?) { 11 | operator fun invoke(): N = value!! 12 | fun copy() = Ptr(value) 13 | override fun toString(): String = value?.toString() ?: "null" 14 | } 15 | 16 | fun ptrOf(value: N) = Ptr(value) -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/stb_/finding the right font.kt: -------------------------------------------------------------------------------- 1 | package imgui.stb_ 2 | 3 | ////////////////////////////////////////////////////////////////////////////// 4 | // 5 | // Finding the right font... 6 | // 7 | // You should really just solve this offline, keep your own tables 8 | // of what font is what, and don't try to get it out of the .ttf file. 9 | // That's because getting it out of the .ttf file is really hard, because 10 | // the names in the file can appear in many possible encodings, in many 11 | // possible languages, and e.g. if you need a case-insensitive comparison, 12 | // the details of that depend on the encoding & language in a complex way 13 | // (actually underspecified in truetype, but also gigantic). 14 | // 15 | // But you can use the provided functions in two possible ways: 16 | // stbtt_FindMatchingFont() will use *case-sensitive* comparisons on 17 | // unicode-encoded names to try to find the font you want; 18 | // you can run this before calling stbtt_InitFont() 19 | // 20 | // stbtt_GetFontNameString() lets you get any of the various strings 21 | // from the file yourself and do your own comparisons on them. 22 | // You have to have called stbtt_InitFont() first. 23 | 24 | 25 | //STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); 26 | //// returns the offset (not index) of the font that matches, or -1 if none 27 | //// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". 28 | //// if you use any other flag, use a font name like "Arial"; this checks 29 | //// the 'macStyle' header field; i don't know if fonts set this consistently 30 | //#define STBTT_MACSTYLE_DONTCARE 0 31 | //#define STBTT_MACSTYLE_BOLD 1 32 | //#define STBTT_MACSTYLE_ITALIC 2 33 | //#define STBTT_MACSTYLE_UNDERSCORE 4 34 | //#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 35 | // 36 | //STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); 37 | //// returns 1/0 whether the first string interpreted as utf8 is identical to 38 | //// the second string interpreted as big-endian utf16... useful for strings from next func 39 | // 40 | //STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); 41 | //// returns the string (which may be big-endian double byte, e.g. for unicode) 42 | //// and puts the length in bytes in *length. 43 | // 44 | //// some of the values for the IDs are below; for more see the truetype spec: 45 | //// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html 46 | //// http://www.microsoft.com/typography/otspec/name.htm 47 | 48 | enum class PlatformID { 49 | UNICODE, MAC, ISO, MICROSOFT; 50 | 51 | val i = ordinal 52 | } 53 | 54 | /** encodingID for STBTT_PLATFORM_ID_UNICODE */ 55 | enum class UnicodeEID { 56 | UNICODE_1_0, UNICODE_1_1, ISO_10646, UNICODE_2_0_BMP, UNICODE_2_0_FULL; 57 | 58 | val i = ordinal 59 | } 60 | 61 | /** encodingID for STBTT_PLATFORM_ID_MICROSOFT */ 62 | enum class MS_EID(val i: Int) { SYMBOL(0), UNICODE_BMP(1), SHIFTJIS(2), UNICODE_FULL(10) } 63 | 64 | /** encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes */ 65 | enum class MAC_EID { 66 | ROMAN, JAPANESE, CHINESE_TRAD, KOREAN, ARABIC, HEBREW, GREEK, RUSSIAN; 67 | 68 | val i = ordinal 69 | } 70 | 71 | /** languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... */ 72 | enum class MS_LANG(val i: Int) { 73 | // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs 74 | ENGLISH(0x0409), 75 | ITALIAN(0x0410), CHINESE(0x0804), JAPANESE(0x0411), DUTCH(0x0413), KOREAN(0x0412), 76 | FRENCH(0x040c), RUSSIAN(0x0419), GERMAN(0x0407), SPANISH(0x0409), HEBREW(0x040d), SWEDISH(0x041D) 77 | } 78 | 79 | enum class MAC_LANG(val i: Int) { // languageID for STBTT_PLATFORM_ID_MAC 80 | ENGLISH(0), JAPANESE(11), 81 | ARABIC(12), KOREAN(23), 82 | DUTCH(4), RUSSIAN(32), 83 | FRENCH(1), SPANISH(6), 84 | GERMAN(2), SWEDISH(5), 85 | HEBREW(10), CHINESE_SIMPLIFIED(33), 86 | ITALIAN(3), CHINESE_TRAD(19) 87 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/stb_/sdf rendering.kt: -------------------------------------------------------------------------------- 1 | package imgui.stb_ 2 | 3 | ////////////////////////////////////////////////////////////////////////////// 4 | // 5 | // Signed Distance Function (or Field) rendering 6 | 7 | // frees the SDF bitmap allocated below 8 | //STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); 9 | 10 | //STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); 11 | 12 | // These functions compute a discretized SDF field for a single character, suitable for storing 13 | // in a single-channel texture, sampling with bilinear filtering, and testing against 14 | // larger than some threshold to produce scalable fonts. 15 | // info -- the font 16 | // scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap 17 | // glyph/codepoint -- the character to generate the SDF for 18 | // padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), 19 | // which allows effects like bit outlines 20 | // onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) 21 | // pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) 22 | // if positive, > onedge_value is inside; if negative, < onedge_value is inside 23 | // width,height -- output height & width of the SDF bitmap (including padding) 24 | // xoff,yoff -- output origin of the character 25 | // return value -- a 2D array of bytes 0..255, width*height in size 26 | // 27 | // pixel_dist_scale & onedge_value are a scale & bias that allows you to make 28 | // optimal use of the limited 0..255 for your application, trading off precision 29 | // and special effects. SDF values outside the range 0..255 are clamped to 0..255. 30 | // 31 | // Example: 32 | // scale = stbtt_ScaleForPixelHeight(22) 33 | // padding = 5 34 | // onedge_value = 180 35 | // pixel_dist_scale = 180/5.0 = 36.0 36 | // 37 | // This will create an SDF bitmap in which the character is about 22 pixels 38 | // high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled 39 | // shape, sample the SDF at each pixel and fill the pixel if the SDF value 40 | // is greater than or equal to 180/255. (You'll actually want to antialias, 41 | // which is beyond the scope of this example.) Additionally, you can compute 42 | // offset outlines (e.g. to stroke the character border inside & outside, 43 | // or only outside). For example, to fill outside the character up to 3 SDF 44 | // pixels, you would compare against (180-36.0*3)/255 = 72/255. The above 45 | // choice of variables maps a range from 5 pixels outside the shape to 46 | // 2 pixels inside the shape to 0..255; this is intended primarily for apply 47 | // outside effects only (the interior range is needed to allow proper 48 | // antialiasing of the font at *smaller* sizes) 49 | // 50 | // The function computes the SDF analytically at each SDF pixel, not by e.g. 51 | // building a higher-res bitmap and approximating it. In theory the quality 52 | // should be as high as possible for an SDF of this size & representation, but 53 | // unclear if this is true in practice (perhaps building a higher-res bitmap 54 | // and computing from that can allow drop-out prevention). 55 | // 56 | // The algorithm has not been optimized at all, so expect it to be slow 57 | // if computing lots of characters or very large sizes. 58 | //STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); 59 | -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/stb_/texture baking api.kt: -------------------------------------------------------------------------------- 1 | package imgui.stb_ 2 | 3 | ////////////////////////////////////////////////////////////////////////////// 4 | // 5 | // TEXTURE BAKING API 6 | // 7 | // If you use this API, you only have to call two functions ever. 8 | // 9 | 10 | // typedef struct 11 | // { 12 | // unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap 13 | // float xoff,yoff,xadvance; 14 | // } stbtt_bakedchar; 15 | // 16 | // STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) 17 | // float pixel_height, // height of font in pixels 18 | // unsigned char *pixels, int pw, int ph, // bitmap to be filled in 19 | // int first_char, int num_chars, // characters to bake 20 | // stbtt_bakedchar *chardata); // you allocate this, it's num_chars long 21 | // if return is positive, the first unused row of the bitmap 22 | // if return is negative, returns the negative of the number of characters that fit 23 | // if return is 0, no characters fit and no rows were used 24 | // This uses a very crappy packing. 25 | 26 | class AlignedQuad { 27 | 28 | // top-left 29 | 30 | var x0 = 0f 31 | var y0 = 0f 32 | var s0 = 0f 33 | var t0 = 0f 34 | 35 | // bottom-right 36 | 37 | var x1 = 0f 38 | var y1 = 0f 39 | var s1 = 0f 40 | var t1 = 0f 41 | } 42 | 43 | // STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above 44 | // int char_index, // character to display 45 | // float *xpos, float *ypos, // pointers to current position in screen pixel space 46 | // stbtt_aligned_quad *q, // output: quad to draw 47 | // int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier 48 | // Call GetBakedQuad with char_index = 'character - first_char', and it 49 | // creates the quad you need to draw and advances the current position. 50 | // 51 | // The coordinate system used assumes y increases downwards. 52 | // 53 | // Characters will extend both above and below the current position; 54 | // see discussion of "BASELINE" above. 55 | // 56 | // It's inefficient; you might want to c&p it and optimize it. 57 | // 58 | // STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); 59 | //// Query the font vertical metrics without having to create a font first. -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/stb_/util.kt: -------------------------------------------------------------------------------- 1 | package imgui.stb_ 2 | 3 | import glm_.b 4 | import glm_.i 5 | import kool.lim 6 | import kool.pos 7 | import java.nio.ByteBuffer 8 | 9 | class PtrChar(val array: CharArray, var offset: Int = 0) { 10 | 11 | operator fun get(index: Int): Char = array[offset + index] 12 | operator fun set(index: Int, char: Char) { 13 | array[offset + index] = char 14 | } 15 | 16 | operator fun plus(offset: Int) = PtrChar(array, this.offset + offset) 17 | } 18 | 19 | class PString(val array: CharSequence, var offset: Int = 0) { 20 | 21 | operator fun get(index: Int): Char = array[offset + index] 22 | 23 | val isValid: Boolean 24 | get() = offset in array.indices 25 | 26 | operator fun minus(int: Int): Int = array[offset].i - int 27 | 28 | operator fun invoke(): Char = array[offset] 29 | 30 | fun next() { 31 | offset++ 32 | } 33 | } 34 | 35 | fun PtrByte(size: Int) = PtrByte(ByteArray(size)) 36 | 37 | class PtrByte(val array: ByteArray, var offset: Int = 0) { 38 | 39 | operator fun get(index: Int): Byte = array[offset + index] 40 | operator fun set(index: Int, byte: Byte) { 41 | array[offset + index] = byte 42 | } 43 | 44 | operator fun plus(offset: Int) = PtrByte(array, this.offset + offset) 45 | 46 | fun fill(int: Int, num: Int) { 47 | for (i in 0 until num) 48 | set(i, int.b) 49 | } 50 | } 51 | 52 | fun PtrFloat(size: Int) = PtrFloat(FloatArray(size)) 53 | 54 | class PtrFloat(val array: FloatArray, var offset: Int = 0) { 55 | 56 | operator fun get(index: Int): Float = array[offset + index] 57 | operator fun set(index: Int, float: Float) { 58 | array[offset + index] = float 59 | } 60 | 61 | operator fun plus(offset: Int) = PtrFloat(array, this.offset + offset) 62 | operator fun minus(offset: Int) = PtrFloat(array, this.offset - offset) 63 | 64 | fun fill(float: Float, num: Int) { 65 | for (i in 0 until num) 66 | set(i, float) 67 | } 68 | } 69 | 70 | fun ByteBuffer.sliceAt(offset: Int, size: Int = lim - offset): ByteBuffer { 71 | val backup = pos 72 | pos = offset 73 | return slice().also { 74 | pos = backup 75 | it.lim = size 76 | } 77 | } 78 | 79 | internal val Int.ub get() = toUByte() 80 | internal val Int.us get() = toUShort() 81 | internal val Int.ui get() = toUInt() 82 | internal val UByte.i get() = toInt() 83 | internal val UByte.f get() = toFloat() 84 | internal val UByte.us get() = toUShort() 85 | internal val UByte.ui get() = toUInt() 86 | internal val UByte.ul get() = toULong() 87 | internal infix fun UByte.has(i: Int) = and(i.toUByte()).i != 0 88 | internal infix fun UByte.hasnt(i: Int) = !has(i) 89 | internal val UInt.f get() = toFloat() 90 | internal val UInt.ub get() = toUByte() 91 | internal val UInt.us get() = toUShort() 92 | internal val UInt.ul get() = toULong() 93 | internal val UInt.i get() = toInt() 94 | internal val UShort.i get() = toInt() 95 | internal val UShort.ui get() = toUInt() 96 | internal val ULong.i get() = toInt() 97 | internal val ULong.ui get() = toUInt() 98 | //internal infix fun UByte.shl(i: Int) = toInt().shl(i).toUInt() 99 | internal infix fun UShort.shr(i: Int) = toUInt().shr(i).toUShort() 100 | -------------------------------------------------------------------------------- /core/src/main/kotlin/imgui/viewport.kt: -------------------------------------------------------------------------------- 1 | package imgui 2 | 3 | import com.livefront.sealedenum.GenSealedEnum 4 | import glm_.vec2.Vec2 5 | import imgui.classes.DrawList 6 | import imgui.internal.sections.ViewportP 7 | 8 | //----------------------------------------------------------------------------- 9 | // [SECTION] Viewports 10 | //----------------------------------------------------------------------------- 11 | 12 | typealias ViewportFlags = Flag 13 | 14 | /** Flags stored in ImGuiViewport::Flags, giving indications to the platform backends. */ 15 | sealed class ViewportFlag : FlagBase() { 16 | /** Represent a Platform Window */ 17 | object IsPlatformWindow : ViewportFlag() 18 | 19 | /** Represent a Platform Monitor (unused yet) */ 20 | object IsPlatformMonitor : ViewportFlag() 21 | 22 | /** Platform Window: is created/managed by the application (rather than a dear imgui backend) */ 23 | object OwnedByApp : ViewportFlag() 24 | 25 | override val i: Int = 1 shl ordinal 26 | 27 | @GenSealedEnum 28 | companion object 29 | } 30 | 31 | // - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows. 32 | // - In 'docking' branch with multi-viewport enabled, we extend this concept to have multiple active viewports. 33 | // - In the future we will extend this concept further to also represent Platform Monitor and support a "no main platform window" operation mode. 34 | // - About Main Area vs Work Area: 35 | // - Main Area = entire viewport. 36 | // - Work Area = entire viewport minus sections used by main menu bars (for platform windows), or by task bar (for platform monitor). 37 | // - Windows are generally trying to stay within the Work Area of their host viewport. 38 | open class Viewport { 39 | /** See ImGuiViewportFlags_ */ 40 | var flags: ViewportFlags = none 41 | 42 | /** Main Area: Position of the viewport (Dear ImGui coordinates are the same as OS desktop/native coordinates) */ 43 | val pos = Vec2() 44 | 45 | /** Main Area: Size of the viewport. */ 46 | val size = Vec2() 47 | 48 | /** Work Area: Position of the viewport minus task bars, menus bars, status bars (>= Pos) */ 49 | val workPos = Vec2() 50 | 51 | /** Work Area: Size of the viewport minus task bars, menu bars, status bars (<= Size) */ 52 | val workSize = Vec2() 53 | 54 | /** Platform/Backend Dependent Data 55 | * 56 | * void* to hold lower-level, platform-native window handle (under Win32 this is expected to be a HWND, unused for other platforms) */ 57 | var platformHandleRaw: Any? = null 58 | 59 | // Helpers 60 | val center: Vec2 61 | get() = Vec2(pos.x + size.x * 0.5f, pos.y + size.y * 0.5f) 62 | 63 | val workCenter: Vec2 64 | get() = Vec2(workPos.x + workSize.x * 0.5f, workPos.y + workSize.y * 0.5f) 65 | 66 | /** !GetBackgroundDrawList(ImGuiViewport* viewport) 67 | * get background draw list for the given viewport. this draw list will be the first rendering one. Useful to quickly draw shapes/text behind dear imgui contents. 68 | */ 69 | val backgroundDrawList: DrawList 70 | get() = (this as ViewportP).getDrawList(0, "##Background") 71 | 72 | /** get foreground draw list for the given viewport. this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents. */ 73 | val foregroundDrawList: DrawList 74 | get() = (this as ViewportP).getDrawList(1, "##Foreground") 75 | } 76 | 77 | //----------------------------------------------------------------------------- 78 | // [SECTION] Platform Dependent Interfaces 79 | //----------------------------------------------------------------------------- 80 | 81 | /** (Optional) Support for IME (Input Method Editor) via the io.SetPlatformImeDataFn() function. */ 82 | data class PlatformImeData( 83 | /** A widget wants the IME to be visible */ 84 | var wantVisible: Boolean = false, 85 | /** Position of the input cursor */ 86 | val inputPos: Vec2 = Vec2(), 87 | /** Line height */ 88 | var inputLineHeight: Float = 0f) { 89 | 90 | constructor(data: PlatformImeData) : this(data.wantVisible, Vec2(data.inputPos), data.inputLineHeight) 91 | } -------------------------------------------------------------------------------- /core/src/main/kotlin/java/lang/helpers.kt: -------------------------------------------------------------------------------- 1 | //package java.lang 2 | // 3 | //import glm_.b 4 | //import sun.nio.cs.ArrayDecoder 5 | //import sun.nio.cs.HistoricallyNamedCharset 6 | //import java.lang.String.* 7 | //import java.nio.ByteBuffer 8 | //import java.nio.CharBuffer 9 | //import java.nio.charset.Charset 10 | //import java.nio.charset.CodingErrorAction 11 | //import java.util.* 12 | //import kotlin.Byte 13 | //import kotlin.String 14 | // 15 | //class Result { 16 | // var value: ByteArray? = null 17 | // var coder = 0.b 18 | // 19 | // fun with(): Result { 20 | // coder = if(COMPACT_STRINGS) LATIN1 else UTF16 21 | // value = ByteArray(0) 22 | // return this 23 | // } 24 | // 25 | // fun with(value: CharArray, off: Int, len: Int): Result { 26 | // if (COMPACT_STRINGS) { 27 | // val bs = StringUTF16.compress(value, off, len) 28 | // if (bs != null) { 29 | // this.value = bs 30 | // coder = LATIN1 31 | // return this 32 | // } 33 | // } 34 | // coder = UTF16 35 | // this.value = StringUTF16.toBytes(value, off, len) 36 | // return this 37 | // } 38 | // 39 | // fun with(value: ByteArray, coder: Byte): Result { 40 | // this.coder = coder 41 | // this.value = value 42 | // return this 43 | // } 44 | //} 45 | // 46 | //class StringDecoder(val cs: Charset, val requestedCharsetName: String) { 47 | // val cd = cs.newDecoder() 48 | // .onMalformedInput(CodingErrorAction.REPLACE) 49 | // .onUnmappableCharacter(CodingErrorAction.REPLACE) 50 | // val isASCIICompatible = cd is ArrayDecoder && cd.isASCIICompatible() 51 | // 52 | // val result = Result() 53 | // 54 | // val charsetName 55 | // get() = (cs as? HistoricallyNamedCharset).historicalName() ?: cs.name() 56 | // 57 | // @ExperimentalStdlibApi 58 | // fun decode(ba: ByteArray, off: Int, len: Int): Result { 59 | // if (len == 0) return result.with() 60 | // // fastpath for ascii compatible 61 | // if (isASCIICompatible && !ba.hasNegatives(off, len)) { 62 | // return when { 63 | // COMPACT_STRINGS -> result.with(ba.copyOfRange(off, off + len), LATIN1) 64 | // else -> result.with(StringLatin1.inflate(ba, off, len), UTF16) 65 | // } 66 | // } 67 | // val en = scale(len, cd.maxCharsPerByte()); 68 | // val ca = CharArray(en) 69 | // if (cd is ArrayDecoder) { 70 | // val clen = cd.decode(ba, off, len, ca) 71 | // return result.with(ca, 0, clen) 72 | // } 73 | // cd.reset() 74 | // val bb = ByteBuffer.wrap(ba, off, len) 75 | // val cb = CharBuffer.wrap(ca); 76 | // try { 77 | // var cr = cd.decode(bb, cb, true) 78 | // if (!cr.isUnderflow) 79 | // cr.throwException() 80 | // cr = cd.flush(cb); 81 | // if (!cr.isUnderflow) 82 | // cr.throwException() 83 | // } catch (x: CharacterCodingException) { 84 | // // Substitution is always enabled, 85 | // // so this shouldn't happen 86 | // throw Error(x) 87 | // } 88 | // return result.with(ca, 0, cb.position()) 89 | // } 90 | //} -------------------------------------------------------------------------------- /core/src/main/kotlin/java/lang/sc.kt: -------------------------------------------------------------------------------- 1 | //package java.lang 2 | // 3 | //import glm_.d 4 | //import java.lang.ref.SoftReference 5 | //import java.nio.charset.Charset 6 | //import kotlin.Float 7 | // 8 | ///** The cached coders for each thread */ 9 | //val decoder = ThreadLocal>() 10 | ////val encoder = ThreadLocal>() 11 | // 12 | //val ThreadLocal>.deref: T? 13 | // get() = get()?.get() 14 | // 15 | //infix fun ThreadLocal>.set(ob: T) = set(SoftReference(ob)) 16 | // 17 | //// Trim the given byte array to the given length 18 | //fun ByteArray.safeTrim(len: Int, isTrusted: Boolean): ByteArray = when { 19 | // len == size && (isTrusted || System.getSecurityManager() == null) -> this 20 | // else -> copyOf(len) 21 | //} 22 | // 23 | //// We need to perform double, not float, arithmetic; otherwise 24 | //// we lose low order bits when len is larger than 2**24. 25 | //fun scale(len: Int, expansionFactor: Float) = (len * expansionFactor.d).i 26 | // 27 | //val kotlin.String.charset: Charset? 28 | // get() = when { 29 | // Charset.isSupported(this) -> Charset.forName(this) 30 | // else -> null 31 | // } 32 | // 33 | // 34 | ////@HotSpotIntrinsicCandidate 35 | //fun ByteArray.hasNegatives(off: Int, len: Int): kotlin.Boolean { 36 | // for (i in off until off + len) 37 | // if (this[i] < 0) 38 | // return true 39 | // return false 40 | //} 41 | // 42 | ////@ExperimentalStdlibApi 43 | ////fun decode(charsetName: String, ba: ByteArray, off: Int, len: Int): Result{ 44 | //// var sd = decoder.deref 45 | //// val csn = charsetName ?: "ISO-8859-1" 46 | //// if (sd == null || !(csn == sd.requestedCharsetName || csn == sd.charsetName)) { 47 | //// sd = null 48 | //// when(val cs = csn.charset) { 49 | //// Charsets.UTF_8 -> return decodeUTF8(ba, off, len, true) 50 | //// Charsets.ISO_8859_1 -> return decodeLatin1(ba, off, len) 51 | //// Charsets.US_ASCII -> return decodeASCII(ba, off, len) 52 | //// sd = StringDecoder(cs, csn) 53 | //// } 54 | //// if (sd == null) 55 | //// throw UnsupportedEncodingException(csn) 56 | //// decoder.set(sd) 57 | //// } 58 | //// return sd.decode(ba, off, len) 59 | ////} -------------------------------------------------------------------------------- /core/src/main/kotlin/kotlin/internal/Annotations.kt: -------------------------------------------------------------------------------- 1 | package kotlin.internal 2 | 3 | /** 4 | * Specifies that the corresponding type should be ignored during type inference. 5 | */ 6 | @Target(AnnotationTarget.TYPE) 7 | @Retention(AnnotationRetention.BINARY) 8 | internal annotation class NoInfer -------------------------------------------------------------------------------- /core/src/main/kotlin/module-info: -------------------------------------------------------------------------------- 1 | module kotlin.graphics.imgui.core { 2 | 3 | requires java.desktop; 4 | requires jdk.jdi; 5 | 6 | requires kotlin.stdlib; 7 | 8 | requires kotlin.graphics.uno.core; 9 | requires kotlin.graphics.gli; 10 | requires kotlin.graphics.glm; 11 | requires kotlin.graphics.kool; 12 | requires kotlin.graphics.unsigned; 13 | 14 | requires org.lwjgl; 15 | requires org.lwjgl.stb; 16 | // requires annotations; 17 | requires java.logging; 18 | 19 | exports imgui.api; 20 | exports imgui.classes; 21 | exports imgui.internal.classes; // TODO remove me https://sormuras.github.io/blog/2018-09-11-testing-in-the-modular-world.html 22 | exports imgui.demo.showExampleApp; 23 | exports imgui.demo; 24 | exports imgui.font; 25 | exports imgui.impl; 26 | exports imgui.internal; 27 | exports imgui; 28 | exports imgui.stb; 29 | exports imgui.windowsIme; 30 | } -------------------------------------------------------------------------------- /core/src/main/resources/fonts/ArialUni.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/core/src/main/resources/fonts/ArialUni.TTF -------------------------------------------------------------------------------- /core/src/main/resources/fonts/Cousine-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/core/src/main/resources/fonts/Cousine-Regular.ttf -------------------------------------------------------------------------------- /core/src/main/resources/fonts/DroidSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/core/src/main/resources/fonts/DroidSans.ttf -------------------------------------------------------------------------------- /core/src/main/resources/fonts/Karla-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/core/src/main/resources/fonts/Karla-Regular.ttf -------------------------------------------------------------------------------- /core/src/main/resources/fonts/ProggyClean.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/core/src/main/resources/fonts/ProggyClean.ttf -------------------------------------------------------------------------------- /core/src/main/resources/fonts/ProggyTiny.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/core/src/main/resources/fonts/ProggyTiny.ttf -------------------------------------------------------------------------------- /core/src/test/kotlin/fontAtlasTest.kt: -------------------------------------------------------------------------------- 1 | import com.aayushatharva.brotli4j.Brotli4jLoader 2 | import com.aayushatharva.brotli4j.decoder.Decoder 3 | import com.aayushatharva.brotli4j.decoder.DecoderJNI 4 | import glm_.i 5 | import imgui.font.FontAtlas 6 | import imgui.font.decode 7 | import kool.indices 8 | import java.math.BigInteger 9 | import kotlin.test.Test 10 | 11 | class fontAtlasTest { 12 | 13 | @Test 14 | fun `glyph backing`() { 15 | 16 | val atlas = FontAtlas() 17 | atlas.build() 18 | 19 | Brotli4jLoader.ensureAvailability() 20 | 21 | val range = (0xD7FF + 1 - 0x0000) + (0xFFFF + 1 - 0xE000) + (Char.MAX_HIGH_SURROGATE.i + 1 - Char.MIN_SURROGATE.i) * (Char.MAX_SURROGATE.i + 1 - Char.MIN_LOW_SURROGATE.i) 22 | var value = BigInteger.ZERO 23 | var i = 0 24 | while (i < encodedCompressedTexPixelsAlpha8.length) { 25 | val s = when (val c = encodedCompressedTexPixelsAlpha8[i++]) { 26 | in Char.MIN_SURROGATE..Char.MAX_SURROGATE -> c.toString() + encodedCompressedTexPixelsAlpha8[i++] 27 | else -> c.toString() 28 | } 29 | value = value * range.toBigInteger() + decode(s).toBigInteger() 30 | } 31 | 32 | val texPixelsAlpha8 = Decoder.decompress(value.toByteArray()).run { 33 | check(resultStatus == DecoderJNI.Status.DONE) 34 | decompressedData 35 | } 36 | 37 | for (j in atlas.texPixelsAlpha8!!.indices) { 38 | if (texPixelsAlpha8[j] != atlas.texPixelsAlpha8!![j]) 39 | error("at $j, ${texPixelsAlpha8[j]} != " + atlas.texPixelsAlpha8!![j]) 40 | } 41 | // for (i in atlas.texPixelsAlpha8!!.indices step 8) { 42 | // val a = atlas.texPixelsAlpha8!![i].toLong() and 0xFF 43 | // val b = atlas.texPixelsAlpha8!![i + 1].toLong() and 0xFF 44 | // val c = atlas.texPixelsAlpha8!![i + 2].toLong() and 0xFF 45 | // val d = atlas.texPixelsAlpha8!![i + 3].toLong() and 0xFF 46 | // val e = atlas.texPixelsAlpha8!![i + 4].toLong() and 0xFF 47 | // val f = atlas.texPixelsAlpha8!![i + 5].toLong() and 0xFF 48 | // val g = atlas.texPixelsAlpha8!![i + 6].toLong() and 0xFF 49 | // val h = atlas.texPixelsAlpha8!![i + 7].toLong() and 0xFF 50 | // val long = (h shl 56) or (g shl 48) or (f shl 40) or (e shl 32) or (d shl 24) or (c shl 16) or (b shl 8) or a 51 | //// println("[${i / 8}] $long") 52 | // if (texPixelsAlpha8[i / 8] != long) 53 | // System.err.println("at ${i / 8}, ${texPixelsAlpha8[i / 8]} != " + long) 54 | // } 55 | } 56 | 57 | // ## Test ImFontAtlas clearing of input data (#4455, #3487) 58 | @Test 59 | fun `clearing of input data`() { 60 | 61 | val atlas = FontAtlas() 62 | atlas.build() 63 | atlas.isBuilt `should be` true 64 | 65 | atlas.clearTexData() 66 | atlas.isBuilt `should be` true 67 | 68 | atlas.clearInputData() 69 | atlas.fonts.size `should be greater than` 0 70 | // #if IMGUI_VERSION_NUM > 18407 71 | atlas.isBuilt `should be` true 72 | // #endif 73 | 74 | atlas.clearFonts() 75 | atlas.fonts.size `should be` 0 76 | atlas.isBuilt `should be` false 77 | 78 | atlas.build() // Build after clear 79 | atlas.build() // Build too many times 80 | } 81 | 82 | companion object { 83 | val encodedCompressedTexPixelsAlpha8 = " 񩣝񺐷𺗨🩐ힰ𴃑💨𝏤󮸌񆣒񝠚󶷓򈍨󐠐𯲴󴪡񊌯󯮓򶿱񦕞򷫊󳞐󺏧𢕍򚘜򙗬󊆈򞖙󷂌𣉆󶱩𞴹򙙱򎰄𮵋󄑩򢒊񏐆򥥼󋂊𡣒򴮭󷃛಍򑅉𓙏񚁾񡜰򎵘򛤉𚘤񲚎󴞻򠄥ﺼ򮴯𢻛󰘖𚻐񸮁񫥽򁝿𨂞񭶤𛉊񽝓򂴶󰿎𶨇񟷴򩉾󃖆𢑹ퟻ񪐗󘴽󓧩򗹫󜕩𮀒񤧤񫜛񘵟🌅񔷢􇔽󞱎򯼐𮷻񮻉򌀪񖧝񭘐򼙛򣺏񐛞򷈶󓉿󣒏䜯󞳪􇲰񧩨𒢈𭲨󷔵𾿐򞖵򴆦𞜉񥇐嚺􆍒򈴋򛇱񮍳󸝐򫷜𾋌𴄝򇖟󕑵󞝡򌩵񁷒󵁖󉙀󧂊􉿠񋟐쌊򮖓򡍑񲘬愆웊𸍶󽳿􀀲񯾑ز򰌳󂱂񫤊󤩮򨹈􀙷񇸑񒧚򸕭𔘖򹡸𚕬񕈞򅃾򝦋񡁌򈱪𠮝󍻑񥵋𜹏񞯴􂱚򌋬򛺦񀁓걦򀬠򻫴񰮞򄫱󓊰򬃥𲵩򌔙򢪅򮸽􌖺񞉀󷫺򅇚񿭅񨂘󇝝񭢨򣆃񯅝􀱤򶇇򔇮􆀋󰰔􄉤􁄧󙱽򃕼񲂋􅊜򭺪󖙿𣬹􆝼鿼􎙹󲏧󼳁󓻮򏽑룥񰘽򄅶򺞙𮱧𨿝缧򭶻𷣁򅂱𵜳򐆲񙹇񵼄􇵘𱾤󶂓񋨳󼿝񻃚󖶝疂󔜌󲹧𬟖󬐆󋨐򪍕𖥳󩜢򚦕󷬌񼻃󽉺󡞛𽻘󛆻򻨌𜸍񘇾򿿺뮋󰠒񨲌ﲷ󍈮󜋎뿅򶡻𓯯䤨󆤗񗊅􁦷󿞯󦴩򡒉򋬉񌌹󿬍񹇷񷥩򭠶򢹑񗭋񂢝񾬡󐏔󰉽񙠤󪧧󘟳񧭎󵶬𨯵󺐝򍬛쇁􋟋񍞼盂󨳯𬃾񂎰򔣓񭩩󈠆򄳥򮋑𔮼𤷁󿷌𵅶𖙵򝬳񛕎󷇬򔰧􆻜噹󩰋󡿖򦛘񔳗𚍞򅪥񨾴򍬨󔓒󉔍𞁓🧅󁁛􉀛򯦔𻈁󜏪򪸅󽩝􏌃󧾮򒞋򈫩𹤤󟲵󪘍걘򪀢򻼢񓸬򥊖󉱍򋍶񈠡񵵞𓜻񧩽򐈫닮񇏙󛀘򡨤򻧨򾧢񤕱򿪬񲑍󊅪𛟝𜾡ᤵ󹤾𽶕򧾁񇆵򀰞񊚲󫂛򏡝󓇹󭽤򄷯𦼐𘖚򞑫𥁡񑤗񷫣񳈈񊸹򓓰󈗲𸂏󡭖𩨇묋𨭘񋻲󥖎􃏓𖛧񗊄䦥𹩺񏟅񼢣Ѷ򩃖󰔷􀑄􇋼􊲣򢰽򽠅񀘺𹏱򊮁󱽁򏙴󜂦󗼚󸭦𨟚𐁬󄫮𺻉󨧾񯵅񐪁􋛭낵􂻼󸚔󪌑􀋚򪆴񤝡򲭃򼎖􁉢𧩀򌕼񦩠󗎔򰲂𴶈𾜫𲺱󯀪󫏪񡩔⪪񣓐򴇉𒉐񶋄򉡮𼴌𧍉񽌔򎋀󅭉򯼍󘐧񨏝𽈑𱠧򤑍⠌񁎇񾼣摉񟌂󈆱拚󚭫󍫢񕪥򐁏󒍴󈙘򟍠󕳛󣤂򯫅􏞲󮯑󛤡󹺷񹮎󀌤򥜬􂄼񎜌󳈾񈘮򭯞󷯅𿭨󇖘󊦄񠄠󑟃񝐨󌕝򴩙񫓀𴣎񽎅𲅕򎗶񕙭񬌵񺔺𮢹񁟅􊟞򲿉󊺞󚄽𚿖󔓒񸗝񷽤𓭷򶩕𗌸􊵠񧏜򷘢򃹇򿇻򏩿򯏲𩩻𱌉򮁣񈩣򲏧򞵨𛬛𝠪񩈷񛟸󠹘󣓽񡦚⦄𕙮򅧏񚆂𰓸񫭢󟼉󒾾󬱶𸡿󿈂򹎈񈨜򊙭񣋍󏴥򷁤𺻜򭏏񧖤毉󌞮򻖱򈾂򷝖󽈽󙌷򊫪𚏅􇷡񺦈⺷񥙸񠗟񓹈򍏢􀃦兣񑳜񕛽𷭪򁜳򥨏򐶽񅇼󷘮򃧫󥙙󔭀򮕋򿟉𥸽󄄀󬩮򲪽󨲻񲤕񶯧򙞃񵑶󒚲󿻋󾕚򬩞򏘤󰒶ឋ𢼂񢾫򉪍񲾅񛅾𥎅𝴄󫈳񽰐򃳩󺅴񾒒򧽵𛄞𰞛򤬃󐬋졇􏓜󃁔󈢠𔩁󞆏󅲽򜳳⍡񽴰񟲝񶁦􌢛𽅃􈩻񹄿򘼲񾕽󆶌󜐇󜫼򓑠򖄎񷩈񻪸𽒏𗲒񗆽񤐣󔹓󋚵𰠑󭫄𿃋󖦇򓄨񠲄񉚨񜿛󾀂񥨯򝮮􀔥𪃈񜄖񲃗󛁃򘗈򌊄𧿙󵤃򗿟򌞴򣚙ꠔ􇮊󰕀𬠷񌟹񹡭񥬾󩊕𠡗񧙌󷴜򌡭򶈞񫱨󚻤󄡨󜬑񶐻󰾢񄲜􂵑򽯨񊄛󑩄󑸼󍍵􂌁" 84 | } 85 | } -------------------------------------------------------------------------------- /core/src/test/kotlin/util.kt: -------------------------------------------------------------------------------- 1 | infix fun T.`should be`(v: T) = assert(this == v) 2 | infix fun > T.`should be greater than`(v: T) = assert(this > v) -------------------------------------------------------------------------------- /gl/gl.gradle.kts: -------------------------------------------------------------------------------- 1 | import magik.createGithubPublication 2 | import magik.github 3 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask 4 | import org.lwjgl.lwjgl 5 | import org.lwjgl.Lwjgl.Module.* 6 | 7 | plugins { 8 | kotlin("jvm") 9 | id("org.lwjgl.plugin") 10 | id("elect86.magik") 11 | `maven-publish` 12 | } 13 | 14 | group = rootProject.group 15 | version = rootProject.version 16 | 17 | dependencies { 18 | implementation(kotlin("stdlib-jdk8")) 19 | implementation(kotlin("reflect")) 20 | 21 | implementation(projects.core) 22 | implementation(projects.glfw) 23 | 24 | api("kotlin.graphics:uno:0.7.21") 25 | lwjgl { implementation(jemalloc, glfw, opengl, remotery, stb) } 26 | 27 | testImplementation("com.github.ajalt:mordant:1.2.1") 28 | testImplementation("io.kotest:kotest-runner-junit5:5.5.5") 29 | testImplementation("io.kotest:kotest-assertions-core:5.5.5") 30 | } 31 | 32 | kotlin.jvmToolchain { languageVersion.set(JavaLanguageVersion.of(8)) } 33 | 34 | tasks { 35 | withType>().configureEach { compilerOptions.freeCompilerArgs.addAll("-opt-in=kotlin.RequiresOptIn", "-Xallow-kotlin-package") } 36 | test { useJUnitPlatform() } 37 | } 38 | 39 | publishing { 40 | publications { 41 | createGithubPublication { 42 | from(components["java"]) 43 | artifactId = "${rootProject.name}-${project.name}" 44 | suppressAllPomMetadataWarnings() 45 | } 46 | } 47 | repositories.github { domain = "kotlin-graphics/mary" } 48 | } 49 | 50 | java.withSourcesJar() -------------------------------------------------------------------------------- /gl/src/main/java/module-info: -------------------------------------------------------------------------------- 1 | module kotlin.graphics.imgui.gl { 2 | 3 | requires java.desktop; 4 | 5 | requires kotlin.stdlib; 6 | 7 | requires kotlin.graphics.imgui.core; 8 | requires kotlin.graphics.imgui.glfw; 9 | requires kotlin.graphics.uno.core; 10 | requires kotlin.graphics.glm; 11 | requires kotlin.graphics.gln; 12 | requires kotlin.graphics.kool; 13 | requires kotlin.graphics.unsigned; 14 | 15 | requires org.lwjgl.opengl; 16 | requires org.lwjgl.glfw; 17 | 18 | exports imgui.impl.gl; 19 | } -------------------------------------------------------------------------------- /gl/src/main/kotlin/imgui/impl/gl/GLInterface.kt: -------------------------------------------------------------------------------- 1 | package imgui.impl.gl 2 | 3 | import imgui.internal.DrawData 4 | 5 | interface GLInterface { 6 | 7 | fun shutdown() 8 | fun newFrame() 9 | fun renderDrawData(drawData: DrawData) 10 | 11 | // Called by Init/NewFrame/Shutdown 12 | fun createFontsTexture(): Boolean 13 | fun destroyFontsTexture() 14 | fun createDeviceObjects(): Boolean 15 | fun destroyDeviceObjects() 16 | } -------------------------------------------------------------------------------- /gl/src/main/kotlin/imgui/impl/gl/ImplBestGL.kt: -------------------------------------------------------------------------------- 1 | package imgui.impl.gl 2 | 3 | import org.lwjgl.opengl.GL 4 | import org.lwjgl.system.Platform 5 | 6 | class ImplBestGL: GLInterface by getNewImpl() { 7 | companion object { 8 | private val caps = GL.getCapabilities() 9 | private fun getNewImpl(): GLInterface { 10 | TODO() 11 | // return when { 12 | // caps.OpenGL32 -> { 13 | // glslVersion = 150 14 | // ImplGL3() 15 | // } 16 | // caps.OpenGL30 && Platform.get() != Platform.MACOSX -> { 17 | // glslVersion = 130 18 | // ImplGL3() 19 | // } 20 | // caps.OpenGL20 -> { 21 | // glslVersion = 110 22 | // if (Platform.get() == Platform.MACOSX) ImplGL2_mac() else ImplGL2() 23 | // } 24 | // else -> throw RuntimeException("OpenGL 2 is not present on this system!") 25 | // } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /gl/src/test/resources/fonts/NotoSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/gl/src/test/resources/fonts/NotoSans-Regular.ttf -------------------------------------------------------------------------------- /gl/src/test/resources/fonts/NotoSansMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/gl/src/test/resources/fonts/NotoSansMono-Regular.ttf -------------------------------------------------------------------------------- /gl/src/test/resources/fonts/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/gl/src/test/resources/fonts/Roboto-Medium.ttf -------------------------------------------------------------------------------- /gl/src/test/resources/fonts/fa5-regular-400.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/gl/src/test/resources/fonts/fa5-regular-400.otf -------------------------------------------------------------------------------- /gl/src/test/resources/fonts/fa5-solid-900.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/gl/src/test/resources/fonts/fa5-solid-900.otf -------------------------------------------------------------------------------- /gl/src/test/resources/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/gl/src/test/resources/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /glfw/glfw.gradle.kts: -------------------------------------------------------------------------------- 1 | import magik.createGithubPublication 2 | import magik.github 3 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask 4 | import org.lwjgl.lwjgl 5 | import org.lwjgl.Lwjgl.Module.* 6 | 7 | plugins { 8 | kotlin("jvm") 9 | id("org.lwjgl.plugin") 10 | id("elect86.magik") 11 | `maven-publish` 12 | } 13 | 14 | group = rootProject.group 15 | version = rootProject.version 16 | 17 | dependencies { 18 | implementation(kotlin("reflect")) 19 | 20 | implementation(projects.core) 21 | 22 | api("kotlin.graphics:uno:0.7.21") 23 | lwjgl { implementation(glfw, opengl, remotery) } 24 | 25 | testImplementation("io.kotest:kotest-runner-junit5:5.5.5") 26 | testImplementation("io.kotest:kotest-assertions-core:5.5.5") 27 | } 28 | 29 | kotlin.jvmToolchain { languageVersion.set(JavaLanguageVersion.of(8)) } 30 | 31 | tasks { 32 | withType>().configureEach { compilerOptions.freeCompilerArgs.addAll("-opt-in=kotlin.RequiresOptIn", "-Xallow-kotlin-package") } 33 | test { useJUnitPlatform() } 34 | } 35 | 36 | publishing { 37 | publications { 38 | createGithubPublication { 39 | from(components["java"]) 40 | artifactId = "${rootProject.name}-${project.name}" 41 | suppressAllPomMetadataWarnings() 42 | } 43 | } 44 | repositories.github { domain = "kotlin-graphics/mary" } 45 | } 46 | 47 | java.withSourcesJar() -------------------------------------------------------------------------------- /glfw/src/main/java/module-info: -------------------------------------------------------------------------------- 1 | module kotlin.graphics.imgui.glfw { 2 | 3 | requires kotlin.stdlib; 4 | 5 | requires kotlin.graphics.imgui.core; 6 | requires kotlin.graphics.uno.core; 7 | requires kotlin.graphics.glm; 8 | requires kotlin.graphics.kool; 9 | 10 | requires org.lwjgl.glfw; 11 | 12 | exports imgui.impl.glfw; 13 | } -------------------------------------------------------------------------------- /glfw/src/main/kotlin/imgui/impl/glfw/wndProc hook.kt: -------------------------------------------------------------------------------- 1 | package imgui.impl.glfw 2 | 3 | import imgui.ImGui 4 | import imgui.MouseSource 5 | import org.lwjgl.system.* 6 | import org.lwjgl.system.libffi.FFICIF 7 | import org.lwjgl.system.libffi.LibFFI 8 | import org.lwjgl.system.windows.User32 9 | 10 | typealias WNDPROC = Long 11 | typealias LPARAM = Long 12 | 13 | // GLFW doesn't allow to distinguish Mouse vs TouchScreen vs Pen. 14 | // Add support for Win32 (based on imgui_impl_win32), because we rely on _TouchScreen info to trickle inputs differently. 15 | val mouseSourceFromMessageExtraInfo: MouseSource 16 | get() { 17 | val extraInfo: LPARAM = User32.GetMessageExtraInfo() 18 | return when { 19 | (extraInfo and 0xFFFFFF80) == 0xFF515700 -> MouseSource.Pen 20 | (extraInfo and 0xFFFFFF80) == 0xFF515780 -> MouseSource.TouchScreen 21 | else -> MouseSource.Mouse 22 | } 23 | } 24 | 25 | //static LRESULT CALLBACK ImGui_ImplGlfw_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 26 | //{ 27 | // ImGui_ImplGlfw_Data * bd = ImGui_ImplGlfw_GetBackendData() 28 | // switch(msg) 29 | // { 30 | // case WM_MOUSEMOVE : case WM_NCMOUSEMOVE: 31 | // case WM_LBUTTONDOWN : case WM_LBUTTONDBLCLK: case WM_LBUTTONUP: 32 | // case WM_RBUTTONDOWN : case WM_RBUTTONDBLCLK: case WM_RBUTTONUP: 33 | // case WM_MBUTTONDOWN : case WM_MBUTTONDBLCLK: case WM_MBUTTONUP: 34 | // case WM_XBUTTONDOWN : case WM_XBUTTONDBLCLK: case WM_XBUTTONUP: 35 | // ImGui::GetIO().AddMouseSourceEvent(GetMouseSourceFromMessageExtraInfo()) 36 | // break 37 | // } 38 | // return ::CallWindowProc(bd->GlfwWndProc, hWnd, msg, wParam, lParam) 39 | //} 40 | 41 | /** 42 | * Instances of this interface may be passed to the [SetWindowFocusCallback][GLFW.glfwSetWindowFocusCallback] method. 43 | * 44 | *

Type

45 | * 46 | *
`
47 |  * void (*[.invoke]) (
48 |  * GLFWwindow *window,
49 |  * int focused
50 |  * )`
51 | * 52 | * @since version 3.0 53 | */ 54 | @FunctionalInterface 55 | @NativeType("ImplGlfw_WndProc") 56 | interface ImplGlfw_WndProcI : CallbackI { 57 | override fun getCallInterface(): FFICIF = CIF 58 | 59 | override fun callback(ret: Long, args: Long) { 60 | invoke(MemoryUtil.memGetAddress(MemoryUtil.memGetAddress(args)), 61 | MemoryUtil.memGetInt(MemoryUtil.memGetAddress(args + Pointer.POINTER_SIZE)) != 0) 62 | } 63 | 64 | /** 65 | * Will be called when the specified window gains or loses focus. 66 | * 67 | * @param window the window that was focused or defocused 68 | * @param focused [TRUE][GLFW.GLFW_TRUE] if the window was focused, or [FALSE][GLFW.GLFW_FALSE] if it was defocused 69 | */ 70 | operator fun invoke(@NativeType("GLFWwindow *") window: Long, @NativeType("int") focused: Boolean) 71 | 72 | companion object { 73 | val CIF = APIUtil.apiCreateCIF( 74 | LibFFI.FFI_DEFAULT_ABI, 75 | LibFFI.ffi_type_void, 76 | LibFFI.ffi_type_uint32, LibFFI.ffi_type_uint32, LibFFI.ffi_type_uint32, LibFFI.ffi_type_uint32 77 | ) 78 | } 79 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-XX:MaxMetaspaceSize=1g 2 | org.gradle.daemon=false 3 | systemProp.alignVerbose=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | zipStoreBase=GRADLE_USER_HOME 3 | zipStorePath=wrapper/dists 4 | distributionPath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip 6 | distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /imgui.ini: -------------------------------------------------------------------------------- 1 | [Window][Debug##Default] 2 | Pos=60,60 3 | Size=400,400 4 | Collapsed=0 5 | 6 | [Window][Hello, world!] 7 | Pos=60,60 8 | Size=339,197 9 | Collapsed=0 10 | 11 | [Window][Dear ImGui Demo] 12 | Pos=650,20 13 | Size=550,680 14 | Collapsed=0 15 | 16 | [Window][Example: Custom rendering] 17 | Pos=60,60 18 | Size=485,414 19 | Collapsed=0 20 | 21 | -------------------------------------------------------------------------------- /imgui_perflog.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/imgui/665b1032094c4f342a4306c0d3adcc944d87d0e7/imgui_perflog.csv -------------------------------------------------------------------------------- /jogl/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id "org.jetbrains.kotlin.jvm" 4 | id "com.github.johnrengelman.shadow" 5 | } 6 | 7 | ext.moduleName = "$group.jogl" 8 | 9 | dependencies { 10 | // implementation "$kot-stdlib-jdk8" 11 | // implementation project(':core') 12 | // implementation "${kx}.glm:glm:$glm_version" 13 | // implementation "$kx:uno-sdk:$uno_version" 14 | // implementation "$kx:gln:$gln_version" 15 | // implementation "$kx:kool:$kool_version" 16 | 17 | def joglVersion = '2.3.2' 18 | implementation "org.jogamp.gluegen:gluegen-rt-main:$joglVersion" 19 | implementation "org.jogamp.jogl:jogl-all-main:$joglVersion" 20 | 21 | [""].each { 22 | // String base = "org.lwjgl:lwjgl$it:$lwjgl_version" 23 | // implementation base 24 | // String natives = "$base:natives-$lwjgl_natives" 25 | // testRuntimeOnly natives 26 | // shadow natives 27 | } 28 | 29 | testImplementation group: 'junit', name: 'junit', version: '4.12' 30 | } 31 | 32 | task lightJar(type: Jar) { 33 | archiveClassifier = 'light' 34 | from sourceSets.main.output 35 | exclude 'extraFonts' 36 | inputs.property("moduleName", moduleName) 37 | // manifest.attributes('Automatic-Module-Name': moduleName) 38 | duplicatesStrategy = DuplicatesStrategy.EXCLUDE 39 | } 40 | 41 | task sourcesJar(type: Jar, dependsOn: classes) { 42 | archiveClassifier = 'sources' 43 | from sourceSets.main.allSource 44 | } 45 | 46 | task javadocJar(type: Jar, dependsOn: javadoc) { 47 | archiveClassifier = 'javadoc' 48 | from javadoc.destinationDir 49 | } 50 | 51 | artifacts { 52 | archives lightJar 53 | archives sourcesJar 54 | // archives javadocJar 55 | } 56 | 57 | shadowJar { 58 | exclude 'module-info.class' 59 | inputs.property("moduleName", moduleName) 60 | // manifest.attributes('Automatic-Module-Name': moduleName) 61 | } 62 | 63 | jar { 64 | inputs.property("moduleName", moduleName) 65 | // manifest.attributes('Automatic-Module-Name': moduleName) 66 | } 67 | 68 | shadowJar.archiveClassifier = 'all' 69 | 70 | compileKotlin { 71 | kotlinOptions.jvmTarget = "11" 72 | destinationDir = compileJava.destinationDir 73 | } 74 | compileTestKotlin { 75 | kotlinOptions.jvmTarget = "11" 76 | destinationDir = compileTestJava.destinationDir 77 | } 78 | 79 | compileJava { 80 | dependsOn(':compileKotlin') 81 | inputs.property("moduleName", moduleName) 82 | doFirst { 83 | options.compilerArgs = [ 84 | '--module-path', classpath.asPath, 85 | '--patch-module', "$moduleName=${sourceSets["main"].output.asPath}"] 86 | classpath = files() 87 | } 88 | } 89 | 90 | jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE } -------------------------------------------------------------------------------- /jogl/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module com.github.kotlin_graphics.imgui_jogl { 2 | 3 | requires kotlin.stdlib; 4 | 5 | requires jogl.all; 6 | requires org.lwjgl; 7 | 8 | requires com.github.kotlin_graphics.glm; 9 | requires com.github.kotlin_graphics.gln; 10 | requires com.github.kotlin_graphics.kool; 11 | } -------------------------------------------------------------------------------- /openjfx/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module kotlin.graphics.imgui.openjfx { 2 | 3 | requires javafx.graphics; 4 | 5 | requires kotlin.stdlib; 6 | 7 | requires kotlin.graphics.imgui.core; 8 | requires kotlin.graphics.glm; 9 | } -------------------------------------------------------------------------------- /openjfx/src/main/kotlin/imgui/impl/OpenJFXDummyMain.kt: -------------------------------------------------------------------------------- 1 | package imgui.impl 2 | 3 | import javafx.application.Application 4 | import javafx.stage.Stage 5 | import kotlin.system.exitProcess 6 | 7 | class OpenJFXDummyMain: Application() { 8 | override fun start(primaryStage: Stage?) { exitProcess(0) } 9 | } -------------------------------------------------------------------------------- /platform/platform.gradle.kts: -------------------------------------------------------------------------------- 1 | 2 | plugins { 3 | `java-platform` 4 | } 5 | 6 | dependencies { 7 | // The platform declares constraints on all components that require alignment 8 | constraints { 9 | api(projects.core) 10 | api(projects.gl) 11 | api(projects.glfw) 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | 2 | pluginManagement { 3 | repositories { 4 | gradlePluginPortal() 5 | // maven("https://raw.githubusercontent.com/kotlin-graphics/mary/master") 6 | // maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev/") 7 | } 8 | // includeBuild("../build-logic") 9 | } 10 | 11 | rootProject.name = "imgui" 12 | 13 | for(module in listOf("core", "glfw", "gl"/*,"vk", "jogl",*//* "openjfx"*//*, "bgfx"*/, "platform")) { 14 | include(module) 15 | project(":$module").buildFileName = "$module.gradle.kts" 16 | } 17 | 18 | //enableFeaturePreview("VERSION_CATALOGS") 19 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") 20 | 21 | gradle.rootProject { 22 | group = "kotlin.graphics" 23 | version = "1.89.7-1" 24 | } 25 | 26 | dependencyResolutionManagement { 27 | repositories { 28 | mavenCentral() 29 | maven("https://raw.githubusercontent.com/kotlin-graphics/mary/master") 30 | maven(url = "https://jitpack.io") // still needed for sealed-enums 31 | } 32 | } -------------------------------------------------------------------------------- /vk/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module kotlin.graphics.imgui.vk { 2 | 3 | requires kotlin.stdlib; 4 | 5 | requires org.lwjgl; 6 | requires org.lwjgl.glfw; 7 | requires org.lwjgl.vulkan; 8 | 9 | requires kotlin.graphics.imgui.core; 10 | requires kotlin.graphics.imgui.glfw; 11 | 12 | requires kotlin.graphics.glm; 13 | requires kotlin.graphics.kool; 14 | requires kotlin.graphics.vkk; 15 | requires kotlin.graphics.gli; 16 | requires kotlin.graphics.uno.core; 17 | requires kotlin.graphics.uno.vk; 18 | } -------------------------------------------------------------------------------- /vk/src/main/kotlin/imgui/impl/vk/tmp.kt: -------------------------------------------------------------------------------- 1 | package imgui.impl.vk 2 | 3 | import kool.Ptr 4 | import org.lwjgl.system.MemoryStack 5 | import org.lwjgl.system.MemoryUtil 6 | import vkk.* 7 | import vkk.entities.* 8 | import vkk.extensions.VkColorSpaceKHR 9 | import vkk.identifiers.CommandBuffer 10 | import vkk.identifiers.Device 11 | import vkk.vk10.structs.* 12 | 13 | // glfw -> T : MemoryStack (for VkStack) 14 | // inline fun loop(block: (MemoryStack) -> Unit) = loop({ isOpen }, block) 15 | 16 | // enum for all reports flags --------------------------------------------------------------------------------