├── .appveyor.yml ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .gitmodules ├── 3rd └── dear-imgui │ ├── LICENSE.txt │ ├── bgfx_utils.h │ ├── imconfig.h │ ├── imgui.cpp │ ├── imgui.h │ ├── imgui │ ├── droidsans.ttf.h │ ├── fs_imgui_image.bin.h │ ├── fs_imgui_image.sc │ ├── fs_ocornut_imgui.bin.h │ ├── fs_ocornut_imgui.sc │ ├── icons_font_awesome.ttf.h │ ├── icons_kenney.ttf.h │ ├── imgui.cpp │ ├── imgui.h │ ├── makefile │ ├── roboto_regular.ttf.h │ ├── robotomono_regular.ttf.h │ ├── varying.def.sc │ ├── vs_imgui_image.bin.h │ ├── vs_imgui_image.sc │ ├── vs_ocornut_imgui.bin.h │ └── vs_ocornut_imgui.sc │ ├── imgui_demo.cpp │ ├── imgui_draw.cpp │ ├── imgui_internal.h │ ├── imgui_tables.cpp │ ├── imgui_user.h │ ├── imgui_user.inl │ ├── imgui_widgets.cpp │ ├── imstb_rectpack.h │ ├── imstb_textedit.h │ ├── imstb_truetype.h │ └── widgets │ ├── color_picker.h │ ├── color_picker.inl │ ├── color_wheel.h │ ├── color_wheel.inl │ ├── dock.h │ ├── dock.inl │ ├── file_list.h │ ├── file_list.inl │ ├── gizmo.h │ ├── gizmo.inl │ ├── markdown.h │ ├── markdown.inl │ ├── memory_editor.h │ ├── range_slider.h │ └── range_slider.inl ├── LICENSE ├── README.md ├── genie ├── genie.lua └── rapp.lua ├── img ├── input_debug.png └── rapp_configs.png ├── inc ├── rapp.h └── widgets │ ├── keyboard.h │ ├── numpad_debug.h │ └── widget_theme.h ├── makefile ├── samples ├── 01_cmd_line │ ├── cmd_line.cpp │ ├── cmd_line_pch.cpp │ └── cmd_line_pch.h ├── 02_job_system │ ├── job_system.cpp │ ├── job_system_pch.cpp │ └── job_system_pch.h ├── 03_bgfx │ ├── bgfx.cpp │ ├── bgfx_pch.cpp │ └── bgfx_pch.h ├── 04_multi_app │ ├── multi_app_1.cpp │ ├── multi_app_2.cpp │ ├── multi_app_3.cpp │ ├── multi_app_pch.cpp │ └── multi_app_pch.h ├── 05_rprof │ ├── rprof.cpp │ ├── rprof_pch.cpp │ └── rprof_pch.h └── rapp.html ├── scripts ├── lin_fetch_dependencies.sh ├── lin_generate_project.sh ├── osx_fetch_dependencies.sh ├── osx_generate_project.sh ├── win_fetch_dependencies.bat └── win_generate_project.bat └── src ├── app_data.h ├── cmd.cpp ├── cmd.h ├── console.cpp ├── console.h ├── dbg.cpp ├── entry.cpp ├── entry_android.cpp ├── entry_html5.cpp ├── entry_ios.mm ├── entry_osx.mm ├── entry_p.h ├── entry_ps4.cpp ├── entry_windows.cpp ├── entry_winrt.cxx ├── entry_x11.cpp ├── entry_xb1.cpp ├── input.cpp ├── input.h ├── job.cpp ├── job.h ├── rapp.cpp ├── rapp_config.h ├── rapp_pch.cpp ├── rapp_pch.h ├── rapp_timer.h ├── rapp_vg.cpp └── widgets └── numpad_debug.cpp /.appveyor.yml: -------------------------------------------------------------------------------- 1 | 2 | environment: 3 | matrix: 4 | - job_name: Windows 5 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 6 | configuration: Debug 7 | 8 | - job_name: Windows 9 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 10 | configuration: Release 11 | 12 | - job_name: Windows 13 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 14 | configuration: Retail 15 | 16 | - job_name: Linux 17 | APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2204 18 | buildcfg: debug64 19 | 20 | - job_name: Linux 21 | APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2204 22 | buildcfg: release64 23 | 24 | - job_name: Linux 25 | APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2204 26 | buildcfg: retail64 27 | 28 | - job_name: OSX 29 | APPVEYOR_BUILD_WORKER_IMAGE: macOS-sonoma 30 | buildcfg: debug64 31 | 32 | - job_name: OSX 33 | APPVEYOR_BUILD_WORKER_IMAGE: macOS-sonoma 34 | buildcfg: release64 35 | 36 | - job_name: OSX 37 | APPVEYOR_BUILD_WORKER_IMAGE: macOS-sonoma 38 | buildcfg: retail64 39 | 40 | shallow_clone: true 41 | 42 | for: 43 | 44 | # ====================================== 45 | # Windows 46 | # ====================================== 47 | 48 | - 49 | matrix: 50 | only: 51 | - job_name: Windows 52 | 53 | init: 54 | - git clone --recursive https://github.com/RudjiGames/rapp rapp 55 | - git clone --depth 1 https://github.com/RudjiGames/build build 56 | - git clone --depth 1 https://github.com/RudjiGames/rbase rbase 57 | - git clone --depth 1 https://github.com/bkaradzic/bx.git bx 58 | - git clone --depth 1 https://github.com/bkaradzic/bimg.git bimg 59 | - git clone --depth 1 https://github.com/bkaradzic/bgfx.git bgfx 60 | 61 | install: 62 | - build\tools\bin\windows\genie.exe --file=rapp\genie\genie.lua vs2022 63 | 64 | build: ../.build/windows/vs2022/rapp/projects/rapp.sln 65 | 66 | # ====================================== 67 | # Linux 68 | # ====================================== 69 | 70 | - 71 | matrix: 72 | only: 73 | - job_name: Linux 74 | 75 | init: 76 | - sudo apt-get update --allow-releaseinfo-change && sudo apt install -y xorg libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libegl1-mesa-dev libx11-dev 77 | - git clone --recursive https://github.com/RudjiGames/rapp rapp 78 | - git clone --depth 1 https://github.com/RudjiGames/build build 79 | - git clone --depth 1 https://github.com/RudjiGames/rbase rbase 80 | - git clone --depth 1 https://github.com/bkaradzic/bx bx 81 | - git clone --depth 1 https://github.com/bkaradzic/bimg bimg 82 | - git clone --depth 1 https://github.com/bkaradzic/bgfx bgfx 83 | - git clone --depth 1 https://github.com/glfw/glfw glfw 84 | - git clone --depth 1 https://github.com/bkaradzic/GENie GENie # build GENie from source: `GLIBC_2.29' not found 85 | - cd GENie && make && cd .. 86 | - mkdir glfwbuild && cd glfwbuild && cmake ../glfw -DGLFW_BUILD_TESTS=OFF && make -j4 && sudo make install && cd .. 87 | 88 | install: 89 | - ./GENie/bin/linux/genie --file=rapp/genie/genie.lua --gcc=linux-gcc gmake 90 | 91 | build_script: 92 | - cd ./.build/linux/linux-gcc/rapp/projects/ 93 | - make config=${buildcfg} 94 | 95 | # ====================================== 96 | # OSX 97 | # ====================================== 98 | 99 | - 100 | matrix: 101 | only: 102 | - job_name: OSX 103 | 104 | init: 105 | - git clone --recursive https://github.com/RudjiGames/rapp rapp 106 | - git clone --depth 1 https://github.com/RudjiGames/build build 107 | - git clone --depth 1 https://github.com/RudjiGames/rbase rbase 108 | - git clone --depth 1 https://github.com/bkaradzic/bx.git bx 109 | - git clone --depth 1 https://github.com/bkaradzic/bimg.git bimg 110 | - git clone --depth 1 https://github.com/bkaradzic/bgfx.git bgfx 111 | - git clone --depth 1 https://github.com/bkaradzic/GENie GENie # build GENie from source: we don't know the target CPU, can't use ARM binary from 'build' 112 | - cd GENie && make && cd .. 113 | 114 | install: 115 | - ./GENie/bin/darwin/genie --file=rapp/genie/genie.lua --gcc=osx-x64 gmake 116 | 117 | build_script: 118 | - cd ./.build/osx/clang/rapp/projects/ 119 | - make config=${buildcfg} 120 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | indent_size = 4 6 | end_of_line = lf 7 | max_line_length = 150 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | max_line_length = 80 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.c eol=lf 2 | *.cpp eol=lf 3 | *.h eol=lf 4 | *.hpp eol=lf 5 | *.hlsl eol=lf 6 | *.md eol=lf 7 | *.lua eol=lf 8 | *.mk eol=lf 9 | makefile eol=lf 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .build 2 | .DS_Store 3 | 4 | 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "3rd/nanovg"] 2 | path = 3rd/nanovg 3 | url = https://github.com/memononen/nanovg.git 4 | branch = master 5 | [submodule "3rd/enkiTS"] 6 | path = 3rd/enkiTS 7 | url = https://github.com/dougbinks/enkiTS.git 8 | [submodule "3rd/vg_renderer"] 9 | path = 3rd/vg_renderer 10 | url = https://github.com/RudjiGames/vg_renderer.git 11 | -------------------------------------------------------------------------------- /3rd/dear-imgui/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2022 Omar Cornut 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 | -------------------------------------------------------------------------------- /3rd/dear-imgui/bgfx_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2025 Branimir Karadzic. All rights reserved. 3 | * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE 4 | */ 5 | 6 | #ifndef BGFX_UTILS_H_HEADER_GUARD 7 | #define BGFX_UTILS_H_HEADER_GUARD 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | namespace stl = tinystl; 18 | 19 | 20 | /// 21 | void* load(const bx::FilePath& _filePath, uint32_t* _size = NULL); 22 | 23 | /// 24 | void unload(void* _ptr); 25 | 26 | /// 27 | bgfx::ShaderHandle loadShader(const bx::StringView& _name); 28 | 29 | /// 30 | bgfx::ProgramHandle loadProgram(const bx::StringView& _vsName, const bx::StringView& _fsName); 31 | 32 | /// 33 | bgfx::TextureHandle loadTexture(const bx::FilePath& _filePath, uint64_t _flags = BGFX_TEXTURE_NONE|BGFX_SAMPLER_NONE, uint8_t _skip = 0, bgfx::TextureInfo* _info = NULL, bimg::Orientation::Enum* _orientation = NULL); 34 | 35 | /// 36 | bimg::ImageContainer* imageLoad(const bx::FilePath& _filePath, bgfx::TextureFormat::Enum _dstFormat); 37 | 38 | /// 39 | void calcTangents(void* _vertices, uint16_t _numVertices, bgfx::VertexLayout _layout, const uint16_t* _indices, uint32_t _numIndices); 40 | 41 | /// Returns true if both internal transient index and vertex buffer have 42 | /// enough space. 43 | /// 44 | /// @param[in] _numVertices Number of vertices. 45 | /// @param[in] _layout Vertex layout. 46 | /// @param[in] _numIndices Number of indices. 47 | /// 48 | inline bool checkAvailTransientBuffers(uint32_t _numVertices, const bgfx::VertexLayout& _layout, uint32_t _numIndices) 49 | { 50 | return _numVertices == bgfx::getAvailTransientVertexBuffer(_numVertices, _layout) 51 | && (0 == _numIndices || _numIndices == bgfx::getAvailTransientIndexBuffer(_numIndices) ) 52 | ; 53 | } 54 | 55 | /// 56 | inline uint32_t encodeNormalRgba8(float _x, float _y = 0.0f, float _z = 0.0f, float _w = 0.0f) 57 | { 58 | const float src[] = 59 | { 60 | _x * 0.5f + 0.5f, 61 | _y * 0.5f + 0.5f, 62 | _z * 0.5f + 0.5f, 63 | _w * 0.5f + 0.5f, 64 | }; 65 | uint32_t dst; 66 | bx::packRgba8(&dst, src); 67 | return dst; 68 | } 69 | 70 | /// 71 | struct MeshState 72 | { 73 | struct Texture 74 | { 75 | uint32_t m_flags; 76 | bgfx::UniformHandle m_sampler; 77 | bgfx::TextureHandle m_texture; 78 | uint8_t m_stage; 79 | }; 80 | 81 | Texture m_textures[4]; 82 | uint64_t m_state; 83 | bgfx::ProgramHandle m_program; 84 | uint8_t m_numTextures; 85 | bgfx::ViewId m_viewId; 86 | }; 87 | 88 | struct Primitive 89 | { 90 | uint32_t m_startIndex; 91 | uint32_t m_numIndices; 92 | uint32_t m_startVertex; 93 | uint32_t m_numVertices; 94 | 95 | bx::Sphere m_sphere; 96 | bx::Aabb m_aabb; 97 | bx::Obb m_obb; 98 | }; 99 | 100 | typedef stl::vector PrimitiveArray; 101 | 102 | struct Group 103 | { 104 | Group(); 105 | void reset(); 106 | 107 | bgfx::VertexBufferHandle m_vbh; 108 | bgfx::IndexBufferHandle m_ibh; 109 | uint16_t m_numVertices; 110 | uint8_t* m_vertices; 111 | uint32_t m_numIndices; 112 | uint16_t* m_indices; 113 | bx::Sphere m_sphere; 114 | bx::Aabb m_aabb; 115 | bx::Obb m_obb; 116 | PrimitiveArray m_prims; 117 | }; 118 | typedef stl::vector GroupArray; 119 | 120 | struct Mesh 121 | { 122 | void load(bx::ReaderSeekerI* _reader, bool _ramcopy); 123 | void unload(); 124 | void submit(bgfx::ViewId _id, bgfx::ProgramHandle _program, const float* _mtx, uint64_t _state) const; 125 | void submit(const MeshState*const* _state, uint8_t _numPasses, const float* _mtx, uint16_t _numMatrices) const; 126 | 127 | bgfx::VertexLayout m_layout; 128 | GroupArray m_groups; 129 | }; 130 | 131 | /// 132 | Mesh* meshLoad(const bx::FilePath& _filePath, bool _ramcopy = false); 133 | 134 | /// 135 | void meshUnload(Mesh* _mesh); 136 | 137 | /// 138 | MeshState* meshStateCreate(); 139 | 140 | /// 141 | void meshStateDestroy(MeshState* _meshState); 142 | 143 | /// 144 | void meshSubmit(const Mesh* _mesh, bgfx::ViewId _id, bgfx::ProgramHandle _program, const float* _mtx, uint64_t _state = BGFX_STATE_MASK); 145 | 146 | /// 147 | void meshSubmit(const Mesh* _mesh, const MeshState*const* _state, uint8_t _numPasses, const float* _mtx, uint16_t _numMatrices = 1); 148 | 149 | /// bgfx::RendererType::Enum to name. 150 | bx::StringView getName(bgfx::RendererType::Enum _type); 151 | 152 | /// Name to bgfx::RendererType::Enum. 153 | bgfx::RendererType::Enum getType(const bx::StringView& _name); 154 | 155 | /// 156 | struct Args 157 | { 158 | Args(int _argc, const char* const* _argv); 159 | 160 | bgfx::RendererType::Enum m_type; 161 | uint16_t m_pciId; 162 | }; 163 | 164 | #endif // BGFX_UTILS_H_HEADER_GUARD 165 | -------------------------------------------------------------------------------- /3rd/dear-imgui/imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // USER IMPLEMENTATION 3 | // This file contains compile-time options for ImGui. 4 | // Other options (memory allocation overrides, callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO(). 5 | //----------------------------------------------------------------------------- 6 | 7 | #pragma once 8 | 9 | #define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 10 | #define IMGUI_DISABLE_OBSOLETE_KEYIO 11 | #define IMGUI_DISABLE_DEFAULT_ALLOCATORS 12 | 13 | //---- Define your own ImVector<> type if you don't want to use the provided implementation defined in imgui.h 14 | //#include 15 | //#define ImVector std::vector 16 | //#define ImVector MyVector 17 | 18 | //---- Define assertion handler. Defaults to calling assert(). 19 | #include 20 | #define IM_ASSERT(_EXPR) assert(_EXPR) 21 | 22 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows. 23 | //#define IMGUI_API __declspec( dllexport ) 24 | //#define IMGUI_API __declspec( dllimport ) 25 | 26 | //---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions) 27 | #define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION 28 | #define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION 29 | 30 | //---- Include imgui_user.inl at the end of imgui.cpp so you can include code that extends ImGui using its private data/functions. 31 | #define IMGUI_INCLUDE_IMGUI_USER_INL 32 | 33 | //---- Include imgui_user.h at the end of imgui.h 34 | #define IMGUI_INCLUDE_IMGUI_USER_H 35 | 36 | //---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions) 37 | #define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS 38 | #define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS 39 | 40 | //---- Don't implement help and test window functionality (ShowUserGuide()/ShowStyleEditor()/ShowTestWindow() methods will be empty) 41 | //#define IMGUI_DISABLE_TEST_WINDOWS 42 | 43 | //---- Implement STB libraries in a namespace to avoid conflicts 44 | //#define IMGUI_STB_NAMESPACE ImStb 45 | 46 | //---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. 47 | /* 48 | #define IM_VEC2_CLASS_EXTRA \ 49 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ 50 | operator MyVec2() const { return MyVec2(x,y); } 51 | 52 | #define IM_VEC4_CLASS_EXTRA \ 53 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ 54 | operator MyVec4() const { return MyVec4(x,y,z,w); } 55 | */ 56 | 57 | //---- Freely implement extra functions within the ImGui:: namespace. 58 | //---- Declare helpers or widgets implemented in imgui_user.inl or elsewhere, so end-user doesn't need to include multiple files. 59 | //---- e.g. you can create variants of the ImGui::Value() helper for your low-level math types, or your own widgets/helpers. 60 | /* 61 | namespace ImGui 62 | { 63 | void Value(const char* prefix, const MyVec2& v, const char* float_format = NULL); 64 | void Value(const char* prefix, const MyVec4& v, const char* float_format = NULL); 65 | } 66 | */ 67 | 68 | -------------------------------------------------------------------------------- /3rd/dear-imgui/imgui/fs_imgui_image.sc: -------------------------------------------------------------------------------- 1 | $input v_texcoord0 2 | 3 | /* 4 | * Copyright 2014 Dario Manesku. All rights reserved. 5 | * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE 6 | */ 7 | 8 | #include 9 | 10 | uniform vec4 u_imageLodEnabled; 11 | SAMPLER2D(s_texColor, 0); 12 | 13 | #define u_imageLod u_imageLodEnabled.x 14 | #define u_imageEnabled u_imageLodEnabled.y 15 | 16 | void main() 17 | { 18 | vec3 color = texture2DLod(s_texColor, v_texcoord0, u_imageLod).xyz; 19 | float alpha = 0.2 + 0.8*u_imageEnabled; 20 | gl_FragColor = vec4(color, alpha); 21 | } 22 | -------------------------------------------------------------------------------- /3rd/dear-imgui/imgui/fs_ocornut_imgui.sc: -------------------------------------------------------------------------------- 1 | $input v_color0, v_texcoord0 2 | 3 | #include "../common.sh" 4 | 5 | SAMPLER2D(s_tex, 0); 6 | 7 | void main() 8 | { 9 | vec4 texel = texture2D(s_tex, v_texcoord0); 10 | gl_FragColor = texel * v_color0; 11 | } 12 | -------------------------------------------------------------------------------- /3rd/dear-imgui/imgui/imgui.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2025 Branimir Karadzic. All rights reserved. 3 | * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE 4 | */ 5 | 6 | #ifndef IMGUI_H_HEADER_GUARD 7 | #define IMGUI_H_HEADER_GUARD 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define IMGUI_MBUT_LEFT 0x01 15 | #define IMGUI_MBUT_RIGHT 0x02 16 | #define IMGUI_MBUT_MIDDLE 0x04 17 | 18 | inline uint32_t imguiRGBA(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a = 255) 19 | { 20 | return 0 21 | | (uint32_t(_r) << 0) 22 | | (uint32_t(_g) << 8) 23 | | (uint32_t(_b) << 16) 24 | | (uint32_t(_a) << 24) 25 | ; 26 | } 27 | 28 | namespace bx { struct AllocatorI; } 29 | 30 | void imguiCreate(float _fontSize = 18.0f, bx::AllocatorI* _allocator = NULL); 31 | void imguiDestroy(); 32 | 33 | void imguiBeginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, uint16_t _width, uint16_t _height, int _inputChar = -1, bgfx::ViewId _view = 255); 34 | void imguiEndFrame(); 35 | 36 | namespace entry { class AppI; } 37 | void showExampleDialog(entry::AppI* _app, const char* _errorText = NULL); 38 | 39 | namespace ImGui 40 | { 41 | #define IMGUI_FLAGS_NONE UINT8_C(0x00) 42 | #define IMGUI_FLAGS_ALPHA_BLEND UINT8_C(0x01) 43 | 44 | /// 45 | inline ImTextureID toId(bgfx::TextureHandle _handle, uint8_t _flags, uint8_t _mip) 46 | { 47 | union { struct { bgfx::TextureHandle handle; uint8_t flags; uint8_t mip; } s; ImTextureID id; } tex; 48 | tex.s.handle = _handle; 49 | tex.s.flags = _flags; 50 | tex.s.mip = _mip; 51 | return tex.id; 52 | } 53 | 54 | // Helper function for passing bgfx::TextureHandle to ImGui::Image. 55 | inline void Image(bgfx::TextureHandle _handle 56 | , uint8_t _flags 57 | , uint8_t _mip 58 | , const ImVec2& _size 59 | , const ImVec2& _uv0 = ImVec2(0.0f, 0.0f) 60 | , const ImVec2& _uv1 = ImVec2(1.0f, 1.0f) 61 | , const ImVec4& _tintCol = ImVec4(1.0f, 1.0f, 1.0f, 1.0f) 62 | , const ImVec4& _borderCol = ImVec4(0.0f, 0.0f, 0.0f, 0.0f) 63 | ) 64 | { 65 | ImageWithBg(toId(_handle, _flags, _mip), _size, _uv0, _uv1, _borderCol, _tintCol); 66 | } 67 | 68 | // Helper function for passing bgfx::TextureHandle to ImGui::Image. 69 | inline void Image(bgfx::TextureHandle _handle 70 | , const ImVec2& _size 71 | , const ImVec2& _uv0 = ImVec2(0.0f, 0.0f) 72 | , const ImVec2& _uv1 = ImVec2(1.0f, 1.0f) 73 | , const ImVec4& _tintCol = ImVec4(1.0f, 1.0f, 1.0f, 1.0f) 74 | , const ImVec4& _borderCol = ImVec4(0.0f, 0.0f, 0.0f, 0.0f) 75 | ) 76 | { 77 | Image(_handle, IMGUI_FLAGS_ALPHA_BLEND, 0, _size, _uv0, _uv1, _tintCol, _borderCol); 78 | } 79 | 80 | // Helper function for passing bgfx::TextureHandle to ImGui::ImageButton. 81 | inline bool ImageButton(bgfx::TextureHandle _handle 82 | , uint8_t _flags 83 | , uint8_t _mip 84 | , const ImVec2& _size 85 | , const ImVec2& _uv0 = ImVec2(0.0f, 0.0f) 86 | , const ImVec2& _uv1 = ImVec2(1.0f, 1.0f) 87 | , const ImVec4& _bgCol = ImVec4(0.0f, 0.0f, 0.0f, 0.0f) 88 | , const ImVec4& _tintCol = ImVec4(1.0f, 1.0f, 1.0f, 1.0f) 89 | ) 90 | { 91 | return ImageButton("image", toId(_handle, _flags, _mip), _size, _uv0, _uv1, _bgCol, _tintCol); 92 | } 93 | 94 | // Helper function for passing bgfx::TextureHandle to ImGui::ImageButton. 95 | inline bool ImageButton(bgfx::TextureHandle _handle 96 | , const ImVec2& _size 97 | , const ImVec2& _uv0 = ImVec2(0.0f, 0.0f) 98 | , const ImVec2& _uv1 = ImVec2(1.0f, 1.0f) 99 | , const ImVec4& _bgCol = ImVec4(0.0f, 0.0f, 0.0f, 0.0f) 100 | , const ImVec4& _tintCol = ImVec4(1.0f, 1.0f, 1.0f, 1.0f) 101 | ) 102 | { 103 | return ImageButton(_handle, IMGUI_FLAGS_ALPHA_BLEND, 0, _size, _uv0, _uv1, _bgCol, _tintCol); 104 | } 105 | 106 | /// 107 | inline void NextLine() 108 | { 109 | SetCursorPosY(GetCursorPosY() + GetTextLineHeightWithSpacing() ); 110 | } 111 | 112 | /// 113 | inline bool MouseOverArea() 114 | { 115 | return false 116 | || ImGui::IsAnyItemActive() 117 | || ImGui::IsAnyItemHovered() 118 | || ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow) 119 | // || ImGuizmo::IsOver() 120 | ; 121 | } 122 | 123 | /// 124 | void PushEnabled(bool _enabled); 125 | 126 | /// 127 | void PopEnabled(); 128 | 129 | } // namespace ImGui 130 | 131 | #endif // IMGUI_H_HEADER_GUARD 132 | -------------------------------------------------------------------------------- /3rd/dear-imgui/imgui/makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011-2025 Branimir Karadzic. All rights reserved. 3 | # License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE 4 | # 5 | 6 | include ../../../scripts/shader-embeded.mk 7 | 8 | droidsans.ttf.h: ../../runtime/font/droidsans.ttf 9 | @bin2c -f $(<) -o $(@) -n s_droidSansTtf 10 | 11 | roboto_regular.ttf.h: ../../runtime/font/roboto-regular.ttf 12 | @bin2c -f $(<) -o $(@) -n s_robotoRegularTtf 13 | 14 | robotomono_regular.ttf.h: ../../runtime/font/robotomono-regular.ttf 15 | @bin2c -f $(<) -o $(@) -n s_robotoMonoRegularTtf 16 | 17 | icons_font_awesome.ttf.h: ../../runtime/font/fontawesome-webfont.ttf 18 | @bin2c -f $(<) -o $(@) -n s_iconsFontAwesomeTtf 19 | 20 | icons_kenney.ttf.h: ../../runtime/font/kenney-icon-font.ttf 21 | @bin2c -f $(<) -o $(@) -n s_iconsKenneyTtf 22 | 23 | fonts: droidsans.ttf.h \ 24 | roboto_regular.ttf.h \ 25 | robotomono_regular.ttf.h \ 26 | icons_font_awesome.ttf.h \ 27 | icons_kenney.ttf.h 28 | 29 | rebuild: fonts 30 | @make -s --no-print-directory clean all 31 | -------------------------------------------------------------------------------- /3rd/dear-imgui/imgui/varying.def.sc: -------------------------------------------------------------------------------- 1 | vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0); 2 | vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0); 3 | 4 | vec2 a_position : POSITION; 5 | vec4 a_color0 : COLOR0; 6 | vec2 a_texcoord0 : TEXCOORD0; 7 | -------------------------------------------------------------------------------- /3rd/dear-imgui/imgui/vs_imgui_image.sc: -------------------------------------------------------------------------------- 1 | $input a_position, a_texcoord0 2 | $output v_texcoord0 3 | 4 | /* 5 | * Copyright 2014 Dario Manesku. All rights reserved. 6 | * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE 7 | */ 8 | 9 | #include 10 | 11 | void main() 12 | { 13 | gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0) ); 14 | v_texcoord0 = a_texcoord0; 15 | } 16 | -------------------------------------------------------------------------------- /3rd/dear-imgui/imgui/vs_ocornut_imgui.sc: -------------------------------------------------------------------------------- 1 | $input a_position, a_texcoord0, a_color0 2 | $output v_color0, v_texcoord0 3 | 4 | #include "../common.sh" 5 | 6 | void main() 7 | { 8 | vec4 pos = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0) ); 9 | gl_Position = vec4(pos.x, pos.y, 0.0, 1.0); 10 | v_texcoord0 = a_texcoord0; 11 | v_color0 = a_color0; 12 | } 13 | -------------------------------------------------------------------------------- /3rd/dear-imgui/imgui_user.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace ImGui 5 | { 6 | struct Font 7 | { 8 | enum Enum 9 | { 10 | Regular, 11 | Mono, 12 | 13 | Count 14 | }; 15 | }; 16 | 17 | void PushFont(Font::Enum _font); 18 | 19 | // BK - simple string class for convenience. 20 | class ImString 21 | { 22 | public: 23 | ImString(); 24 | ImString(const ImString& rhs); 25 | ImString(const char* rhs); 26 | ~ImString(); 27 | 28 | ImString& operator=(const ImString& rhs); 29 | ImString& operator=(const char* rhs); 30 | 31 | void Clear(); 32 | bool IsEmpty() const; 33 | 34 | const char* CStr() const 35 | { 36 | return NULL == Ptr ? "" : Ptr; 37 | } 38 | 39 | private: 40 | char* Ptr; 41 | }; 42 | 43 | } // namespace ImGui 44 | 45 | #include "widgets/color_picker.h" 46 | #include "widgets/color_wheel.h" 47 | #include "widgets/dock.h" 48 | #include "widgets/file_list.h" 49 | #include "widgets/gizmo.h" 50 | #include "widgets/markdown.h" 51 | #include "widgets/range_slider.h" 52 | -------------------------------------------------------------------------------- /3rd/dear-imgui/imgui_user.inl: -------------------------------------------------------------------------------- 1 | namespace ImGui 2 | { 3 | ImString::ImString() 4 | : Ptr(NULL) 5 | { 6 | } 7 | 8 | ImString::ImString(const ImString& rhs) 9 | : Ptr(NULL) 10 | { 11 | if (NULL != rhs.Ptr 12 | && 0 != strcmp(rhs.Ptr, "")) 13 | { 14 | Ptr = ImStrdup(rhs.Ptr); 15 | } 16 | } 17 | 18 | ImString::ImString(const char* rhs) 19 | : Ptr(NULL) 20 | { 21 | if (NULL != rhs 22 | && 0 != strcmp(rhs, "")) 23 | { 24 | Ptr = ImStrdup(rhs); 25 | } 26 | } 27 | 28 | ImString::~ImString() 29 | { 30 | Clear(); 31 | } 32 | 33 | ImString& ImString::operator=(const ImString& rhs) 34 | { 35 | if (this != &rhs) 36 | { 37 | *this = rhs.Ptr; 38 | } 39 | 40 | return *this; 41 | } 42 | 43 | ImString& ImString::operator=(const char* rhs) 44 | { 45 | if (Ptr != rhs) 46 | { 47 | Clear(); 48 | 49 | if (NULL != rhs 50 | && 0 != strcmp(rhs, "")) 51 | { 52 | Ptr = ImStrdup(rhs); 53 | } 54 | } 55 | 56 | return *this; 57 | } 58 | 59 | void ImString::Clear() 60 | { 61 | if (NULL != Ptr) 62 | { 63 | MemFree(Ptr); 64 | Ptr = NULL; 65 | } 66 | } 67 | 68 | bool ImString::IsEmpty() const 69 | { 70 | return NULL == Ptr; 71 | } 72 | } // namespace 73 | 74 | #include "widgets/color_picker.inl" 75 | #include "widgets/color_wheel.inl" 76 | #include "widgets/dock.inl" 77 | #include "widgets/file_list.inl" 78 | #include "widgets/gizmo.inl" 79 | #include "widgets/markdown.inl" 80 | #include "widgets/range_slider.inl" 81 | -------------------------------------------------------------------------------- /3rd/dear-imgui/imstb_rectpack.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /3rd/dear-imgui/imstb_textedit.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /3rd/dear-imgui/imstb_truetype.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /3rd/dear-imgui/widgets/color_picker.h: -------------------------------------------------------------------------------- 1 | namespace ImGui 2 | { 3 | bool ColorPicker4(float* col, bool show_alpha); 4 | bool ColorPicker3(float col[3]); 5 | 6 | inline bool ColorEdit4(const char* label, uint32_t* _rgba, bool show_alpha = true) 7 | { 8 | uint8_t* rgba = (uint8_t*)_rgba; 9 | float col[4] = 10 | { 11 | rgba[0]/255.0f, 12 | rgba[1]/255.0f, 13 | rgba[2]/255.0f, 14 | rgba[3]/255.0f, 15 | }; 16 | bool result = ColorEdit4(label, col, show_alpha); 17 | rgba[0] = uint8_t(col[0]*255.0f); 18 | rgba[1] = uint8_t(col[1]*255.0f); 19 | rgba[2] = uint8_t(col[2]*255.0f); 20 | rgba[3] = uint8_t(col[3]*255.0f); 21 | return result; 22 | } 23 | 24 | } // namespace ImGui 25 | -------------------------------------------------------------------------------- /3rd/dear-imgui/widgets/color_picker.inl: -------------------------------------------------------------------------------- 1 | // https://github.com/ocornut/imgui/issues/346#issuecomment-171961296 2 | // [src] https://github.com/ocornut/imgui/issues/346 3 | 4 | namespace ImGui 5 | { 6 | bool ColorPicker4(float* col, bool show_alpha) 7 | { 8 | ImGuiIO& io = ImGui::GetIO(); 9 | ImGuiStyle& style = ImGui::GetStyle(); 10 | ImDrawList* draw_list = ImGui::GetWindowDrawList(); 11 | 12 | // Setup 13 | ImVec2 picker_pos = ImGui::GetCursorScreenPos(); 14 | ImVec2 sv_picker_size = ImVec2(256.0f, 256.0f); // Saturation/Value picking box 15 | float bars_width = ImGui::GetFontSize() + style.FramePadding.y*2.0f; // Width of Hue/Alpha picking bars (using Framepadding.y to match the ColorButton sides) 16 | float bar0_pos_x = picker_pos.x + sv_picker_size.x + style.ItemInnerSpacing.x; 17 | float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x; 18 | 19 | float H,S,V; 20 | ImGui::ColorConvertRGBtoHSV(col[0], col[1], col[2], H, S, V); 21 | 22 | // Color matrix logic 23 | bool value_changed = false, hsv_changed = false; 24 | ImGui::BeginGroup(); 25 | ImGui::InvisibleButton("sv", sv_picker_size); 26 | if (ImGui::IsItemActive()) 27 | { 28 | S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size.x-1)); 29 | V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size.y-1)); 30 | value_changed = hsv_changed = true; 31 | } 32 | 33 | // Hue bar logic 34 | ImGui::SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y)); 35 | ImGui::InvisibleButton("hue", ImVec2(bars_width, sv_picker_size.y)); 36 | if (ImGui::IsItemActive()) 37 | { 38 | H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size.y-1)); 39 | value_changed = hsv_changed = true; 40 | } 41 | 42 | // Alpha bar logic 43 | if (show_alpha) 44 | { 45 | ImGui::SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y)); 46 | ImGui::InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size.y)); 47 | if (ImGui::IsItemActive()) 48 | { 49 | col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size.y-1)); 50 | value_changed = true; 51 | } 52 | } 53 | 54 | // Convert back to RGB 55 | if (hsv_changed) 56 | ImGui::ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10*1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]); 57 | 58 | // R,G,B or H,S,V color editor 59 | ImGui::PushItemWidth((show_alpha ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x); 60 | value_changed |= show_alpha ? ImGui::ColorEdit4("##edit", col) : ImGui::ColorEdit3("##edit", col); 61 | ImGui::PopItemWidth(); 62 | 63 | // Try to cancel hue wrap (after ColorEdit), if any 64 | if (value_changed) 65 | { 66 | float new_H, new_S, new_V; 67 | ImGui::ColorConvertRGBtoHSV(col[0], col[1], col[2], new_H, new_S, new_V); 68 | if (new_H <= 0 && H > 0) 69 | { 70 | if (new_V <= 0 && V != new_V) 71 | ImGui::ColorConvertHSVtoRGB(H, S, new_V <= 0 ? V * 0.5f : new_V, col[0], col[1], col[2]); 72 | else if (new_S <= 0) 73 | ImGui::ColorConvertHSVtoRGB(H, new_S <= 0 ? S * 0.5f : new_S, new_V, col[0], col[1], col[2]); 74 | } 75 | } 76 | 77 | // Render hue bar 78 | ImU32 hue_colors[] = { IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255), IM_COL32(0,255,255,255), IM_COL32(0,0,255,255), IM_COL32(255,0,255,255), IM_COL32(255,0,0,255) }; 79 | for (int i = 0; i < 6; ++i) 80 | { 81 | draw_list->AddRectFilledMultiColor( 82 | ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size.y / 6)), 83 | ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size.y / 6)), 84 | hue_colors[i], hue_colors[i], hue_colors[i + 1], hue_colors[i + 1]); 85 | } 86 | float bar0_line_y = (float)(int)(picker_pos.y + H * sv_picker_size.y + 0.5f); 87 | draw_list->AddLine(ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bar0_pos_x + bars_width + 1, bar0_line_y), IM_COL32_WHITE); 88 | 89 | // Render alpha bar 90 | if (show_alpha) 91 | { 92 | float alpha = ImSaturate(col[3]); 93 | float bar1_line_y = (float)(int)(picker_pos.y + (1.0f-alpha) * sv_picker_size.y + 0.5f); 94 | draw_list->AddRectFilledMultiColor(ImVec2(bar1_pos_x, picker_pos.y), ImVec2(bar1_pos_x + bars_width, picker_pos.y + sv_picker_size.y), IM_COL32_WHITE, IM_COL32_WHITE, IM_COL32_BLACK, IM_COL32_BLACK); 95 | draw_list->AddLine(ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bar1_pos_x + bars_width + 1, bar1_line_y), IM_COL32_WHITE); 96 | } 97 | 98 | // Render color matrix 99 | ImVec4 hue_color_f(1, 1, 1, 1); 100 | ImGui::ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z); 101 | ImU32 hue_color32 = ImGui::ColorConvertFloat4ToU32(hue_color_f); 102 | draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + sv_picker_size, IM_COL32_WHITE, hue_color32, hue_color32, IM_COL32_WHITE); 103 | draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + sv_picker_size, IM_COL32_BLACK_TRANS, IM_COL32_BLACK_TRANS, IM_COL32_BLACK, IM_COL32_BLACK); 104 | 105 | // Render cross-hair 106 | const float CROSSHAIR_SIZE = 7.0f; 107 | ImVec2 p((float)(int)(picker_pos.x + S * sv_picker_size.x + 0.5f), (float)(int)(picker_pos.y + (1 - V) * sv_picker_size.y + 0.5f)); 108 | draw_list->AddLine(ImVec2(p.x - CROSSHAIR_SIZE, p.y), ImVec2(p.x - 2, p.y), IM_COL32_WHITE); 109 | draw_list->AddLine(ImVec2(p.x + CROSSHAIR_SIZE, p.y), ImVec2(p.x + 2, p.y), IM_COL32_WHITE); 110 | draw_list->AddLine(ImVec2(p.x, p.y + CROSSHAIR_SIZE), ImVec2(p.x, p.y + 2), IM_COL32_WHITE); 111 | draw_list->AddLine(ImVec2(p.x, p.y - CROSSHAIR_SIZE), ImVec2(p.x, p.y - 2), IM_COL32_WHITE); 112 | ImGui::EndGroup(); 113 | 114 | return value_changed; 115 | } 116 | 117 | bool ColorPicker3(float col[3]) 118 | { 119 | return ColorPicker4(col, false); 120 | } 121 | 122 | } // namespace ImGui 123 | -------------------------------------------------------------------------------- /3rd/dear-imgui/widgets/color_wheel.h: -------------------------------------------------------------------------------- 1 | namespace ImGui 2 | { 3 | void ColorWheel(const char* _text, float* _rgba, float _size); 4 | 5 | void ColorWheel(const char* _text, uint32_t* _rgba, float _size); 6 | 7 | } // namespace ImGui 8 | -------------------------------------------------------------------------------- /3rd/dear-imgui/widgets/color_wheel.inl: -------------------------------------------------------------------------------- 1 | namespace ImGui 2 | { 3 | void ColorWheel(const char* _text, float* _rgba, float _size) 4 | { 5 | (void)_size; 6 | ColorEdit4(_text 7 | , _rgba, 0 8 | | ImGuiColorEditFlags_PickerHueWheel 9 | | ImGuiColorEditFlags_Float 10 | ); 11 | } 12 | 13 | inline void decodeRgba(float* _dst, const uint32_t* _src) 14 | { 15 | uint8_t* src = (uint8_t*)_src; 16 | _dst[0] = float(src[0] / 255.0f); 17 | _dst[1] = float(src[1] / 255.0f); 18 | _dst[2] = float(src[2] / 255.0f); 19 | _dst[3] = float(src[3] / 255.0f); 20 | } 21 | 22 | inline void encodeRgba(uint32_t* _dst, const float* _src) 23 | { 24 | uint8_t* dst = (uint8_t*)_dst; 25 | dst[0] = uint8_t(_src[0] * 255.0); 26 | dst[1] = uint8_t(_src[1] * 255.0); 27 | dst[2] = uint8_t(_src[2] * 255.0); 28 | dst[3] = uint8_t(_src[3] * 255.0); 29 | } 30 | 31 | void ColorWheel(const char* _text, uint32_t* _rgba, float _size) 32 | { 33 | float rgba[4]; 34 | decodeRgba(rgba, _rgba); 35 | ColorWheel(_text, rgba, _size); 36 | encodeRgba(_rgba, rgba); 37 | } 38 | 39 | } // namespace ImGui 40 | -------------------------------------------------------------------------------- /3rd/dear-imgui/widgets/dock.h: -------------------------------------------------------------------------------- 1 | namespace ImGui 2 | { 3 | /// 4 | IMGUI_API void InitDockContext(); 5 | 6 | /// 7 | IMGUI_API void ShutdownDockContext(); 8 | 9 | /// 10 | IMGUI_API void RootDock(const ImVec2& pos, const ImVec2& size); 11 | 12 | /// 13 | IMGUI_API bool BeginDock(const char* label, bool* opened = NULL, ImGuiWindowFlags extra_flags = 0); 14 | 15 | /// 16 | IMGUI_API void EndDock(); 17 | 18 | /// 19 | IMGUI_API void SetDockActive(); 20 | 21 | } // namespace ImGui 22 | -------------------------------------------------------------------------------- /3rd/dear-imgui/widgets/file_list.h: -------------------------------------------------------------------------------- 1 | namespace ImGui 2 | { 3 | struct ImFileInfo 4 | { 5 | ImFileInfo(const char* name, int64_t size); 6 | ~ImFileInfo(); 7 | 8 | ImString Name; 9 | int64_t Size; 10 | }; 11 | 12 | struct ImFileList 13 | { 14 | typedef ImVector FileInfoArray; 15 | FileInfoArray FileList; 16 | int Pos; 17 | 18 | ImFileList(const char* path = ".") 19 | : Pos(0) 20 | { 21 | ChDir(path); 22 | } 23 | 24 | void ChDir(const char* path); 25 | void Draw(); 26 | }; 27 | 28 | } // namespace ImGui 29 | -------------------------------------------------------------------------------- /3rd/dear-imgui/widgets/file_list.inl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace ImGui 6 | { 7 | ImFileInfo::ImFileInfo(const char* name, int64_t size) 8 | : Name(name) 9 | , Size(size) 10 | { 11 | } 12 | 13 | ImFileInfo::~ImFileInfo() 14 | { 15 | } 16 | 17 | void ImFileList::ChDir(const char* path) 18 | { 19 | #if BX_PLATFORM_PS4 20 | BX_UNUSED(path); 21 | #else 22 | DIR* dir = opendir(path); 23 | if (NULL != dir) 24 | { 25 | FileList.clear(); 26 | 27 | for (dirent* item = readdir(dir); NULL != item; item = readdir(dir) ) 28 | { 29 | if (0 == ImStricmp(item->d_name, "..") ) 30 | { 31 | FileList.push_back(ImFileInfo(item->d_name, -1) ); 32 | } 33 | else if (0 != ImStricmp(item->d_name, ".") ) 34 | { 35 | if (item->d_type & DT_DIR) 36 | { 37 | FileList.push_back(ImFileInfo(item->d_name, -1) ); 38 | } 39 | else 40 | { 41 | struct stat statbuf; 42 | stat(item->d_name, &statbuf); 43 | FileList.push_back(ImFileInfo(item->d_name, statbuf.st_size) ); 44 | } 45 | } 46 | } 47 | 48 | closedir(dir); 49 | } 50 | #endif // BX_PLATFORM_PS4 51 | } 52 | 53 | void ImFileList::Draw() 54 | { 55 | BeginChild("##file_list", ImVec2(0.0f, 0.0f) ); 56 | PushFont(Font::Mono); 57 | 58 | PushItemWidth(-1); 59 | if (BeginListBox("##empty", ImVec2(0.0f, 0.0f) ) ) 60 | { 61 | const float lineHeight = GetTextLineHeightWithSpacing(); 62 | 63 | ImString chdir; 64 | 65 | int pos = 0; 66 | ImGuiListClipper clipper; 67 | clipper.Begin(FileList.size(), lineHeight); 68 | clipper.Step(); 69 | 70 | for (FileInfoArray::const_iterator it = FileList.begin(), itEnd = FileList.end() 71 | ; it != itEnd 72 | ; ++it 73 | ) 74 | { 75 | if (pos >= clipper.DisplayStart 76 | && pos < clipper.DisplayEnd) 77 | { 78 | PushID(pos); 79 | 80 | const bool isDir = -1 == it->Size; 81 | bool isSelected = Pos == pos; 82 | 83 | bool clicked = Selectable(it->Name.CStr(), &isSelected); 84 | SameLine(150); 85 | if (isDir) 86 | { 87 | Text("%10s", ""); 88 | } 89 | else 90 | { 91 | Text("%10" PRId64, it->Size); 92 | } 93 | 94 | if (clicked) 95 | { 96 | if (0 == strcmp(it->Name.CStr(), "..") ) 97 | { 98 | chdir = it->Name; 99 | } 100 | 101 | Pos = pos; 102 | 103 | if (isDir) 104 | { 105 | chdir = it->Name; 106 | } 107 | } 108 | 109 | PopID(); 110 | } 111 | ++pos; 112 | } 113 | clipper.End(); 114 | 115 | EndListBox(); 116 | 117 | if (!chdir.IsEmpty() ) 118 | { 119 | ChDir(chdir.CStr() ); 120 | } 121 | } 122 | 123 | PopFont(); 124 | EndChild(); 125 | } 126 | 127 | } // namespace ImGui 128 | -------------------------------------------------------------------------------- /3rd/dear-imgui/widgets/gizmo.h: -------------------------------------------------------------------------------- 1 | // https://github.com/CedricGuillemet/ImGuizmo 2 | // v 1.84 WIP 3 | // 4 | // The MIT License(MIT) 5 | // 6 | // Copyright(c) 2021 Cedric Guillemet 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files(the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and / or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions : 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | // 26 | // ------------------------------------------------------------------------------------------- 27 | // History : 28 | // 2019/11/03 View gizmo 29 | // 2016/09/11 Behind camera culling. Scaling Delta matrix not multiplied by source matrix scales. local/world rotation and translation fixed. Display message is incorrect (X: ... Y:...) in local mode. 30 | // 2016/09/09 Hatched negative axis. Snapping. Documentation update. 31 | // 2016/09/04 Axis switch and translation plan autohiding. Scale transform stability improved 32 | // 2016/09/01 Mogwai changed to Manipulate. Draw debug cube. Fixed inverted scale. Mixing scale and translation/rotation gives bad results. 33 | // 2016/08/31 First version 34 | // 35 | // ------------------------------------------------------------------------------------------- 36 | // Future (no order): 37 | // 38 | // - Multi view 39 | // - display rotation/translation/scale infos in local/world space and not only local 40 | // - finish local/world matrix application 41 | // - OPERATION as bitmask 42 | // 43 | // ------------------------------------------------------------------------------------------- 44 | // Example 45 | #if 0 46 | void EditTransform(const Camera& camera, matrix_t& matrix) 47 | { 48 | static ImGuizmo::OPERATION mCurrentGizmoOperation(ImGuizmo::ROTATE); 49 | static ImGuizmo::MODE mCurrentGizmoMode(ImGuizmo::WORLD); 50 | if (ImGui::IsKeyPressed(90)) 51 | mCurrentGizmoOperation = ImGuizmo::TRANSLATE; 52 | if (ImGui::IsKeyPressed(69)) 53 | mCurrentGizmoOperation = ImGuizmo::ROTATE; 54 | if (ImGui::IsKeyPressed(82)) // r Key 55 | mCurrentGizmoOperation = ImGuizmo::SCALE; 56 | if (ImGui::RadioButton("Translate", mCurrentGizmoOperation == ImGuizmo::TRANSLATE)) 57 | mCurrentGizmoOperation = ImGuizmo::TRANSLATE; 58 | ImGui::SameLine(); 59 | if (ImGui::RadioButton("Rotate", mCurrentGizmoOperation == ImGuizmo::ROTATE)) 60 | mCurrentGizmoOperation = ImGuizmo::ROTATE; 61 | ImGui::SameLine(); 62 | if (ImGui::RadioButton("Scale", mCurrentGizmoOperation == ImGuizmo::SCALE)) 63 | mCurrentGizmoOperation = ImGuizmo::SCALE; 64 | float matrixTranslation[3], matrixRotation[3], matrixScale[3]; 65 | ImGuizmo::DecomposeMatrixToComponents(matrix.m16, matrixTranslation, matrixRotation, matrixScale); 66 | ImGui::InputFloat3("Tr", matrixTranslation, 3); 67 | ImGui::InputFloat3("Rt", matrixRotation, 3); 68 | ImGui::InputFloat3("Sc", matrixScale, 3); 69 | ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, matrix.m16); 70 | 71 | if (mCurrentGizmoOperation != ImGuizmo::SCALE) 72 | { 73 | if (ImGui::RadioButton("Local", mCurrentGizmoMode == ImGuizmo::LOCAL)) 74 | mCurrentGizmoMode = ImGuizmo::LOCAL; 75 | ImGui::SameLine(); 76 | if (ImGui::RadioButton("World", mCurrentGizmoMode == ImGuizmo::WORLD)) 77 | mCurrentGizmoMode = ImGuizmo::WORLD; 78 | } 79 | static bool useSnap(false); 80 | if (ImGui::IsKeyPressed(83)) 81 | useSnap = !useSnap; 82 | ImGui::Checkbox("", &useSnap); 83 | ImGui::SameLine(); 84 | vec_t snap; 85 | switch (mCurrentGizmoOperation) 86 | { 87 | case ImGuizmo::TRANSLATE: 88 | snap = config.mSnapTranslation; 89 | ImGui::InputFloat3("Snap", &snap.x); 90 | break; 91 | case ImGuizmo::ROTATE: 92 | snap = config.mSnapRotation; 93 | ImGui::InputFloat("Angle Snap", &snap.x); 94 | break; 95 | case ImGuizmo::SCALE: 96 | snap = config.mSnapScale; 97 | ImGui::InputFloat("Scale Snap", &snap.x); 98 | break; 99 | } 100 | ImGuiIO& io = ImGui::GetIO(); 101 | ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y); 102 | ImGuizmo::Manipulate(camera.mView.m16, camera.mProjection.m16, mCurrentGizmoOperation, mCurrentGizmoMode, matrix.m16, NULL, useSnap ? &snap.x : NULL); 103 | } 104 | #endif 105 | #pragma once 106 | 107 | #ifdef USE_IMGUI_API 108 | #include "imconfig.h" 109 | #endif 110 | #ifndef IMGUI_API 111 | #define IMGUI_API 112 | #endif 113 | 114 | #ifndef IMGUIZMO_NAMESPACE 115 | #define IMGUIZMO_NAMESPACE ImGuizmo 116 | #endif 117 | 118 | namespace IMGUIZMO_NAMESPACE 119 | { 120 | // call inside your own window and before Manipulate() in order to draw gizmo to that window. 121 | // Or pass a specific ImDrawList to draw to (e.g. ImGui::GetForegroundDrawList()). 122 | IMGUI_API void SetDrawlist(ImDrawList* drawlist = nullptr); 123 | 124 | // call BeginFrame right after ImGui_XXXX_NewFrame(); 125 | IMGUI_API void BeginFrame(); 126 | 127 | // this is necessary because when imguizmo is compiled into a dll, and imgui into another 128 | // globals are not shared between them. 129 | // More details at https://stackoverflow.com/questions/19373061/what-happens-to-global-and-static-variables-in-a-shared-library-when-it-is-dynam 130 | // expose method to set imgui context 131 | IMGUI_API void SetImGuiContext(ImGuiContext* ctx); 132 | 133 | // return true if mouse cursor is over any gizmo control (axis, plan or screen component) 134 | IMGUI_API bool IsOver(); 135 | 136 | // return true if mouse IsOver or if the gizmo is in moving state 137 | IMGUI_API bool IsUsing(); 138 | 139 | // enable/disable the gizmo. Stay in the state until next call to Enable. 140 | // gizmo is rendered with gray half transparent color when disabled 141 | IMGUI_API void Enable(bool enable); 142 | 143 | // helper functions for manualy editing translation/rotation/scale with an input float 144 | // translation, rotation and scale float points to 3 floats each 145 | // Angles are in degrees (more suitable for human editing) 146 | // example: 147 | // float matrixTranslation[3], matrixRotation[3], matrixScale[3]; 148 | // ImGuizmo::DecomposeMatrixToComponents(gizmoMatrix.m16, matrixTranslation, matrixRotation, matrixScale); 149 | // ImGui::InputFloat3("Tr", matrixTranslation, 3); 150 | // ImGui::InputFloat3("Rt", matrixRotation, 3); 151 | // ImGui::InputFloat3("Sc", matrixScale, 3); 152 | // ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, gizmoMatrix.m16); 153 | // 154 | // These functions have some numerical stability issues for now. Use with caution. 155 | IMGUI_API void DecomposeMatrixToComponents(const float* matrix, float* translation, float* rotation, float* scale); 156 | IMGUI_API void RecomposeMatrixFromComponents(const float* translation, const float* rotation, const float* scale, float* matrix); 157 | 158 | IMGUI_API void SetRect(float x, float y, float width, float height); 159 | // default is false 160 | IMGUI_API void SetOrthographic(bool isOrthographic); 161 | 162 | // Render a cube with face color corresponding to face normal. Usefull for debug/tests 163 | IMGUI_API void DrawCubes(const float* view, const float* projection, const float* matrices, int matrixCount); 164 | IMGUI_API void DrawGrid(const float* view, const float* projection, const float* matrix, const float gridSize); 165 | 166 | // call it when you want a gizmo 167 | // Needs view and projection matrices. 168 | // matrix parameter is the source matrix (where will be gizmo be drawn) and might be transformed by the function. Return deltaMatrix is optional 169 | // translation is applied in world space 170 | enum OPERATION 171 | { 172 | TRANSLATE_X = (1u << 0), 173 | TRANSLATE_Y = (1u << 1), 174 | TRANSLATE_Z = (1u << 2), 175 | ROTATE_X = (1u << 3), 176 | ROTATE_Y = (1u << 4), 177 | ROTATE_Z = (1u << 5), 178 | ROTATE_SCREEN = (1u << 6), 179 | SCALE_X = (1u << 7), 180 | SCALE_Y = (1u << 8), 181 | SCALE_Z = (1u << 9), 182 | BOUNDS = (1u << 10), 183 | SCALE_XU = (1u << 11), 184 | SCALE_YU = (1u << 12), 185 | SCALE_ZU = (1u << 13), 186 | 187 | TRANSLATE = TRANSLATE_X | TRANSLATE_Y | TRANSLATE_Z, 188 | ROTATE = ROTATE_X | ROTATE_Y | ROTATE_Z | ROTATE_SCREEN, 189 | SCALE = SCALE_X | SCALE_Y | SCALE_Z, 190 | SCALEU = SCALE_XU | SCALE_YU | SCALE_ZU, // universal 191 | UNIVERSAL = TRANSLATE | ROTATE | SCALEU 192 | }; 193 | 194 | inline OPERATION operator|(OPERATION lhs, OPERATION rhs) 195 | { 196 | return static_cast(static_cast(lhs) | static_cast(rhs)); 197 | } 198 | 199 | enum MODE 200 | { 201 | LOCAL, 202 | WORLD 203 | }; 204 | 205 | IMGUI_API bool Manipulate(const float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float* deltaMatrix = NULL, const float* snap = NULL, const float* localBounds = NULL, const float* boundsSnap = NULL); 206 | // 207 | // Please note that this cubeview is patented by Autodesk : https://patents.google.com/patent/US7782319B2/en 208 | // It seems to be a defensive patent in the US. I don't think it will bring troubles using it as 209 | // other software are using the same mechanics. But just in case, you are now warned! 210 | // 211 | IMGUI_API void ViewManipulate(float* view, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor); 212 | 213 | IMGUI_API void SetID(int id); 214 | 215 | // return true if the cursor is over the operation's gizmo 216 | IMGUI_API bool IsOver(OPERATION op); 217 | IMGUI_API void SetGizmoSizeClipSpace(float value); 218 | 219 | // Allow axis to flip 220 | // When true (default), the guizmo axis flip for better visibility 221 | // When false, they always stay along the positive world/local axis 222 | IMGUI_API void AllowAxisFlip(bool value); 223 | } 224 | -------------------------------------------------------------------------------- /3rd/dear-imgui/widgets/markdown.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // License: zlib 4 | // Copyright (c) 2019 Juliette Foucaut & Doug Binks 5 | // 6 | // This software is provided 'as-is', without any express or implied 7 | // warranty. In no event will the authors be held liable for any damages 8 | // arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose, 11 | // including commercial applications, and to alter it and redistribute it 12 | // freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would be 17 | // appreciated but is not required. 18 | // 2. Altered source versions must be plainly marked as such, and must not be 19 | // misrepresented as being the original software. 20 | // 3. This notice may not be removed or altered from any source distribution. 21 | 22 | 23 | /* 24 | imgui_markdown https://github.com/juliettef/imgui_markdown 25 | Markdown for Dear ImGui 26 | 27 | A permissively licensed markdown single-header library for https://github.com/ocornut/imgui 28 | 29 | imgui_markdown currently supports the following markdown functionality: 30 | - Wrapped text 31 | - Headers H1, H2, H3 32 | - Indented text, multi levels 33 | - Unordered lists and sub-lists 34 | - Links 35 | 36 | Syntax 37 | 38 | Wrapping: 39 | Text wraps automatically. To add a new line, use 'Return'. 40 | 41 | Headers: 42 | # H1 43 | ## H2 44 | ### H3 45 | 46 | Indents: 47 | On a new line, at the start of the line, add two spaces per indent. 48 | Indent level 1 49 | Indent level 2 50 | 51 | Unordered lists: 52 | On a new line, at the start of the line, add two spaces, an asterisks and a space. 53 | For nested lists, add two additional spaces in front of the asterisk per list level increment. 54 | * Unordered List level 1 55 | * Unordered List level 2 56 | 57 | Links: 58 | [link description](https://...) 59 | 60 | =============================================================================== 61 | 62 | // Example use on Windows with links opening in a browser 63 | 64 | #include "ImGui.h" // https://github.com/ocornut/imgui 65 | #include "imgui_markdown.h" // https://github.com/juliettef/imgui_markdown 66 | #include "IconsFontAwesome5.h" // https://github.com/juliettef/IconFontCppHeaders 67 | 68 | // Following includes for Windows LinkCallback 69 | #define WIN32_LEAN_AND_MEAN 70 | #include 71 | #include "Shellapi.h" 72 | #include 73 | 74 | // You can make your own Markdown function with your prefered string container and markdown config. 75 | static ImGui::MarkdownConfig mdConfig{ LinkCallback, ICON_FA_LINK, { NULL, true, NULL, true, NULL, false } }; 76 | 77 | void LinkCallback( const char* link_, uint32_t linkLength_ ) 78 | { 79 | std::string url( link_, linkLength_ ); 80 | ShellExecuteA( NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL ); 81 | } 82 | 83 | void LoadFonts( float fontSize_ = 12.0f ) 84 | { 85 | ImGuiIO& io = ImGui::GetIO(); 86 | io.Fonts->Clear(); 87 | // Base font 88 | io.Fonts->AddFontFromFileTTF( "myfont.ttf", fontSize_ ); 89 | // Bold headings H2 and H3 90 | mdConfig.headingFormats[ 1 ].font = io.Fonts->AddFontFromFileTTF( "myfont-bold.ttf", fontSize_ ); 91 | mdConfig.headingFormats[ 2 ].font = mdConfig.headingFormats[ 1 ].font; 92 | // bold heading H1 93 | float fontSizeH1 = fontSize_ * 1.1f; 94 | mdConfig.headingFormats[ 0 ].font = io.Fonts->AddFontFromFileTTF( "myfont-bold.ttf", fontSizeH1 ); 95 | } 96 | 97 | void Markdown( const std::string& markdown_ ) 98 | { 99 | // fonts for, respectively, headings H1, H2, H3 and beyond 100 | ImGui::Markdown( markdown_.c_str(), markdown_.length(), mdConfig ); 101 | } 102 | 103 | void MarkdownExample() 104 | { 105 | const std::string markdownText = u8R"( 106 | # H1 Header: Text and Links 107 | You can add [links like this one to enkisoftware](https://www.enkisoftware.com/) and lines will wrap well. 108 | ## H2 Header: indented text. 109 | This text has an indent (two leading spaces). 110 | This one has two. 111 | ### H3 Header: Lists 112 | * Unordered lists 113 | * Lists can be indented with two extra spaces. 114 | * Lists can have [links like this one to Avoyd](https://www.avoyd.com/) 115 | )"; 116 | Markdown( markdownText ); 117 | } 118 | 119 | =============================================================================== 120 | */ 121 | 122 | #include 123 | 124 | namespace ImGui 125 | { 126 | // Configuration struct for Markdown 127 | // * linkCallback is called when a link is clicked on 128 | // * linkIcon is a string which encode a "Link" icon, if available in the current font (e.g. linkIcon = ICON_FA_LINK with FontAwesome + IconFontCppHeaders https://github.com/juliettef/IconFontCppHeaders) 129 | // * HeadingFormat controls the format of heading H1 to H3, those above H3 use H3 format 130 | // * font is the index into the ImGui font array 131 | // * separator controls whether an underlined separator is drawn after the header 132 | struct MarkdownConfig 133 | { 134 | typedef void MarkdownLinkCallback( const char* link_, uint32_t linkLength_ ); 135 | struct HeadingFormat{ ImFont* font; bool separator; }; 136 | 137 | static const int NUMHEADINGS = 3; 138 | 139 | MarkdownLinkCallback* linkCallback = 0; 140 | const char* linkIcon = ""; 141 | HeadingFormat headingFormats[ NUMHEADINGS ] = { { NULL, true }, { NULL, true }, { NULL, true } }; 142 | }; 143 | 144 | // External interface 145 | void Markdown( const char* markdown_, int32_t markdownLength_, const MarkdownConfig& mdConfig_ ); 146 | } 147 | -------------------------------------------------------------------------------- /3rd/dear-imgui/widgets/markdown.inl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RudjiGames/rapp/fe13e24a1a5e04f872bb4c58475b12849db45a39/3rd/dear-imgui/widgets/markdown.inl -------------------------------------------------------------------------------- /3rd/dear-imgui/widgets/memory_editor.h: -------------------------------------------------------------------------------- 1 | namespace ImGui 2 | { 3 | struct MemoryEditor 4 | { 5 | bool AllowEdits; 6 | bool HexII; 7 | int Rows; 8 | int DataEditingAddr; 9 | bool DataEditingTakeFocus; 10 | char DataInput[32]; 11 | char AddrInput[32]; 12 | 13 | MemoryEditor() 14 | { 15 | AllowEdits = true; 16 | HexII = true; 17 | Rows = 16; 18 | DataEditingAddr = -1; 19 | DataEditingTakeFocus = false; 20 | strcpy(DataInput, ""); 21 | strcpy(AddrInput, ""); 22 | } 23 | 24 | void Draw(void* mem_data, int mem_size, int base_display_addr = 0); 25 | void Draw(const void* mem_data, int mem_size, int base_display_addr = 0); 26 | }; 27 | } // namespace ImGui 28 | -------------------------------------------------------------------------------- /3rd/dear-imgui/widgets/range_slider.h: -------------------------------------------------------------------------------- 1 | namespace ImGui 2 | { 3 | IMGUI_API bool RangeSliderFloat(const char* label, float* v1, float* v2, float v_min, float v_max, const char* display_format = "(%.3f, %.3f)", float power = 1.0f); 4 | 5 | } // namespace ImGui 6 | -------------------------------------------------------------------------------- /3rd/dear-imgui/widgets/range_slider.inl: -------------------------------------------------------------------------------- 1 | // https://github.com/ocornut/imgui/issues/76 2 | // Taken from: https://github.com/wasikuss/imgui/commit/a50515ace6d9a62ebcd69817f1da927d31c39bb1 3 | 4 | namespace ImGui 5 | { 6 | 7 | extern float RoundScalarWithFormatFloat(const char* format, ImGuiDataType data_type, float v); 8 | 9 | extern float SliderCalcRatioFromValueFloat(ImGuiDataType data_type, float v, float v_min, float v_max, float power, float linear_zero_pos); 10 | 11 | // ~80% common code with ImGui::SliderBehavior 12 | bool RangeSliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v1, float* v2, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags) 13 | { 14 | ImGuiContext& g = *GImGui; 15 | ImGuiWindow* window = GetCurrentWindow(); 16 | const ImGuiStyle& style = g.Style; 17 | 18 | // Draw frame 19 | RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); 20 | 21 | const bool is_non_linear = (power < 1.0f-0.00001f) || (power > 1.0f+0.00001f); 22 | const bool is_horizontal = (flags & ImGuiSliderFlags_Vertical) == 0; 23 | 24 | const float grab_padding = 2.0f; 25 | const float slider_sz = is_horizontal ? (frame_bb.GetWidth() - grab_padding * 2.0f) : (frame_bb.GetHeight() - grab_padding * 2.0f); 26 | float grab_sz; 27 | if (decimal_precision > 0) 28 | grab_sz = ImMin(style.GrabMinSize, slider_sz); 29 | else 30 | grab_sz = ImMin(ImMax(1.0f * (slider_sz / ((v_min < v_max ? v_max - v_min : v_min - v_max) + 1.0f)), style.GrabMinSize), slider_sz); // Integer sliders, if possible have the grab size represent 1 unit 31 | const float slider_usable_sz = slider_sz - grab_sz; 32 | const float slider_usable_pos_min = (is_horizontal ? frame_bb.Min.x : frame_bb.Min.y) + grab_padding + grab_sz*0.5f; 33 | const float slider_usable_pos_max = (is_horizontal ? frame_bb.Max.x : frame_bb.Max.y) - grab_padding - grab_sz*0.5f; 34 | 35 | // For logarithmic sliders that cross over sign boundary we want the exponential increase to be symmetric around 0.0f 36 | float linear_zero_pos = 0.0f; // 0.0->1.0f 37 | if (v_min * v_max < 0.0f) 38 | { 39 | // Different sign 40 | const float linear_dist_min_to_0 = powf(fabsf(0.0f - v_min), 1.0f/power); 41 | const float linear_dist_max_to_0 = powf(fabsf(v_max - 0.0f), 1.0f/power); 42 | linear_zero_pos = linear_dist_min_to_0 / (linear_dist_min_to_0+linear_dist_max_to_0); 43 | } 44 | else 45 | { 46 | // Same sign 47 | linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f; 48 | } 49 | 50 | // Process clicking on the slider 51 | bool value_changed = false; 52 | if (g.ActiveId == id) 53 | { 54 | if (g.IO.MouseDown[0]) 55 | { 56 | const float mouse_abs_pos = is_horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; 57 | float clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f; 58 | if (!is_horizontal) 59 | clicked_t = 1.0f - clicked_t; 60 | 61 | float new_value; 62 | if (is_non_linear) 63 | { 64 | // Account for logarithmic scale on both sides of the zero 65 | if (clicked_t < linear_zero_pos) 66 | { 67 | // Negative: rescale to the negative range before powering 68 | float a = 1.0f - (clicked_t / linear_zero_pos); 69 | a = powf(a, power); 70 | new_value = ImLerp(ImMin(v_max,0.0f), v_min, a); 71 | } 72 | else 73 | { 74 | // Positive: rescale to the positive range before powering 75 | float a; 76 | if (fabsf(linear_zero_pos - 1.0f) > 1.e-6f) 77 | a = (clicked_t - linear_zero_pos) / (1.0f - linear_zero_pos); 78 | else 79 | a = clicked_t; 80 | a = powf(a, power); 81 | new_value = ImLerp(ImMax(v_min,0.0f), v_max, a); 82 | } 83 | } 84 | else 85 | { 86 | // Linear slider 87 | new_value = ImLerp(v_min, v_max, clicked_t); 88 | } 89 | 90 | char fmt[64]; 91 | snprintf(fmt, 64, "%%.%df", decimal_precision); 92 | 93 | // Round past decimal precision 94 | new_value = RoundScalarWithFormatFloat(fmt, ImGuiDataType_Float, new_value); 95 | if (*v1 != new_value || *v2 != new_value) 96 | { 97 | if (fabsf(*v1 - new_value) < fabsf(*v2 - new_value)) 98 | { 99 | *v1 = new_value; 100 | } 101 | else 102 | { 103 | *v2 = new_value; 104 | } 105 | value_changed = true; 106 | } 107 | } 108 | else 109 | { 110 | ClearActiveID(); 111 | } 112 | } 113 | 114 | // Calculate slider grab positioning 115 | float grab_t = SliderCalcRatioFromValueFloat(ImGuiDataType_Float, *v1, v_min, v_max, power, linear_zero_pos); 116 | 117 | // Draw 118 | if (!is_horizontal) 119 | grab_t = 1.0f - grab_t; 120 | float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); 121 | ImRect grab_bb1; 122 | if (is_horizontal) 123 | grab_bb1 = ImRect(ImVec2(grab_pos - grab_sz*0.5f, frame_bb.Min.y + grab_padding), ImVec2(grab_pos + grab_sz*0.5f, frame_bb.Max.y - grab_padding)); 124 | else 125 | grab_bb1 = ImRect(ImVec2(frame_bb.Min.x + grab_padding, grab_pos - grab_sz*0.5f), ImVec2(frame_bb.Max.x - grab_padding, grab_pos + grab_sz*0.5f)); 126 | window->DrawList->AddRectFilled(grab_bb1.Min, grab_bb1.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding); 127 | 128 | // Calculate slider grab positioning 129 | grab_t = SliderCalcRatioFromValueFloat(ImGuiDataType_Float, *v2, v_min, v_max, power, linear_zero_pos); 130 | 131 | // Draw 132 | if (!is_horizontal) 133 | grab_t = 1.0f - grab_t; 134 | grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); 135 | ImRect grab_bb2; 136 | if (is_horizontal) 137 | grab_bb2 = ImRect(ImVec2(grab_pos - grab_sz*0.5f, frame_bb.Min.y + grab_padding), ImVec2(grab_pos + grab_sz*0.5f, frame_bb.Max.y - grab_padding)); 138 | else 139 | grab_bb2 = ImRect(ImVec2(frame_bb.Min.x + grab_padding, grab_pos - grab_sz*0.5f), ImVec2(frame_bb.Max.x - grab_padding, grab_pos + grab_sz*0.5f)); 140 | window->DrawList->AddRectFilled(grab_bb2.Min, grab_bb2.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding); 141 | 142 | ImRect connector(grab_bb1.Min, grab_bb2.Max); 143 | connector.Min.x += grab_sz; 144 | connector.Min.y += grab_sz*0.3f; 145 | connector.Max.x -= grab_sz; 146 | connector.Max.y -= grab_sz*0.3f; 147 | 148 | window->DrawList->AddRectFilled(connector.Min, connector.Max, GetColorU32(ImGuiCol_SliderGrab), style.GrabRounding); 149 | 150 | return value_changed; 151 | } 152 | 153 | // ~95% common code with ImGui::SliderFloat 154 | bool RangeSliderFloat(const char* label, float* v1, float* v2, float v_min, float v_max, const char* display_format, float power) 155 | { 156 | ImGuiWindow* window = GetCurrentWindow(); 157 | if (window->SkipItems) 158 | return false; 159 | 160 | ImGuiContext& g = *GImGui; 161 | const ImGuiStyle& style = g.Style; 162 | const ImGuiID id = window->GetID(label); 163 | const float w = CalcItemWidth(); 164 | 165 | const ImVec2 label_size = CalcTextSize(label, NULL, true); 166 | const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); 167 | const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); 168 | 169 | // NB- we don't call ItemSize() yet because we may turn into a text edit box below 170 | if (!ItemAdd(total_bb, id)) 171 | { 172 | ItemSize(total_bb, style.FramePadding.y); 173 | return false; 174 | } 175 | 176 | const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags); 177 | if (hovered) 178 | SetHoveredID(id); 179 | 180 | if (!display_format) 181 | display_format = "(%.3f, %.3f)"; 182 | int decimal_precision = ImParseFormatPrecision(display_format, 3); 183 | 184 | // Tabbing or CTRL-clicking on Slider turns it into an input box 185 | bool start_text_input = false; 186 | if (hovered && g.IO.MouseClicked[0]) 187 | { 188 | SetActiveID(id, window); 189 | FocusWindow(window); 190 | 191 | if (g.IO.KeyCtrl) 192 | { 193 | start_text_input = true; 194 | g.TempInputId = 0; 195 | } 196 | } 197 | 198 | if (start_text_input || (g.ActiveId == id && g.TempInputId == id)) 199 | { 200 | char fmt[64]; 201 | snprintf(fmt, 64, "%%.%df", decimal_precision); 202 | return TempInputScalar(frame_bb, id, label, ImGuiDataType_Float, v1, fmt); 203 | } 204 | 205 | ItemSize(total_bb, style.FramePadding.y); 206 | 207 | // Actual slider behavior + render grab 208 | const bool value_changed = RangeSliderBehavior(frame_bb, id, v1, v2, v_min, v_max, power, decimal_precision, 0); 209 | 210 | // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. 211 | char value_buf[64]; 212 | const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v1, *v2); 213 | RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f)); 214 | 215 | if (label_size.x > 0.0f) 216 | RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); 217 | 218 | return value_changed; 219 | } 220 | 221 | } // namespace ImGui 222 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright 2025 Milos Tosic 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![Build status](https://ci.appveyor.com/api/projects/status/5ai0w0mu6ay2wcme?svg=true)](https://ci.appveyor.com/project/milostosic/rapp-6qu5f) 4 | [![License](https://img.shields.io/badge/license-BSD--2%20clause-blue.svg)](https://github.com/RudjiGames/rapp/blob/master/LICENSE) 5 | 6 | **rapp** is a library that provides cross-platform application entry point and additional functionality. 7 | rapp is **heavily** based on [bgfx](https://github.com/bkaradzic/bgfx) examples entry point code that can be found [here](https://github.com/bkaradzic/bgfx/tree/master/examples/common/entry). Graphics code is still [bgfx](https://github.com/bkaradzic/bgfx) based but.. 8 | 9 | ...dependecy on [bx](https://github.com/bkaradzic/bx) and [bgfx](https://github.com/bkaradzic/bgfx) has been removed by aggressively copying code and by a special feature of [build](https://github.com/RudjiGames/build) system that allows to have the same library in a 'solution' with different configurations. 10 | To clarify, in the screenshot below first sample (command line) links against **rapp** and [rbase](https://github.com/RudjiGames/rbase) while the second one (graphics) links against **rapp_bgfx**, [rbase](https://github.com/RudjiGames/rbase), [bx](https://github.com/bkaradzic/bx), [bimg](https://github.com/bkaradzic/bimg) and [bgfx](https://github.com/bkaradzic/bgfx) - this is all automated. 11 | 12 | 13 | 14 | Thanks to multiple configurations per project feature of [build](https://github.com/RudjiGames/build), script taking care of this is very short and can be seen [here](https://github.com/RudjiGames/rapp/blob/master/genie/rapp.lua), basically it just enables a library wide define. 15 | 16 | Features 17 | ====== 18 | 19 | **rapp** currently has the following functionality: 20 | * Applications written as classes with init/shutdown/suspend/resume functionality 21 | * Command line (tools, unit tests, etc.) or graphics applications (games, etc.) 22 | * Custom commands 23 | * Input controllers (mouse, keyboard, gamepad, etc.) with input binding callbacks and debug visualizations 24 | * Ability to run code on main/message loop thread 25 | * Job scheduler with job stealing for fine grained parallelism 26 | * [ImGui](https://github.com/ocornut/imgui) and [NanoVG](https://github.com/memononen/nanovg) integration 27 | * Quake like console - [ImGui](https://github.com/ocornut/imgui) based 28 | * Built-in [**rprof**](https://github.com/RudjiGames/rprof) CPU profiler 29 | * Multiple applications in one binary 30 | * Window functions 31 | 32 | [**rprof**](https://github.com/RudjiGames/rprof) CPU profiler is an optional dependency and needs to be explicitly requested when generating project files, for example: 33 | 34 | GENie --with-rprof vs2022 35 | 36 | Here's a screenshot of a [bgfx](https://github.com/bkaradzic/bgfx) sample showing input debugging, [ImGui](https://github.com/ocornut/imgui) dialog and Quake like console as well as [NanoVG](https://github.com/memononen/nanovg) shape (eyes): 37 | 38 | 39 | Platform support 40 | ====== 41 | 42 | | | Input (KMG) | Threading | Console | Graphics | 43 | |------------------|-------------|-----------|---------|----------| 44 | | **Windows** | ✓✓✓ | ✓ | ✓ | ✓ | 45 | | **Xbox One** | ✓✓✓ | ✓ | ✓ | ✓ | 46 | | **PlayStation 4**| ✓✓✓ | ✓ | ✓ | ✓ | 47 | | **Linux** | ✓✓X | ✓ | ✓ | ✓ | 48 | | **Android** | XXX | ✓ | ? | ✓ | 49 | | **OSX** | ✓✓X | ✓ | ✓ | ✓ | 50 | | **Emscripten** | ✓✓✓ | X | ✓ | ✓ | 51 | 52 | ✓ - Working 53 | X - Not yet implemented 54 | ? - Not supported 55 | 56 | Platforms with partial implementations or not tested: **iOS, UWP, FreeBSD** 57 | Input (KMG) stands for Keyboard, Mouse and Gamepad 58 | 59 | Source Code 60 | ====== 61 | 62 | You can get the latest source code by cloning it from github: 63 | 64 | git clone https://github.com/RudjiGames/rapp.git 65 | 66 | Build and dependencies 67 | ====== 68 | 69 | There's quite a few dependencies and they can be fetched manually or using a [batch file](https://github.com/RudjiGames/rapp/blob/master/scripts/fetch_dependencies.bat). 70 | For the list of dependencies please refer to the batch file. 71 | 72 | Once dependencies are cloned, [GENie](https://github.com/bkaradzic/genie) project generator tool can be used to generate project files/solution. [This](https://github.com/RudjiGames/rapp/blob/master/scripts/generate_project.bat) batch file is an example of generating a solution and project files for VS2022. 73 | 74 | License (BSD 2-clause) 75 | ====== 76 | 77 | 78 | 79 | 80 | 81 | Copyright 2025 Milos Tosic. All rights reserved. 82 | 83 | https://github.com/RudjiGames/rapp 84 | 85 | Redistribution and use in source and binary forms, with or without 86 | modification, are permitted provided that the following conditions are met: 87 | 88 | 1. Redistributions of source code must retain the above copyright notice, 89 | this list of conditions and the following disclaimer. 90 | 91 | 2. Redistributions in binary form must reproduce the above copyright 92 | notice, this list of conditions and the following disclaimer in the 93 | documentation and/or other materials provided with the distribution. 94 | 95 | THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR 96 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 97 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 98 | EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 99 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 100 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 101 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 102 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 103 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 104 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 105 | -------------------------------------------------------------------------------- /genie/genie.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- Copyright 2025 Milos Tosic. All rights reserved. 3 | -- License: http://www.opensource.org/licenses/BSD-2-Clause 4 | -- 5 | 6 | local cp = (function(x) return debug.getinfo(2, "S").source:sub(2):match("(.*[/\\])") end)() 7 | while os.isdir(cp) do cp = path.getabsolute(cp .. "/..") local tp = cp .. "/build/build.lua" 8 | if os.isfile(tp) then dofile (tp) break end end if RTM_ROOT_DIR == nil then 9 | print("EROR: dependency missing - build. Cannot continue.") os.exit() end 10 | 11 | solution "rapp" 12 | setPlatforms() 13 | 14 | addLibProjects("rapp") 15 | -------------------------------------------------------------------------------- /genie/rapp.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- Copyright 2025 Milos Tosic. All rights reserved. 3 | -- License: http://www.opensource.org/licenses/BSD-2-Clause 4 | -- 5 | 6 | function projectDependencies_rapp() 7 | return { "rbase", "enkiTS" } 8 | end 9 | 10 | function projectAdd_rapp() 11 | addProject_lib("rapp", Lib.Runtime) 12 | end 13 | 14 | function projectDependencies_rapp_bgfx() 15 | local dependencies = {} 16 | if (getTargetOS() == "linux" or getTargetOS() == "freebsd") then 17 | table.insert(dependencies, "X11") 18 | end 19 | dependencies = mergeTwoTables(dependencies, { "bgfx" }) 20 | dependencies = mergeTables( projectDependencies_rapp(), dependencies ) 21 | return dependencies 22 | end 23 | 24 | function projectExtraConfigExecutable_rapp() 25 | configuration { "linux-* or freebsd" } 26 | buildoptions { 27 | "-fPIC", 28 | } 29 | links { 30 | "pthread", 31 | "X11", 32 | "GL", 33 | } 34 | configuration {} 35 | 36 | configuration { "osx" } 37 | linkoptions { 38 | "-framework CoreFoundation", 39 | "-framework Cocoa", 40 | "-framework OpenGL", 41 | } 42 | 43 | configuration {} 44 | end 45 | 46 | function projectExtraConfig_rapp_bgfx() 47 | local bgfxPath = find3rdPartyProject("bgfx") 48 | local rappPath = getProjectPath("rapp") 49 | 50 | if bgfxPath == nil then 51 | return 52 | end 53 | 54 | files { 55 | bgfxPath .. "3rdparty/ib-compress/**.*", 56 | rappPath .. "/3rd/dear-imgui/imgui/**.h", 57 | rappPath .. "/3rd/dear-imgui/imgui/**.cpp", 58 | rappPath .. "/3rd/dear-imgui/imgui/**.inl", 59 | rappPath .. "/3rd/dear-imgui/imgui.cpp", 60 | rappPath .. "/3rd/dear-imgui/imgui_draw.cpp", 61 | rappPath .. "/3rd/dear-imgui/imgui_tables.cpp", 62 | rappPath .. "/3rd/dear-imgui/imgui_widgets.cpp", 63 | rappPath .. "/3rd/dear-imgui/**.h", 64 | rappPath .. "/3rd/dear-imgui/**.inl", 65 | rappPath .. "/3rd/nanovg_bgfx/**.h", 66 | rappPath .. "/3rd/nanovg_bgfx/**.cpp", 67 | rappPath .. "/3rd/nanovg_bgfx/**.c", 68 | rappPath .. "/3rd/vg_renderer/include/**.h", 69 | rappPath .. "/3rd/vg_renderer/include/**.inl", 70 | rappPath .. "/3rd/vg_renderer/src/**.c", 71 | rappPath .. "/3rd/vg_renderer/src/**.cpp", 72 | rappPath .. "/3rd/vg_renderer/src/**.h" 73 | } 74 | excludes { 75 | rappPath .. "/3rd/vg_renderer/src/libs/stb_truetype.cpp" 76 | } 77 | includedirs { 78 | bgfxPath .. "3rdparty/", 79 | rappPath .. "/3rd/", 80 | rappPath .. "/3rd/vg_renderer/include" 81 | } 82 | defines { "RAPP_WITH_BGFX" } 83 | 84 | configuration { "debug" } 85 | defines { "BX_CONFIG_DEBUG=1" } 86 | configuration { "not debug" } 87 | defines { "BX_CONFIG_DEBUG=0" } 88 | configuration {} 89 | 90 | configuration { "vs*", "windows" } 91 | -- 4324 - structure was padded due to alignment specifier 92 | -- 4389 - '==': signed/unsigned mismatch 93 | -- 4244 - vg_renderer: 'argument': conversion from 'float' to 'uint16_t', possible loss of data 94 | -- 4334 - vg_renderer: '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?) 95 | -- 4505 - unreferenced function with internal linkage has been removed 96 | buildoptions { "/wd4133 /wd4389 /wd4244 /wd4334 /wd4505"} 97 | configuration {} 98 | end 99 | 100 | function projectExtraConfigExecutable_rapp_bgfx() 101 | projectExtraConfigExecutable_rapp() 102 | local bgfxPath = find3rdPartyProject("bgfx") 103 | if bgfxPath == nil then 104 | return 105 | end 106 | includedirs { 107 | bgfxPath .. "3rdparty/", 108 | bgfxPath .. "examples/common/" 109 | } 110 | defines { "IMGUI_STB_NAMESPACE=ImStb" } 111 | end 112 | 113 | function projectAdd_rapp_bgfx() 114 | addProject_lib("rapp", Lib.Runtime, false, "_bgfx", true) 115 | end 116 | -------------------------------------------------------------------------------- /img/input_debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RudjiGames/rapp/fe13e24a1a5e04f872bb4c58475b12849db45a39/img/input_debug.png -------------------------------------------------------------------------------- /img/rapp_configs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RudjiGames/rapp/fe13e24a1a5e04f872bb4c58475b12849db45a39/img/rapp_configs.png -------------------------------------------------------------------------------- /inc/widgets/keyboard.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #ifndef RTM_RAPP_KEYBOARD_H 7 | #define RTM_RAPP_KEYBOARD_H 8 | 9 | #include 10 | 11 | #ifdef RAPP_WITH_BGFX 12 | 13 | #include 14 | #include 15 | 16 | namespace rapp { 17 | 18 | constexpr float RAPP_VK_BUTTON_SIZE_X = 39.0f; 19 | constexpr float RAPP_VK_BUTTON_SIZE_Y = 30.0f; 20 | constexpr float RAPP_VK_BUTTON_SPACING = 3.0f; 21 | 22 | static void rappVirtualKeyboardClick(KeyboardState::Key _key) 23 | { 24 | ImGui::SetWindowFocus("Console"); 25 | inputEmitKeyPress(_key); 26 | // ImGui::SetKeyboardFocusHere(-1); // TODO: kbd should have no focus 27 | } 28 | 29 | static void rappVirtualKeyboardLine(const char* key, KeyboardState::Key* _keyMap, float _scale) 30 | { 31 | size_t num = rtm::strLen(key); 32 | for (size_t i=0; i 10 | 11 | #ifdef RAPP_WITH_BGFX 12 | 13 | #include 14 | #include 15 | 16 | #define RAPP_DEBUG_WITH_STD_STRING 1 17 | 18 | #if RAPP_DEBUG_WITH_STD_STRING 19 | #include 20 | #endif // RAPP_DEBUG_WITH_STD_STRING 21 | 22 | // TODO: 23 | // 1. custom types undo 24 | // 2. keyboard navigation 25 | // 3. simplify macros? 26 | 27 | namespace rapp { 28 | 29 | struct Property 30 | { 31 | enum Type : uint32_t 32 | { 33 | None, 34 | Int8, 35 | Int16, 36 | Int32, 37 | Int64, 38 | Uint8, 39 | Uint16, 40 | Uint32, 41 | Uint64, 42 | Float, 43 | Double, 44 | Bool, 45 | Color, 46 | #if RAPP_DEBUG_WITH_STD_STRING 47 | StdString, 48 | #endif // RAPP_DEBUG_WITH_STD_STRING 49 | Custom, 50 | }; 51 | 52 | enum Edit 53 | { 54 | Editing, 55 | Accept, 56 | Cancel 57 | }; 58 | }; 59 | 60 | // Example usage: 61 | // -------------------------- 62 | // 63 | // struct CustomProp {}; // some custom type 64 | // void CustomDfltFn(void*){} // custom default value setter 65 | // void CustomEditorFn(rapp::DebugMenu*){} // custom type editor 66 | // void CustomPreviewFn(rapp::DebugMenu*, ImDrawList*, ImVec2, ImVec2){} // custom type preview 67 | // 68 | // struct Graphics 69 | // { 70 | // float m_clear[4]; 71 | // bool m_hdr; 72 | // float m_minZ; 73 | // uint16_t m_num16; 74 | // CustomProp m_custom; 75 | // }; 76 | // 77 | // Graphics g_Graphics; 78 | // 79 | // RAPP_DEBUG_MENU_ROOT(Graphics, "Graphics") 80 | // RAPP_DEBUG_MENU_PROPERTY(Background, Graphics, rapp::Property::Color, "Background color", &g_Graphics.m_clear, PAPP_ARRAY_ARG({ 0.46f, 0.23f, 0.69f, 1.0f })) 81 | // RAPP_DEBUG_MENU_PROP_VEC(Vector4, Graphics, rapp::Property::Float, "float4 vec", 4) 82 | // RAPP_DEBUG_MENU_PROP_VEC_ELEMENT_RNG(R, Vector4, "R", &g_Graphics.m_vector[0], 0.2f, 0.0f, 1.0f) 83 | // RAPP_DEBUG_MENU_PROP_VEC_ELEMENT_RNG(G, Vector4, "G", &g_Graphics.m_vector[1], 0.4f, 0.0f, 1.0f) 84 | // RAPP_DEBUG_MENU_PROP_VEC_ELEMENT_RNG(B, Vector4, "B", &g_Graphics.m_vector[2], 0.6f, 0.0f, 1.0f) 85 | // RAPP_DEBUG_MENU_PROP_VEC_ELEMENT_RNG(A, Vector4, "A", &g_Graphics.m_vector[3], 1.0f, 0.0f, 1.0f) 86 | // RAPP_DEBUG_MENU_PROP_RNG(MinZ, Graphics, rapp::Property::Float, "Min Z", &g_Graphics.m_minZ, 0.46f, 0.1f, 0.89f) 87 | // RAPP_DEBUG_MENU_PROP_RNG(Num16, Graphics, rapp::Property::Uint16, "Num 16", &g_Graphics.m_num16, 123, 89, 189) 88 | // RAPP_DEBUG_MENU_PROP_CUS(Custom, Graphics, rapp::Property::Custom, "Custom", &g_Graphics.m_custom, CustomDfltFn, CustomEditorFn, CustomPreviewFn) 89 | 90 | // Arrays must be guarded 91 | #define PAPP_ARRAY_ARG(...) __VA_ARGS__ 92 | 93 | // Declares a root debug menu 94 | #define RAPP_DEBUG_MENU_ROOT(_name, _label) \ 95 | rapp::DebugMenu rapp##_name(0, _label); 96 | 97 | // Declares a debug menu 98 | #define RAPP_DEBUG_MENU(_name, _parentName, _label) \ 99 | rapp::DebugMenu rapp##_name(&rapp##_parentName, _label); 100 | 101 | // Declares a vector property with specified element count 102 | #define RAPP_DEBUG_MENU_PROP_VEC(_name, _parentName, _type, _label, _count) \ 103 | rapp::DebugMenu rapp##_name(&rapp##_parentName, _label, _count, _type); 104 | 105 | // Declares a vector property element 106 | #define RAPP_DEBUG_MENU_PROP_VEC_ELEMENT(_name, _parentName, _label, _pointer, _defaultValue) \ 107 | auto rapp##_name##__LINE__ = _defaultValue; \ 108 | rapp::DebugMenu rapp##_name(&rapp##_parentName, _label, rapp##_parentName.m_type, _pointer, &rapp##_name##__LINE__); 109 | 110 | // Declares a vector property element with range 111 | #define RAPP_DEBUG_MENU_PROP_VEC_ELEMENT_RNG(_name, _parentName, _label, _pointer, _defaultValue, _min, _max) \ 112 | auto rapp##_name##__LINE__ = _defaultValue; \ 113 | auto rapp##_name##_min_##__LINE__ = _min; \ 114 | auto rapp##_name##_max_##__LINE__ = _max; \ 115 | rapp::DebugMenu rapp##_name(&rapp##_parentName, _label, rapp##_parentName.m_type, _pointer, &rapp##_name##__LINE__, &rapp##_name##_min_##__LINE__, &rapp##_name##_max_##__LINE__); 116 | 117 | // Declares a property, each property belongs to a menu 118 | #define RAPP_DEBUG_MENU_PROPERTY(_name, _parentName, _type, _label, _pointer, _defaultValue) \ 119 | auto rapp##_name##__LINE__ = _defaultValue; \ 120 | rapp::DebugMenu rapp##_name(&rapp##_parentName, _label, _type, _pointer, &rapp##_name##__LINE__); 121 | 122 | // Declares a ranged property (has minimum and maximum) 123 | #define RAPP_DEBUG_MENU_PROP_RNG(_name, _parentName, _type, _label, _pointer, _defaultValue, _min, _max) \ 124 | auto rapp##_name##__LINE__ = _defaultValue; \ 125 | auto rapp##_name##_min_##__LINE__ = _min; \ 126 | auto rapp##_name##_max_##__LINE__ = _max; \ 127 | rapp::DebugMenu rapp##_name(&rapp##_parentName, _label, _type, _pointer, &rapp##_name##__LINE__, &rapp##_name##_min_##__LINE__, &rapp##_name##_max_##__LINE__); 128 | 129 | // Declares a custom property 130 | #define RAPP_DEBUG_MENU_PROP_CUS(_name, _parentName, _type, _label, _pointer, _setDefaultFn, _editFn, _viewFn) \ 131 | rapp::DebugMenu rapp##_name(&rapp##_parentName, _label, _type, _pointer, 0, 0, 0, _setDefaultFn, _editFn, _viewFn); 132 | 133 | #if RAPP_DEBUG_WITH_STD_STRING 134 | #define RAPP_DEBUG_MENU_PROP_STR(_name, _parentName, _type, _label, _pointer) \ 135 | RAPP_DEBUG_MENU_PROP_CUS(_name, _parentName, _type, _label, _pointer, rapp::stringSetDefaultFn, rapp::stringEditorFn, rapp::stringPreviewFn) 136 | #endif // RAPP_DEBUG_WITH_STD_STRING 137 | 138 | // Forward declaration of the debug menu drawing function 139 | void rappDebugMenu(); 140 | 141 | struct DebugMenu 142 | { 143 | typedef void (*CustomDfltFn)(void* _pointer); 144 | typedef void (*CustomEditFn)(void* _pointer); 145 | typedef void (*CustomPrevFn)(void* _pointer, ImDrawList* _drawList, ImVec2 _minXY, ImVec2 _size); 146 | 147 | static const int MAX_VARIABLES = 8; 148 | static const int MAX_VARIABLE_SIZE = sizeof(double); 149 | static const int MAX_STORAGE_SIZE = sizeof(double); 150 | 151 | struct MinMax 152 | { 153 | uint8_t m_min[MAX_STORAGE_SIZE]; 154 | uint8_t m_max[MAX_STORAGE_SIZE]; 155 | }; 156 | 157 | DebugMenu* m_parent; 158 | uint32_t m_index; 159 | uint32_t m_numChildren; 160 | union 161 | { 162 | DebugMenu* m_children[8]; 163 | MinMax m_minMax; 164 | }; 165 | const char* m_label; 166 | Property::Type m_type; 167 | uint32_t m_width; 168 | void* m_value; 169 | CustomEditFn m_customEditor; 170 | CustomPrevFn m_customPreview; 171 | bool m_minmaxSet; 172 | 173 | DebugMenu(DebugMenu* _parent = 0, const char* _label = 0, uint32_t _width = 1, Property::Type _type = Property::None); 174 | 175 | DebugMenu(DebugMenu* _parent, const char* _label, Property::Type _type, void* _pointer 176 | , void* _defaultValue = 0 177 | , void* _minValue = 0 178 | , void* _maxValue = 0 179 | , CustomDfltFn _customDefault = 0 180 | , CustomEditFn _customEditor = 0 181 | , CustomPrevFn _customPreview = 0); 182 | }; 183 | 184 | #if RAPP_DEBUG_WITH_STD_STRING 185 | void stringSetDefaultFn(void* _var); 186 | void stringEditorFn(void* _var); 187 | void stringPreviewFn(void* _var, ImDrawList* _drawList, ImVec2 _minXY, ImVec2 _size); 188 | #endif // RAPP_DEBUG_WITH_STD_STRING 189 | 190 | } // namespace rapp 191 | 192 | #endif // RAPP_WITH_BGFX 193 | 194 | #endif // RTM_RAPP_DEBUG_H 195 | -------------------------------------------------------------------------------- /inc/widgets/widget_theme.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #ifndef RTM_RAPP_IMGUI_COLORS_H 7 | #define RTM_RAPP_IMGUI_COLORS_H 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #define RAPP_COLOR_WIDGET_OUTLINE IM_COL32( 96, 96,128,255) 14 | #define RAPP_COLOR_WIDGET IM_COL32( 32, 32, 48,255) 15 | #define RAPP_COLOR_WIDGET_HIGHLIGHT IM_COL32(128,128,160,255) 16 | #define RAPP_COLOR_WIDGET_BLINK IM_COL32( 24, 24, 32,255) 17 | #define RAPP_COLOR_TEXT IM_COL32(255,255,255,255) 18 | #define RAPP_COLOR_TEXT_HIGHLIGHT IM_COL32(128,255,255,255) 19 | #define RAPP_COLOR_TEXT_TITLE IM_COL32(255,255,155,255) 20 | #define RAPP_COLOR_TEXT_SHADOW IM_COL32( 0, 0, 0,255) 21 | #define RAPP_COLOR_TEXT_INACTIVE IM_COL32(192,192,192,255) 22 | #define RAPP_COLOR_TEXT_STATUS IM_COL32(192, 32, 32,255) 23 | 24 | #define RAPP_WIDGET_SPACING 6 25 | #define RAPP_WIDGET_OUTLINE 3 26 | 27 | #define RAPP_FLASH_TIME_IN_MS 240.0f 28 | 29 | namespace rapp { 30 | 31 | template 32 | static inline T rappMax(T _v1, T _v2) { return _v1 > _v2 ? _v1 : _v2; } 33 | template 34 | static inline T rappMin(T _v1, T _v2) { return _v1 < _v2 ? _v1 : _v2; } 35 | 36 | inline static void flashColorElapsed(ImU32& _drawColor, ImU32 _target, uint64_t _elapsedTime) 37 | { 38 | ImVec4 target = ImColor(_target); 39 | 40 | float msSince = rtm::CPU::time(_elapsedTime, rtm::CPU::frequency()); 41 | msSince = rappMin(msSince * 1000.0f, RAPP_FLASH_TIME_IN_MS); 42 | msSince = 1.0f - (msSince / RAPP_FLASH_TIME_IN_MS); 43 | 44 | ImVec4 col4 = ImColor(_drawColor); 45 | _drawColor = ImColor( col4.x + (target.x - col4.x) * msSince, 46 | col4.y + (target.y - col4.y) * msSince, 47 | col4.z + (target.z - col4.z) * msSince, 48 | 255.0f); 49 | } 50 | 51 | } // namespace rapp 52 | 53 | #endif // RTM_RAPP_IMGUI_COLORS_H 54 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 Milos Toisc. All rights reserved. 3 | # License: http://www.opensource.org/licenses/BSD-2-Clause 4 | # 5 | 6 | GENIE=../build/tools/bin/$(OS)/genie 7 | 8 | all: 9 | $(GENIE) vs2015 10 | $(GENIE) vs2017 11 | $(GENIE) --gcc=android-arm gmake 12 | $(GENIE) --gcc=android-mips gmake 13 | $(GENIE) --gcc=android-x86 gmake 14 | $(GENIE) --gcc=mingw-gcc gmake 15 | $(GENIE) --gcc=linux-gcc gmake 16 | $(GENIE) --gcc=osx gmake 17 | $(GENIE) --gcc=ios-arm gmake 18 | $(GENIE) --gcc=ios-simulator gmake 19 | $(GENIE) --gcc=ios-simulator64 gmake 20 | $(GENIE) xcode4 21 | 22 | gmake-linux: 23 | $(GENIE) --file=genie/genie.lua --gcc=linux-gcc --with-glfw gmake 24 | linux-debug32: gmake-linux 25 | make -R -C ../.build/linux/gcc/rapp/projects config=debug32 26 | linux-release32: gmake-linux 27 | make -R -C ../.build/linux/gcc/rapp/projects config=release32 28 | linux-debug64: gmake-linux 29 | make -R -C ../.build/linux/gcc/rapp/projects config=debug64 30 | linux-release64: gmake-linux 31 | make -R -C ../.build/linux/gcc/rapp/projects config=release64 32 | #linux: linux-debug32 linux-release32 linux-debug64 linux-release64 33 | linux: linux-debug64 linux-release64 34 | 35 | gmake-mingw-gcc: 36 | $(GENIE) --file=genie/genie.lua --gcc=mingw-gcc gmake 37 | mingw-gcc-debug32: gmake-mingw-gcc 38 | make -R -C ../.build/windows/mingw-gcc/rapp/projects config=debug32 39 | mingw-gcc-release32: gmake-mingw-gcc 40 | make -R -C ../.build/windows/mingw-gcc/rapp/projects config=release32 41 | mingw-gcc-debug64: gmake-mingw-gcc 42 | make -R -C ../.build/windows/mingw-gcc/rapp/projects config=debug64 43 | mingw-gcc-release64: gmake-mingw-gcc 44 | make -R -C ../.build/windows/mingw-gcc/rapp/projects config=release64 45 | mingw-gcc: mingw-gcc-debug32 mingw-gcc-release32 mingw-gcc-debug64 mingw-gcc-release64 46 | 47 | gmake-mingw-clang: 48 | $(GENIE) --file=genie/genie.lua --clang=mingw-clang gmake 49 | mingw-clang-debug32: gmake-mingw-clang 50 | make -R -C ../.build/windows/mingw-clang/rapp/projects config=debug32 51 | mingw-clang-release32: gmake-mingw-clang 52 | make -R -C ../.build/windows/mingw-clang/rapp/projects config=release32 53 | mingw-clang-debug64: gmake-mingw-clang 54 | make -R -C ../.build/windows/mingw-clang/rapp/projects config=debug64 55 | mingw-clang-release64: gmake-mingw-clang 56 | make -R -C ../.build/windows/mingw-clang/rapp/projects config=release64 57 | mingw-clang: mingw-clang-debug32 mingw-clang-release32 mingw-clang-debug64 mingw-clang-release64 58 | 59 | vs2015: 60 | $(GENIE) --file=genie/genie.lua vs2015 61 | 62 | vs2017: 63 | $(GENIE) --file=genie/genie.lua vs2017 64 | 65 | ../.build/osx/clang/rapp/projects: 66 | $(GENIE) --file=genie/genie.lua --gcc=osx gmake 67 | osx-debug64: ../.build/osx/clang/rapp/projects 68 | make -R -C ../.build/osx/clang/rapp/projects config=debug64 69 | osx-release64: ../.build/osx/clang/rapp/projects 70 | make -R -C ../.build/osx/clang/rapp/projects config=release64 71 | osx: osx-debug64 osx-release64 72 | 73 | clean: 74 | @echo Cleaning... 75 | -@rm -rf ../.build 76 | 77 | ### 78 | 79 | SILENT ?= @ 80 | 81 | UNAME := $(shell uname) 82 | ifeq ($(UNAME),$(filter $(UNAME),Linux GNU Darwin)) 83 | ifeq ($(UNAME),$(filter $(UNAME),Darwin)) 84 | OS=darwin 85 | else 86 | OS=linux 87 | endif 88 | else 89 | OS=windows 90 | endif 91 | 92 | -------------------------------------------------------------------------------- /samples/01_cmd_line/cmd_line.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | 8 | struct CmdLineApp : public rapp::App 9 | { 10 | RAPP_CLASS(CmdLineApp) 11 | 12 | int init(int32_t /*_argc*/, const char* const* /*_argv*/, rtmLibInterface* /*_libInterface = 0*/) 13 | { 14 | static const rapp::InputBinding bindings[] = 15 | { 16 | { NULL, "exit", 1, { rapp::KeyboardState::Key::KeyQ, rapp::KeyboardState::Modifier::LCtrl }}, 17 | { NULL, "exit", 1, { rapp::KeyboardState::Key::KeyQ, rapp::KeyboardState::Modifier::RCtrl }}, 18 | RAPP_INPUT_BINDING_END 19 | }; 20 | 21 | rapp::inputAddBindings("bindings", bindings); 22 | rapp::cmdAdd("exit", cmdExit); 23 | 24 | return 0; 25 | } 26 | 27 | void suspend() {} 28 | void resume() {} 29 | 30 | void update(float /*_time*/) 31 | { 32 | } 33 | 34 | void draw(float /*_alpha*/) 35 | { 36 | appRunOnMainThread(mainThreadFunc, this); 37 | rtm::Console::rgb(255, 255, 0, "Printing from app thread (ID: %u)\n", (uint32_t)rtm::Thread::getThreadID()); 38 | } 39 | 40 | void shutDown() 41 | { 42 | rtm::Console::rgb(255, 255, 0, "Shutting down app\n", (uint32_t)rtm::Thread::getThreadID()); 43 | rapp::inputRemoveBindings("bindings"); 44 | } 45 | 46 | static void mainThreadFunc(void* /*_appClass*/) 47 | { 48 | rtm::Console::rgb(0, 255, 0, "Printing from main thread (ID: %u)\n", (uint32_t)rtm::Thread::getThreadID()); 49 | } 50 | 51 | static int cmdExit(App* _app, void* _userData, int _argc, char const* const* _argv) 52 | { 53 | RTM_UNUSED_3(_userData, _argv, _argc); 54 | _app->quit(); 55 | return 0; 56 | } 57 | }; 58 | 59 | RAPP_REGISTER(CmdLineApp, "Command line", "Example of command line application"); 60 | -------------------------------------------------------------------------------- /samples/01_cmd_line/cmd_line_pch.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | 8 | -------------------------------------------------------------------------------- /samples/01_cmd_line/cmd_line_pch.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #define RBASE_NAMESPACE rapp 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /samples/02_job_system/job_system.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | 8 | struct JobSystemApp : public rapp::App 9 | { 10 | RAPP_CLASS(JobSystemApp) 11 | 12 | enum Mode 13 | { 14 | Serial, 15 | Parallel 16 | }; 17 | 18 | Mode m_runMode; 19 | 20 | struct Tile 21 | { 22 | uint32_t x, y, w, h, tw, th; 23 | }; 24 | 25 | int init(int32_t /*_argc*/, const char* const* /*_argv*/, rtmLibInterface* /*_libInterface = 0*/) 26 | { 27 | static const rapp::InputBinding bindings[] = 28 | { 29 | { NULL, "switch", 1, { rapp::KeyboardState::Key::KeyS, rapp::KeyboardState::Modifier::LCtrl }}, 30 | { NULL, "exit", 1, { rapp::KeyboardState::Key::KeyQ, rapp::KeyboardState::Modifier::LCtrl }}, 31 | RAPP_INPUT_BINDING_END 32 | }; 33 | 34 | rapp::inputAddBindings("bindings", bindings); 35 | rapp::cmdAdd("exit", cmdExit); 36 | rapp::cmdAdd("switch", cmdSwitchMode); 37 | 38 | m_runMode = Mode::Parallel; 39 | return 0; 40 | } 41 | 42 | void suspend() {} 43 | void resume() {} 44 | 45 | static const uint32_t s_width = 2048; 46 | static const uint32_t s_height = 2048; 47 | static const uint32_t s_tile = 64; 48 | static const uint32_t s_tileX = s_width / s_tile; 49 | static const uint32_t s_tileY = s_height / s_tile; 50 | 51 | void update(float /*_time*/) 52 | { 53 | static Tile s_tiles[s_tileX * s_tileY]; 54 | for (uint32_t y=0; yy; Y < tile->y + tile->h; ++Y) 111 | for (uint32_t X = tile->x; X < tile->x + tile->w; ++X) 112 | { 113 | float x = (float)Y * 2 / tile->tw - 1.5f; 114 | float y = (float)X * 2 / tile->th - 1; 115 | 116 | int iteration = 0; 117 | while (++iteration < 12) 118 | { 119 | const float nx = x * x - y * y; 120 | const float ny = 2.0f * x * y; 121 | x = nx; 122 | y = ny; 123 | } 124 | } 125 | } 126 | } 127 | 128 | static int cmdExit(App* _app, void* _userData, int _argc, char const* const* _argv) 129 | { 130 | RTM_UNUSED_3(_userData, _argv, _argc); 131 | _app->quit(); 132 | return 0; 133 | } 134 | 135 | static int cmdSwitchMode(App* _app, void* _userData, int _argc, char const* const* _argv) 136 | { 137 | RTM_UNUSED_3(_userData, _argv, _argc); 138 | JobSystemApp* app = (JobSystemApp*)_app; 139 | app->m_runMode = (app->m_runMode == Mode::Parallel) ? Mode::Serial : Mode::Parallel; 140 | return 0; 141 | } 142 | }; 143 | 144 | RAPP_REGISTER(JobSystemApp, "Job system", "Example of using the job system"); 145 | -------------------------------------------------------------------------------- /samples/02_job_system/job_system_pch.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | 8 | -------------------------------------------------------------------------------- /samples/02_job_system/job_system_pch.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #define RBASE_NAMESPACE rapp 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /samples/03_bgfx/bgfx.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | #include 8 | 9 | struct bgfxApp : public rapp::App 10 | { 11 | RAPP_CLASS(bgfxApp) 12 | 13 | rapp::WindowHandle m_window; 14 | float m_time; 15 | 16 | int init(int32_t /*_argc*/, const char* const* /*_argv*/, rtmLibInterface* /*_libInterface = 0*/) 17 | { 18 | m_time = 0.0f; 19 | 20 | static const rapp::InputBinding bindings[] = 21 | { 22 | { NULL, "exit", 1, { rapp::KeyboardState::Key::KeyQ, rapp::KeyboardState::Modifier::LCtrl }}, 23 | { NULL, "exit", 1, { rapp::KeyboardState::Key::KeyQ, rapp::KeyboardState::Modifier::RCtrl }}, 24 | { NULL, "hide", 1, { rapp::KeyboardState::Key::Tilde, rapp::KeyboardState::Modifier::NoMods }}, 25 | RAPP_INPUT_BINDING_END 26 | }; 27 | 28 | rapp::inputAddBindings("bindings", bindings); 29 | rapp::cmdAdd("exit", cmdExit, 0, "quits application"); 30 | rapp::cmdAdd("hide", cmdHideConsole, 0, "hides console"); 31 | 32 | uint32_t width, height; 33 | rapp::windowGetDefaultSize(&width, &height); 34 | m_width = width; 35 | m_height = height; 36 | 37 | rapp::appGraphicsInit(this, m_width, m_height); 38 | 39 | return 0; 40 | } 41 | 42 | void suspend() {} 43 | void resume() {} 44 | void update(float _time) 45 | { 46 | m_time += _time; 47 | } 48 | 49 | void draw(float /*_alpha*/) 50 | { 51 | appRunOnMainThread(mainThreadFunc, this); 52 | 53 | rtm::Console::rgb(255, 255, 0, "Printing from app thread (ID: %u)\n", (uint32_t)rtm::Thread::getThreadID()); 54 | 55 | // Use debug font to print information about this example. 56 | bgfx::dbgTextClear(); 57 | bgfx::dbgTextPrintf(0, 1, 0x17, "rapp/samples/bgfx"); 58 | bgfx::dbgTextPrintf(0, 2, 0x37, m_description); 59 | 60 | // debug input 61 | rapp::inputDgbGamePads(); 62 | rapp::inputDgbMouse(); 63 | rapp::inputDgbKeyboard(); 64 | rapp::inputDgbTouch(); 65 | } 66 | 67 | void drawEyes(float x, float y, float w, float h, float mx, float my) 68 | { 69 | float ex = w *0.23f; 70 | float ey = h * 0.5f; 71 | float lx = x + ex; 72 | float ly = y + ey; 73 | float rx = x + w - ex; 74 | float ry = y + ey; 75 | float dx,dy,d; 76 | float br = (ex < ey ? ex : ey) * 0.5f; 77 | float blink = 1 - powf(sinf(m_time*0.5f),200)*0.8f; 78 | 79 | rapp::vgBeginPath(); 80 | rapp::vgEllipse(lx,ly, ex,ey); 81 | rapp::vgEllipse(rx,ry, ex,ey); 82 | rapp::vgFillLinearGradient(x, y + h * 0.25f, x + w * 0.1f, y + h, rapp::vgColor(220, 220, 220, 255), rapp::vgColor(128, 128, 128, 255)); 83 | 84 | dx = (mx - rx) / (ex * 10); 85 | dy = (my - ry) / (ey * 10); 86 | d = sqrtf(dx*dx+dy*dy); 87 | if (d > 1.0f) { 88 | dx /= d; dy /= d; 89 | } 90 | dx *= ex*0.4f; 91 | dy *= ey*0.5f; 92 | rapp::vgBeginPath(); 93 | rapp::vgEllipse(lx+dx,ly+dy+ey*0.25f*(1-blink), br,br*blink); 94 | rapp::vgFill(rapp::vgColor(32, 32, 32, 255), 0); 95 | 96 | dx = (mx - rx) / (ex * 10); 97 | dy = (my - ry) / (ey * 10); 98 | d = sqrtf(dx*dx+dy*dy); 99 | if (d > 1.0f) { 100 | dx /= d; dy /= d; 101 | } 102 | dx *= ex*0.4f; 103 | dy *= ey*0.5f; 104 | rapp::vgBeginPath(); 105 | rapp::vgEllipse(rx+dx,ry+dy+ey*0.25f*(1-blink), br,br*blink); 106 | rapp::vgFill(rapp::vgColor(32, 32, 32, 255), 0); 107 | 108 | rapp::vgBeginPath(); 109 | rapp::vgEllipse(lx,ly, ex,ey); 110 | rapp::vgFillRadialGradient(lx - ex * 0.25f, ly - ey * 0.5f, ex * 0.1f, ex * 0.75f, rapp::vgColor(255, 255, 255, 128), rapp::vgColor(255, 255, 255, 0)); 111 | 112 | rapp::vgBeginPath(); 113 | rapp::vgEllipse(rx,ry, ex,ey); 114 | rapp::vgFillRadialGradient(rx-ex*0.25f,ry-ey*0.5f, ex*0.1f,ex*0.75f, rapp::vgColor(255,255,255,128), rapp::vgColor(255,255,255,0) ); 115 | } 116 | 117 | void drawGUI() 118 | { 119 | ImGui::SetNextWindowPos(ImVec2(10.0f, 666.0f), ImGuiCond_FirstUseEver); 120 | ImGui::SetNextWindowSize(ImVec2(300.0f, 80.0f), ImGuiCond_FirstUseEver); 121 | ImGui::Begin("ImGui dialog"); 122 | ImGui::Separator(); 123 | ImGui::Button("Button", ImVec2(180.0f,23.0f)); 124 | ImGui::End(); 125 | 126 | rapp::MouseState ms; 127 | rapp::inputGetMouseState(ms); 128 | drawEyes(150.0f, 150.0f, 150.0f, 100.0f, (float)ms.m_absolute[0], (float)ms.m_absolute[1]); 129 | } 130 | 131 | void shutDown() 132 | { 133 | rtm::Console::rgb(255, 255, 0, "Shutting down app\n"); 134 | rapp::appGraphicsShutdown(this, m_window); 135 | rapp::inputRemoveBindings("bindings"); 136 | } 137 | 138 | static void mainThreadFunc(void* /*_appClass*/) 139 | { 140 | rtm::Console::rgb(0, 255, 0, "Printing from main thread (ID: %u)\n", (uint32_t)rtm::Thread::getThreadID()); 141 | } 142 | 143 | static int cmdExit(rapp::App* _app, void* _userData, int _argc, char const* const* _argv) 144 | { 145 | RTM_UNUSED_3(_userData, _argv, _argc); 146 | _app->quit(); 147 | return 0; 148 | } 149 | 150 | static int cmdHideConsole(rapp::App* _app, void* _userData, int _argc, char const* const* _argv) 151 | { 152 | RTM_UNUSED_3(_userData, _argv, _argc); 153 | rapp::cmdConsoleToggle(_app); 154 | return 0; 155 | } 156 | }; 157 | 158 | RAPP_REGISTER(bgfxApp, "bgfx", "Example of bgfx based application"); 159 | -------------------------------------------------------------------------------- /samples/03_bgfx/bgfx_pch.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | 8 | -------------------------------------------------------------------------------- /samples/03_bgfx/bgfx_pch.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #define RBASE_NAMESPACE rapp 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define RAPP_WITH_BGFX 13 | #include 14 | -------------------------------------------------------------------------------- /samples/04_multi_app/multi_app_1.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | 8 | struct app1 : public rapp::App 9 | { 10 | RAPP_CLASS(app1) 11 | 12 | rapp::WindowHandle m_window; 13 | 14 | int init(int32_t /*_argc*/, const char* const* /*_argv*/, rtmLibInterface* /*_libInterface = 0*/) 15 | { 16 | static const rapp::InputBinding bindings[] = 17 | { 18 | { NULL, "exit", 1, { rapp::KeyboardState::Key::KeyQ, rapp::KeyboardState::Modifier::LCtrl }}, 19 | { NULL, "exit", 1, { rapp::KeyboardState::Key::KeyQ, rapp::KeyboardState::Modifier::RCtrl }}, 20 | { NULL, "hide", 1, { rapp::KeyboardState::Key::Tilde, rapp::KeyboardState::Modifier::NoMods }}, 21 | RAPP_INPUT_BINDING_END 22 | }; 23 | 24 | rapp::inputAddBindings("bindings", bindings); 25 | rapp::cmdAdd("exit", cmdExit, 0, "quits application"); 26 | rapp::cmdAdd("hide", cmdHideConsole, 0, "hides console"); 27 | 28 | uint32_t width, height; 29 | rapp::windowGetDefaultSize(&width, &height); 30 | m_width = width; 31 | m_height = height; 32 | 33 | m_window = rapp::appGraphicsInit(this, m_width, m_height); 34 | return 0; 35 | } 36 | 37 | void suspend() {} 38 | void resume() {} 39 | void update(float /*_time*/) {} 40 | 41 | void draw(float /*_alpha*/) 42 | { 43 | // Use debug font to print information about this example. 44 | bgfx::dbgTextClear(); 45 | bgfx::dbgTextPrintf(0, 1, 0x17, "rapp/samples/multi_app"); 46 | bgfx::dbgTextPrintf(0, 2, 0x37, m_description); 47 | 48 | // debug input 49 | rapp::inputDgbGamePads(); 50 | rapp::inputDgbMouse(); 51 | rapp::inputDgbKeyboard(); 52 | rapp::inputDgbTouch(); 53 | } 54 | 55 | void drawGUI() 56 | { 57 | ImGui::SetNextWindowPos(ImVec2(10.0f, 666.0f), ImGuiCond_FirstUseEver); 58 | ImGui::SetNextWindowSize(ImVec2(300.0f, 80.0f), ImGuiCond_FirstUseEver); 59 | ImGui::Begin("ImGui dialog"); 60 | ImGui::Separator(); 61 | ImGui::Button("Button", ImVec2(180.0f,23.0f)); 62 | ImGui::End(); 63 | } 64 | 65 | void shutDown() 66 | { 67 | rtm::Console::rgb(255, 255, 0, "Shutting down app\n", (uint32_t)rtm::Thread::getThreadID()); 68 | rapp::appGraphicsShutdown(this, m_window); 69 | rapp::inputRemoveBindings("bindings"); 70 | } 71 | 72 | static int cmdExit(rapp::App* _app, void* _userData, int _argc, char const* const* _argv) 73 | { 74 | RTM_UNUSED_3(_userData, _argv, _argc); 75 | _app->quit(); 76 | return 0; 77 | } 78 | 79 | static int cmdHideConsole(rapp::App* _app, void* _userData, int _argc, char const* const* _argv) 80 | { 81 | RTM_UNUSED_3(_userData, _argv, _argc); 82 | rapp::cmdConsoleToggle(_app); 83 | return 0; 84 | } 85 | }; 86 | 87 | RAPP_REGISTER(app1, "app1", "Application 1"); 88 | -------------------------------------------------------------------------------- /samples/04_multi_app/multi_app_2.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | 8 | struct app2 : public rapp::App 9 | { 10 | RAPP_CLASS(app2) 11 | 12 | rapp::WindowHandle m_window; 13 | 14 | int init(int32_t /*_argc*/, const char* const* /*_argv*/, rtmLibInterface* /*_libInterface = 0*/) 15 | { 16 | static const rapp::InputBinding bindings[] = 17 | { 18 | { NULL, "exit", 1, { rapp::KeyboardState::Key::KeyQ, rapp::KeyboardState::Modifier::LCtrl }}, 19 | { NULL, "exit", 1, { rapp::KeyboardState::Key::KeyQ, rapp::KeyboardState::Modifier::RCtrl }}, 20 | { NULL, "hide", 1, { rapp::KeyboardState::Key::Tilde, rapp::KeyboardState::Modifier::NoMods }}, 21 | RAPP_INPUT_BINDING_END 22 | }; 23 | 24 | rapp::inputAddBindings("bindings", bindings); 25 | rapp::cmdAdd("exit", cmdExit, 0, "quits application"); 26 | rapp::cmdAdd("hide", cmdHideConsole, 0, "hides console"); 27 | 28 | uint32_t width, height; 29 | rapp::windowGetDefaultSize(&width, &height); 30 | m_width = width; 31 | m_height = height; 32 | 33 | m_window = rapp::appGraphicsInit(this, m_width, m_height); 34 | return 0; 35 | } 36 | 37 | void suspend() {} 38 | void resume() {} 39 | void update(float /*_time*/) {} 40 | 41 | void draw(float /*_alpha*/) 42 | { 43 | // Use debug font to print information about this example. 44 | bgfx::dbgTextClear(); 45 | bgfx::dbgTextPrintf(0, 1, 0x17, "rapp/samples/multi_app"); 46 | bgfx::dbgTextPrintf(0, 2, 0x37, m_description); 47 | 48 | // debug input 49 | rapp::inputDgbGamePads(); 50 | rapp::inputDgbMouse(); 51 | rapp::inputDgbKeyboard(); 52 | rapp::inputDgbTouch(); 53 | } 54 | 55 | void drawGUI() 56 | { 57 | ImGui::SetNextWindowPos(ImVec2(10.0f, 666.0f), ImGuiCond_FirstUseEver); 58 | ImGui::SetNextWindowSize(ImVec2(300.0f, 80.0f), ImGuiCond_FirstUseEver); 59 | ImGui::Begin("ImGui dialog"); 60 | ImGui::Separator(); 61 | ImGui::Button("Button", ImVec2(180.0f,23.0f)); 62 | ImGui::End(); 63 | } 64 | 65 | void shutDown() 66 | { 67 | rtm::Console::rgb(255, 255, 0, "Shutting down app\n", (uint32_t)rtm::Thread::getThreadID()); 68 | rapp::appGraphicsShutdown(this, m_window); 69 | rapp::inputRemoveBindings("bindings"); 70 | } 71 | 72 | static int cmdExit(rapp::App* _app, void* _userData, int _argc, char const* const* _argv) 73 | { 74 | RTM_UNUSED_3(_userData, _argv, _argc); 75 | _app->quit(); 76 | return 0; 77 | } 78 | 79 | static int cmdHideConsole(rapp::App* _app, void* _userData, int _argc, char const* const* _argv) 80 | { 81 | RTM_UNUSED_3(_userData, _argv, _argc); 82 | rapp::cmdConsoleToggle(_app); 83 | return 0; 84 | } 85 | }; 86 | 87 | RAPP_REGISTER(app2, "app2", "Application 2"); 88 | -------------------------------------------------------------------------------- /samples/04_multi_app/multi_app_3.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | 8 | struct app3 : public rapp::App 9 | { 10 | RAPP_CLASS(app3) 11 | 12 | rapp::WindowHandle m_window; 13 | 14 | int init(int32_t /*_argc*/, const char* const* /*_argv*/, rtmLibInterface* /*_libInterface = 0*/) 15 | { 16 | static const rapp::InputBinding bindings[] = 17 | { 18 | { NULL, "exit", 1, { rapp::KeyboardState::Key::KeyQ, rapp::KeyboardState::Modifier::LCtrl }}, 19 | { NULL, "exit", 1, { rapp::KeyboardState::Key::KeyQ, rapp::KeyboardState::Modifier::RCtrl }}, 20 | { NULL, "hide", 1, { rapp::KeyboardState::Key::Tilde, rapp::KeyboardState::Modifier::NoMods }}, 21 | RAPP_INPUT_BINDING_END 22 | }; 23 | 24 | rapp::inputAddBindings("bindings", bindings); 25 | rapp::cmdAdd("exit", cmdExit, 0, "quits application"); 26 | rapp::cmdAdd("hide", cmdHideConsole, 0, "hides console"); 27 | 28 | uint32_t width, height; 29 | rapp::windowGetDefaultSize(&width, &height); 30 | m_width = width; 31 | m_height = height; 32 | 33 | m_window = rapp::appGraphicsInit(this, m_width, m_height); 34 | return 0; 35 | } 36 | 37 | void suspend() {} 38 | void resume() {} 39 | void update(float /*_time*/) {} 40 | 41 | void draw(float /*_alpha*/) 42 | { 43 | // Use debug font to print information about this example. 44 | bgfx::dbgTextClear(); 45 | bgfx::dbgTextPrintf(0, 1, 0x17, "rapp/samples/multi_app"); 46 | bgfx::dbgTextPrintf(0, 2, 0x37, m_description); 47 | 48 | // debug input 49 | rapp::inputDgbGamePads(); 50 | rapp::inputDgbMouse(); 51 | rapp::inputDgbKeyboard(); 52 | rapp::inputDgbTouch(); 53 | } 54 | 55 | void drawGUI() 56 | { 57 | ImGui::SetNextWindowPos(ImVec2(10.0f, 666.0f), ImGuiCond_FirstUseEver); 58 | ImGui::SetNextWindowSize(ImVec2(300.0f, 80.0f), ImGuiCond_FirstUseEver); 59 | ImGui::Begin("ImGui dialog"); 60 | ImGui::Separator(); 61 | ImGui::Button("Button", ImVec2(180.0f,23.0f)); 62 | ImGui::End(); 63 | } 64 | 65 | void shutDown() 66 | { 67 | rtm::Console::rgb(255, 255, 0, "Shutting down app\n"); 68 | rapp::appGraphicsShutdown(this, m_window); 69 | rapp::inputRemoveBindings("bindings"); 70 | } 71 | 72 | static int cmdExit(rapp::App* _app, void* _userData, int _argc, char const* const* _argv) 73 | { 74 | RTM_UNUSED_3(_userData, _argv, _argc); 75 | _app->quit(); 76 | return 0; 77 | } 78 | 79 | static int cmdHideConsole(rapp::App* _app, void* _userData, int _argc, char const* const* _argv) 80 | { 81 | RTM_UNUSED_3(_userData, _argv, _argc); 82 | rapp::cmdConsoleToggle(_app); 83 | return 0; 84 | } 85 | }; 86 | 87 | RAPP_REGISTER(app3, "app3", "Application 3"); 88 | -------------------------------------------------------------------------------- /samples/04_multi_app/multi_app_pch.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | 8 | -------------------------------------------------------------------------------- /samples/04_multi_app/multi_app_pch.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #define RBASE_NAMESPACE rapp 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define RAPP_WITH_BGFX 13 | #include 14 | -------------------------------------------------------------------------------- /samples/05_rprof/rprof.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | struct rprofApp : public rapp::App 11 | { 12 | RAPP_CLASS(rprofApp) 13 | 14 | rapp::WindowHandle m_window; 15 | float m_time; 16 | 17 | int init(int32_t _argc, const char* const* _argv, rtmLibInterface* _libInterface) 18 | { 19 | RTM_UNUSED_3(_argc, _argv, _libInterface); 20 | 21 | m_time = 0.0f; 22 | 23 | static const rapp::InputBinding bindings[] = 24 | { 25 | { NULL, "exit", 1, { rapp::KeyboardState::Key::KeyQ, rapp::KeyboardState::Modifier::LCtrl }}, 26 | { NULL, "exit", 1, { rapp::KeyboardState::Key::KeyQ, rapp::KeyboardState::Modifier::RCtrl }}, 27 | { NULL, "hide", 1, { rapp::KeyboardState::Key::Tilde, rapp::KeyboardState::Modifier::NoMods }}, 28 | RAPP_INPUT_BINDING_END 29 | }; 30 | 31 | rapp::inputAddBindings("bindings", bindings); 32 | rapp::cmdAdd("exit", cmdExit, 0, "quits application"); 33 | rapp::cmdAdd("hide", cmdHideConsole, 0, "hides console"); 34 | 35 | uint32_t width, height; 36 | rapp::windowGetDefaultSize(&width, &height); 37 | m_width = width; 38 | m_height = height; 39 | 40 | rapp::appGraphicsInit(this, m_width, m_height); 41 | 42 | #ifdef RAPP_WITH_RPROF 43 | rprofInit(); 44 | #endif // RAPP_WITH_RPROF 45 | 46 | return 0; 47 | } 48 | 49 | void suspend() {} 50 | void resume() {} 51 | void update(float _time) 52 | { 53 | #ifdef RAPP_WITH_RPROF 54 | RPROF_SCOPE("Update"); 55 | #endif // RAPP_WITH_RPROF 56 | 57 | m_time += _time; 58 | } 59 | 60 | void draw(float /*_alpha*/) 61 | { 62 | #ifdef RAPP_WITH_RPROF 63 | rprofBeginFrame(); 64 | RPROF_SCOPE("Draw"); 65 | #endif // RAPP_WITH_RPROF 66 | 67 | appRunOnMainThread(mainThreadFunc, this); 68 | 69 | //rtm::Console::rgb(255, 255, 0, "Printing from app thread (ID: %u)\n", (uint32_t)rtm::Thread::getThreadID()); 70 | 71 | // Use debug font to print information about this example. 72 | bgfx::dbgTextClear(); 73 | bgfx::dbgTextPrintf(0, 1, 0x17, "rapp/samples/bgfx"); 74 | bgfx::dbgTextPrintf(0, 2, 0x37, m_description); 75 | 76 | // debug input 77 | rapp::inputDgbGamePads(); 78 | rapp::inputDgbMouse(); 79 | rapp::inputDgbKeyboard(); 80 | rapp::inputDgbTouch(); 81 | } 82 | 83 | void drawGUI() 84 | { 85 | #ifdef RAPP_WITH_RPROF 86 | ProfilerFrame frame; 87 | rprofGetFrame(&frame); 88 | rprofDrawFrame(&frame); 89 | #endif // RAPP_WITH_RPROF 90 | 91 | ImGui::SetNextWindowPos(ImVec2(10.0f, 666.0f), ImGuiCond_FirstUseEver); 92 | ImGui::SetNextWindowSize(ImVec2(300.0f, 80.0f), ImGuiCond_FirstUseEver); 93 | ImGui::Begin("ImGui dialog"); 94 | ImGui::Separator(); 95 | ImGui::Button("Button", ImVec2(180.0f,23.0f)); 96 | ImGui::End(); 97 | 98 | rapp::rappVirtualKeyboard(); 99 | 100 | rapp::MouseState ms; 101 | rapp::inputGetMouseState(ms); 102 | } 103 | 104 | void shutDown() 105 | { 106 | #ifdef RAPP_WITH_RPROF 107 | rprofShutDown(); 108 | #endif // RAPP_WITH_RPROF 109 | //rtm::Console::rgb(255, 255, 0, "Shutting down app\n"); 110 | rapp::appGraphicsShutdown(this, m_window); 111 | rapp::inputRemoveBindings("bindings"); 112 | } 113 | 114 | static void mainThreadFunc(void* /*_appClass*/) 115 | { 116 | //rtm::Console::rgb(0, 255, 0, "Printing from main thread (ID: %u)\n", (uint32_t)rtm::Thread::getThreadID()); 117 | } 118 | 119 | static int cmdExit(rapp::App* _app, void* _userData, int _argc, char const* const* _argv) 120 | { 121 | RTM_UNUSED_3(_userData, _argv, _argc); 122 | _app->quit(); 123 | return 0; 124 | } 125 | 126 | static int cmdHideConsole(rapp::App* _app, void* _userData, int _argc, char const* const* _argv) 127 | { 128 | RTM_UNUSED_3(_userData, _argv, _argc); 129 | rapp::cmdConsoleToggle(_app); 130 | return 0; 131 | } 132 | }; 133 | 134 | RAPP_REGISTER(rprofApp, "rprof", "Example of an app with rprof profiler built in"); 135 | -------------------------------------------------------------------------------- /samples/05_rprof/rprof_pch.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | 8 | -------------------------------------------------------------------------------- /samples/05_rprof/rprof_pch.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #define RBASE_NAMESPACE rapp 7 | #include 8 | #include 9 | #include 10 | 11 | #define RAPP_WITH_BGFX 12 | #include 13 | 14 | #ifdef RAPP_WITH_RPROF 15 | #include 16 | #include 17 | #endif // RAPP_WITH_RPROF 18 | -------------------------------------------------------------------------------- /samples/rapp.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | rapp Sample 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /scripts/lin_fetch_dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | git clone https://github.com/bkaradzic/bx.git ../../bx ) else ( echo skipping bx - directory exists ) 4 | git clone https://github.com/bkaradzic/bimg.git ../../bimg ) else ( echo skipping bimg - directory exists ) 5 | git clone https://github.com/bkaradzic/bgfx.git ../../bgfx ) else ( echo skipping bgfx - directory exists ) 6 | 7 | git clone https://github.com/RudjiGames/build.git ../../build ) else ( echo skipping build - directory exists ) 8 | git clone https://github.com/RudjiGames/rbase.git ../../rbase ) else ( echo skipping rbase - directory exists ) 9 | git clone https://github.com/RudjiGames/rprof.git ../../rprof ) else ( echo skipping rprof - directory exists ) 10 | 11 | git submodule update --init 12 | -------------------------------------------------------------------------------- /scripts/lin_generate_project.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | target="$1" 3 | 4 | if [ -z "$target" ]; then 5 | action="--gcc=linux-gcc-9 gmake" 6 | fi 7 | 8 | if [[ "$target" == "emscripten" ]]; then 9 | action="--gcc=asmjs gmake" 10 | echo $action 11 | fi 12 | 13 | cd ../genie 14 | ../build/tools/bin/linux/genie $action 15 | cd ../scripts 16 | -------------------------------------------------------------------------------- /scripts/osx_fetch_dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | git clone https://github.com/bkaradzic/bx.git ../../bx ) else ( echo skipping bx - directory exists ) 4 | git clone https://github.com/bkaradzic/bimg.git ../../bimg ) else ( echo skipping bimg - directory exists ) 5 | git clone https://github.com/bkaradzic/bgfx.git ../../bgfx ) else ( echo skipping bgfx - directory exists ) 6 | 7 | git clone https://github.com/RudjiGames/build.git ../../build ) else ( echo skipping build - directory exists ) 8 | git clone https://github.com/RudjiGames/rbase.git ../../rbase ) else ( echo skipping rbase - directory exists ) 9 | git clone https://github.com/RudjiGames/rprof.git ../../rprof ) else ( echo skipping rprof - directory exists ) 10 | 11 | git submodule update --init 12 | -------------------------------------------------------------------------------- /scripts/osx_generate_project.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | target="$1" 3 | 4 | if [ -z "$target" ]; then 5 | action="--gcc=osx gmake" 6 | fi 7 | 8 | if [[ "$target" == "emscripten" ]]; then 9 | action="--gcc=asmjs gmake" 10 | echo $action 11 | fi 12 | 13 | cd ../genie 14 | ../build/tools/bin/darwin/genie $action 15 | cd ../scripts 16 | -------------------------------------------------------------------------------- /scripts/win_fetch_dependencies.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo This will clone dependencies in the parent directory. 3 | echo Note that this is only needed if you want to generate the demo project. 4 | echo _ 5 | :choice 6 | set /P c=Are you sure you want to continue[Y/N]? 7 | if /I "%c%" EQU "Y" goto :clone_deps 8 | if /I "%c%" EQU "N" goto :exit 9 | goto :choice 10 | 11 | :clone_deps 12 | if not exist ../../bx ( git clone https://github.com/bkaradzic/bx.git ../../bx ) else ( echo skipping bx - directory exists ) 13 | if not exist ../../bimg ( git clone https://github.com/bkaradzic/bimg.git ../../bimg ) else ( echo skipping bimg - directory exists ) 14 | if not exist ../../bgfx ( git clone https://github.com/bkaradzic/bgfx.git ../../bgfx ) else ( echo skipping bgfx - directory exists ) 15 | 16 | if not exist ../../build ( git clone https://github.com/RudjiGames/build.git ../../build ) else ( echo skipping build - directory exists ) 17 | if not exist ../../rbase ( git clone https://github.com/RudjiGames/rbase.git ../../rbase ) else ( echo skipping rbase - directory exists ) 18 | if not exist ../../rprof ( git clone https://github.com/RudjiGames/rprof.git ../../rprof ) else ( echo skipping rprof - directory exists ) 19 | 20 | git submodule update --init 21 | 22 | :exit 23 | -------------------------------------------------------------------------------- /scripts/win_generate_project.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set ACTION=vs2022 3 | IF "%1"=="emscripten" set ACTION=--gcc=asmjs gmake 4 | cd ..\genie 5 | ..\..\build\tools\bin\windows\genie.exe %ACTION% 6 | cd ..\scripts 7 | -------------------------------------------------------------------------------- /src/app_data.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #ifndef RTM_RAPP_APP_DATA_H 7 | #define RTM_RAPP_APP_DATA_H 8 | 9 | #ifdef RAPP_WITH_BGFX 10 | 11 | #include 12 | #include "../3rd/vg_renderer/include/vg/vg.h" 13 | #include "../3rd/vg_renderer/include/vg/path.h" 14 | #include "../3rd/vg_renderer/include/vg/stroker.h" 15 | 16 | namespace rapp { 17 | 18 | struct AppData 19 | { 20 | Console* m_console; 21 | vg::Context* m_vg; 22 | AppData() 23 | : m_console(0) 24 | , m_vg(0) 25 | {} 26 | }; 27 | 28 | } // namespace rtm 29 | 30 | #else // RAPP_WITH_BGFX 31 | 32 | namespace rapp { 33 | 34 | struct AppData 35 | { 36 | }; 37 | 38 | } // namespace rtm 39 | 40 | #endif // RAPP_WITH_BGFX 41 | 42 | #endif // RTM_RAPP_APP_DATA_H 43 | -------------------------------------------------------------------------------- /src/cmd.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include // time 14 | #include // isspace 15 | #include 16 | #include // size_t 17 | #include // strlen 18 | 19 | namespace rapp { 20 | 21 | bool isSpace(char _ch) 22 | { 23 | return ' ' == _ch 24 | || '\t' == _ch 25 | || '\n' == _ch 26 | || '\v' == _ch 27 | || '\f' == _ch 28 | || '\r' == _ch 29 | ; 30 | } 31 | 32 | // Reference: 33 | // http://msdn.microsoft.com/en-us/library/a1y7w461.aspx 34 | const char* tokenizeCommandLine(const char* _commandLine, char* _buffer, uint32_t& _bufferSize, int32_t& _argc, char* _argv[], int32_t _maxArgvs, char _term) 35 | { 36 | int32_t argc = 0; 37 | const char* curr = _commandLine; 38 | char* currOut = _buffer; 39 | char term = ' '; 40 | bool sub = false; 41 | 42 | enum ParserState 43 | { 44 | SkipWhitespace, 45 | SetTerm, 46 | Copy, 47 | Escape, 48 | End, 49 | }; 50 | 51 | ParserState state = SkipWhitespace; 52 | 53 | while ('\0' != *curr 54 | && _term != *curr 55 | && argc < _maxArgvs) 56 | { 57 | switch (state) 58 | { 59 | case SkipWhitespace: 60 | for (; isSpace(*curr); ++curr) {}; // skip whitespace 61 | state = SetTerm; 62 | break; 63 | 64 | case SetTerm: 65 | if ('"' == *curr) 66 | { 67 | term = '"'; 68 | ++curr; // skip begining quote 69 | } 70 | else 71 | { 72 | term = ' '; 73 | } 74 | 75 | _argv[argc] = currOut; 76 | ++argc; 77 | 78 | state = Copy; 79 | break; 80 | 81 | case Copy: 82 | if ('\\' == *curr) 83 | { 84 | state = Escape; 85 | } 86 | else if ('"' == *curr 87 | && '"' != term) 88 | { 89 | sub = !sub; 90 | } 91 | else if (isSpace(*curr) && !sub) 92 | { 93 | state = End; 94 | } 95 | else if (term != *curr || sub) 96 | { 97 | *currOut = *curr; 98 | ++currOut; 99 | } 100 | else 101 | { 102 | state = End; 103 | } 104 | ++curr; 105 | break; 106 | 107 | case Escape: 108 | { 109 | const char* start = --curr; 110 | for (; '\\' == *curr; ++curr) {}; 111 | 112 | if ('"' != *curr) 113 | { 114 | int32_t count = (int32_t)(curr-start); 115 | 116 | curr = start; 117 | for (int32_t ii = 0; ii < count; ++ii) 118 | { 119 | *currOut = *curr; 120 | ++currOut; 121 | ++curr; 122 | } 123 | } 124 | else 125 | { 126 | curr = start+1; 127 | *currOut = *curr; 128 | ++currOut; 129 | ++curr; 130 | } 131 | } 132 | state = Copy; 133 | break; 134 | 135 | case End: 136 | *currOut = '\0'; 137 | ++currOut; 138 | state = SkipWhitespace; 139 | break; 140 | } 141 | } 142 | 143 | *currOut = '\0'; 144 | if (0 < argc 145 | && '\0' == _argv[argc-1][0]) 146 | { 147 | --argc; 148 | } 149 | 150 | _bufferSize = (uint32_t)(currOut - _buffer); 151 | _argc = argc; 152 | 153 | if ('\0' != *curr) 154 | { 155 | ++curr; 156 | } 157 | 158 | return curr; 159 | } 160 | 161 | void CmdContext::add(const char* _name, ConsoleFn _fn, void* _userData, const char* _description) 162 | { 163 | uint32_t cmd = rtm::hashStr(_name, (uint32_t)strlen(_name) ); 164 | Func fn = { _fn, _userData, _name, _description }; 165 | 166 | uint32_t cmdIdx = cmd & RAPP_HASH_MASK; 167 | m_lookup[cmdIdx] = fn; 168 | 169 | updateMaxLen(); 170 | } 171 | 172 | void CmdContext::remove(const char* _name) 173 | { 174 | uint32_t cmd = rtm::hashStr(_name, (uint32_t)strlen(_name) ); 175 | uint32_t cmdIdx = cmd & RAPP_HASH_MASK; 176 | m_lookup[cmdIdx] = { 0, 0, 0, 0 }; 177 | updateMaxLen(); 178 | } 179 | 180 | void CmdContext::updateMaxLen() 181 | { 182 | size_t len = 0; 183 | for (int i=0; i len) len = clen; 188 | } 189 | m_maxCommandLength = (uint32_t)len; 190 | } 191 | 192 | bool CmdContext::exec(App* _app, const char* _cmd, int* _errorCode) 193 | { 194 | for (const char* next = _cmd; '\0' != *next; _cmd = next) 195 | { 196 | char commandLine[1024]; 197 | uint32_t size = sizeof(commandLine); 198 | int argc; 199 | char* argv[64]; 200 | next = tokenizeCommandLine(_cmd, commandLine, size, argc, argv, RTM_NUM_ELEMENTS(argv), '\n'); 201 | if (argc > 0) 202 | { 203 | int err = -1; 204 | uint32_t cmd = rtm::hashStr(argv[0], (uint32_t)strlen(argv[0]) ); 205 | 206 | uint32_t cmdIdx = cmd & RAPP_HASH_MASK; 207 | auto& it = m_lookup[cmdIdx]; 208 | if (it.m_fn) 209 | { 210 | err = it.m_fn(_app, it.m_userData, argc, argv); 211 | if (_errorCode) 212 | *_errorCode = err; 213 | return true; 214 | } 215 | } 216 | } 217 | return false; 218 | } 219 | 220 | static CmdContext* s_cmdContext = 0; 221 | 222 | void cmdInit() 223 | { 224 | s_cmdContext = rtm_new(); 225 | } 226 | 227 | void cmdShutdown() 228 | { 229 | rtm_delete(s_cmdContext); 230 | s_cmdContext = 0; 231 | } 232 | 233 | CmdContext* cmdGetContext() 234 | { 235 | return s_cmdContext; 236 | } 237 | 238 | void cmdAdd(const char* _name, ConsoleFn _fn, void* _userData, const char* _description) 239 | { 240 | s_cmdContext->add(_name, _fn, _userData, _description); 241 | } 242 | 243 | void cmdRemove(const char* _name) 244 | { 245 | s_cmdContext->remove(_name); 246 | } 247 | 248 | bool cmdExec(App* _app, const char* _cmd, int* _errorCode) 249 | { 250 | return s_cmdContext->exec(_app, _cmd, _errorCode); 251 | } 252 | 253 | void cmdConsoleLog(App* _app, const char* _fmt, ...) 254 | { 255 | RTM_UNUSED_2(_app, _fmt); 256 | 257 | #ifdef RAPP_WITH_BGFX 258 | char buf[2048]; 259 | va_list args; 260 | va_start(args, _fmt); 261 | vsnprintf(buf, RTM_NUM_ELEMENTS(buf), _fmt, args); 262 | buf[RTM_NUM_ELEMENTS(buf)-1] = 0; 263 | va_end(args); 264 | 265 | _app->m_data->m_console->addLog(buf); 266 | #endif // RAPP_WITH_BGFX 267 | } 268 | 269 | void cmdConsoleLogRGB(uint8_t _r, uint8_t _g, uint8_t _b, App* _app, const char* _fmt, ...) 270 | { 271 | RTM_UNUSED_5(_r, _g, _b, _app, _fmt); 272 | 273 | #ifdef RAPP_WITH_BGFX 274 | char buf[2048]; 275 | va_list args; 276 | va_start(args, _fmt); 277 | vsnprintf(buf, RTM_NUM_ELEMENTS(buf), _fmt, args); 278 | buf[RTM_NUM_ELEMENTS(buf)-1] = 0; 279 | va_end(args); 280 | 281 | _app->m_data->m_console->addLog(_r, _g, _b, buf); 282 | #endif // RAPP_WITH_BGFX 283 | } 284 | 285 | void cmdConsoleToggle(App* _app) 286 | { 287 | RTM_UNUSED(_app); 288 | #ifdef RAPP_WITH_BGFX 289 | _app->m_data->m_console->toggleVisibility(); 290 | #endif // RAPP_WITH_BGFX 291 | } 292 | 293 | float g_consoleToggleTime = 0.23f; 294 | void cmdConsoleSetToggleTime(float _time) 295 | { 296 | RTM_ASSERT(_time > 0.0f && _time < 3.0f, "Really?"); 297 | g_consoleToggleTime = _time; 298 | } 299 | 300 | 301 | inline bool toBool(const char* _str) 302 | { 303 | char ch = rtm::toLower(_str[0]); 304 | return ch == 't' || ch == '1'; 305 | } 306 | 307 | 308 | bool toggleFlag(uint32_t& _flags, const char* _name, uint32_t _bit, int _first, int _argc, char const* const* _argv) 309 | { 310 | if (0 == strcmp(_argv[_first], _name) ) 311 | { 312 | int arg = _first+1; 313 | if (_argc > arg) 314 | { 315 | _flags &= ~_bit; 316 | _flags |= toBool(_argv[arg]) ? _bit : 0; 317 | } 318 | else 319 | { 320 | _flags ^= _bit; 321 | } 322 | 323 | return true; 324 | } 325 | 326 | return false; 327 | } 328 | 329 | int cmdMouseLock(App* _app, void* _userData, int _argc, char const* const* _argv) 330 | { 331 | RTM_UNUSED_2(_app, _userData); 332 | 333 | if (_argc > 1) 334 | { 335 | inputSetMouseLock(_argc > 1 ? toBool(_argv[1]) : !inputIsMouseLocked() ); 336 | return 0; 337 | } 338 | 339 | return 1; 340 | } 341 | 342 | #ifdef RAPP_WITH_BGFX 343 | uint32_t g_debug = BGFX_DEBUG_TEXT; 344 | uint32_t g_reset = BGFX_RESET_VSYNC; 345 | #else 346 | uint32_t g_debug = 0; 347 | uint32_t g_reset = 0; 348 | #endif 349 | int cmdGraphics(App* _app, void* _userData, int _argc, char const* const* _argv) 350 | { 351 | RTM_UNUSED_4(_app, _userData, _argc, _argv); 352 | 353 | #ifdef RAPP_WITH_BGFX 354 | if (_argc > 1) 355 | { 356 | if (rtm::striCmp(_argv[1], "help") == 0) 357 | { 358 | cmdConsoleLog(_app, "graphics vsync - toggle vsync on/off"); 359 | cmdConsoleLog(_app, "graphics maxaniso - set maximum anisotropy"); 360 | cmdConsoleLog(_app, "graphics hmd - HMD stereo rendering"); 361 | cmdConsoleLog(_app, "graphics hmddbg - HMD stereo rendering debug mode"); 362 | cmdConsoleLog(_app, "graphics hmdrecenter - HMD calibration"); 363 | cmdConsoleLog(_app, "graphics msaa4 - MSAA 4x mode"); 364 | cmdConsoleLog(_app, "graphics msaa8 - MSAA 8x mode"); 365 | cmdConsoleLog(_app, "graphics msaa16 - MSAA 16x mode"); 366 | cmdConsoleLog(_app, "graphics flush - flush rendering after submitting to GPU"); 367 | cmdConsoleLog(_app, "graphics flip - toggle flip before (default) and after rendering new frame"); 368 | cmdConsoleLog(_app, "graphics stats - display rendering statistics"); 369 | cmdConsoleLog(_app, "graphics ifh - toggle 'infinitely fast hardware', no draw calls submitted to driver"); 370 | cmdConsoleLog(_app, "graphics text - toggle vsync on/off"); 371 | cmdConsoleLog(_app, "graphics wireframe - toggle wireframe for all primitives"); 372 | cmdConsoleLog(_app, "graphics screenshot - take screenshot and save it to disk"); 373 | cmdConsoleLog(_app, "graphics fullscreen - toggle fullscreen"); 374 | return 0; 375 | } 376 | 377 | if ( toggleFlag(g_reset, "vsync", BGFX_RESET_VSYNC, 1, _argc, _argv) 378 | || toggleFlag(g_reset, "maxaniso", BGFX_RESET_MAXANISOTROPY, 1, _argc, _argv) 379 | || toggleFlag(g_reset, "msaa4", BGFX_RESET_MSAA_X4, 1, _argc, _argv) 380 | || toggleFlag(g_reset, "msaa8", BGFX_RESET_MSAA_X8, 1, _argc, _argv) 381 | || toggleFlag(g_reset, "msaa16", BGFX_RESET_MSAA_X16, 1, _argc, _argv) 382 | || toggleFlag(g_reset, "flush", BGFX_RESET_FLUSH_AFTER_RENDER, 1, _argc, _argv) 383 | || toggleFlag(g_reset, "flip", BGFX_RESET_FLIP_AFTER_RENDER, 1, _argc, _argv) 384 | || toggleFlag(g_debug, "stats", BGFX_DEBUG_STATS, 1, _argc, _argv) 385 | || toggleFlag(g_debug, "ifh", BGFX_DEBUG_IFH, 1, _argc, _argv) 386 | || toggleFlag(g_debug, "text", BGFX_DEBUG_TEXT, 1, _argc, _argv) 387 | || toggleFlag(g_debug, "wireframe", BGFX_DEBUG_WIREFRAME, 1, _argc, _argv) ) 388 | { 389 | return 0; 390 | } 391 | else if (0 == strcmp(_argv[1], "screenshot") ) 392 | { 393 | bgfx::FrameBufferHandle fbh = BGFX_INVALID_HANDLE; 394 | 395 | if (_argc > 2) 396 | { 397 | bgfx::requestScreenShot(fbh, _argv[2]); 398 | } 399 | else 400 | { 401 | time_t tt; 402 | time(&tt); 403 | 404 | char filePath[256]; 405 | ::snprintf(filePath, sizeof(filePath), "temp/screenshot-%" PRId64 "", (uint64_t)tt); 406 | bgfx::requestScreenShot(fbh, filePath); 407 | } 408 | 409 | return 0; 410 | } 411 | else if (0 == strcmp(_argv[1], "fullscreen") ) 412 | { 413 | WindowHandle window = { 0 }; 414 | windowToggleFullscreen(window); 415 | return 0; 416 | } 417 | } 418 | 419 | #endif 420 | return 1; 421 | } 422 | 423 | 424 | rtm::FixedArray& appGetRegistered(); 425 | void appSwitch(App* _app); 426 | 427 | int cmdApp(App* _app, void* _userData, int _argc, char const* const* _argv) 428 | { 429 | RTM_UNUSED_2(_app, _userData); 430 | 431 | if (_argc > 1) 432 | { 433 | if (rtm::striCmp(_argv[1], "help") == 0) 434 | { 435 | cmdConsoleLog(_app, "app list - lists registered applications"); 436 | cmdConsoleLog(_app, "app run [idx/name] - runs application with given index or name"); 437 | return 0; 438 | } 439 | 440 | rtm::FixedArray& apps = appGetRegistered(); 441 | 442 | if (rtm::striCmp(_argv[1], "list") == 0) 443 | { 444 | cmdConsoleLogRGB(127, 255, 255, _app, "Registered apps:"); 445 | uint32_t maxNameLen = 0; 446 | for (uint32_t i=0; im_name)); 448 | 449 | for (uint32_t i=0; im_name, 453 | apps[i]->m_description); 454 | return 0; 455 | } 456 | 457 | if (rtm::striCmp(_argv[1], "run") == 0) 458 | { 459 | if (_argc != 3) 460 | return 1; 461 | 462 | uint32_t appIndex = (uint32_t)atoi(_argv[2]); 463 | if (appIndex < 1 || appIndex > apps.size()) 464 | { 465 | // try by name 466 | for (uint32_t i=0; im_name) == 0) 468 | { 469 | appSwitch(apps[i]); 470 | return 0; 471 | } 472 | } 473 | else 474 | { 475 | App* app = appGet(appIndex - 1); 476 | appSwitch(app); 477 | return 0; 478 | } 479 | } 480 | } 481 | 482 | return 1; 483 | } 484 | 485 | } // namespace rapp 486 | -------------------------------------------------------------------------------- /src/cmd.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #ifndef RTM_RAPP_CMD_H 7 | #define RTM_RAPP_CMD_H 8 | 9 | namespace rapp { 10 | 11 | struct CmdContext 12 | { 13 | CmdContext() 14 | : m_maxCommandLength(0) 15 | { 16 | rtm::memSet(m_lookup, 0, sizeof(m_lookup)); 17 | } 18 | 19 | void add(const char* _name, ConsoleFn _fn, void* _userData, const char* _description); 20 | void remove(const char* _name); 21 | void updateMaxLen(); 22 | bool exec(App* _app, const char* _cmd, int* _errorCode); 23 | 24 | struct Func 25 | { 26 | ConsoleFn m_fn; 27 | void* m_userData; 28 | const char* m_name; 29 | const char* m_description; 30 | }; 31 | 32 | Func m_lookup[RAPP_HASH_SIZE]; 33 | uint32_t m_maxCommandLength; 34 | }; 35 | 36 | /// 37 | void cmdInit(); 38 | 39 | /// 40 | void cmdShutdown(); 41 | 42 | /// 43 | CmdContext* cmdGetContext(); 44 | 45 | int cmdMouseLock(App* _app, void* _userData, int _argc, char const* const* _argv); 46 | int cmdGraphics(App* _app, void* _userData, int _argc, char const* const* _argv); 47 | int cmdApp(App* _app, void* _userData, int _argc, char const* const* _argv); 48 | 49 | } // namespace rtm 50 | 51 | #endif // RTM_RAPP_CMD_H 52 | -------------------------------------------------------------------------------- /src/console.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #ifdef RAPP_WITH_BGFX 13 | 14 | #include 15 | 16 | namespace rapp { 17 | 18 | static char* strdup(const char *str) 19 | { 20 | size_t len = strlen(str) + 1; 21 | void* buff = rtm_alloc(len); 22 | return (char*)memcpy(buff, (const void*)str, len); 23 | } 24 | 25 | Console::Console(App* _app) 26 | : m_app(_app) 27 | { 28 | m_hide = true; 29 | m_visible = 0.0f; 30 | 31 | m_items = (char**)rtm_alloc(sizeof(char*) * s_bufferHeight); 32 | m_itemColors = (Color*)rtm_alloc(sizeof(Color) * s_bufferHeight); 33 | m_itemsStart = 0; 34 | m_itemsEnd = 0; 35 | 36 | memset(m_items, 0, sizeof(char*) * s_bufferHeight); 37 | memset(m_itemColors, 0xff, sizeof(Color) * s_bufferHeight); 38 | 39 | memset(m_inputBuf, 0, sizeof(m_inputBuf)); 40 | m_historyPos = -1; 41 | 42 | updateCommands(); 43 | } 44 | 45 | Console::~Console() 46 | { 47 | clearLog(); 48 | for (int i = 0; i < m_history.Size; i++) 49 | { 50 | rtm_free(m_history[i]); 51 | } 52 | rtm_free(m_items); 53 | rtm_free(m_itemColors); 54 | } 55 | 56 | void Console::clearLog() 57 | { 58 | uint32_t numLogs = (m_itemsEnd - m_itemsStart) & s_bufferMask; 59 | for (uint32_t i=0; i 0.0f)) 121 | { 122 | m_visible -= delta/g_consoleToggleTime; 123 | m_visible = m_visible < 0.0f ? 0.0f : m_visible; 124 | } 125 | 126 | if (!m_hide && m_visible < 1.0f) 127 | { 128 | m_visible += delta/g_consoleToggleTime; 129 | m_visible = m_visible > 1.0f ? 1.0f : m_visible; 130 | } 131 | 132 | if (m_visible == 0.0f) 133 | return; 134 | 135 | lastDrawTime = currDrawTime; 136 | 137 | float posY = -(1.0f - m_visible) * float(m_app->m_height/2); 138 | ImGui::SetNextWindowPos(ImVec2(float(m_app->m_width/5), posY), ImGuiCond_Always); 139 | ImGui::SetNextWindowSize(ImVec2(float(m_app->m_width*6/10), float(m_app->m_height/2)), ImGuiCond_Always); 140 | bool p_open; 141 | if (!ImGui::Begin("Console", &p_open, ImGuiWindowFlags_NoTitleBar | 142 | ImGuiWindowFlags_NoResize | 143 | ImGuiWindowFlags_NoMove)) 144 | { 145 | ImGui::End(); 146 | return; 147 | } 148 | 149 | bool copy_to_clipboard = false; 150 | 151 | ImGui::BeginChild("ScrollingRegion", ImVec2(0, -ImGui::GetStyle().ItemSpacing.y - ImGui::GetFrameHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText 152 | if (ImGui::BeginPopupContextWindow()) 153 | { 154 | if (ImGui::Selectable("Clear")) clearLog(); 155 | if (ImGui::Selectable("Copy")) copy_to_clipboard = true; 156 | if (ImGui::Selectable("Scroll to bottom")) m_scrollToBottom = true; 157 | ImGui::EndPopup(); 158 | } 159 | 160 | ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing 161 | ImGui::PushFont(ImGui::Font::Mono); 162 | 163 | if (copy_to_clipboard) 164 | { 165 | ImGui::LogToClipboard(); 166 | } 167 | 168 | uint32_t numLogs = (m_itemsEnd - m_itemsStart) & s_bufferMask; 169 | ImGuiListClipper clipper; 170 | clipper.Begin(numLogs); 171 | while (clipper.Step()) 172 | for (int i=clipper.DisplayStart; i"); 203 | ImGui::SameLine(); 204 | ImGui::SetNextItemWidth(-1); 205 | 206 | if (ImGui::InputText("##", m_inputBuf, RTM_NUM_ELEMENTS(m_inputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &textEditCallbackStub, (void*)this)) 207 | { 208 | char* input_end = m_inputBuf+strlen(m_inputBuf); 209 | while (input_end > m_inputBuf && input_end[-1] == ' ') { input_end--; } *input_end = 0; 210 | if (m_inputBuf[0]) 211 | execCommand(m_inputBuf); 212 | strcpy(m_inputBuf, ""); 213 | } 214 | } 215 | 216 | // Demonstrate keeping auto focus on the input box 217 | if (ImGui::IsItemHovered() || (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0))) 218 | ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget 219 | 220 | ImGui::End(); 221 | } 222 | 223 | void Console::execCommand(const char* command_line) 224 | { 225 | addLog(147, 255, 147, "$> %s\n", command_line); 226 | 227 | // Insert into history. First find match and delete it so it can be pushed to the back. This isn't trying to be smart or optimal. 228 | m_historyPos = -1; 229 | for (int i = m_history.Size-1; i >= 0; i--) 230 | if (rtm::striCmp(m_history[i], command_line) == 0) 231 | { 232 | rtm_free(m_history[i]); 233 | m_history.erase(m_history.begin() + i); 234 | break; 235 | } 236 | m_history.push_back(strdup(command_line)); 237 | 238 | // Process command 239 | if (rtm::striCmp(command_line, "CLEAR") == 0) 240 | { 241 | clearLog(); 242 | } 243 | else 244 | if (rtm::striCmp(command_line, "HELP") == 0) 245 | { 246 | addLog("Available commands:"); 247 | for (int i = 0; i < m_commands.Size; i++) 248 | { 249 | addLog("> %-*s - %s", cmdGetContext()->m_maxCommandLength + 3, 250 | m_commands[i].m_name, 251 | m_commands[i].m_description); 252 | } 253 | } 254 | else if (rtm::striCmp(command_line, "HISTORY") == 0) 255 | { 256 | int first = m_history.Size - 10; 257 | for (int i = first > 0 ? first : 0; i < m_history.Size; i++) 258 | { 259 | addLog(77, 175, 77, "%3d: %s\n", i, m_history[i]); 260 | } 261 | } 262 | else 263 | { 264 | int error; 265 | if (!cmdExec(m_app, command_line, &error)) 266 | addLog("Unknown command: '%s'\n", command_line); 267 | else 268 | { 269 | if (error) 270 | addLog("Command '%s' returned error code: %d\n", command_line, error); 271 | } 272 | } 273 | } 274 | 275 | int Console::textEditCallbackStub(ImGuiInputTextCallbackData* data) 276 | { 277 | Console* console = (Console*)data->UserData; 278 | return console->textEditCallback(data); 279 | } 280 | 281 | int Console::textEditCallback(ImGuiInputTextCallbackData* data) 282 | { 283 | switch (data->EventFlag) 284 | { 285 | case ImGuiInputTextFlags_CallbackCompletion: 286 | { 287 | // Example of TEXT COMPLETION 288 | 289 | // Locate beginning of current word 290 | const char* word_end = data->Buf + data->CursorPos; 291 | const char* word_start = word_end; 292 | while (word_start > data->Buf) 293 | { 294 | const char c = word_start[-1]; 295 | if (c == ' ' || c == '\t' || c == ',' || c == ';') 296 | break; 297 | word_start--; 298 | } 299 | 300 | // Build a list of candidates 301 | ImVector candidates; 302 | for (int i = 0; i < m_commands.Size; i++) 303 | if (rtm::striCmp(m_commands[i].m_name, word_start, (int)(word_end-word_start)) == 0) 304 | candidates.push_back(&m_commands[i]); 305 | 306 | if (candidates.Size == 0) 307 | { 308 | // No match 309 | addLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start); 310 | } 311 | else if (candidates.Size == 1) 312 | { 313 | // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing 314 | data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start)); 315 | data->InsertChars(data->CursorPos, candidates[0]->m_name); 316 | data->InsertChars(data->CursorPos, " "); 317 | } 318 | else 319 | { 320 | // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY" 321 | int match_len = (int)(word_end - word_start); 322 | for (;;) 323 | { 324 | int c = 0; 325 | bool all_candidates_matches = true; 326 | for (int i = 0; i < candidates.Size && all_candidates_matches; i++) 327 | if (i == 0) 328 | c = rtm::toUpper(candidates[i]->m_name[match_len]); 329 | else if (c == 0 || c != rtm::toUpper(candidates[i]->m_name[match_len])) 330 | all_candidates_matches = false; 331 | if (!all_candidates_matches) 332 | break; 333 | match_len++; 334 | } 335 | 336 | if (match_len > 0) 337 | { 338 | data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start)); 339 | data->InsertChars(data->CursorPos, candidates[0]->m_name, candidates[0]->m_name + match_len); 340 | } 341 | 342 | // List matches 343 | addLog("Possible matches:\n"); 344 | for (int i = 0; i < candidates.Size; i++) 345 | addLog("> %-*s - %s", cmdGetContext()->m_maxCommandLength + 3, 346 | candidates[i]->m_name, 347 | candidates[i]->m_description); 348 | } 349 | 350 | break; 351 | } 352 | 353 | case ImGuiInputTextFlags_CallbackHistory: 354 | { 355 | // Example of HISTORY 356 | const int prev_history_pos = m_historyPos; 357 | if (data->EventKey == ImGuiKey_UpArrow) 358 | { 359 | if (m_historyPos == -1) 360 | m_historyPos = m_history.Size - 1; 361 | else if (m_historyPos > 0) 362 | m_historyPos--; 363 | } 364 | else if (data->EventKey == ImGuiKey_DownArrow) 365 | { 366 | if (m_historyPos != -1) 367 | if (++m_historyPos >= m_history.Size) 368 | m_historyPos = -1; 369 | } 370 | 371 | // A better implementation would preserve the data on the current input line along with cursor position. 372 | if (prev_history_pos != m_historyPos) 373 | { 374 | data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = (int)snprintf(data->Buf, (size_t)data->BufSize, "%s", (m_historyPos >= 0) ? m_history[m_historyPos] : ""); 375 | data->BufDirty = true; 376 | } 377 | } 378 | } 379 | return 0; 380 | } 381 | 382 | void Console::toggleVisibility() 383 | { 384 | m_hide = !m_hide; 385 | } 386 | 387 | void Console::updateCommands() 388 | { 389 | m_commands.clear(); 390 | m_commands.push_back({0, 0, "clear", "Clears the console buffer"}); 391 | m_commands.push_back({0, 0, "history", "Lists history of entered commands"}); 392 | 393 | CmdContext* context = cmdGetContext(); 394 | 395 | if (!context) return; 396 | 397 | for (int i=0; im_lookup[i].m_fn) 399 | m_commands.push_back(context->m_lookup[i]); 400 | } 401 | 402 | } // namespace rapp 403 | 404 | #endif // RAPP_WITH_BGFX 405 | -------------------------------------------------------------------------------- /src/console.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #ifndef RTM_RAPP_CONSOLE_H 7 | #define RTM_RAPP_CONSOLE_H 8 | 9 | #ifdef RAPP_WITH_BGFX 10 | 11 | #include 12 | #include 13 | 14 | namespace rapp { 15 | 16 | struct Console 17 | { 18 | static const uint32_t s_bufferHeight = (1 << 12); 19 | static const uint32_t s_bufferMask = s_bufferHeight - 1; 20 | 21 | struct Color { uint8_t r, g, b; }; 22 | 23 | App* m_app; 24 | char m_inputBuf[256]; 25 | char** m_items; 26 | Color* m_itemColors; 27 | uint32_t m_itemsStart; 28 | uint32_t m_itemsEnd; 29 | bool m_scrollToBottom; 30 | ImVector m_history; 31 | int m_historyPos; // -1: new line, 0..History.Size-1 browsing history. 32 | ImVector m_commands; 33 | bool m_hide; 34 | float m_visible; 35 | 36 | Console(App* _app); 37 | ~Console(); 38 | 39 | void clearLog(); 40 | void addLog(const char* fmt, ...); 41 | void addLog(uint8_t _r, uint8_t _g, uint8_t _b, const char* fmt, ...); 42 | void draw(); 43 | void execCommand(const char* command_line); 44 | int textEditCallback(ImGuiInputTextCallbackData* data); 45 | void toggleVisibility(); 46 | void updateCommands(); 47 | 48 | static int textEditCallbackStub(ImGuiInputTextCallbackData* data); 49 | }; 50 | 51 | } // namespace rapp 52 | 53 | #endif // RAPP_WITH_BGFX 54 | 55 | #endif // RTM_RAPP_CONSOLE_H 56 | -------------------------------------------------------------------------------- /src/dbg.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include // isprint 11 | #if !RTM_PLATFORM_WINDOWS 12 | #include // alloca 13 | #endif 14 | #if RTM_PLATFORM_ANDROID 15 | #include 16 | #endif 17 | 18 | #if RTM_PLATFORM_IOS || RTM_PLATFORM_OSX 19 | #if defined(__OBJC__) 20 | #import 21 | #else 22 | #include 23 | extern "C" void NSLog(CFStringRef _format, ...); 24 | #endif 25 | #endif 26 | 27 | namespace rapp { 28 | 29 | int32_t snprintf(char* _out, int32_t _max, const char* _format, ...) 30 | { 31 | va_list argList; 32 | va_start(argList, _format); 33 | int32_t total = vsnprintf(_out, _max, _format, argList); 34 | va_end(argList); 35 | return total; 36 | } 37 | 38 | int32_t vsnprintf(char* _out, int32_t _max, const char* _format, va_list _argList) 39 | { 40 | va_list argList; 41 | va_copy(argList, _argList); 42 | int32_t total = 0; 43 | #if RTM_COMPILER_MSVC 44 | int32_t len = -1; 45 | if (NULL != _out) 46 | { 47 | va_list argListCopy; 48 | va_copy(argListCopy, _argList); 49 | len = ::vsnprintf_s(_out, _max, size_t(-1), _format, argListCopy); 50 | va_end(argListCopy); 51 | } 52 | total = -1 == len ? ::_vscprintf(_format, argList) : len; 53 | #else // RTM_COMPILER_MSVC 54 | total = ::vsnprintf(_out, _max, _format, argList); 55 | #endif // RTM_COMPILER_MSVC 56 | va_end(argList); 57 | return total; 58 | } 59 | 60 | void debugOutput(const char* _out) 61 | { 62 | #if RTM_PLATFORM_ANDROID 63 | __android_log_write(ANDROID_LOG_DEBUG, "", _out); 64 | #elif RTM_PLATFORM_WINDOWS \ 65 | || RTM_PLATFORM_WINRT \ 66 | || RTM_PLATFORM_XBOXONE 67 | OutputDebugStringA(_out); 68 | #elif RTM_PLATFORM_IOS || RTM_PLATFORM_OSX 69 | # if defined(__OBJC__) 70 | NSLog(@"%s", _out); 71 | # else 72 | NSLog(__CFStringMakeConstantString("%s"), _out); 73 | # endif // defined(__OBJC__) 74 | #elif RTM_PLATFORM_PS4 75 | ::printf("%s",_out); 76 | #else 77 | RTM_UNUSED(_out); 78 | #endif // RTM_PLATFORM_ 79 | } 80 | 81 | void dbgPrintfVargs(const char* _format, va_list _argList) 82 | { 83 | char temp[8192]; 84 | char* out = temp; 85 | int32_t len = vsnprintf(out, sizeof(temp), _format, _argList); 86 | if ( (int32_t)sizeof(temp) < len) 87 | { 88 | out = (char*)alloca(len+1); 89 | len = vsnprintf(out, len, _format, _argList); 90 | } 91 | out[len] = '\0'; 92 | debugOutput(out); 93 | } 94 | 95 | void dbgPrintf(const char* _format, ...) 96 | { 97 | va_list argList; 98 | va_start(argList, _format); 99 | dbgPrintfVargs(_format, argList); 100 | va_end(argList); 101 | } 102 | 103 | #define DBG_ADDRESS "%" PRIxPTR 104 | 105 | void dbgPrintfData(const void* _data, uint32_t _size, const char* _format, ...) 106 | { 107 | #define HEX_DUMP_WIDTH 16 108 | #define HEX_DUMP_SPACE_WIDTH 48 109 | #define HEX_DUMP_FORMAT "%-" RAPP_DBG_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "." RAPP_DBG_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "s" 110 | 111 | va_list argList; 112 | va_start(argList, _format); 113 | dbgPrintfVargs(_format, argList); 114 | va_end(argList); 115 | 116 | dbgPrintf("\ndata: " DBG_ADDRESS ", size: %d\n", _data, _size); 117 | 118 | if (NULL != _data) 119 | { 120 | const uint8_t* data = reinterpret_cast(_data); 121 | char hex[HEX_DUMP_WIDTH*3+1]; 122 | char ascii[HEX_DUMP_WIDTH+1]; 123 | uint32_t hexPos = 0; 124 | uint32_t asciiPos = 0; 125 | for (uint32_t ii = 0; ii < _size; ++ii) 126 | { 127 | snprintf(&hex[hexPos], sizeof(hex)-hexPos, "%02x ", data[asciiPos]); 128 | hexPos += 3; 129 | 130 | ascii[asciiPos] = isprint(data[asciiPos]) ? data[asciiPos] : '.'; 131 | asciiPos++; 132 | 133 | if (HEX_DUMP_WIDTH == asciiPos) 134 | { 135 | ascii[asciiPos] = '\0'; 136 | dbgPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii); 137 | data += asciiPos; 138 | hexPos = 0; 139 | asciiPos = 0; 140 | } 141 | } 142 | 143 | if (0 != asciiPos) 144 | { 145 | ascii[asciiPos] = '\0'; 146 | dbgPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii); 147 | } 148 | } 149 | 150 | #undef HEX_DUMP_WIDTH 151 | #undef HEX_DUMP_SPACE_WIDTH 152 | #undef HEX_DUMP_FORMAT 153 | } 154 | 155 | } // namespace rapp 156 | -------------------------------------------------------------------------------- /src/entry.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace rapp 16 | { 17 | int rapp_main(int _argc, const char* const*); 18 | 19 | struct CmdContext; 20 | 21 | #ifdef RAPP_WITH_BGFX 22 | extern uint32_t g_debug; 23 | extern uint32_t g_reset; 24 | #else 25 | extern uint32_t g_debug; 26 | extern uint32_t g_reset; 27 | #endif 28 | 29 | static const char* s_keyName[] = 30 | { 31 | "None", 32 | "Esc", 33 | "Return", 34 | "Tab", 35 | "Space", 36 | "Backspace", 37 | "Up", 38 | "Down", 39 | "Left", 40 | "Right", 41 | "Insert", 42 | "Delete", 43 | "Home", 44 | "End", 45 | "PageUp", 46 | "PageDown", 47 | "Print", 48 | "Plus", 49 | "Minus", 50 | "Equal", 51 | "LeftBracket", 52 | "RightBracket", 53 | "Semicolon", 54 | "Quote", 55 | "Comma", 56 | "Period", 57 | "Slash", 58 | "Backslash", 59 | "Tilde", 60 | "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", 61 | "NumPad0", "NumPad1", "NumPad2", "NumPad3", "NumPad4", 62 | "NumPad5", "NumPad6", "NumPad7", "NumPad8", "NumPad9", 63 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 64 | "Dummy", "Dummy", "Dummy", "Dummy", // padding for 'A' to be 65 65 | "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", 66 | "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" 67 | }; 68 | RTM_STATIC_ASSERT(KeyboardState::Key::Count == RTM_NUM_ELEMENTS(s_keyName) ); 69 | 70 | #ifdef RAPP_WITH_BGFX 71 | ImGuiKey s_keyMap[KeyboardState::Key::Count]; 72 | #endif // RAPP_WITH_BGFX 73 | 74 | const char* getName(KeyboardState::Key _key) 75 | { 76 | RTM_ASSERT(_key < KeyboardState::Key::Count, "Invalid key %d.", _key); 77 | return s_keyName[_key]; 78 | } 79 | 80 | #ifdef RAPP_WITH_BGFX 81 | static const InputBinding s_bindingsGraphics[] = 82 | { 83 | { NULL, "graphics fullscreen", 1, { KeyboardState::Key::KeyF, KeyboardState::Modifier::LCtrl }}, 84 | { NULL, "graphics fullscreen", 1, { KeyboardState::Key::KeyF, KeyboardState::Modifier::RCtrl }}, 85 | { NULL, "graphics fullscreen", 1, { KeyboardState::Key::F11, KeyboardState::Modifier::NoMods }}, 86 | { NULL, "graphics stats", 1, { KeyboardState::Key::F1, KeyboardState::Modifier::NoMods }}, 87 | { NULL, "graphics stats 0\ngraphics text 0", 1, { KeyboardState::Key::F1, KeyboardState::Modifier::LShift }}, 88 | { NULL, "graphics wireframe", 1, { KeyboardState::Key::F3, KeyboardState::Modifier::NoMods }}, 89 | { NULL, "graphics hmd", 1, { KeyboardState::Key::F4, KeyboardState::Modifier::NoMods }}, 90 | { NULL, "graphics hmdrecenter", 1, { KeyboardState::Key::F4, KeyboardState::Modifier::LShift }}, 91 | { NULL, "graphics hmddbg", 1, { KeyboardState::Key::F4, KeyboardState::Modifier::LCtrl }}, 92 | { NULL, "graphics vsync", 1, { KeyboardState::Key::F7, KeyboardState::Modifier::NoMods }}, 93 | { NULL, "graphics msaa16", 1, { KeyboardState::Key::F8, KeyboardState::Modifier::NoMods }}, 94 | { NULL, "graphics flush", 1, { KeyboardState::Key::F9, KeyboardState::Modifier::NoMods }}, 95 | { NULL, "graphics screenshot", 1, { KeyboardState::Key::Print, KeyboardState::Modifier::NoMods }}, 96 | 97 | RAPP_INPUT_BINDING_END 98 | }; 99 | #endif 100 | 101 | int main(int _argc, const char* const* _argv) 102 | { 103 | cmdInit(); 104 | cmdAdd("mouselock", cmdMouseLock, 0, "locks mouse to window"); 105 | #ifdef RAPP_WITH_BGFX 106 | cmdAdd("graphics", cmdGraphics, 0, "Graphics related commands, type 'graphics help' for list of options"); 107 | rapp::inputAddBindings("graphics", s_bindingsGraphics); 108 | 109 | for (int i=0; im_type) 181 | { 182 | case Event::Axis: 183 | { 184 | const AxisEvent* axis = static_cast(ev); 185 | inputSetGamepadAxis(axis->m_gamepad, axis->m_axis, axis->m_value); 186 | } 187 | break; 188 | 189 | case Event::Char: 190 | { 191 | const CharEvent* chev = static_cast(ev); 192 | inputChar(chev->m_len, chev->m_char); 193 | #ifdef RAPP_WITH_BGFX 194 | if (_app->isGUImode()) 195 | if (ImGui::GetIO().WantCaptureKeyboard && (keysBindings == false)) 196 | ImGui::GetIO().AddInputCharactersUTF8((const char*)chev->m_char); 197 | #endif // RAPP_WITH_BGFX 198 | 199 | } 200 | break; 201 | 202 | case Event::Exit: 203 | return true; 204 | 205 | case Event::Gamepad: 206 | { 207 | const GamepadEvent* gev = static_cast(ev); 208 | inputSetGamepadConnected(gev->m_gamepad, gev->m_connected); 209 | RAPP_DBG("gamepad %d, %d", gev->m_gamepad.idx, gev->m_connected); 210 | } 211 | break; 212 | 213 | case Event::GamepadButton: 214 | { 215 | const GamepadButtonEvent* gev = static_cast(ev); 216 | inputSetGamepadButtonState(gev->m_gamepad, gev->m_button, gev->m_pressed); 217 | } 218 | break; 219 | 220 | case Event::Mouse: 221 | { 222 | const MouseEvent* mouse = static_cast(ev); 223 | handle = mouse->m_handle; 224 | 225 | if (mouse->m_move) 226 | { 227 | inputSetMousePos(mouse->m_mx, mouse->m_my, mouse->m_mz); 228 | } 229 | else 230 | { 231 | inputSetMouseButtonState(mouse->m_button, mouse->m_down); 232 | } 233 | } 234 | break; 235 | 236 | case Event::Key: 237 | { 238 | const KeyEvent* key = static_cast(ev); 239 | handle = key->m_handle; 240 | inputSetKeyState(key->m_key, key->m_modifiers, key->m_down); 241 | #ifdef RAPP_WITH_BGFX 242 | if (_app->isGUImode()) 243 | ImGui::GetIO().AddKeyEvent(s_keyMap[key->m_key], key->m_down); 244 | #endif // RAPP_WITH_BGFX 245 | } 246 | break; 247 | 248 | case Event::Size: 249 | { 250 | const SizeEvent* size = static_cast(ev); 251 | handle = size->m_handle; 252 | 253 | if ((_app->m_width != size->m_width) || 254 | (_app->m_height != size->m_height)) 255 | { 256 | _app->m_width = size->m_width; 257 | _app->m_height = size->m_height; 258 | 259 | reset = !g_reset; // force reset 260 | } 261 | } 262 | break; 263 | 264 | case Event::Suspend: 265 | break; 266 | 267 | case Event::Window: 268 | break; 269 | 270 | default: 271 | break; 272 | } 273 | } 274 | 275 | } while (NULL != ev); 276 | 277 | if ((handle.idx == kDefaultWindowHandle.idx) && (reset != g_reset)) 278 | { 279 | reset = g_reset; 280 | #ifdef RAPP_WITH_BGFX 281 | _app->m_resetView = true; 282 | #endif 283 | inputSetMouseResolution((uint16_t)_app->m_width, (uint16_t)_app->m_height); 284 | } 285 | 286 | return _app->m_exitCode != -1; 287 | } 288 | 289 | } // namespace rapp 290 | -------------------------------------------------------------------------------- /src/entry_ios.mm: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #if RTM_PLATFORM_IOS 11 | 12 | #import 13 | #import 14 | #import 15 | 16 | #ifdef RAPP_WITH_BGFX 17 | #include 18 | #endif 19 | 20 | namespace rapp 21 | { 22 | struct MainThreadEntry 23 | { 24 | int m_argc; 25 | char** m_argv; 26 | 27 | static int32_t threadFunc(void* _userData); 28 | }; 29 | 30 | static WindowHandle s_defaultWindow = { 0 }; 31 | 32 | struct Context 33 | { 34 | Context(uint32_t _width, uint32_t _height) 35 | { 36 | static const char* argv[1] = { "ios" }; 37 | m_mte.m_argc = 1; 38 | m_mte.m_argv = const_cast(argv); 39 | 40 | m_eventQueue.postSizeEvent(s_defaultWindow, _width, _height); 41 | 42 | #ifdef RAPP_WITH_BGFX 43 | // Prevent render thread creation. 44 | bgfx::renderFrame(); 45 | #endif 46 | 47 | m_thread.start(MainThreadEntry::threadFunc, &m_mte); 48 | } 49 | 50 | ~Context() 51 | { 52 | m_thread.stop(); 53 | } 54 | 55 | MainThreadEntry m_mte; 56 | rtm::Thread m_thread; 57 | 58 | EventQueue m_eventQueue; 59 | }; 60 | 61 | static Context* s_ctx; 62 | 63 | int32_t MainThreadEntry::threadFunc(void* _userData) 64 | { 65 | CFBundleRef mainBundle = CFBundleGetMainBundle(); 66 | if ( mainBundle != nil ) 67 | { 68 | CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle); 69 | if ( resourcesURL != nil ) 70 | { 71 | char path[PATH_MAX]; 72 | if (CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX) ) 73 | { 74 | chdir(path); 75 | } 76 | CFRelease(resourcesURL); 77 | } 78 | } 79 | 80 | MainThreadEntry* self = (MainThreadEntry*)_userData; 81 | int32_t result = main(self->m_argc, self->m_argv); 82 | return result; 83 | } 84 | 85 | const Event* poll() 86 | { 87 | return s_ctx->m_eventQueue.poll(); 88 | } 89 | 90 | const Event* poll(WindowHandle _handle) 91 | { 92 | return s_ctx->m_eventQueue.poll(_handle); 93 | } 94 | 95 | void release(const Event* _event) 96 | { 97 | s_ctx->m_eventQueue.release(_event); 98 | } 99 | 100 | void appRunOnMainThread(App::threadFn _fn, void* _userData) 101 | { 102 | } 103 | 104 | void windowGetDefaultSize(uint32_t* _width, uint32_t* _height) 105 | { 106 | RTM_ASSERT(_width, ""); 107 | RTM_ASSERT(_height, ""); 108 | *_width = 1920; 109 | *_height = 1080; 110 | } 111 | 112 | WindowHandle windowCreate(App* _app, int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title) 113 | { 114 | RTM_UNUSED_6(_x, _y, _width, _height, _flags, _title); 115 | WindowHandle handle = { UINT16_MAX }; 116 | return handle; 117 | } 118 | 119 | void windowDestroy(WindowHandle _handle) 120 | { 121 | RTM_UNUSED(_handle); 122 | } 123 | 124 | void windowSetPos(WindowHandle _handle, int32_t _x, int32_t _y) 125 | { 126 | RTM_UNUSED_3(_handle, _x, _y); 127 | } 128 | 129 | void windowSetSize(WindowHandle _handle, uint32_t _width, uint32_t _height) 130 | { 131 | RTM_UNUSED_3(_handle, _width, _height); 132 | } 133 | 134 | void windowSetTitle(WindowHandle _handle, const char* _title) 135 | { 136 | RTM_UNUSED_2(_handle, _title); 137 | } 138 | 139 | void windowToggleFrame(WindowHandle _handle) 140 | { 141 | RTM_UNUSED(_handle); 142 | } 143 | 144 | void windowToggleFullscreen(WindowHandle _handle) 145 | { 146 | RTM_UNUSED(_handle); 147 | } 148 | 149 | void windowSetMouseLock(WindowHandle _handle, bool _lock) 150 | { 151 | RTM_UNUSED(_handle, _lock); 152 | } 153 | 154 | void inputEmitKeyPress(KeyboardState::Key _key, uint8_t _modifiers) 155 | { 156 | s_ctx.m_eventQueue.postKeyEvent(rapp::kDefaultWindowHandle, _key, _modifiers, true); 157 | s_ctx.m_eventQueue.postKeyEvent(rapp::kDefaultWindowHandle, _key, _modifiers, false); 158 | } 159 | 160 | } // namespace rapp 161 | 162 | using namespace rapp; 163 | 164 | @interface View : UIView 165 | { 166 | CADisplayLink* m_displayLink; 167 | } 168 | 169 | @end 170 | 171 | @implementation View 172 | 173 | + (Class)layerClass 174 | { 175 | return [CAEAGLLayer class]; 176 | } 177 | 178 | - (id)initWithFrame:(CGRect)rect 179 | { 180 | self = [super initWithFrame:rect]; 181 | 182 | if (nil == self) 183 | { 184 | return nil; 185 | } 186 | 187 | #ifdef RAPP_WITH_BGFX 188 | CAEAGLLayer* layer = (CAEAGLLayer*)self.layer; 189 | bgfx::iosSetEaglLayer(layer); 190 | #endif 191 | return self; 192 | } 193 | 194 | - (void)start 195 | { 196 | if (nil == m_displayLink) 197 | { 198 | m_displayLink = [self.window.screen displayLinkWithTarget:self selector:@selector(renderFrame)]; 199 | //[m_displayLink setFrameInterval:1]; 200 | //[m_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 201 | // [m_displayLink addToRunLoop:[NSRunLoop currentRunLoop]]; 202 | [m_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; 203 | } 204 | } 205 | 206 | - (void)stop 207 | { 208 | if (nil != m_displayLink) 209 | { 210 | [m_displayLink invalidate]; 211 | m_displayLink = nil; 212 | } 213 | } 214 | 215 | - (void)renderFrame 216 | { 217 | #ifdef RAPP_WITH_BGFX 218 | bgfx::renderFrame(); 219 | #endif 220 | } 221 | 222 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 223 | { 224 | RTM_UNUSED(touches); 225 | UITouch *touch = [[event allTouches] anyObject]; 226 | CGPoint touchLocation = [touch locationInView:self]; 227 | 228 | s_ctx->m_eventQueue.postMouseEvent(s_defaultWindow, touchLocation.x, touchLocation.y, 0); 229 | s_ctx->m_eventQueue.postMouseEvent(s_defaultWindow, touchLocation.x, touchLocation.y, 0, MouseButton::Left, true); 230 | } 231 | 232 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 233 | { 234 | RTM_UNUSED(touches); 235 | UITouch *touch = [[event allTouches] anyObject]; 236 | CGPoint touchLocation = [touch locationInView:self]; 237 | s_ctx->m_eventQueue.postMouseEvent(s_defaultWindow, touchLocation.x, touchLocation.y, 0, MouseButton::Left, false); 238 | } 239 | 240 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 241 | { 242 | RTM_UNUSED(touches); 243 | UITouch *touch = [[event allTouches] anyObject]; 244 | CGPoint touchLocation = [touch locationInView:self]; 245 | s_ctx->m_eventQueue.postMouseEvent(s_defaultWindow, touchLocation.x, touchLocation.y, 0); 246 | } 247 | 248 | - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 249 | { 250 | RTM_UNUSED(touches); 251 | UITouch *touch = [[event allTouches] anyObject]; 252 | CGPoint touchLocation = [touch locationInView:self]; 253 | s_ctx->m_eventQueue.postMouseEvent(s_defaultWindow, touchLocation.x, touchLocation.y, 0, MouseButton::Left, false); 254 | } 255 | 256 | @end 257 | 258 | @interface AppDelegate : UIResponder 259 | { 260 | UIWindow* m_window; 261 | View* m_view; 262 | } 263 | 264 | @property (nonatomic, retain) UIWindow* m_window; 265 | @property (nonatomic, retain) View* m_view; 266 | 267 | @end 268 | 269 | @implementation AppDelegate 270 | 271 | @synthesize m_window; 272 | @synthesize m_view; 273 | 274 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 275 | { 276 | RTM_UNUSED(application, launchOptions); 277 | 278 | CGRect rect = [ [UIScreen mainScreen] bounds]; 279 | m_window = [ [UIWindow alloc] initWithFrame: rect]; 280 | m_view = [ [View alloc] initWithFrame: rect]; 281 | 282 | [m_window addSubview: m_view]; 283 | [m_window makeKeyAndVisible]; 284 | 285 | //float scaleFactor = [[UIScreen mainScreen] scale]; // should use this, but ui is too small on ipad retina 286 | float scaleFactor = 1.0f; 287 | [m_view setContentScaleFactor: scaleFactor ]; 288 | 289 | s_ctx = new Context((uint32_t)(scaleFactor*rect.size.width), (uint32_t)(scaleFactor*rect.size.height)); 290 | return YES; 291 | } 292 | 293 | - (void)applicationWillResignActive:(UIApplication *)application 294 | { 295 | RTM_UNUSED(application); 296 | [m_view stop]; 297 | } 298 | 299 | - (void)applicationDidEnterBackground:(UIApplication *)application 300 | { 301 | RTM_UNUSED(application); 302 | } 303 | 304 | - (void)applicationWillEnterForeground:(UIApplication *)application 305 | { 306 | RTM_UNUSED(application); 307 | } 308 | 309 | - (void)applicationDidBecomeActive:(UIApplication *)application 310 | { 311 | RTM_UNUSED(application); 312 | [m_view start]; 313 | } 314 | 315 | - (void)applicationWillTerminate:(UIApplication *)application 316 | { 317 | RTM_UNUSED(application); 318 | [m_view stop]; 319 | } 320 | 321 | - (void)dealloc 322 | { 323 | [m_window release]; 324 | [m_view release]; 325 | [super dealloc]; 326 | } 327 | 328 | @end 329 | 330 | int main(int _argc, char* _argv[]) 331 | { 332 | NSAutoreleasePool* pool = [ [NSAutoreleasePool alloc] init]; 333 | int exitCode = UIApplicationMain(_argc, _argv, @"UIApplication", NSStringFromClass([AppDelegate class]) ); 334 | [pool release]; 335 | return exitCode; 336 | } 337 | 338 | #endif // RTM_PLATFORM_IOS 339 | -------------------------------------------------------------------------------- /src/entry_p.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #ifndef RTM_RAPP_ENTRY_P_H 7 | #define RTM_RAPP_ENTRY_P_H 8 | 9 | #include 10 | #include 11 | #include // memcpy 12 | 13 | #ifndef ENTRY_CONFIG_MAX_GAMEPADS 14 | # define ENTRY_CONFIG_MAX_GAMEPADS 4 15 | #endif // ENTRY_CONFIG_MAX_GAMEPADS 16 | 17 | #define ENTRY_IMPLEMENT_EVENT(_class, _type) \ 18 | _class(WindowHandle _handle) : Event(_type, _handle) {} 19 | 20 | namespace rapp 21 | { 22 | int main(int _argc, const char* const* _argv); 23 | 24 | struct Event 25 | { 26 | enum Enum 27 | { 28 | Axis, 29 | Char, 30 | Exit, 31 | Gamepad, 32 | GamepadButton, 33 | Key, 34 | Mouse, 35 | Size, 36 | Window, 37 | Suspend 38 | }; 39 | 40 | Event(Enum _type) 41 | : m_type(_type) 42 | { 43 | m_handle.idx = UINT16_MAX; 44 | } 45 | 46 | Event(Enum _type, WindowHandle _handle) 47 | : m_type(_type) 48 | , m_handle(_handle) 49 | { 50 | } 51 | 52 | Event::Enum m_type; 53 | WindowHandle m_handle; 54 | }; 55 | 56 | struct AxisEvent : public Event 57 | { 58 | ENTRY_IMPLEMENT_EVENT(AxisEvent, Event::Axis); 59 | 60 | GamepadAxis::Enum m_axis; 61 | int32_t m_value; 62 | GamepadHandle m_gamepad; 63 | }; 64 | 65 | struct CharEvent : public Event 66 | { 67 | ENTRY_IMPLEMENT_EVENT(CharEvent, Event::Char); 68 | 69 | uint8_t m_len; 70 | uint8_t m_char[4]; 71 | }; 72 | 73 | struct GamepadEvent : public Event 74 | { 75 | ENTRY_IMPLEMENT_EVENT(GamepadEvent, Event::Gamepad); 76 | 77 | GamepadHandle m_gamepad; 78 | bool m_connected; 79 | }; 80 | 81 | struct GamepadButtonEvent : public Event 82 | { 83 | ENTRY_IMPLEMENT_EVENT(GamepadButtonEvent, Event::GamepadButton); 84 | 85 | GamepadHandle m_gamepad; 86 | GamepadState::Buttons m_button; 87 | bool m_pressed; 88 | }; 89 | 90 | struct KeyEvent : public Event 91 | { 92 | ENTRY_IMPLEMENT_EVENT(KeyEvent, Event::Key); 93 | 94 | KeyboardState::Key m_key; 95 | uint8_t m_modifiers; 96 | bool m_down; 97 | }; 98 | 99 | struct MouseEvent : public Event 100 | { 101 | ENTRY_IMPLEMENT_EVENT(MouseEvent, Event::Mouse); 102 | 103 | int32_t m_mx; 104 | int32_t m_my; 105 | int32_t m_mz; 106 | MouseState::Button m_button; 107 | bool m_down; 108 | bool m_doubleClick; 109 | bool m_move; 110 | uint8_t m_modifiers; 111 | }; 112 | 113 | struct SizeEvent : public Event 114 | { 115 | ENTRY_IMPLEMENT_EVENT(SizeEvent, Event::Size); 116 | 117 | uint16_t m_width; 118 | uint16_t m_height; 119 | }; 120 | 121 | struct WindowEvent : public Event 122 | { 123 | ENTRY_IMPLEMENT_EVENT(WindowEvent, Event::Window); 124 | 125 | void* m_nwh; 126 | }; 127 | 128 | struct SuspendEvent : public Event 129 | { 130 | enum Enum 131 | { 132 | DidSuspend, 133 | DidResume, 134 | WillSuspend, 135 | WillResume 136 | }; 137 | 138 | ENTRY_IMPLEMENT_EVENT(SuspendEvent, Event::Suspend); 139 | 140 | void* m_nwh; 141 | SuspendEvent::Enum m_eventState; 142 | }; 143 | 144 | const Event* poll(); 145 | const Event* poll(WindowHandle _handle); 146 | void release(const Event* _event); 147 | 148 | class EventQueue 149 | { 150 | public: 151 | EventQueue() 152 | : m_queue(2048) 153 | {} 154 | 155 | ~EventQueue() 156 | { 157 | for (const Event* ev = poll(); NULL != ev; ev = poll() ) 158 | { 159 | release(ev); 160 | } 161 | } 162 | 163 | void postAxisEvent(WindowHandle _handle, GamepadHandle _gamepad, GamepadAxis::Enum _axis, int32_t _value) 164 | { 165 | AxisEvent* ev = new AxisEvent(_handle); 166 | ev->m_gamepad = _gamepad; 167 | ev->m_axis = _axis; 168 | ev->m_value = _value; 169 | while(!m_queue.write(ev)); 170 | } 171 | 172 | void postCharEvent(WindowHandle _handle, uint8_t _len, const uint8_t _char[4]) 173 | { 174 | CharEvent* ev = new CharEvent(_handle); 175 | ev->m_len = _len; 176 | memcpy(ev->m_char, _char, 4); 177 | while(!m_queue.write(ev)); 178 | } 179 | 180 | void postExitEvent() 181 | { 182 | Event* ev = new Event(Event::Exit); 183 | while(!m_queue.write(ev)); 184 | } 185 | 186 | void postGamepadEvent(WindowHandle _handle, GamepadHandle _gamepad, bool _connected) 187 | { 188 | GamepadEvent* ev = new GamepadEvent(_handle); 189 | ev->m_gamepad = _gamepad; 190 | ev->m_connected = _connected; 191 | while(!m_queue.write(ev)); 192 | } 193 | 194 | void postGamepadButtonEvent(WindowHandle _handle, GamepadHandle _gamepad, GamepadState::Buttons _button, bool _pressed) 195 | { 196 | GamepadButtonEvent* ev = new GamepadButtonEvent(_handle); 197 | ev->m_gamepad = _gamepad; 198 | ev->m_button = _button; 199 | ev->m_pressed = _pressed; 200 | while(!m_queue.write(ev)); 201 | } 202 | 203 | void postKeyEvent(WindowHandle _handle, KeyboardState::Key _key, uint8_t _modifiers, bool _down) 204 | { 205 | KeyEvent* ev = new KeyEvent(_handle); 206 | ev->m_key = _key; 207 | ev->m_modifiers = _modifiers; 208 | ev->m_down = _down; 209 | ev->m_modifiers = _modifiers; 210 | while(!m_queue.write(ev)); 211 | } 212 | 213 | void postMouseEvent(WindowHandle _handle, int32_t _mx, int32_t _my, int32_t _mz, uint8_t _modifiers) 214 | { 215 | MouseEvent* ev = new MouseEvent(_handle); 216 | ev->m_mx = _mx; 217 | ev->m_my = _my; 218 | ev->m_mz = _mz; 219 | ev->m_button = MouseState::Button::None; 220 | ev->m_down = false; 221 | ev->m_move = true; 222 | ev->m_modifiers = _modifiers; 223 | ev->m_doubleClick = false; 224 | while(!m_queue.write(ev)); 225 | } 226 | 227 | void postMouseEvent(WindowHandle _handle, int32_t _mx, int32_t _my, int32_t _mz, MouseState::Button _button, uint8_t _modifiers, bool _down, bool _double) 228 | { 229 | MouseEvent* ev = new MouseEvent(_handle); 230 | ev->m_mx = _mx; 231 | ev->m_my = _my; 232 | ev->m_mz = _mz; 233 | ev->m_button = _button; 234 | ev->m_down = _down; 235 | ev->m_move = false; 236 | ev->m_modifiers = _modifiers; 237 | ev->m_doubleClick = _double; 238 | while(!m_queue.write(ev)); 239 | } 240 | 241 | void postSizeEvent(WindowHandle _handle, uint32_t _width, uint32_t _height) 242 | { 243 | SizeEvent* ev = new SizeEvent(_handle); 244 | ev->m_width = static_cast(_width); 245 | ev->m_height = static_cast(_height); 246 | while(!m_queue.write(ev)); 247 | } 248 | 249 | void postWindowEvent(WindowHandle _handle, void* _nwh = NULL) 250 | { 251 | WindowEvent* ev = new WindowEvent(_handle); 252 | ev->m_nwh = _nwh; 253 | while(!m_queue.write(ev)); 254 | } 255 | 256 | void postSuspendEvent(WindowHandle _handle, SuspendEvent::Enum _suspendState) 257 | { 258 | SuspendEvent* ev = new SuspendEvent(_handle); 259 | ev->m_eventState = _suspendState; 260 | while(!m_queue.write(ev)); 261 | } 262 | 263 | const Event* poll() 264 | { 265 | Event* e = 0; 266 | m_queue.read(&e); 267 | return (Event*)e; 268 | } 269 | 270 | const Event* poll(WindowHandle _handle) 271 | { 272 | if (isValid(_handle) ) 273 | { 274 | Event* ev = 0; 275 | m_queue.peek((void**)&ev); 276 | if (NULL == ev 277 | || ev->m_handle.idx != _handle.idx) 278 | { 279 | return NULL; 280 | } 281 | } 282 | 283 | return poll(); 284 | } 285 | 286 | void release(const Event* _event) const 287 | { 288 | delete _event; 289 | } 290 | 291 | private: 292 | rtm::SpScQueue m_queue; 293 | }; 294 | 295 | } // namespace rapp 296 | 297 | #endif // RTM_RAPP_ENTRY_P_H 298 | -------------------------------------------------------------------------------- /src/input.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #ifndef RTM_RAPP_INPUT_H 7 | #define RTM_RAPP_INPUT_H 8 | 9 | #include 10 | #include 11 | 12 | namespace rapp { 13 | 14 | const char* getName(KeyboardState::Key _key); 15 | 16 | struct GamepadHandle { uint16_t idx; }; 17 | inline bool isValid(GamepadHandle _handle) { return UINT16_MAX != _handle.idx; } 18 | 19 | struct GamepadAxis 20 | { 21 | enum Enum 22 | { 23 | LeftX, 24 | LeftY, 25 | LeftZ, 26 | RightX, 27 | RightY, 28 | RightZ, 29 | 30 | Count 31 | }; 32 | }; 33 | 34 | /// 35 | void inputInit(); 36 | 37 | /// 38 | void inputShutdown(); 39 | 40 | /// 41 | bool inputProcess(App* _app); 42 | 43 | /// 44 | void inputSetKeyState(KeyboardState::Key _key, uint8_t _modifiers, bool _down); 45 | 46 | /// 47 | uint8_t inputGetModifiersState(); 48 | 49 | /// Adds single UTF-8 encoded character into input buffer. 50 | void inputChar(uint8_t _len, const uint8_t _char[4]); 51 | 52 | /// Returns single UTF-8 encoded character from input buffer. 53 | void inputGetChar(uint8_t _char[4]); 54 | 55 | /// Flush internal input buffer. 56 | void inputCharFlush(); 57 | 58 | /// 59 | void inputSetMouseResolution(uint16_t _width, uint16_t _height); 60 | 61 | /// 62 | void inputSetMousePos(int32_t _mx, int32_t _my, int32_t _mz); 63 | 64 | /// 65 | void inputResetMouseMovement(); 66 | 67 | /// 68 | void inputResetGamepadAxisMovement(); 69 | 70 | /// 71 | void inputSetMouseButtonState(MouseState::Button _button, uint8_t _state); 72 | 73 | /// 74 | void inputGetMouse(float _mouse[3]); 75 | 76 | /// 77 | bool inputIsMouseLocked(); 78 | 79 | /// 80 | void inputSetGamepadConnected(GamepadHandle _handle, bool _connected); 81 | 82 | /// 83 | void inputSetGamepadButtonState(GamepadHandle _handle, GamepadState::Buttons _button, bool _pressed); 84 | 85 | /// 86 | void inputSetGamepadAxis(GamepadHandle _handle, GamepadAxis::Enum _axis, int32_t _value); 87 | 88 | /// 89 | int32_t inputGetGamepadAxis(GamepadHandle _handle, GamepadAxis::Enum _axis); 90 | 91 | } // namespace rapp 92 | 93 | #endif // RTM_RAPP_INPUT_H 94 | -------------------------------------------------------------------------------- /src/job.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #if RTM_COMPILER_MSVC 11 | __pragma(warning(push)) 12 | __pragma(warning(disable:4100)) 13 | #endif 14 | 15 | #define ENKI_CUSTOM_ALLOC_FILE_AND_LINE 16 | 17 | #if RTM_PLATFORM_POSIX 18 | #include 19 | #include 20 | #include 21 | #endif 22 | 23 | #include "../3rd/enkiTS/src/TaskScheduler.h" 24 | 25 | #if RTM_COMPILER_MSVC 26 | __pragma(warning(pop)) 27 | #endif 28 | 29 | #include 30 | #include 31 | 32 | using namespace enki; 33 | 34 | namespace rapp { 35 | 36 | enki::TaskScheduler g_TS; 37 | 38 | struct CompletionActionDelete : ICompletable 39 | { 40 | Dependency m_Dependency; 41 | void OnDependenciesComplete(TaskScheduler* pTaskScheduler_, uint32_t threadNum_) 42 | { 43 | ICompletable::OnDependenciesComplete(pTaskScheduler_, threadNum_); 44 | delete m_Dependency.GetDependencyTask(); 45 | } 46 | }; 47 | 48 | class Job : public enki::ITaskSet 49 | { 50 | public: 51 | JobFn m_function; 52 | void* m_userData; 53 | uint32_t m_stride; 54 | uint32_t m_start; 55 | uint32_t m_end; 56 | CompletionActionDelete m_taskDeleter; 57 | 58 | 59 | Job(uint32_t _numJobs, bool _delete) 60 | : enki::ITaskSet(_numJobs) 61 | , m_function(0) 62 | , m_userData(0) 63 | , m_stride(0) 64 | , m_start(0) 65 | , m_end(0) 66 | { 67 | if (_delete) 68 | m_taskDeleter.SetDependency(m_taskDeleter.m_Dependency, this); 69 | } 70 | 71 | void ExecuteRange(enki::TaskSetPartition _range, uint32_t /*_threadnum*/) override 72 | { 73 | #ifdef RAPP_WITH_RPROF 74 | RPROF_SCOPE("test"); 75 | #endif // RAPP_WITH_RPROF 76 | 77 | m_function(m_userData, _range.start, _range.end); 78 | } 79 | }; 80 | 81 | void jobInit() 82 | { 83 | g_TS.Initialize(); 84 | } 85 | 86 | void jobShutdown() 87 | { 88 | g_TS.WaitforAllAndShutdown(); 89 | } 90 | 91 | JobHandle jobCreate(JobFn _func, void* _userData, bool _deleteOnFinish) 92 | { 93 | return jobCreateGroup(_func, _userData, 0, 1, _deleteOnFinish); 94 | } 95 | 96 | JobHandle jobCreateGroup(JobFn _func, void* _userData, uint32_t _dataStride, uint32_t _numJobs, bool _deleteOnFinish) 97 | { 98 | Job* j = new Job(_numJobs, _deleteOnFinish); 99 | j->m_function = _func; 100 | j->m_userData = _userData; 101 | j->m_stride = _dataStride; 102 | j->m_start = 0; 103 | j->m_end = _numJobs; 104 | return { (uintptr_t)j }; 105 | } 106 | 107 | void jobDestroy(JobHandle _job) 108 | { 109 | Job* j = (Job*)_job.idx; 110 | if (!j->GetIsComplete()) 111 | g_TS.WaitforTask(j); 112 | delete j; 113 | } 114 | 115 | void jobRun(JobHandle _job) 116 | { 117 | Job* j = (Job*)_job.idx; 118 | g_TS.AddTaskSetToPipe(j); 119 | } 120 | 121 | void jobWait(JobHandle _job) 122 | { 123 | Job* j = (Job*)_job.idx; 124 | g_TS.WaitforTask(j); 125 | } 126 | 127 | uint32_t jobStatus(JobHandle _job) 128 | { 129 | Job* j = (Job*)_job.idx; 130 | return j->GetIsComplete() ? 1 : 0; 131 | } 132 | 133 | } // namespace rapp 134 | -------------------------------------------------------------------------------- /src/job.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #ifndef RTM_RAPP_JOB_H 7 | #define RTM_RAPP_JOB_H 8 | 9 | #include 10 | #include 11 | 12 | namespace rapp { 13 | 14 | /// 15 | void jobInit(); 16 | 17 | /// 18 | void jobShutdown(); 19 | 20 | } // namespace rapp 21 | 22 | #endif // RTM_RAPP_JOB_H 23 | -------------------------------------------------------------------------------- /src/rapp_config.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #ifndef RTM_RAPP_CONFIG_H 7 | #define RTM_RAPP_CONFIG_H 8 | 9 | #define RAPP_MAX_WINDOWS 2048 10 | 11 | #define RAPP_JOBS_PER_THREAD 16*1024 12 | #define RAPP_JOBS_PER_QUEUE 8*1024 13 | #define RAPP_JOBS_QUEUE_MASK (RAPP_JOBS_PER_QUEUE - 1) 14 | 15 | #endif // RTM_RAPP_CONFIG_H 16 | -------------------------------------------------------------------------------- /src/rapp_pch.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | -------------------------------------------------------------------------------- /src/rapp_pch.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | #include 8 | 9 | //#define RTM_DEFINE_STL_TYPES 10 | #define RAPP_HASH_SIZE 32768 11 | #define RAPP_HASH_MASK 32767 12 | #define RAPP_MAX_APPS 64 13 | 14 | #define RBASE_NAMESPACE rapp 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #ifdef RAPP_WITH_RPROF 29 | #include 30 | #endif // RAPP_WITH_RPROF 31 | 32 | -------------------------------------------------------------------------------- /src/rapp_timer.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #ifndef RTM_RAPP_TIMER_H 7 | #define RTM_RAPP_TIMER_H 8 | 9 | #include 10 | 11 | namespace rapp { 12 | 13 | class FrameStep 14 | { 15 | uint64_t m_startClock; 16 | float m_accumulator; 17 | float m_currentTime; 18 | float m_step; 19 | 20 | public: 21 | FrameStep(uint32_t _fps = 60) 22 | : m_startClock(rtm::CPU::clock()) 23 | , m_accumulator(0.0f) 24 | , m_currentTime(0.0f) 25 | , m_step(1.0f / float(_fps)) 26 | { 27 | m_currentTime = rtm::CPU::time(m_startClock); 28 | } 29 | 30 | inline void setFrameRate(uint32_t _fps) 31 | { 32 | m_startClock = rtm::CPU::clock(); 33 | m_accumulator = 0.0f; 34 | m_currentTime = 0.0f; 35 | m_step = 1.0f / float(_fps); 36 | } 37 | 38 | inline uint32_t frameRate() 39 | { 40 | return (uint32_t)((1.0f / m_step) + 0.5f); 41 | } 42 | 43 | inline bool update() 44 | { 45 | if (m_accumulator <= m_step) 46 | { 47 | float newTime = rtm::CPU::time(m_startClock); 48 | float frameTime = newTime - m_currentTime; 49 | if (frameTime > 0.25f) 50 | frameTime = 0.25f; 51 | 52 | m_currentTime = newTime; 53 | m_accumulator += frameTime; 54 | } 55 | 56 | if (m_accumulator > m_step) 57 | { 58 | m_accumulator -= m_step; 59 | return true; 60 | } 61 | return false; 62 | } 63 | 64 | inline float step() 65 | { 66 | return m_step; 67 | } 68 | 69 | inline float alpha() 70 | { 71 | return m_accumulator / m_step; 72 | } 73 | }; 74 | 75 | } // namespace rapp 76 | 77 | #endif // RTM_RAPP_TIMER_H 78 | -------------------------------------------------------------------------------- /src/rapp_vg.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------// 2 | /// Copyright 2025 Milos Tosic. All Rights Reserved. /// 3 | /// License: http://www.opensource.org/licenses/BSD-2-Clause /// 4 | //--------------------------------------------------------------------------// 5 | 6 | #include 7 | 8 | #ifdef RAPP_WITH_BGFX 9 | 10 | #include <../3rd/vg_renderer/include/vg/vg.h> 11 | #include <../3rd/vg_renderer/include/vg/path.h> 12 | #include <../3rd/vg_renderer/include/vg/stroker.h> 13 | 14 | vg::Context* g_currentContext = 0; 15 | vg::FillFlags::Enum g_fillFlags = vg::FillFlags::ConvexAA; 16 | vg::StrokeFlags::Enum g_strokeFlags = vg::StrokeFlags::ButtRoundAA; 17 | 18 | inline static vg::Color getVGColor(uint32_t _color) 19 | { 20 | return _color; 21 | } 22 | 23 | #define VG_CALL( X ) X 24 | #else 25 | #define VG_CALL( X ) 26 | #endif 27 | 28 | namespace rapp { 29 | 30 | /// 31 | uint32_t vgColor(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a) 32 | { 33 | return (_r << 24) | (_g << 16) | (_b << 8) | (_a); 34 | } 35 | 36 | void vgSave() 37 | { 38 | VG_CALL(vg::pushState(g_currentContext);) 39 | } 40 | 41 | void vgRestore() 42 | { 43 | VG_CALL(vg::popState(g_currentContext);) 44 | } 45 | 46 | /// 47 | void vgGlobalAlpha(float _opacity) 48 | { 49 | RTM_UNUSED(_opacity); 50 | VG_CALL(vg::setGlobalAlpha(g_currentContext, _opacity);) 51 | } 52 | 53 | void vgBeginPath() 54 | { 55 | VG_CALL(vg::beginPath(g_currentContext);) 56 | } 57 | 58 | void vgMoveTo(float _x, float _y) 59 | { 60 | RTM_UNUSED_2(_x, _y); 61 | VG_CALL(vg::moveTo(g_currentContext, _x, _y);) 62 | } 63 | 64 | void vgLineTo(float _x, float _y) 65 | { 66 | RTM_UNUSED_2(_x, _y); 67 | VG_CALL(vg::lineTo(g_currentContext, _x, _y);) 68 | } 69 | 70 | void vgBezierTo(float _c1x, float _c1y, float _c2x, float _c2y, float _x, float _y) 71 | { 72 | RTM_UNUSED_6(_c1x, _c1y, _c2x, _c2y, _x, _y); 73 | VG_CALL(vg::cubicTo(g_currentContext, _c1x, _c1y, _c2x, _c2y, _x, _y);) 74 | } 75 | 76 | void vgQuadraticTo(float _cx, float _cy, float _x, float _y) 77 | { 78 | RTM_UNUSED_4(_cx, _cy, _x, _y); 79 | VG_CALL(vg::quadraticTo(g_currentContext, _cx, _cy, _x, _y);) 80 | } 81 | 82 | void vgArcTo(float _x1, float _y1, float _x2, float _y2, float _r) 83 | { 84 | RTM_UNUSED_5(_x1, _y1, _x2, _y2, _r); 85 | VG_CALL(vg::arcTo(g_currentContext, _x1, _y1, _x2, _y2, _r);) 86 | } 87 | 88 | void vgArc(float _cx, float _cy, float _r, float _a0, float _a1, int _dir) 89 | { 90 | RTM_UNUSED_6(_cx, _cy, _r, _a0, _a1, _dir); 91 | VG_CALL(vg::arc(g_currentContext, _cx, _cy, _r, _a0, _a1, _dir ? vg::Winding::CW : vg::Winding::CCW);) 92 | } 93 | 94 | void vgRect(float _x, float _y, float _w, float _h) 95 | { 96 | RTM_UNUSED_4(_x, _y, _w, _h); 97 | VG_CALL(vg::rect(g_currentContext, _x, _y, _w, _h);) 98 | } 99 | 100 | void vgRect(float _x, float _y, float _w, float _h, float _r) 101 | { 102 | RTM_UNUSED_5(_x, _y, _w, _h, _r); 103 | VG_CALL(vg::roundedRect(g_currentContext, _x, _y, _w, _h, _r);) 104 | } 105 | 106 | void vgRoundedRectVarying(float _x, float _y, float _w, float _h, float _rtl, float _rtr, float _rbr, float _rbl) 107 | { 108 | RTM_UNUSED_4(_x, _y, _w, _h); 109 | RTM_UNUSED_4(_rtl, _rtr, _rbr, _rbl); 110 | VG_CALL(vg::roundedRectVarying(g_currentContext, _x, _y, _w, _h, _rtl, _rtr, _rbr, _rbl);) 111 | } 112 | 113 | void vgCircle(float _cx, float _cy, float _radius) 114 | { 115 | RTM_UNUSED_3(_cx, _cy, _radius); 116 | VG_CALL(vg::circle(g_currentContext, _cx, _cy, _radius);) 117 | } 118 | 119 | void vgEllipse(float _cx, float _cy, float _rx, float _ry) 120 | { 121 | RTM_UNUSED_4(_cx, _cy, _rx, _ry); 122 | VG_CALL(vg::ellipse(g_currentContext, _cx, _cy, _rx, _ry);) 123 | } 124 | 125 | void vgPolyline(const float* _coords, uint32_t _numPoints) 126 | { 127 | RTM_UNUSED_2(_coords, _numPoints); 128 | VG_CALL(vg::polyline(g_currentContext, _coords, _numPoints);) 129 | } 130 | 131 | void vgPathWinding(int _winding) 132 | { 133 | RTM_UNUSED(_winding); 134 | VG_CALL(g_fillFlags = _winding == VG_CCW ? vg::FillFlags::ConvexAA : vg::FillFlags::ConcaveNonZeroAA); 135 | } 136 | 137 | void vgClosePath() 138 | { 139 | VG_CALL(vg::closePath(g_currentContext);) 140 | } 141 | 142 | void vgFill(uint32_t _color, uint32_t _flags) 143 | { 144 | RTM_UNUSED_2(_color, _flags); 145 | VG_CALL(vg::fillPath(g_currentContext, getVGColor(_color), g_fillFlags);) 146 | } 147 | 148 | void vgFillLinearGradient(float _sx, float _sy, float _ex, float _ey, uint32_t _icol, uint32_t _ocol) 149 | { 150 | RTM_UNUSED_6(_sx, _sy, _ex, _ey, _icol, _ocol); 151 | VG_CALL(vg::GradientHandle gradient = vg::createLinearGradient(g_currentContext, _sx, _sy, _ex, _ey, getVGColor(_icol), getVGColor(_ocol));) 152 | VG_CALL(vg::fillPath(g_currentContext, gradient, g_fillFlags);) 153 | } 154 | 155 | void vgFillBoxGradient(float _x, float _y, float _w, float _h, float _r, float _f, uint32_t _icol, uint32_t _ocol) 156 | { 157 | RTM_UNUSED_6(_x, _y, _w, _h, _r, _f); 158 | RTM_UNUSED_2(_icol, _ocol); 159 | VG_CALL(vg::GradientHandle gradient = vg::createBoxGradient(g_currentContext, _x, _y, _w, _h, _r, _f, getVGColor(_icol), getVGColor(_ocol));) 160 | VG_CALL(vg::fillPath(g_currentContext, gradient, g_fillFlags);) 161 | } 162 | 163 | void vgFillRadialGradient(float _cx, float _cy, float _inr, float _outr, uint32_t _icol, uint32_t _ocol) 164 | { 165 | RTM_UNUSED_4(_cx, _cy, _inr, _outr); 166 | RTM_UNUSED_2(_icol, _ocol); 167 | VG_CALL(vg::GradientHandle gradient = vg::createRadialGradient(g_currentContext, _cx, _cy, _inr, _outr, getVGColor(_icol), getVGColor(_ocol));) 168 | VG_CALL(vg::fillPath(g_currentContext, gradient, g_fillFlags);) 169 | } 170 | 171 | void vgStroke(uint32_t _color, float _width, uint32_t _flags) 172 | { 173 | RTM_UNUSED_3(_color, _width, _flags); 174 | VG_CALL(vg::strokePath(g_currentContext, getVGColor(_color), _width, g_strokeFlags);) 175 | } 176 | 177 | void vgStrokeLinearGradient(float _sx, float _sy, float _ex, float _ey, uint32_t _icol, uint32_t _ocol, float _width) 178 | { 179 | RTM_UNUSED_4(_sx, _sy, _ex, _ey); 180 | RTM_UNUSED_3(_icol, _ocol, _width); 181 | VG_CALL(vg::GradientHandle gradient = vg::createLinearGradient(g_currentContext, _sx, _sy, _ex, _ey, getVGColor(_icol), getVGColor(_ocol));) 182 | VG_CALL(vg::strokePath(g_currentContext, gradient, _width, g_strokeFlags);) 183 | } 184 | 185 | void vgStrokeBoxGradient(float _x, float _y, float _w, float _h, float _r, float _f, uint32_t _icol, uint32_t _ocol, float _width) 186 | { 187 | RTM_UNUSED_6(_x, _y, _w, _h, _r, _f); 188 | RTM_UNUSED_3(_icol, _ocol, _width); 189 | VG_CALL(vg::GradientHandle gradient = vg::createBoxGradient(g_currentContext, _x, _y, _w, _h, _r, _f, getVGColor(_icol), getVGColor(_ocol));) 190 | VG_CALL(vg::strokePath(g_currentContext, gradient, _width, g_strokeFlags);) 191 | } 192 | 193 | void vgStrokeRadialGradient(float _cx, float _cy, float _inr, float _outr, uint32_t _icol, uint32_t _ocol, float _width) 194 | { 195 | RTM_UNUSED_4(_cx, _cy, _inr, _outr); 196 | RTM_UNUSED_3(_icol, _ocol, _width); 197 | VG_CALL(vg::GradientHandle gradient = vg::createRadialGradient(g_currentContext, _cx, _cy, _inr, _outr, getVGColor(_icol), getVGColor(_ocol));) 198 | VG_CALL(vg::strokePath(g_currentContext, gradient, _width, g_strokeFlags);) 199 | } 200 | 201 | void vgLineCapJoin(int _lineCap, int _lineJoin) 202 | { 203 | RTM_UNUSED_2(_lineCap, _lineJoin); 204 | VG_CALL(g_strokeFlags = (vg::StrokeFlags::Enum)VG_STROKE_FLAGS(_lineCap, _lineJoin, 1);) 205 | } 206 | 207 | void vgTransformPoint(float* dx, float* dy, const float* t, float sx, float sy) 208 | { 209 | *dx = sx * t[0] + sy * t[2] + t[4]; 210 | *dy = sx * t[1] + sy * t[3] + t[5]; 211 | } 212 | 213 | void vgTransformScale(float* _xform, float _scaleX, float _scaleY) 214 | { 215 | _xform[0] = _scaleX; 216 | _xform[1] = 0.0f; 217 | _xform[2] = 0.0f; 218 | _xform[3] = _scaleY; 219 | _xform[4] = 0.0f; 220 | _xform[5] = 0.0f; 221 | } 222 | 223 | void vgTransformTranslate(float* _xform, float _translateX, float _translateY) 224 | { 225 | _xform[0] = 1.0f; 226 | _xform[1] = 0.0f; 227 | _xform[2] = 0.0f; 228 | _xform[3] = 1.0f; 229 | _xform[4] = _translateX; 230 | _xform[5] = _translateY; 231 | } 232 | 233 | void vgTransformTranslateScale(float* _xform, float _translateX, float _translateY, float _scaleX, float _scaleY) 234 | { 235 | _xform[0] = _scaleX; 236 | _xform[1] = 0.0f; 237 | _xform[2] = 0.0f; 238 | _xform[3] = _scaleY; 239 | _xform[4] = _translateX; 240 | _xform[5] = _translateY; 241 | } 242 | 243 | void vgTransformRotate(float* _xform, float _angleRadian) 244 | { 245 | float cs = cosf(_angleRadian); 246 | float sn = sinf(_angleRadian); 247 | _xform[0] = cs; 248 | _xform[1] = sn; 249 | _xform[2] = -sn; 250 | _xform[3] = cs; 251 | _xform[4] = 0.0f; 252 | _xform[5] = 0.0f; 253 | } 254 | 255 | void vgTransformMultiply(float* _xform, const float* _left, const float* _right) 256 | { 257 | float t0 = _left[0] * _right[0] + _left[1] * _right[2]; 258 | float t2 = _left[2] * _right[0] + _left[3] * _right[2]; 259 | float t4 = _left[4] * _right[0] + _left[5] * _right[2] + _right[4]; 260 | _xform[1] = _left[0] * _right[1] + _left[1] * _right[3]; 261 | _xform[3] = _left[2] * _right[1] + _left[3] * _right[3]; 262 | _xform[5] = _left[4] * _right[1] + _left[5] * _right[3] + _right[5]; 263 | _xform[0] = t0; 264 | _xform[2] = t2; 265 | _xform[4] = t4; 266 | } 267 | 268 | } // namespace rapp 269 | --------------------------------------------------------------------------------