summaryrefslogtreecommitdiff
path: root/skeleton/imgui/imgui_impl_rw.cpp
diff options
context:
space:
mode:
authorclaude-bot <[email protected]>2026-07-13 12:40:03 +0000
committerclaude-bot <[email protected]>2026-07-13 12:40:03 +0000
commit847962910f0bff071f3bf07c9abb87764fb6cac3 (patch)
treeddcd429e134c7fd5f72ddc97ced175de8d66fcd0 /skeleton/imgui/imgui_impl_rw.cpp
downloadlibrw-master.tar.gz
librw-master.zip
Import aap/librw @ masterHEADmaster
Snapshot for re3/reVC vendoring, per @lzcnt. Source: https://github.com/aap/librw (master).
Diffstat (limited to 'skeleton/imgui/imgui_impl_rw.cpp')
-rw-r--r--skeleton/imgui/imgui_impl_rw.cpp345
1 files changed, 345 insertions, 0 deletions
diff --git a/skeleton/imgui/imgui_impl_rw.cpp b/skeleton/imgui/imgui_impl_rw.cpp
new file mode 100644
index 0000000..1081716
--- /dev/null
+++ b/skeleton/imgui/imgui_impl_rw.cpp
@@ -0,0 +1,345 @@
+#define WITH_D3D
+#include <rw.h>
+#include <skeleton.h>
+#include <assert.h>
+
+#include "imgui/imgui.h"
+#include "imgui_impl_rw.h"
+
+using namespace rw::RWDEVICE;
+
+static rw::Texture *g_FontTexture;
+static Im2DVertex *g_vertbuf;
+static int g_vertbufSize;
+
+// TODO: scissor from librw itself
+static void
+SetClip(const ImVec4 &clip)
+{
+ ImGuiIO &io = ImGui::GetIO();
+ float x1 = clip.x; float y1 = clip.y;
+ float x2 = clip.z; float y2 = clip.w;
+#ifdef RW_OPENGL
+ glScissor(x1, io.DisplaySize.y-y2, x2-x1, y2-y1);
+ glEnable(GL_SCISSOR_TEST);
+#endif
+#ifdef RW_D3D9
+ rw::d3d::d3ddevice->SetRenderState(D3DRS_SCISSORTESTENABLE, 1);
+ RECT r = { (LONG)x1, (LONG)y1, (LONG)x2, (LONG)y2 };
+ rw::d3d::d3ddevice->SetScissorRect(&r);
+#endif
+}
+
+static void
+DisableClip(void)
+{
+#ifdef RW_OPENGL
+ glDisable(GL_SCISSOR_TEST);
+#endif
+#ifdef RW_D3D9
+ rw::d3d::d3ddevice->SetRenderState(D3DRS_SCISSORTESTENABLE, 0);
+#endif
+}
+
+void
+ImGui_ImplRW_RenderDrawLists(ImDrawData* draw_data)
+{
+ ImGuiIO &io = ImGui::GetIO();
+
+ // minimized
+ if (io.DisplaySize.x <= 0.0f || io.DisplaySize.y <= 0.0f)
+ return;
+
+ if(g_vertbuf == nil || g_vertbufSize < draw_data->TotalVtxCount){
+ if(g_vertbuf){
+ rwFree(g_vertbuf);
+ g_vertbuf = nil;
+ }
+ g_vertbufSize = draw_data->TotalVtxCount + 5000;
+ g_vertbuf = rwNewT(Im2DVertex, g_vertbufSize, 0);
+ }
+
+ float xoff = 0.0f;
+ float yoff = 0.0f;
+#ifdef RWHALFPIXEL
+ xoff = -0.5;
+ yoff = 0.5;
+#endif
+
+ rw::Camera *cam = (rw::Camera*)rw::engine->currentCamera;
+ Im2DVertex *vtx_dst = g_vertbuf;
+ float recipZ = 1.0f/cam->nearPlane;
+ for(int n = 0; n < draw_data->CmdListsCount; n++){
+ const ImDrawList *cmd_list = draw_data->CmdLists[n];
+ const ImDrawVert *vtx_src = cmd_list->VtxBuffer.Data;
+ for(int i = 0; i < cmd_list->VtxBuffer.Size; i++){
+ vtx_dst[i].setScreenX(vtx_src[i].pos.x + xoff);
+ vtx_dst[i].setScreenY(vtx_src[i].pos.y + yoff);
+ vtx_dst[i].setScreenZ(rw::im2d::GetNearZ());
+ vtx_dst[i].setCameraZ(cam->nearPlane);
+ vtx_dst[i].setRecipCameraZ(recipZ);
+ vtx_dst[i].setColor(vtx_src[i].col&0xFF, vtx_src[i].col>>8 & 0xFF, vtx_src[i].col>>16 & 0xFF, vtx_src[i].col>>24 & 0xFF);
+ vtx_dst[i].setU(vtx_src[i].uv.x, recipZ);
+ vtx_dst[i].setV(vtx_src[i].uv.y, recipZ);
+ }
+ vtx_dst += cmd_list->VtxBuffer.Size;
+ }
+
+ int vertexAlpha = rw::GetRenderState(rw::VERTEXALPHA);
+ int srcBlend = rw::GetRenderState(rw::SRCBLEND);
+ int dstBlend = rw::GetRenderState(rw::DESTBLEND);
+ int ztest = rw::GetRenderState(rw::ZTESTENABLE);
+ void *tex = rw::GetRenderStatePtr(rw::TEXTURERASTER);
+ int addrU = rw::GetRenderState(rw::TEXTUREADDRESSU);
+ int addrV = rw::GetRenderState(rw::TEXTUREADDRESSV);
+ int filter = rw::GetRenderState(rw::TEXTUREFILTER);
+ int cullmode = rw::GetRenderState(rw::CULLMODE);
+
+ rw::SetRenderState(rw::VERTEXALPHA, 1);
+ rw::SetRenderState(rw::SRCBLEND, rw::BLENDSRCALPHA);
+ rw::SetRenderState(rw::DESTBLEND, rw::BLENDINVSRCALPHA);
+ rw::SetRenderState(rw::ZTESTENABLE, 0);
+ rw::SetRenderState(rw::CULLMODE, rw::CULLNONE);
+
+ int vtx_offset = 0;
+ for(int n = 0; n < draw_data->CmdListsCount; n++){
+ const ImDrawList *cmd_list = draw_data->CmdLists[n];
+ int idx_offset = 0;
+ for(int i = 0; i < cmd_list->CmdBuffer.Size; i++){
+ const ImDrawCmd *pcmd = &cmd_list->CmdBuffer[i];
+ if(pcmd->UserCallback)
+ pcmd->UserCallback(cmd_list, pcmd);
+ else{
+ rw::Texture *tex = (rw::Texture*)pcmd->GetTexID();
+ if(tex && tex->raster){
+ rw::SetRenderStatePtr(rw::TEXTURERASTER, tex->raster);
+ rw::SetRenderState(rw::TEXTUREADDRESSU, tex->getAddressU());
+ rw::SetRenderState(rw::TEXTUREADDRESSV, tex->getAddressV());
+ rw::SetRenderState(rw::TEXTUREFILTER, tex->getFilter());
+ }else
+ rw::SetRenderStatePtr(rw::TEXTURERASTER, nil);
+
+ SetClip(pcmd->ClipRect);
+ rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST,
+ g_vertbuf+vtx_offset, cmd_list->VtxBuffer.Size,
+ cmd_list->IdxBuffer.Data+idx_offset, pcmd->ElemCount);
+ DisableClip();
+ }
+ idx_offset += pcmd->ElemCount;
+ }
+ vtx_offset += cmd_list->VtxBuffer.Size;
+ }
+
+ rw::SetRenderState(rw::VERTEXALPHA,vertexAlpha);
+ rw::SetRenderState(rw::SRCBLEND, srcBlend);
+ rw::SetRenderState(rw::DESTBLEND, dstBlend);
+ rw::SetRenderState(rw::ZTESTENABLE, ztest);
+ rw::SetRenderStatePtr(rw::TEXTURERASTER, tex);
+ rw::SetRenderState(rw::TEXTUREADDRESSU, addrU);
+ rw::SetRenderState(rw::TEXTUREADDRESSV, addrV);
+ rw::SetRenderState(rw::TEXTUREFILTER, filter);
+ rw::SetRenderState(rw::CULLMODE, cullmode);
+}
+
+bool
+ImGui_ImplRW_Init(void)
+{
+ using namespace sk;
+
+ ImGui::CreateContext();
+ ImGuiIO &io = ImGui::GetIO();
+
+ return true;
+}
+
+void
+ImGui_ImplRW_Shutdown(void)
+{
+}
+
+static bool
+ImGui_ImplRW_CreateFontsTexture()
+{
+ // Build texture atlas
+ ImGuiIO &io = ImGui::GetIO();
+ unsigned char *pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, nil);
+
+ rw::Image *image;
+ image = rw::Image::create(width, height, 32);
+ image->allocate();
+ for(int y = 0; y < height; y++)
+ memcpy(image->pixels + image->stride*y, pixels + width*4* y, width*4);
+ g_FontTexture = rw::Texture::create(rw::Raster::createFromImage(image));
+ g_FontTexture->setFilter(rw::Texture::LINEAR);
+ image->destroy();
+
+ // Store our identifier
+ io.Fonts->TexID = (void*)g_FontTexture;
+
+ return true;
+}
+
+bool
+ImGui_ImplRW_CreateDeviceObjects()
+{
+ if(!ImGui_ImplRW_CreateFontsTexture())
+ return false;
+ return true;
+}
+
+void
+ImGui_ImplRW_NewFrame(float timeDelta)
+{
+ if(!g_FontTexture)
+ ImGui_ImplRW_CreateDeviceObjects();
+
+ ImGuiIO &io = ImGui::GetIO();
+
+ io.DisplaySize = ImVec2(sk::globals.width, sk::globals.height);
+ io.DeltaTime = timeDelta;
+
+ io.KeyCtrl = ImGui::IsKeyPressed(ImGuiKey_LeftCtrl) || ImGui::IsKeyPressed(ImGuiKey_RightCtrl);
+ io.KeyShift = ImGui::IsKeyPressed(ImGuiKey_LeftShift) || ImGui::IsKeyPressed(ImGuiKey_RightShift);
+ io.KeyAlt = ImGui::IsKeyPressed(ImGuiKey_LeftAlt) || ImGui::IsKeyPressed(ImGuiKey_RightAlt);
+ io.KeySuper = false;
+
+ if(io.WantSetMousePos)
+ sk::SetMousePosition(io.MousePos.x, io.MousePos.y);
+
+ ImGui::NewFrame();
+}
+
+static ImGuiKey SkKeyToImGuiKey(int keycode)
+{
+ switch (keycode) {
+ case ' ': return ImGuiKey_Space;
+ case '\'': return ImGuiKey_Apostrophe;
+ case '-': return ImGuiKey_Minus;
+ case '.': return ImGuiKey_Period;
+ case '/': return ImGuiKey_Slash;
+ case '0': return ImGuiKey_0;
+ case '1': return ImGuiKey_1;
+ case '2': return ImGuiKey_2;
+ case '3': return ImGuiKey_3;
+ case '4': return ImGuiKey_4;
+ case '5': return ImGuiKey_5;
+ case '6': return ImGuiKey_6;
+ case '7': return ImGuiKey_7;
+ case '8': return ImGuiKey_8;
+ case '9': return ImGuiKey_9;
+
+ case ';': return ImGuiKey_Semicolon;
+ case '=': return ImGuiKey_Equal;
+
+ case 'A': return ImGuiKey_A;
+ case 'B': return ImGuiKey_B;
+ case 'C': return ImGuiKey_C;
+ case 'D': return ImGuiKey_D;
+ case 'E': return ImGuiKey_E;
+ case 'F': return ImGuiKey_F;
+ case 'G': return ImGuiKey_G;
+ case 'H': return ImGuiKey_H;
+ case 'I': return ImGuiKey_I;
+ case 'J': return ImGuiKey_J;
+ case 'K': return ImGuiKey_K;
+ case 'L': return ImGuiKey_L;
+ case 'M': return ImGuiKey_M;
+ case 'N': return ImGuiKey_N;
+ case 'O': return ImGuiKey_O;
+ case 'P': return ImGuiKey_P;
+ case 'Q': return ImGuiKey_Q;
+ case 'R': return ImGuiKey_R;
+ case 'S': return ImGuiKey_S;
+ case 'T': return ImGuiKey_T;
+ case 'U': return ImGuiKey_U;
+ case 'V': return ImGuiKey_V;
+ case 'W': return ImGuiKey_W;
+ case 'X': return ImGuiKey_X;
+ case 'Y': return ImGuiKey_Y;
+ case 'Z': return ImGuiKey_Z;
+
+ case '[': return ImGuiKey_LeftBracket;
+ case '\\': return ImGuiKey_Backslash;
+ case ']': return ImGuiKey_RightBracket;
+ case '`': return ImGuiKey_GraveAccent;
+ case sk::KEY_ESC: return ImGuiKey_Escape;
+ case sk::KEY_ENTER: return ImGuiKey_Enter;
+ case sk::KEY_TAB: return ImGuiKey_Tab;
+ case sk::KEY_BACKSP: return ImGuiKey_Backspace;
+ case sk::KEY_INS: return ImGuiKey_Insert;
+ case sk::KEY_DEL: return ImGuiKey_Delete;
+ case sk::KEY_RIGHT: return ImGuiKey_RightArrow;
+ case sk::KEY_LEFT: return ImGuiKey_LeftArrow;
+ case sk::KEY_DOWN: return ImGuiKey_DownArrow;
+ case sk::KEY_UP: return ImGuiKey_UpArrow;
+ case sk::KEY_PGUP: return ImGuiKey_PageUp;
+ case sk::KEY_PGDN: return ImGuiKey_PageDown;
+ case sk::KEY_HOME: return ImGuiKey_Home;
+ case sk::KEY_END: return ImGuiKey_End;
+ case sk::KEY_CAPSLK: return ImGuiKey_CapsLock;
+
+ case sk::KEY_F1: return ImGuiKey_F1;
+ case sk::KEY_F2: return ImGuiKey_F2;
+ case sk::KEY_F3: return ImGuiKey_F3;
+ case sk::KEY_F4: return ImGuiKey_F4;
+ case sk::KEY_F5: return ImGuiKey_F5;
+ case sk::KEY_F6: return ImGuiKey_F6;
+ case sk::KEY_F7: return ImGuiKey_F7;
+ case sk::KEY_F8: return ImGuiKey_F8;
+ case sk::KEY_F9: return ImGuiKey_F9;
+ case sk::KEY_F10: return ImGuiKey_F10;
+ case sk::KEY_F11: return ImGuiKey_F11;
+ case sk::KEY_F12: return ImGuiKey_F12;
+
+ case sk::KEY_LSHIFT: return ImGuiKey_LeftShift;
+ case sk::KEY_LCTRL: return ImGuiKey_LeftCtrl;
+ case sk::KEY_LALT: return ImGuiKey_LeftAlt;
+ case sk::KEY_RSHIFT: return ImGuiKey_RightShift;
+ case sk::KEY_RCTRL: return ImGuiKey_RightCtrl;
+ case sk::KEY_RALT: return ImGuiKey_RightAlt;
+
+ case sk::KEY_NULL: return ImGuiKey_None;
+ }
+ return ImGuiKey_None;
+}
+
+sk::EventStatus
+ImGuiEventHandler(sk::Event e, void *param)
+{
+ using namespace sk;
+
+ ImGuiIO &io = ImGui::GetIO();
+ MouseState *ms;
+ uint c;
+
+ switch(e){
+ case KEYDOWN:
+ io.AddKeyEvent(SkKeyToImGuiKey(*(int*)param), true);
+ return EVENTPROCESSED;
+ case KEYUP:
+ io.AddKeyEvent(SkKeyToImGuiKey(*(int*)param), false);
+ return EVENTPROCESSED;
+ case CHARINPUT:
+ c = (uint)(uintptr)param;
+ io.AddInputCharacter((unsigned short)c);
+ return EVENTPROCESSED;
+ case MOUSEMOVE:
+ ms = (MouseState*)param;
+ io.MousePos.x = ms->posx;
+ io.MousePos.y = ms->posy;
+ return EVENTPROCESSED;
+ case MOUSEBTN:
+ ms = (MouseState*)param;
+ io.MouseDown[0] = !!(ms->buttons & 1);
+ io.MouseDown[2] = !!(ms->buttons & 2);
+ io.MouseDown[1] = !!(ms->buttons & 4);
+ return EVENTPROCESSED;
+ case MOUSEWHEEL:
+ ms = (MouseState*)param;
+ io.MouseWheel += ms->wheelDelta;
+ return EVENTPROCESSED;
+ }
+ return EVENTPROCESSED;
+}