Skip to content

Commit

Permalink
feat: clipboard driver 1
Browse files Browse the repository at this point in the history
  • Loading branch information
Force67 committed Feb 11, 2022
1 parent 9e62ad0 commit 226efd1
Show file tree
Hide file tree
Showing 6 changed files with 405 additions and 98 deletions.
98 changes: 0 additions & 98 deletions Code/client/Services/Generic/ImguiService.cpp
Original file line number Diff line number Diff line change
@@ -1,83 +1,10 @@
#include <TiltedOnlinePCH.h>

#include <Services/ImguiService.h>

#include <Systems/RenderSystemD3D11.h>
#include <d3d11.h>

#include <imgui.h>
#include <imgui/imgui_impl_dx11.h>
#include <imgui/imgui_impl_win32.h>
#include <imgui/ImguiFont.inl>

static void SetTiltedImStyle()
{
// cherry colors, 3 intensities
#define HI(v) ImVec4(0.502f, 0.075f, 0.256f, v)
#define MED(v) ImVec4(0.455f, 0.198f, 0.301f, v)
#define LOW(v) ImVec4(0.232f, 0.201f, 0.271f, v)
// backgrounds (@todo: complete with BG_MED, BG_LOW)
#define BG(v) ImVec4(0.200f, 0.220f, 0.270f, v)
// text
#define TEXT(v) ImVec4(0.860f, 0.930f, 0.890f, v)

auto& style = ImGui::GetStyle();
style.Colors[ImGuiCol_Text] = TEXT(0.78f);
style.Colors[ImGuiCol_TextDisabled] = TEXT(0.28f);
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.13f, 0.14f, 0.17f, 1.00f);
style.Colors[ImGuiCol_ChildBg] = BG(0.58f);
style.Colors[ImGuiCol_PopupBg] = BG(0.9f);
style.Colors[ImGuiCol_Border] = ImVec4(0.31f, 0.31f, 1.00f, 0.00f);
style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
style.Colors[ImGuiCol_FrameBg] = BG(1.00f);
style.Colors[ImGuiCol_FrameBgHovered] = MED(0.78f);
style.Colors[ImGuiCol_FrameBgActive] = MED(1.00f);
style.Colors[ImGuiCol_TitleBg] = LOW(1.00f);
style.Colors[ImGuiCol_TitleBgActive] = HI(1.00f);
style.Colors[ImGuiCol_TitleBgCollapsed] = BG(0.75f);
style.Colors[ImGuiCol_MenuBarBg] = BG(0.47f);
style.Colors[ImGuiCol_ScrollbarBg] = BG(1.00f);
style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.09f, 0.15f, 0.16f, 1.00f);
style.Colors[ImGuiCol_ScrollbarGrabHovered] = MED(0.78f);
style.Colors[ImGuiCol_ScrollbarGrabActive] = MED(1.00f);
style.Colors[ImGuiCol_CheckMark] = ImVec4(0.71f, 0.22f, 0.27f, 1.00f);
style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.47f, 0.77f, 0.83f, 0.14f);
style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.71f, 0.22f, 0.27f, 1.00f);
style.Colors[ImGuiCol_Button] = ImVec4(0.47f, 0.77f, 0.83f, 0.14f);
style.Colors[ImGuiCol_ButtonHovered] = MED(0.86f);
style.Colors[ImGuiCol_ButtonActive] = MED(1.00f);
style.Colors[ImGuiCol_Header] = MED(0.76f);
style.Colors[ImGuiCol_HeaderHovered] = MED(0.86f);
style.Colors[ImGuiCol_HeaderActive] = HI(1.00f);
style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.47f, 0.77f, 0.83f, 0.04f);
style.Colors[ImGuiCol_ResizeGripHovered] = MED(0.78f);
style.Colors[ImGuiCol_ResizeGripActive] = MED(1.00f);
style.Colors[ImGuiCol_PlotLines] = TEXT(0.63f);
style.Colors[ImGuiCol_PlotLinesHovered] = MED(1.00f);
style.Colors[ImGuiCol_PlotHistogram] = TEXT(0.63f);
style.Colors[ImGuiCol_PlotHistogramHovered] = MED(1.00f);
style.Colors[ImGuiCol_TextSelectedBg] = MED(0.43f);
style.Colors[ImGuiCol_ModalWindowDimBg] = BG(0.73f);

style.WindowPadding = ImVec2(6, 4);
style.WindowRounding = 0.0f;
style.FramePadding = ImVec2(5, 2);
style.FrameRounding = 3.0f;
style.ItemSpacing = ImVec2(7, 1);
style.ItemInnerSpacing = ImVec2(1, 1);
style.TouchExtraPadding = ImVec2(0, 0);
style.IndentSpacing = 6.0f;
style.ScrollbarSize = 12.0f;
style.ScrollbarRounding = 16.0f;
style.GrabMinSize = 20.0f;
style.GrabRounding = 2.0f;

style.WindowTitleAlign.x = 0.50f;

style.Colors[ImGuiCol_Border] = ImVec4(0.539f, 0.479f, 0.255f, 0.162f);
style.FrameBorderSize = 0.0f;
style.WindowBorderSize = 1.0f;
}

ImguiService::ImguiService() : OnDraw(m_drawSignal)
{
Expand All @@ -92,31 +19,6 @@ void ImguiService::Create(RenderSystemD3D11* apRenderSystem, HWND aHwnd)
ID3D11Device* d3dDevice = nullptr;
ID3D11DeviceContext* d3dContext = nullptr;

// create imgui
ImGui::CreateContext();

auto& io = ImGui::GetIO();
io.Fonts->AddFontFromMemoryCompressedBase85TTF(Roboto_compressed_data_base85, 30.f);
// io.IniFilename = nullptr;

auto& st = ImGui::GetStyle();
st.FrameBorderSize = 1.0f;
st.FramePadding = ImVec2(4.0f, 2.0f);
st.ItemSpacing = ImVec2(8.0f, 2.0f);
st.WindowBorderSize = 1.0f;
st.TabBorderSize = 1.0f;

// make everything have smooth edges
st.WindowRounding = 2.0f;
st.ChildRounding = 2.0f;
st.FrameRounding = 3.0f;
st.ScrollbarRounding = 3.0f;
st.GrabRounding = 2.f;
st.TabRounding = 1.0f;
SetTiltedImStyle();

// TODO: should hard fail here.

// init platform
if (!ImGui_ImplWin32_Init(aHwnd))
spdlog::error("Failed to initialize Imgui-Win32");
Expand Down
3 changes: 3 additions & 0 deletions Code/client/Services/ImguiService.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <imgui/ImGuiDriver.h>

struct RenderSystemD3D9;
struct RenderSystemD3D11;

Expand All @@ -24,5 +26,6 @@ struct ImguiService

private:

ImGuiImpl::ImGuiDriver m_imDriver;
entt::sigh<TCallback> m_drawSignal;
};
254 changes: 254 additions & 0 deletions Code/components/imgui/ImGuiClipboard_Win32.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
// Copyright (C) 2022 TiltedPhoques SRL.
// For licensing information see LICENSE at the root of this distribution.
// Taken from https://github.com/xposure/ImGuiSharp/blob/58860d38a9ec066f492c983c9c63393d6e00a442/ImGuiSharp.Shared/ImGui.h/Helpers.cpp

#include "imgui.h"
#include <Windows.h>
#include <imgui/ImGuiClipboard_Win32.h>

namespace ImGuiImpl
{
namespace
{
int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end)
{
unsigned int c = (unsigned int)-1;
const unsigned char* str = (const unsigned char*)in_text;
if (!(*str & 0x80))
{
c = (unsigned int)(*str++);
*out_char = c;
return 1;
}
if ((*str & 0xe0) == 0xc0)
{
*out_char = 0xFFFD; // will be invalid but not end of string
if (in_text_end && in_text_end - (const char*)str < 2)
return 1;
if (*str < 0xc2)
return 2;
c = (unsigned int)((*str++ & 0x1f) << 6);
if ((*str & 0xc0) != 0x80)
return 2;
c += (*str++ & 0x3f);
*out_char = c;
return 2;
}
if ((*str & 0xf0) == 0xe0)
{
*out_char = 0xFFFD; // will be invalid but not end of string
if (in_text_end && in_text_end - (const char*)str < 3)
return 1;
if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf))
return 3;
if (*str == 0xed && str[1] > 0x9f)
return 3; // str[1] < 0x80 is checked below
c = (unsigned int)((*str++ & 0x0f) << 12);
if ((*str & 0xc0) != 0x80)
return 3;
c += (unsigned int)((*str++ & 0x3f) << 6);
if ((*str & 0xc0) != 0x80)
return 3;
c += (*str++ & 0x3f);
*out_char = c;
return 3;
}
if ((*str & 0xf8) == 0xf0)
{
*out_char = 0xFFFD; // will be invalid but not end of string
if (in_text_end && in_text_end - (const char*)str < 4)
return 1;
if (*str > 0xf4)
return 4;
if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf))
return 4;
if (*str == 0xf4 && str[1] > 0x8f)
return 4; // str[1] < 0x80 is checked below
c = (unsigned int)((*str++ & 0x07) << 18);
if ((*str & 0xc0) != 0x80)
return 4;
c += (unsigned int)((*str++ & 0x3f) << 12);
if ((*str & 0xc0) != 0x80)
return 4;
c += (unsigned int)((*str++ & 0x3f) << 6);
if ((*str & 0xc0) != 0x80)
return 4;
c += (*str++ & 0x3f);
// utf-8 encodings of values used in surrogate pairs are invalid
if ((c & 0xFFFFF800) == 0xD800)
return 4;
*out_char = c;
return 4;
}
*out_char = 0;
return 0;
}

int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end,
const char** in_text_remaining)
{
ImWchar* buf_out = buf;
ImWchar* buf_end = buf + buf_size;
while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
{
unsigned int c;
in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
if (c == 0)
break;
if (c < 0x10000) // FIXME: Losing characters that don't fit in 2 bytes
*buf_out++ = (ImWchar)c;
}
*buf_out = 0;
if (in_text_remaining)
*in_text_remaining = in_text;
return (int)(buf_out - buf);
}

int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end)
{
int char_count = 0;
while ((!in_text_end || in_text < in_text_end) && *in_text)
{
unsigned int c;
in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
if (c == 0)
break;
if (c < 0x10000)
char_count++;
}
return char_count;
}

// Based on stb_to_utf8() from github.com/nothings/stb/
static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c)
{
if (c < 0x80)
{
buf[0] = (char)c;
return 1;
}
if (c < 0x800)
{
if (buf_size < 2)
return 0;
buf[0] = (char)(0xc0 + (c >> 6));
buf[1] = (char)(0x80 + (c & 0x3f));
return 2;
}
if (c >= 0xdc00 && c < 0xe000)
{
return 0;
}
if (c >= 0xd800 && c < 0xdc00)
{
if (buf_size < 4)
return 0;
buf[0] = (char)(0xf0 + (c >> 18));
buf[1] = (char)(0x80 + ((c >> 12) & 0x3f));
buf[2] = (char)(0x80 + ((c >> 6) & 0x3f));
buf[3] = (char)(0x80 + ((c)&0x3f));
return 4;
}
// else if (c < 0x10000)
{
if (buf_size < 3)
return 0;
buf[0] = (char)(0xe0 + (c >> 12));
buf[1] = (char)(0x80 + ((c >> 6) & 0x3f));
buf[2] = (char)(0x80 + ((c)&0x3f));
return 3;
}
}

static inline int ImTextCountUtf8BytesFromChar(unsigned int c)
{
if (c < 0x80)
return 1;
if (c < 0x800)
return 2;
if (c >= 0xdc00 && c < 0xe000)
return 0;
if (c >= 0xd800 && c < 0xdc00)
return 4;
return 3;
}

int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end)
{
char* buf_out = buf;
const char* buf_end = buf + buf_size;
while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
{
unsigned int c = (unsigned int)(*in_text++);
if (c < 0x80)
*buf_out++ = (char)c;
else
buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end - buf_out - 1), c);
}
*buf_out = 0;
return (int)(buf_out - buf);
}

int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end)
{
int bytes_count = 0;
while ((!in_text_end || in_text < in_text_end) && *in_text)
{
unsigned int c = (unsigned int)(*in_text++);
if (c < 0x80)
bytes_count++;
else
bytes_count += ImTextCountUtf8BytesFromChar(c);
}
return bytes_count;
}

static const char* GetClipboardTextFn_DefaultImpl(void*)
{
static char* buf_local = NULL;
if (buf_local)
{
ImGui::MemFree(buf_local);
buf_local = NULL;
}
if (!OpenClipboard(NULL))
return NULL;
HANDLE wbuf_handle = GetClipboardData(CF_UNICODETEXT);
if (wbuf_handle == NULL)
return NULL;
if (ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle))
{
int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1;
buf_local = (char*)ImGui::MemAlloc(buf_len * sizeof(char));
ImTextStrToUtf8(buf_local, buf_len, wbuf_global, NULL);
}
GlobalUnlock(wbuf_handle);
CloseClipboard();
return buf_local;
}

static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
{
if (!OpenClipboard(NULL))
return;

const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1;
HGLOBAL wbuf_handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar));
if (wbuf_handle == NULL)
return;
ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle);
ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL, NULL);
GlobalUnlock(wbuf_handle);
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, wbuf_handle);
CloseClipboard();
}

} // namespace

void InstallClipboardHandlers(ImGuiIO& aIO)
{
aIO.SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
aIO.GetClipboardTextFn = GetClipboardTextFn_DefaultImpl;
}
} // namespace ImGuiImpl
10 changes: 10 additions & 0 deletions Code/components/imgui/ImGuiClipboard_Win32.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (C) 2022 TiltedPhoques SRL.
// For licensing information see LICENSE at the root of this distribution.
#pragma once

struct ImGuiIO;

namespace ImGuiImpl
{
void InstallClipboardHandlers(ImGuiIO& aIO);
}
Loading

0 comments on commit 226efd1

Please sign in to comment.