├── .gitattributes ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── _BuildThirdparty.bat ├── app.cpp ├── app.h ├── app.vpc ├── imgui_impl_source.cpp ├── imgui_impl_source.h ├── main.cpp ├── studiomodel.cpp ├── studiomodel.h └── thirdparty └── imconfig_but_in_a_different_folder_so_i_dont_have_another_repo.h /.gitattributes: -------------------------------------------------------------------------------- 1 | creategameprojects text 2 | createallprojects text 3 | xcode_ccache_wrapper text 4 | vpc text 5 | vpc_linux binary 6 | vpc_osx binary 7 | 8 | *.sh text 9 | *.bat text 10 | *.txt text 11 | *.c text 12 | *.h text 13 | *.H text 14 | *.cc text 15 | *.cpp text 16 | *.vpc text 17 | *.vgc text 18 | *.nut text 19 | *.awk text 20 | *.pl text 21 | *.py text 22 | *.xcconfig text 23 | *.vcd text 24 | *.vbsp text 25 | *.proto text 26 | *.inc text 27 | *.fxc text 28 | *.vsh text 29 | *.lst text 30 | *.mm text 31 | *.cfg text 32 | *.res text 33 | *.rc text 34 | *.def text 35 | *.vmt text 36 | *.inl text 37 | *.asm text 38 | 39 | .gitignore text 40 | sourcesdk_def.mak text 41 | smdlexp.mak text 42 | README text 43 | CONTRIBUTING text 44 | LICENSE text 45 | 46 | *.exe binary 47 | protoc binary 48 | ccache binary 49 | 50 | gtest_output_test_golden_lin.txt binary 51 | mod_*_english.txt binary 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Files to ignore when considering what GIT should commit. 2 | 3 | # Visual Studio 4 | *.suo 5 | *.user 6 | *.sln.docstates 7 | *.obj 8 | *.pch 9 | *.tlog 10 | *.log 11 | *.scc 12 | *.exp 13 | *.ilk 14 | *.lastbuildstate 15 | vc100.pdb 16 | ipch 17 | *.sdf 18 | *.opensdf 19 | *.idb 20 | *.vcxproj 21 | *.sln 22 | .vs/ 23 | *.vcproj 24 | UpgradeLog.htm 25 | 26 | [Dd]ebug*/ 27 | [Rr]elease*/ 28 | 29 | gitparams.h 30 | 31 | game_shader_dx9.dll 32 | game_shader_dx9.lib 33 | 34 | vcslist.txt 35 | uniquefilestocopy.txt 36 | makefil* 37 | inclist.txt 38 | filestocopy.txt 39 | *.enc 40 | 41 | GameState.txt 42 | ep1_gamestats.dat 43 | 44 | *.scr 45 | downloadlists 46 | ServerConfig.vdf 47 | *.sav 48 | *.hl* 49 | 50 | modelsounds.cache 51 | stats.txt 52 | textwindow_temp.html 53 | voice_ban.dt 54 | server_blacklist.txt 55 | *.ain 56 | sound.cache 57 | user_custom 58 | 59 | mathlib.lib 60 | tier1.lib 61 | vgui_controls.lib 62 | raytrace.lib 63 | fgdlib.lib 64 | 65 | *.vcxproj.filters 66 | *.pdb 67 | *.vpc_crc 68 | *.vpc.sentinel 69 | vpc.exe.bak 70 | 71 | src/.vs 72 | 73 | # OSX/Linux build products 74 | *.mak 75 | *.mak.vpc_crc 76 | *.xcodeproj/ 77 | *.project 78 | *.a 79 | obj*/ 80 | !devtools/*.mak 81 | !utils/smdlexp/smdlexp.mak 82 | 83 | # Specific Source build products 84 | client.pdb 85 | client.dll 86 | client.lib 87 | server.pdb 88 | server.dll 89 | server.lib 90 | 91 | client.so* 92 | server.so* 93 | server_srv.so* 94 | 95 | client.dylib 96 | client.dylib.dSYM/ 97 | server.dylib 98 | server.dylib.dSYM/ 99 | 100 | # files generated by running a mod 101 | config.cfg 102 | 103 | # shader files 104 | *.tmp 105 | 106 | # Game bin directories 107 | /game/* 108 | src/materialsystem/stdshaders/filelist.txt 109 | src/materialsystem/stdshaders/filelistgen.txt 110 | src/enc_temp_folder 111 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "thirdparty/glfw"] 2 | path = thirdparty/glfw 3 | url = https://github.com/glfw/glfw.git 4 | [submodule "thirdparty/imgui"] 5 | path = thirdparty/imgui 6 | url = https://github.com/ocornut/imgui.git 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. 2 | 3 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is an example program for integrating Dear ImGui and GLFW into Source Engine's app system, which is the same thing Source's tools use. 2 | 3 | Feel free to do with this as you please, and if you make something cool or have a complaint send it to me via an issue on this repo or any other platform. 4 | 5 | If you have issues compiling Dear ImGui with Visual Studio 2013, [I would suggest trying out Visual Studio 2022 using my other repo.](https://github.com/ozxybox/source-mp13-vs2022) 6 | 7 | ![Screenshot](https://raw.githubusercontent.com/ozxybox/readme_screenshots/main/imgui_source_2013.PNG) 8 | 9 | -------------------------------------------------------------------------------- /_BuildThirdparty.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | set A_CDSTART=%cd% 4 | 5 | @REM CMake Check 6 | cmake --version 7 | set A_ERRORLEVEL=%ERRORLEVEL% 8 | if %A_ERRORLEVEL% neq 0 goto missingCMake 9 | 10 | @REM DearImGui 11 | cd thirdparty 12 | xcopy /y /f imconfig_but_in_a_different_folder_so_i_dont_have_another_repo.h imgui\imconfig.h 13 | 14 | @REM GLFW 15 | cd glfw 16 | cmake . -B "build" -A Win32 -D CMAKE_BUILD_TYPE=Release -D GLFW_BUILD_EXAMPLES=OFF -D GLFW_BUILD_TESTS=OFF -D GLFW_BUILD_DOCS=OFF -D CMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded 17 | cmake --build build --config Release 18 | 19 | copy build\src\Release\glfw3.lib glfw3.lib 20 | 21 | goto done 22 | 23 | :missingCMake 24 | echo ============================= 25 | echo Failed to install thirdparty! 26 | echo Please download CMake! 27 | echo ============================= 28 | cd %A_CDSTART% 29 | exit /b 1 30 | 31 | :done 32 | echo ============================= 33 | echo Compile complete! 34 | echo ============================= 35 | cd %A_CDSTART% 36 | -------------------------------------------------------------------------------- /app.cpp: -------------------------------------------------------------------------------- 1 | #include "app.h" 2 | #include "materialsystem/imaterialproxyfactory.h" 3 | #include "materialsystem/ITexture.h" 4 | #include "materialsystem/MaterialSystem_Config.h" 5 | #include "istudiorender.h" 6 | #include "tier2/camerautils.h" 7 | 8 | #include "studiomodel.h" 9 | 10 | // Bring in our non-source things 11 | #include "memdbgoff.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #ifdef _WIN32 18 | #define GLFW_EXPOSE_NATIVE_WIN32 1 19 | #endif 20 | #include 21 | #include 22 | 23 | 24 | // Currently blank, but might be worth filling in if you need mat proxies 25 | class CDummyMaterialProxyFactory : public IMaterialProxyFactory 26 | { 27 | public: 28 | virtual IMaterialProxy *CreateProxy(const char *proxyName) { return nullptr; } 29 | virtual void DeleteProxy(IMaterialProxy *pProxy) { } 30 | }; 31 | CDummyMaterialProxyFactory g_DummyMaterialProxyFactory; 32 | 33 | 34 | 35 | 36 | void CImGuiSourceApp::Init() 37 | { 38 | if (!glfwInit()) 39 | return; 40 | 41 | // We're handled by matsys, no api 42 | glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 43 | m_pWindow = glfwCreateWindow(640, 480, "Example Dear ImGui Source App", NULL, NULL); 44 | if (!m_pWindow) 45 | return; 46 | 47 | glfwMakeContextCurrent(m_pWindow); 48 | #ifdef _WIN32 49 | HWND hwnd = glfwGetWin32Window(m_pWindow); 50 | #endif 51 | 52 | // Set up matsys 53 | MaterialSystem_Config_t config; 54 | config = g_pMaterialSystem->GetCurrentConfigForVideoCard(); 55 | config.SetFlag(MATSYS_VIDCFG_FLAGS_WINDOWED, true); 56 | config.SetFlag(MATSYS_VIDCFG_FLAGS_RESIZING, true); 57 | 58 | // Feed material system our window 59 | if (!g_pMaterialSystem->SetMode((void*)hwnd, config)) 60 | return; 61 | g_pMaterialSystem->OverrideConfig(config, false); 62 | 63 | // We want to set this before we load up any mats, else it'll reload em all 64 | g_pMaterialSystem->SetMaterialProxyFactory(&g_DummyMaterialProxyFactory); 65 | 66 | // White out our cubemap and lightmap, as we don't have either 67 | m_pWhiteTexture = g_pMaterialSystem->FindTexture("white", NULL, true); 68 | m_pWhiteTexture->AddRef(); 69 | g_pMaterialSystem->GetRenderContext()->BindLocalCubemap(m_pWhiteTexture); 70 | g_pMaterialSystem->GetRenderContext()->BindLightmapTexture(m_pWhiteTexture); 71 | 72 | // If we don't do this, all models will render black 73 | int samples = g_pStudioRender->GetNumAmbientLightSamples(); 74 | m_ambientLightColors = new Vector[samples]; 75 | for (int i = 0; i < samples; i++) 76 | m_ambientLightColors[i] = { 1,1,1 }; 77 | g_pStudioRender->SetAmbientLightColors(m_ambientLightColors); 78 | 79 | // Init Dear ImGui 80 | ImGui::CreateContext(); 81 | ImGui_ImplSource_Init(); 82 | ImGui::StyleColorsDark(); 83 | ImGui_ImplGlfw_InitForOther(m_pWindow, true); 84 | // ImGui_ImplSourceGLFW_Init(m_pWindow, (void*)hwnd); 85 | 86 | m_lastFrameTime = glfwGetTime(); 87 | 88 | // Main app loop 89 | while (!glfwWindowShouldClose(m_pWindow)) 90 | { 91 | glfwPollEvents(); 92 | ImGui_ImplGlfw_NewFrame(); 93 | DrawFrame(); 94 | } 95 | } 96 | 97 | void CImGuiSourceApp::Destroy() 98 | { 99 | ImGui_ImplSource_Shutdown(); 100 | ImGui_ImplGlfw_Shutdown(); 101 | 102 | // Clean up all of our assets, windows, etc 103 | if(m_ambientLightColors) 104 | delete[] m_ambientLightColors; 105 | 106 | if (m_pWhiteTexture) 107 | m_pWhiteTexture->DecrementReferenceCount(); 108 | 109 | if(m_pWindow) 110 | glfwDestroyWindow(m_pWindow); 111 | glfwTerminate(); 112 | } 113 | 114 | // Current model in use 115 | static char s_modelName[256] = "models/barney.mdl"; 116 | 117 | void CImGuiSourceApp::DrawFrame() 118 | { 119 | // What's our delta time? 120 | float curTime = glfwGetTime(); 121 | float dt = curTime - m_lastFrameTime; 122 | m_lastFrameTime = curTime; 123 | 124 | // Start Frame 125 | g_pMaterialSystem->BeginFrame(0); 126 | 127 | // Clear out the old frame 128 | CMatRenderContextPtr ctx(g_pMaterialSystem); 129 | ctx->ClearColor3ub(0x30, 0x30, 0x30); 130 | ctx->ClearBuffers(true, true); 131 | 132 | // Let it know our window size 133 | int w, h; 134 | glfwGetWindowSize(m_pWindow, &w, &h); 135 | ctx->Viewport(0, 0, w, h); 136 | 137 | // Begin ImGui 138 | // Ideally this happens before we branch off into other functions, as it needs to be setup for other sections of code to use imgui 139 | ImGuiIO& io = ImGui::GetIO(); 140 | ImGui::NewFrame(); 141 | 142 | // Make us a nice camera 143 | VMatrix viewMatrix; 144 | VMatrix projMatrix; 145 | static float zoom = 120.0; 146 | static Camera_t cam = { {-zoom, 0, 0}, {0, 0, 0}, 65, 1.0f, 20000.0f }; 147 | ComputeViewMatrix(&viewMatrix, cam); 148 | ComputeProjectionMatrix(&projMatrix, cam, w, h); 149 | 150 | // 3D Rendering mode 151 | ctx->MatrixMode(MATERIAL_PROJECTION); 152 | ctx->LoadMatrix(projMatrix); 153 | ctx->MatrixMode(MATERIAL_VIEW); 154 | ctx->LoadMatrix(viewMatrix); 155 | 156 | // Draw our model 157 | static CStudioModel* model = new CStudioModel(s_modelName); 158 | static QAngle ang = { 0, 0,0 }; 159 | static Vector pos = -model->Center(); 160 | model->m_time = curTime; 161 | model->m_sequence = 40; 162 | model->Draw(pos, ang); 163 | 164 | // Mouse input 165 | // If we're dragging a window, we don't want to be dragging our model too 166 | if (!io.WantCaptureMouse) 167 | { 168 | // Slow down our zoom as we get closer in for finer movements 169 | float mw = io.MouseWheel; 170 | mw *= zoom / 20.0f; 171 | 172 | // Don't allow zooming into and past our model 173 | zoom += mw; 174 | if (zoom <= 1) 175 | zoom = 1; 176 | 177 | // Camera rotation 178 | float x = io.MousePos.x; 179 | float y = io.MousePos.y; 180 | static float ox = 0, oy = 0; 181 | if (io.MouseDown[0]) 182 | { 183 | cam.m_angles.y -= x - ox; 184 | cam.m_angles.x += y - oy; 185 | } 186 | ox = x; 187 | oy = y; 188 | 189 | // Set the camera to its new position 190 | Vector forward; 191 | AngleVectors(cam.m_angles, &forward); 192 | cam.m_origin = forward * -zoom; 193 | } 194 | 195 | // Model Properties 196 | if (ImGui::Begin("Model")) 197 | { 198 | ImGui::InputText("Path", s_modelName, sizeof(s_modelName)); 199 | ImGui::SameLine(); 200 | if (ImGui::Button("Apply")) 201 | { 202 | delete model; 203 | model = new CStudioModel(s_modelName); 204 | } 205 | 206 | ImGui::InputFloat3("pos", pos.Base()); 207 | ImGui::SliderFloat3("ang", ang.Base(), -360, 360); 208 | } 209 | ImGui::End(); 210 | 211 | ImGui::ShowDemoWindow(); 212 | 213 | // End ImGui, and let it draw 214 | ImGui::Render(); 215 | ImGui_ImplSource_RenderDrawData(ImGui::GetDrawData()); 216 | 217 | // End Frame 218 | g_pMaterialSystem->SwapBuffers(); 219 | g_pMaterialSystem->EndFrame(); 220 | } 221 | -------------------------------------------------------------------------------- /app.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct GLFWwindow; 4 | class ITexture; 5 | class Vector; 6 | 7 | // I would just merge this into CSteamAppLoader, but it makes such a mess 8 | class CImGuiSourceApp 9 | { 10 | public: 11 | void Init(); 12 | void Destroy(); 13 | private: 14 | void DrawFrame(); 15 | 16 | GLFWwindow* m_pWindow; 17 | ITexture *m_pWhiteTexture; 18 | 19 | float m_lastFrameTime; 20 | 21 | Vector* m_ambientLightColors; 22 | }; -------------------------------------------------------------------------------- /app.vpc: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // APP.VPC 3 | // 4 | // Project Script 5 | //----------------------------------------------------------------------------- 6 | 7 | $Macro SRCDIR ".." 8 | $Macro OUTBINDIR "$SRCDIR\..\game\bin" 9 | $Macro OUTBINNAME "exampleapp" 10 | $Macro PUBLIC "$SRCDIR\public" 11 | 12 | 13 | $Include "$SRCDIR\vpc_scripts\source_exe_con_base.vpc" 14 | 15 | $Configuration 16 | { 17 | $Compiler 18 | { 19 | $AdditionalIncludeDirectories "$BASE;./;../public/mathlib;../public/;./thirdparty;./thirdparty/glfw/include;./thirdparty/imgui" 20 | $TreatWarningsAsErrors "No (/WX-)" 21 | $PreprocessorDefinitions "$BASE;" 22 | } 23 | 24 | $Linker [$WIN32] 25 | { 26 | $EnableLargeAddresses "Support Addresses Larger Than 2 Gigabytes (/LARGEADDRESSAWARE)" 27 | $SubSystem "Windows (/SUBSYSTEM:WINDOWS)" 28 | $AdditionalDependencies "$BASE;comctl32.lib" 29 | $EntryPoint "mainCRTStartup" 30 | } 31 | } 32 | 33 | $Project "Example ImGui Source App" 34 | { 35 | $Folder "Dear ImGui" 36 | { 37 | $File "thirdparty\imgui\imconfig.h" 38 | $File "thirdparty\imgui\imgui.h" 39 | $File "thirdparty\imgui\imgui_internal.h" 40 | $File "thirdparty\imgui\imstb_rectpack.h" 41 | $File "thirdparty\imgui\imstb_textedit.h" 42 | $File "thirdparty\imgui\imstb_truetype.h" 43 | $File "thirdparty\imgui\backends\imgui_impl_glfw.h" 44 | 45 | $File "thirdparty\imgui\imgui.cpp" 46 | $File "thirdparty\imgui\imgui_demo.cpp" 47 | $File "thirdparty\imgui\imgui_draw.cpp" 48 | $File "thirdparty\imgui\imgui_tables.cpp" 49 | $File "thirdparty\imgui\imgui_widgets.cpp" 50 | $File "thirdparty\imgui\backends\imgui_impl_glfw.cpp" 51 | 52 | } 53 | $Folder "Source Files" 54 | { 55 | $Folder "Public" 56 | { 57 | $File "$PUBLIC\filesystem_helpers.cpp" 58 | $File "$PUBLIC\filesystem_init.cpp" 59 | $File "$PUBLIC\tier0\memoverride.cpp" 60 | $File "$PUBLIC\studio.cpp" 61 | $File "$PUBLIC\bone_setup.cpp" 62 | $File "$PUBLIC\CollisionUtils.cpp" 63 | } 64 | $File "imgui_impl_source.h" 65 | $File "imgui_impl_source.cpp" 66 | 67 | $File "main.cpp" 68 | 69 | $File "app.h" 70 | $File "app.cpp" 71 | 72 | $File "studiomodel.h" 73 | $File "studiomodel.cpp" 74 | 75 | } 76 | 77 | $Folder "Libraries" 78 | { 79 | $Lib "appframework" 80 | $Lib "bitmap" 81 | $Lib "mathlib" 82 | $Lib "tier0" 83 | $Lib "tier1" 84 | $Lib "tier2" 85 | $Lib "vstdlib" 86 | $Lib "vtf" 87 | $Lib "$LIBCOMMON/lzma" 88 | 89 | $Lib "./thirdparty/glfw/glfw3" 90 | 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /imgui_impl_source.cpp: -------------------------------------------------------------------------------- 1 | // Derived from Dear ImGui's Renderer Backend for DirectX9 2 | 3 | #include "imgui_impl_source.h" 4 | #include "materialsystem/imesh.h" 5 | #include "materialsystem/itexture.h" 6 | #include "keyvalues.h" 7 | #include 8 | 9 | static IMaterial* g_pFontMat = nullptr; 10 | 11 | void ImGui_ImplSource_SetupRenderState(IMatRenderContext* ctx, ImDrawData* draw_data) 12 | { 13 | // Apply imgui's display dimensions 14 | ctx->Viewport(draw_data->DisplayPos.x, draw_data->DisplayPos.y, draw_data->DisplaySize.x, draw_data->DisplaySize.y); 15 | 16 | // Setup orthographic projection matrix 17 | // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. 18 | ctx->MatrixMode(MATERIAL_PROJECTION); 19 | ctx->PushMatrix(); 20 | ctx->LoadIdentity(); 21 | 22 | float L = draw_data->DisplayPos.x + 0.5f; 23 | float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f; 24 | float T = draw_data->DisplayPos.y + 0.5f; 25 | float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f; 26 | ctx->Ortho(L, B, R, T, 0, 1); 27 | g_pMaterialSystem->GetRenderContext()->MatrixMode(MATERIAL_VIEW); 28 | g_pMaterialSystem->GetRenderContext()->PushMatrix(); 29 | g_pMaterialSystem->GetRenderContext()->LoadIdentity(); 30 | } 31 | 32 | void ImGui_ImplSource_RenderDrawData(ImDrawData* draw_data) 33 | { 34 | // Avoid rendering when minimized 35 | if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) 36 | return; 37 | 38 | IMatRenderContext* ctx = materials->GetRenderContext(); 39 | 40 | ImGui_ImplSource_SetupRenderState(ctx, draw_data); 41 | 42 | // We pass g_pFontMat, as we need something bound to be able to use dynamic meshes 43 | // This must be set as unbuffered, otherwise our scissor rect breaks 44 | IMesh* mesh = ctx->GetDynamicMesh(false, nullptr, nullptr, g_pFontMat); 45 | 46 | CMeshBuilder mb; 47 | 48 | // Render command lists 49 | ImVec2 clip_off = draw_data->DisplayPos; 50 | for (int n = 0; n CmdListsCount; n++) 51 | { 52 | 53 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 54 | 55 | // Fill in the mesh 56 | mb.Begin(mesh, MATERIAL_TRIANGLES, cmd_list->VtxBuffer.Size, cmd_list->IdxBuffer.Size); 57 | 58 | const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data; 59 | for (int i = 0; i < cmd_list->VtxBuffer.Size; i++) 60 | { 61 | mb.Position3f(vtx_src->pos.x, vtx_src->pos.y, 0); 62 | mb.Color4ubv(reinterpret_cast(&vtx_src->col)); 63 | mb.TexCoord2f(0, vtx_src->uv.x, vtx_src->uv.y); 64 | mb.AdvanceVertex(); 65 | vtx_src++; 66 | } 67 | 68 | // CMeshBuilder doesn't support FastIndexList, but CIndexBuilder does! 69 | ((CIndexBuilder&)mb).FastIndexList(cmd_list->IdxBuffer.Data, 0, cmd_list->IdxBuffer.Size); 70 | 71 | mb.End(); 72 | 73 | // Draw the mesh 74 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 75 | { 76 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 77 | if (pcmd->UserCallback != NULL) 78 | { 79 | // User callback, registered via ImDrawList::AddCallback() 80 | // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) 81 | if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) 82 | ImGui_ImplSource_SetupRenderState(ctx, draw_data); 83 | else 84 | pcmd->UserCallback(cmd_list, pcmd); 85 | } 86 | else 87 | { 88 | if (pcmd->GetTexID()) 89 | { 90 | Vector2D clipmin = { pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y }; 91 | Vector2D clipmax = { pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y }; 92 | 93 | // Avoid rendering completely clipped draws 94 | if (clipmax.x <= clipmin.x || clipmax.y <= clipmin.y) 95 | continue; 96 | 97 | ctx->Bind(pcmd->GetTexID()); 98 | ctx->SetScissorRect(clipmin.x, clipmin.y, clipmax.x, clipmax.y, true); 99 | mesh->Draw(pcmd->IdxOffset, pcmd->ElemCount); 100 | } 101 | } 102 | } 103 | 104 | } 105 | 106 | // Disable our scissor now that we're done 107 | ctx->SetScissorRect(-1, -1, -1, -1, false); 108 | } 109 | 110 | bool ImGui_ImplSource_Init() 111 | { 112 | // Setup backend capabilities flags 113 | ImGuiIO& io = ImGui::GetIO(); 114 | io.BackendRendererName = "imgui_impl_source"; 115 | io.BackendFlags = ImGuiBackendFlags_None; 116 | 117 | ImGui_ImplSource_CreateDeviceObjects(); 118 | return true; 119 | } 120 | 121 | void ImGui_ImplSource_Shutdown() 122 | { 123 | ImGui_ImplSource_InvalidateDeviceObjects(); 124 | } 125 | 126 | static bool ImGui_ImplSource_CreateFontsTexture() 127 | { 128 | if (g_pFontMat) 129 | return true; 130 | 131 | // Build texture atlas 132 | ImGuiIO& io = ImGui::GetIO(); 133 | unsigned char* pixels; 134 | int width, height, bytes_per_pixel; 135 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel); 136 | 137 | // Create a material for the texture 138 | materials->CreateNamedTextureFromBitsEx("imgui_font", TEXTURE_GROUP_VGUI, width, height, 1, IMAGE_FORMAT_RGBA8888, width * height * bytes_per_pixel, pixels, TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_IGNORE_PICMIP | TEXTUREFLAGS_POINTSAMPLE); 139 | KeyValues* vmt = new KeyValues("UnlitGeneric"); 140 | vmt->SetString("$basetexture", "imgui_font"); 141 | vmt->SetInt("$nocull", 1); 142 | vmt->SetInt("$vertexcolor", 1); 143 | vmt->SetInt("$alphatest", 1); 144 | g_pFontMat = materials->CreateMaterial("imgui_font_mat", vmt); 145 | g_pFontMat->AddRef(); 146 | 147 | // Store our identifier 148 | io.Fonts->SetTexID(g_pFontMat); 149 | 150 | return true; 151 | } 152 | 153 | bool ImGui_ImplSource_CreateDeviceObjects() 154 | { 155 | if (!ImGui_ImplSource_CreateFontsTexture()) 156 | return false; 157 | return true; 158 | } 159 | 160 | void ImGui_ImplSource_InvalidateDeviceObjects() 161 | { 162 | if (g_pFontMat) 163 | { 164 | g_pFontMat->DecrementReferenceCount(); 165 | g_pFontMat = 0; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /imgui_impl_source.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct ImDrawData; 4 | bool ImGui_ImplSource_Init(); 5 | void ImGui_ImplSource_Shutdown(); 6 | void ImGui_ImplSource_RenderDrawData(ImDrawData* draw_data); 7 | 8 | // Use if you want to reset your rendering device without losing Dear ImGui state. 9 | bool ImGui_ImplSource_CreateDeviceObjects(); 10 | void ImGui_ImplSource_InvalidateDeviceObjects(); 11 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "app.h" 2 | #include "tier0/icommandline.h" 3 | #include "appframework/appframework.h" 4 | #include "materialsystem/imaterialsystem.h" 5 | #include "istudiorender.h" 6 | #include "vphysics_interface.h" 7 | #include "Datacache/imdlcache.h" 8 | #include "datacache/idatacache.h" 9 | #include "filesystem_init.h" 10 | #include "tier1/tier1.h" 11 | #include "tier2/tier2.h" 12 | 13 | #include "memdbgoff.h" 14 | 15 | IFileSystem* g_pFileSystem; 16 | IStudioRender* g_pStudioRender; 17 | IMDLCache* g_pMDLCache; 18 | 19 | class CSteamAppLoader : public CSteamAppSystemGroup 20 | { 21 | public: 22 | virtual bool Create(); 23 | virtual bool PreInit(); 24 | virtual int Main(); 25 | virtual void PostShutdown() {} 26 | virtual void Destroy(); 27 | 28 | }; 29 | 30 | int main (int argc, char **argv) 31 | { 32 | CommandLine()->CreateCmdLine( argc, argv ); 33 | 34 | CSteamAppLoader smaugsteamapp; 35 | CSteamApplication steamapp( &smaugsteamapp ); 36 | return steamapp.Run(); 37 | } 38 | 39 | // Prep ourselves for app system loading 40 | bool CSteamAppLoader::PreInit() 41 | { 42 | // Set up the filesystem 43 | 44 | // Make sure we always at least have something? 45 | // Otherwise the next step will close the program 46 | if (!CommandLine()->FindParm("-game")) 47 | CommandLine()->AppendParm("-game", "../hl2"); 48 | 49 | // Find the route to our gameinfo file 50 | CFSSteamSetupInfo steamInfo; 51 | steamInfo.m_pDirectoryName = NULL; 52 | steamInfo.m_bOnlyUseDirectoryName = false; 53 | steamInfo.m_bToolsMode = true; 54 | steamInfo.m_bSetSteamDLLPath = true; 55 | steamInfo.m_bSteam = g_pFileSystem->IsSteam(); 56 | if (FileSystem_SetupSteamEnvironment(steamInfo) != FS_OK) 57 | return false; 58 | 59 | // Mount the game 60 | CFSMountContentInfo fsInfo; 61 | fsInfo.m_pFileSystem = g_pFileSystem; 62 | fsInfo.m_bToolsMode = true; 63 | fsInfo.m_pDirectoryName = steamInfo.m_GameInfoPath; 64 | if (FileSystem_MountContent(fsInfo) != FS_OK) 65 | return false; 66 | 67 | // Finally, load the search paths for the "GAME" path. 68 | CFSSearchPathsInit searchPathsInit; 69 | searchPathsInit.m_pDirectoryName = steamInfo.m_GameInfoPath; 70 | searchPathsInit.m_pFileSystem = fsInfo.m_pFileSystem; 71 | if (FileSystem_LoadSearchPaths(searchPathsInit) != FS_OK) 72 | return false; 73 | 74 | // Add platform to our search path 75 | char platform[MAX_PATH]; 76 | Q_strncpy(platform, steamInfo.m_GameInfoPath, MAX_PATH); 77 | Q_StripTrailingSlash(platform); 78 | Q_strncat(platform, "/../platform", MAX_PATH, MAX_PATH); 79 | fsInfo.m_pFileSystem->AddSearchPath(platform, "PLATFORM"); 80 | 81 | 82 | MathLib_Init(); 83 | 84 | g_pMaterialSystem->SetAdapter(0, 0); 85 | 86 | return true; 87 | } 88 | 89 | // Load up all our app systems 90 | bool CSteamAppLoader::Create() 91 | { 92 | AppSystemInfo_t appSystems[] = 93 | { 94 | { "materialsystem.dll", MATERIAL_SYSTEM_INTERFACE_VERSION }, 95 | { "studiorender.dll", STUDIO_RENDER_INTERFACE_VERSION }, 96 | { "vphysics.dll", VPHYSICS_INTERFACE_VERSION }, // Annoyingly, we need vphyiscs as well :P 97 | { "datacache.dll", DATACACHE_INTERFACE_VERSION }, 98 | { "datacache.dll", MDLCACHE_INTERFACE_VERSION }, 99 | { "", "" } // Required to terminate the list 100 | }; 101 | 102 | if (!AddSystems(appSystems)) 103 | return false; 104 | 105 | CreateInterfaceFn factory = GetFactory(); 106 | ConnectTier1Libraries(&factory, 1); 107 | ConnectTier2Libraries(&factory, 1); 108 | 109 | g_pFileSystem = (IFileSystem*)FindSystem(FILESYSTEM_INTERFACE_VERSION); 110 | g_pMaterialSystem = (IMaterialSystem*)FindSystem(MATERIAL_SYSTEM_INTERFACE_VERSION); 111 | g_pStudioRender = (IStudioRender*)FindSystem(STUDIO_RENDER_INTERFACE_VERSION); 112 | g_pMDLCache = (IMDLCache*)FindSystem(MDLCACHE_INTERFACE_VERSION); 113 | 114 | if (!g_pFileSystem || !g_pMaterialSystem || !g_pStudioRender || !g_pMDLCache) 115 | { 116 | Error("Unable to load required library interface!\n"); 117 | return false; 118 | } 119 | 120 | g_pMaterialSystem->SetShaderAPI("shaderapidx9"); 121 | g_pMaterialSystem->Connect(factory); 122 | 123 | // Must be done after material system is connected up! 124 | g_pMaterialSystemHardwareConfig = (IMaterialSystemHardwareConfig*)FindSystem(MATERIALSYSTEM_HARDWARECONFIG_INTERFACE_VERSION); 125 | 126 | return true; 127 | } 128 | 129 | // Disconnect our app systems 130 | void CSteamAppLoader::Destroy() 131 | { 132 | DisconnectTier1Libraries(); 133 | DisconnectTier2Libraries(); 134 | 135 | g_pFileSystem = NULL; 136 | g_pMaterialSystem = NULL; 137 | } 138 | 139 | int CSteamAppLoader::Main() 140 | { 141 | g_pMaterialSystem->ModInit(); 142 | 143 | // Starts up the app and runs the main loop 144 | CImGuiSourceApp* app = new CImGuiSourceApp; 145 | app->Init(); 146 | app->Destroy(); 147 | delete app; 148 | 149 | g_pMaterialSystem->ModShutdown(); 150 | 151 | return 0; 152 | } 153 | 154 | -------------------------------------------------------------------------------- /studiomodel.cpp: -------------------------------------------------------------------------------- 1 | #include "studiomodel.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | extern IMDLCache* g_pMDLCache; 8 | 9 | static float s_flexdescweight[MAXSTUDIOFLEXDESC]; 10 | static float s_flexdescweight2[MAXSTUDIOFLEXDESC]; 11 | static float s_flexweightsrc[MAXSTUDIOFLEXCTRL * 4]; 12 | 13 | 14 | CStudioModel::CStudioModel(const char* path) 15 | { 16 | MDLHandle_t mdlHandle = g_pMDLCache->FindMDL(path); 17 | 18 | CStudioHdr* studiohdr = new CStudioHdr(g_pMDLCache->GetStudioHdr(mdlHandle), g_pMDLCache); 19 | studiohwdata_t* studiohwdata = g_pMDLCache->GetHardwareData(mdlHandle); 20 | if (studiohdr->GetRenderHdr()->version != STUDIO_VERSION) 21 | { 22 | Error("Bad model version on %s! Expected %d, got %d!\n", path, STUDIO_VERSION, studiohdr->GetRenderHdr()->version); 23 | return; 24 | } 25 | 26 | m_studiohdr = studiohdr; 27 | m_studiohwdata = studiohwdata; 28 | m_sequence = 0; 29 | m_posepos = new Vector[studiohdr->numbones()]; 30 | m_poseang = new Quaternion[studiohdr->numbones()]; 31 | m_poseparameter = new float[studiohdr->GetNumPoseParameters()]; 32 | m_poseparameterProcessed = new float[studiohdr->GetNumPoseParameters()]; 33 | 34 | for (int i = 0; i < studiohdr->numbones(); i++) 35 | { 36 | m_posepos[i].Init(); 37 | m_poseang[i].Init(); 38 | } 39 | 40 | for (int i = 0; i < studiohdr->GetNumPoseParameters(); i++) 41 | { 42 | m_poseparameter[i] = 0; 43 | m_poseparameterProcessed[i] = 0; 44 | } 45 | 46 | } 47 | 48 | CStudioModel::~CStudioModel() 49 | { 50 | if (m_posepos) 51 | delete[] m_posepos; 52 | 53 | if (m_poseang) 54 | delete[] m_poseang; 55 | 56 | if(m_poseparameter) 57 | delete[] m_poseparameter; 58 | 59 | if(m_poseparameterProcessed) 60 | delete[] m_poseparameterProcessed; 61 | 62 | } 63 | 64 | 65 | void CStudioModel::Draw(Vector& pos, QAngle& ang) 66 | { 67 | // Set the transform 68 | matrix3x4_t rootmatrix; 69 | AngleMatrix(ang, rootmatrix); 70 | MatrixSetColumn(pos, 3, rootmatrix); 71 | 72 | Draw(rootmatrix); 73 | } 74 | 75 | void CStudioModel::Draw(matrix3x4_t& rootmatrix) 76 | { 77 | if (!m_studiohdr || !m_studiohwdata) 78 | return; 79 | 80 | // Set the info 81 | DrawModelInfo_t info; 82 | memset(&info, 0, sizeof(info)); 83 | info.m_pStudioHdr = const_cast(m_studiohdr->GetRenderHdr()); 84 | info.m_pHardwareData = m_studiohwdata; 85 | info.m_Lod = -1; 86 | 87 | 88 | // Draw it 89 | if (m_studiohdr->flags() & STUDIOHDR_FLAGS_STATIC_PROP) 90 | g_pStudioRender->DrawModelStaticProp(info, rootmatrix); 91 | else 92 | { 93 | memset(s_flexdescweight, 0, sizeof(s_flexdescweight)); 94 | memset(s_flexdescweight2, 0, sizeof(s_flexdescweight2)); 95 | 96 | int flexcount = m_studiohdr->numflexdesc(); 97 | 98 | for (int i = 0; i < m_studiohdr->GetNumPoseParameters(); i++) 99 | { 100 | m_poseparameter[i] = Studio_SetPoseParameter(m_studiohdr, i, m_poseparameter[i], m_poseparameterProcessed[i]); 101 | } 102 | 103 | IBoneSetup boneSetup(m_studiohdr, BONE_USED_BY_ANYTHING, m_poseparameterProcessed); 104 | boneSetup.InitPose(m_posepos, m_poseang); 105 | 106 | 107 | float cycleRate = Studio_CPS(m_studiohdr, m_studiohdr->pSeqdesc(m_sequence), m_sequence, m_poseparameter); 108 | boneSetup.AccumulatePose(m_posepos, m_poseang, m_sequence, fmod(m_time * cycleRate, 1.0), 1.0, m_time, 0); 109 | 110 | matrix3x4_t* g_pBoneToWorld = g_pStudioRender->LockBoneMatrices(MAXSTUDIOBONES); 111 | 112 | for (int i = 0; i < m_studiohdr->numbones(); i++) 113 | { 114 | if (CalcProceduralBone(m_studiohdr, i, CBoneAccessor(g_pBoneToWorld))) 115 | continue; 116 | 117 | // Set the transform 118 | matrix3x4_t matrix; 119 | QuaternionMatrix(m_poseang[i], matrix); 120 | MatrixSetColumn(m_posepos[i], 3, matrix); 121 | 122 | mstudiobone_t* pBone = m_studiohdr->pBone(i); 123 | if (pBone->parent == -1) 124 | ConcatTransforms(rootmatrix, matrix, g_pBoneToWorld[i]); 125 | else 126 | ConcatTransforms(g_pBoneToWorld[pBone->parent], matrix, g_pBoneToWorld[i]); 127 | } 128 | 129 | for (int i = 0; i < flexcount; i++) 130 | { 131 | s_flexdescweight[i] = 0.0; 132 | } 133 | 134 | for (LocalFlexController_t i = (LocalFlexController_t)0; i < m_studiohdr->numflexcontrollers(); i++) 135 | { 136 | m_studiohdr->pFlexcontroller(i)->localToGlobal = i; 137 | } 138 | 139 | for (LocalFlexController_t i = (LocalFlexController_t)0; i < m_studiohdr->numflexcontrollers(); i++) 140 | { 141 | mstudioflexcontroller_t* pflex = m_studiohdr->pFlexcontroller(i); 142 | int j = m_studiohdr->pFlexcontroller(i)->localToGlobal; 143 | // remap m_flexweights to full dynamic range, global flexcontroller indexes 144 | s_flexweightsrc[j] = 0.5f * (pflex->max - pflex->min) + pflex->min; 145 | } 146 | 147 | m_studiohdr->RunFlexRules(s_flexweightsrc, s_flexdescweight); 148 | 149 | 150 | // Apparently, we have to hand these over to be allocated and then copy into them now. 151 | float* pFlexdescweight; 152 | float* pFlexdescweight2; 153 | g_pStudioRender->LockFlexWeights(flexcount, &pFlexdescweight, &pFlexdescweight2); 154 | for (int i = 0; i < m_studiohdr->numflexdesc(); i++) 155 | { 156 | s_flexdescweight2[i] = s_flexdescweight2[i] * 0/*weight ratio*/ + s_flexdescweight[i] * (1 - 0/*weight ratio*/); 157 | pFlexdescweight[i] = s_flexdescweight[i]; 158 | pFlexdescweight2[i] = s_flexdescweight2[i]; 159 | } 160 | g_pStudioRender->UnlockFlexWeights(); 161 | 162 | g_pStudioRender->UnlockBoneMatrices(); 163 | g_pStudioRender->DrawModel(0, info, g_pBoneToWorld, 0, 0, { rootmatrix.m_flMatVal[0][3], rootmatrix.m_flMatVal[1][3], rootmatrix.m_flMatVal[2][3]}); 164 | } 165 | } 166 | 167 | Vector CStudioModel::Center() 168 | { 169 | return (m_studiohdr->hull_max() + m_studiohdr->hull_min()) * 0.5f; 170 | } 171 | 172 | 173 | // Would just include studio_generic_io, but I'm not sure what nonsense is happening in there... 174 | 175 | // This function would be useful, if it was static... 176 | const studiohdr_t* studiohdr_t::FindModel(void** cache, char const* modelname) const 177 | { 178 | MDLHandle_t handle = g_pMDLCache->FindMDL(modelname); 179 | *cache = (void*)handle; 180 | return g_pMDLCache->GetStudioHdr(handle); 181 | } 182 | 183 | virtualmodel_t* studiohdr_t::GetVirtualModel() const 184 | { 185 | return g_pMDLCache->GetVirtualModel((MDLHandle_t)virtualModel); 186 | } 187 | 188 | byte* studiohdr_t::GetAnimBlock(int i) const 189 | { 190 | return g_pMDLCache->GetAnimBlock((MDLHandle_t)virtualModel, i); 191 | } 192 | 193 | int studiohdr_t::GetAutoplayList(unsigned short** pOut) const 194 | { 195 | return g_pMDLCache->GetAutoplayList((MDLHandle_t)virtualModel, pOut); 196 | } 197 | 198 | const studiohdr_t* virtualgroup_t::GetStudioHdr() const 199 | { 200 | return g_pMDLCache->GetStudioHdr((MDLHandle_t)cache); 201 | } -------------------------------------------------------------------------------- /studiomodel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | struct CStudioModel 5 | { 6 | CStudioModel(const char* path); 7 | 8 | ~CStudioModel(); 9 | 10 | void Draw(Vector& pos, QAngle& ang); 11 | void Draw(matrix3x4_t& mat); 12 | 13 | Vector Center(); 14 | 15 | CStudioHdr* m_studiohdr; 16 | studiohwdata_t* m_studiohwdata; 17 | int m_sequence; 18 | Vector* m_posepos; 19 | Quaternion* m_poseang; 20 | float* m_poseparameter; 21 | float* m_poseparameterProcessed; 22 | 23 | float m_time; 24 | }; -------------------------------------------------------------------------------- /thirdparty/imconfig_but_in_a_different_folder_so_i_dont_have_another_repo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class IMaterial; 4 | #define ImTextureID IMaterial* 5 | --------------------------------------------------------------------------------