From 847962910f0bff071f3bf07c9abb87764fb6cac3 Mon Sep 17 00:00:00 2001 From: claude-bot Date: Mon, 13 Jul 2026 12:40:03 +0000 Subject: Import aap/librw @ master Snapshot for re3/reVC vendoring, per @lzcnt. Source: https://github.com/aap/librw (master). --- skeleton/imgui/imgui_impl_rw.cpp | 345 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 skeleton/imgui/imgui_impl_rw.cpp (limited to 'skeleton/imgui/imgui_impl_rw.cpp') 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 +#include +#include + +#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; +} -- cgit v1.2.3