basic imgui stuff
This commit is contained in:
parent
5ba9adfe07
commit
8e1a112980
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -45,3 +45,6 @@
|
|||||||
path = deps/zlib
|
path = deps/zlib
|
||||||
url = https://github.com/madler/zlib.git
|
url = https://github.com/madler/zlib.git
|
||||||
branch = develop
|
branch = develop
|
||||||
|
[submodule "deps/imgui"]
|
||||||
|
path = deps/imgui
|
||||||
|
url = https://github.com/fedddddd/imgui.git
|
||||||
|
1
deps/imgui
vendored
Submodule
1
deps/imgui
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 22e9093da37f0443f008b947caa6221724e760d6
|
31
deps/premake/imgui.lua
vendored
Normal file
31
deps/premake/imgui.lua
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
imgui = {
|
||||||
|
source = path.join(dependencies.basePath, "imgui")
|
||||||
|
}
|
||||||
|
|
||||||
|
function imgui.import()
|
||||||
|
links {"imgui"}
|
||||||
|
imgui.includes()
|
||||||
|
end
|
||||||
|
|
||||||
|
function imgui.includes()
|
||||||
|
includedirs {imgui.source}
|
||||||
|
end
|
||||||
|
|
||||||
|
function imgui.project()
|
||||||
|
project "imgui"
|
||||||
|
language "C++"
|
||||||
|
|
||||||
|
imgui.includes()
|
||||||
|
|
||||||
|
files {path.join(imgui.source, "*.cpp"), path.join(imgui.source, "*.hpp"), path.join(imgui.source, "*.c"),
|
||||||
|
path.join(imgui.source, "*.h"), path.join(imgui.source, "backends/imgui_impl_dx11.cpp"),
|
||||||
|
path.join(imgui.source, "backends/imgui_impl_dx11.h"),
|
||||||
|
path.join(imgui.source, "backends/imgui_impl_win32.cpp"),
|
||||||
|
path.join(imgui.source, "backends/imgui_impl_win32.h"), path.join(imgui.source, "misc/cpp/imgui_stdlib.cpp"),
|
||||||
|
path.join(imgui.source, "misc/cpp/imgui_stdlib.h")}
|
||||||
|
|
||||||
|
warnings "Off"
|
||||||
|
kind "StaticLib"
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(dependencies, imgui)
|
334
src/client/component/gui.cpp
Normal file
334
src/client/component/gui.cpp
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include "game/game.hpp"
|
||||||
|
#include "game/dvars.hpp"
|
||||||
|
|
||||||
|
#include "scheduler.hpp"
|
||||||
|
#include "gui.hpp"
|
||||||
|
|
||||||
|
#include <utils/string.hpp>
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
#include <utils/concurrency.hpp>
|
||||||
|
|
||||||
|
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
namespace gui
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, bool> enabled_menus;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct frame_callback
|
||||||
|
{
|
||||||
|
std::function<void()> callback;
|
||||||
|
bool always;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct event
|
||||||
|
{
|
||||||
|
HWND hWnd;
|
||||||
|
UINT msg;
|
||||||
|
WPARAM wParam;
|
||||||
|
LPARAM lParam;
|
||||||
|
};
|
||||||
|
|
||||||
|
utils::concurrency::container<std::vector<frame_callback>> on_frame_callbacks;
|
||||||
|
utils::concurrency::container<std::deque<notification_t>> notifications;
|
||||||
|
utils::concurrency::container<std::vector<event>> event_queue;
|
||||||
|
|
||||||
|
ID3D11Device* device;
|
||||||
|
ID3D11DeviceContext* device_context;
|
||||||
|
bool initialized = false;
|
||||||
|
bool toggled = false;
|
||||||
|
|
||||||
|
void initialize_gui_context()
|
||||||
|
{
|
||||||
|
ImGui::CreateContext();
|
||||||
|
ImGui::StyleColorsDark();
|
||||||
|
|
||||||
|
ImGui_ImplWin32_Init(*game::hWnd);
|
||||||
|
ImGui_ImplDX11_Init(device, device_context);
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_event_queue()
|
||||||
|
{
|
||||||
|
event_queue.access([](std::vector<event>& queue)
|
||||||
|
{
|
||||||
|
for (const auto& event : queue)
|
||||||
|
{
|
||||||
|
ImGui_ImplWin32_WndProcHandler(event.hWnd, event.msg, event.wParam, event.lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void new_gui_frame()
|
||||||
|
{
|
||||||
|
ImGui::GetIO().MouseDrawCursor = toggled;
|
||||||
|
if (toggled)
|
||||||
|
{
|
||||||
|
*game::keyCatchers |= 0x10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*game::keyCatchers &= ~0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui_ImplDX11_NewFrame();
|
||||||
|
ImGui_ImplWin32_NewFrame();
|
||||||
|
run_event_queue();
|
||||||
|
|
||||||
|
ImGui::NewFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void end_gui_frame()
|
||||||
|
{
|
||||||
|
ImGui::EndFrame();
|
||||||
|
ImGui::Render();
|
||||||
|
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle_menu(const std::string& name)
|
||||||
|
{
|
||||||
|
enabled_menus[name] = !enabled_menus[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_notifications()
|
||||||
|
{
|
||||||
|
static const auto window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings |
|
||||||
|
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav |
|
||||||
|
ImGuiWindowFlags_NoMove;
|
||||||
|
|
||||||
|
notifications.access([](std::deque<notification_t>& notifications_)
|
||||||
|
{
|
||||||
|
auto index = 0;
|
||||||
|
for (auto i = notifications_.begin(); i != notifications_.end();)
|
||||||
|
{
|
||||||
|
const auto now = std::chrono::high_resolution_clock::now();
|
||||||
|
if (now - i->creation_time >= i->duration)
|
||||||
|
{
|
||||||
|
i = notifications_.erase(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto title = utils::string::truncate(i->title, 34, "...");
|
||||||
|
const auto text = utils::string::truncate(i->text, 34, "...");
|
||||||
|
|
||||||
|
ImGui::SetNextWindowSizeConstraints(ImVec2(250, 50), ImVec2(250, 50));
|
||||||
|
ImGui::SetNextWindowBgAlpha(0.6f);
|
||||||
|
ImGui::Begin(utils::string::va("Notification #%i", index), nullptr, window_flags);
|
||||||
|
|
||||||
|
ImGui::SetWindowPos(ImVec2(10, 30.f + static_cast<float>(index) * 60.f));
|
||||||
|
ImGui::SetWindowSize(ImVec2(250, 0));
|
||||||
|
ImGui::Text(title.data());
|
||||||
|
ImGui::Text(text.data());
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
|
++i;
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_checkbox(const std::string& name, const std::string& menu)
|
||||||
|
{
|
||||||
|
ImGui::Checkbox(name.data(), &enabled_menus[menu]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_frame_callbacks()
|
||||||
|
{
|
||||||
|
on_frame_callbacks.access([](std::vector<frame_callback>& callbacks)
|
||||||
|
{
|
||||||
|
for (const auto& callback : callbacks)
|
||||||
|
{
|
||||||
|
if (callback.always || toggled)
|
||||||
|
{
|
||||||
|
callback.callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_main_menu_bar()
|
||||||
|
{
|
||||||
|
if (ImGui::BeginMainMenuBar())
|
||||||
|
{
|
||||||
|
if (ImGui::BeginMenu("Windows"))
|
||||||
|
{
|
||||||
|
menu_checkbox("Console", "console");
|
||||||
|
menu_checkbox("Script console", "script_console");
|
||||||
|
menu_checkbox("Debug", "debug");
|
||||||
|
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndMainMenuBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_on_frame()
|
||||||
|
{
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
printf("initialzed gui context\n");
|
||||||
|
initialize_gui_context();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_gui_frame();
|
||||||
|
run_frame_callbacks();
|
||||||
|
end_gui_frame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT d3d11_create_device_stub(IDXGIAdapter* pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software,
|
||||||
|
UINT Flags, const D3D_FEATURE_LEVEL* pFeatureLevels, UINT FeatureLevels, UINT SDKVersion,
|
||||||
|
ID3D11Device** ppDevice, D3D_FEATURE_LEVEL* pFeatureLevel, ID3D11DeviceContext** ppImmediateContext)
|
||||||
|
{
|
||||||
|
const auto result = D3D11CreateDevice(pAdapter, DriverType, Software, Flags, pFeatureLevels,
|
||||||
|
FeatureLevels, SDKVersion, ppDevice, pFeatureLevel, ppImmediateContext);
|
||||||
|
|
||||||
|
if (ppDevice != nullptr && ppImmediateContext != nullptr)
|
||||||
|
{
|
||||||
|
device = *ppDevice;
|
||||||
|
device_context = *ppImmediateContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dxgi_swap_chain_present_stub(utils::hook::assembler& a)
|
||||||
|
{
|
||||||
|
a.pushad64();
|
||||||
|
a.call_aligned(gui_on_frame);
|
||||||
|
a.popad64();
|
||||||
|
|
||||||
|
a.mov(r8d, esi);
|
||||||
|
a.mov(edx, r15d);
|
||||||
|
a.mov(rcx, rdi);
|
||||||
|
a.call_aligned(rbx);
|
||||||
|
a.mov(dword_ptr(rsp, 0x20), eax);
|
||||||
|
|
||||||
|
a.jmp(0x6CB185_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::hook::detour wnd_proc_hook;
|
||||||
|
LRESULT wnd_proc_stub(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (wParam != VK_ESCAPE && toggled)
|
||||||
|
{
|
||||||
|
event_queue.access([hWnd, msg, wParam, lParam](std::vector<event>& queue)
|
||||||
|
{
|
||||||
|
queue.push_back({hWnd, msg, wParam, lParam});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return wnd_proc_hook.invoke<LRESULT>(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gui_key_event(const int local_client_num, const int key, const int down)
|
||||||
|
{
|
||||||
|
printf("gui key event\n");
|
||||||
|
|
||||||
|
if (key == game::K_INS && down)
|
||||||
|
{
|
||||||
|
toggled = !toggled;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == game::K_ESCAPE && down && toggled)
|
||||||
|
{
|
||||||
|
toggled = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !toggled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gui_char_event(const int local_client_num, const int key)
|
||||||
|
{
|
||||||
|
return !toggled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gui_mouse_event(const int local_client_num, int x, int y)
|
||||||
|
{
|
||||||
|
return !toggled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_frame(const std::function<void()>& callback, bool always)
|
||||||
|
{
|
||||||
|
on_frame_callbacks.access([always, callback](std::vector<frame_callback>& callbacks)
|
||||||
|
{
|
||||||
|
callbacks.push_back({callback, always});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_menu_open(const std::string& name)
|
||||||
|
{
|
||||||
|
return enabled_menus[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
void notification(const std::string& title, const std::string& text, const std::chrono::milliseconds duration)
|
||||||
|
{
|
||||||
|
notification_t notification{};
|
||||||
|
notification.title = title;
|
||||||
|
notification.text = text;
|
||||||
|
notification.duration = duration;
|
||||||
|
notification.creation_time = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
notifications.access([notification](std::deque<notification_t>& notifications_)
|
||||||
|
{
|
||||||
|
notifications_.push_front(notification);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_to_clipboard(const std::string& text)
|
||||||
|
{
|
||||||
|
utils::string::set_clipboard_data(text);
|
||||||
|
gui::notification("Text copied to clipboard", utils::string::va("\"%s\"", text.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void* load_import(const std::string& library, const std::string& function) override
|
||||||
|
{
|
||||||
|
if (function == "D3D11CreateDevice")
|
||||||
|
{
|
||||||
|
return d3d11_create_device_stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
utils::hook::jump(0x6CB176_b, utils::hook::assemble(dxgi_swap_chain_present_stub), true);
|
||||||
|
|
||||||
|
wnd_proc_hook.create(0x5162D0_b, wnd_proc_stub);
|
||||||
|
|
||||||
|
on_frame([]()
|
||||||
|
{
|
||||||
|
show_notifications();
|
||||||
|
draw_main_menu_bar();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void pre_destroy() override
|
||||||
|
{
|
||||||
|
if (initialized)
|
||||||
|
{
|
||||||
|
ImGui_ImplWin32_Shutdown();
|
||||||
|
ImGui::DestroyContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(gui::component)
|
23
src/client/component/gui.hpp
Normal file
23
src/client/component/gui.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace gui
|
||||||
|
{
|
||||||
|
struct notification_t
|
||||||
|
{
|
||||||
|
std::string title;
|
||||||
|
std::string text;
|
||||||
|
std::chrono::milliseconds duration{};
|
||||||
|
std::chrono::high_resolution_clock::time_point creation_time{};
|
||||||
|
};
|
||||||
|
|
||||||
|
extern std::unordered_map<std::string, bool> enabled_menus;
|
||||||
|
|
||||||
|
bool gui_key_event(const int local_client_num, const int key, const int down);
|
||||||
|
bool gui_char_event(const int local_client_num, const int key);
|
||||||
|
bool gui_mouse_event(const int local_client_num, int x, int y);
|
||||||
|
|
||||||
|
void on_frame(const std::function<void()>& callback, bool always = false);
|
||||||
|
bool is_menu_open(const std::string& name);
|
||||||
|
void notification(const std::string& title, const std::string& text, const std::chrono::milliseconds duration = 3s);
|
||||||
|
void copy_to_clipboard(const std::string& text);
|
||||||
|
}
|
@ -4,6 +4,7 @@
|
|||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
|
|
||||||
#include "game_console.hpp"
|
#include "game_console.hpp"
|
||||||
|
#include "gui.hpp"
|
||||||
#include "game/ui_scripting/execution.hpp"
|
#include "game/ui_scripting/execution.hpp"
|
||||||
|
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
@ -36,12 +37,15 @@ namespace input
|
|||||||
|
|
||||||
void cl_key_event_stub(const int local_client_num, const int key, const int down)
|
void cl_key_event_stub(const int local_client_num, const int key, const int down)
|
||||||
{
|
{
|
||||||
|
const auto key_to_string = game::Key_KeynumToString(key, 0, 1);
|
||||||
|
printf("key to string: %s\n", key_to_string);
|
||||||
|
|
||||||
if (ui_scripting::lui_running())
|
if (ui_scripting::lui_running())
|
||||||
{
|
{
|
||||||
ui_scripting::notify(down ? "keydown" : "keyup",
|
ui_scripting::notify(down ? "keydown" : "keyup",
|
||||||
{
|
{
|
||||||
{"keynum", key},
|
{"keynum", key},
|
||||||
{"key", game::Key_KeynumToString(key, 0, 1)},
|
{"key", key_to_string},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,6 +54,11 @@ namespace input
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!gui::gui_key_event(local_client_num, key, down))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cl_key_event_hook.invoke<void>(local_client_num, key, down);
|
cl_key_event_hook.invoke<void>(local_client_num, key, down);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,6 +228,8 @@ namespace game
|
|||||||
* Variables
|
* Variables
|
||||||
**************************************************************/
|
**************************************************************/
|
||||||
|
|
||||||
|
WEAK symbol<HWND> hWnd{0x0, 0xC9DD2E0};
|
||||||
|
|
||||||
WEAK symbol<CmdArgs> sv_cmd_args{0xB48FF90, 0x2ED1EB0};
|
WEAK symbol<CmdArgs> sv_cmd_args{0xB48FF90, 0x2ED1EB0};
|
||||||
|
|
||||||
WEAK symbol<int> g_script_error_level{0xC3FD358, 0xB7AC1A4};
|
WEAK symbol<int> g_script_error_level{0xC3FD358, 0xB7AC1A4};
|
||||||
|
@ -89,6 +89,13 @@
|
|||||||
#include <asmjit/core/jitruntime.h>
|
#include <asmjit/core/jitruntime.h>
|
||||||
#include <asmjit/x86/x86assembler.h>
|
#include <asmjit/x86/x86assembler.h>
|
||||||
|
|
||||||
|
#include <d3d11.h>
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <imgui_internal.h>
|
||||||
|
#include <backends/imgui_impl_dx11.h>
|
||||||
|
#include <backends/imgui_impl_win32.h>
|
||||||
|
#include <misc/cpp/imgui_stdlib.h>
|
||||||
|
|
||||||
#include <google/protobuf/stubs/logging.h>
|
#include <google/protobuf/stubs/logging.h>
|
||||||
#include <proto/auth.pb.h>
|
#include <proto/auth.pb.h>
|
||||||
|
|
||||||
@ -100,6 +107,7 @@
|
|||||||
#pragma comment(lib, "urlmon.lib" )
|
#pragma comment(lib, "urlmon.lib" )
|
||||||
#pragma comment(lib, "iphlpapi.lib")
|
#pragma comment(lib, "iphlpapi.lib")
|
||||||
#pragma comment(lib, "Crypt32.lib")
|
#pragma comment(lib, "Crypt32.lib")
|
||||||
|
#pragma comment(lib, "d3d11.lib")
|
||||||
|
|
||||||
#include "resource.hpp"
|
#include "resource.hpp"
|
||||||
|
|
||||||
|
@ -105,6 +105,22 @@ namespace utils::string
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_clipboard_data(const std::string& text)
|
||||||
|
{
|
||||||
|
const auto len = text.size() + 1;
|
||||||
|
const auto mem = GlobalAlloc(GMEM_MOVEABLE, len);
|
||||||
|
|
||||||
|
memcpy(GlobalLock(mem), text.data(), len);
|
||||||
|
GlobalUnlock(mem);
|
||||||
|
|
||||||
|
if (OpenClipboard(nullptr))
|
||||||
|
{
|
||||||
|
EmptyClipboard();
|
||||||
|
SetClipboardData(CF_TEXT, mem);
|
||||||
|
CloseClipboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void strip(const char* in, char* out, int max)
|
void strip(const char* in, char* out, int max)
|
||||||
{
|
{
|
||||||
if (!in || !out) return;
|
if (!in || !out) return;
|
||||||
@ -177,6 +193,13 @@ namespace utils::string
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string truncate(const std::string& text, const size_t length, const std::string& end)
|
||||||
|
{
|
||||||
|
return text.size() <= length
|
||||||
|
? text
|
||||||
|
: text.substr(0, length - end.size()) + end;
|
||||||
|
}
|
||||||
|
|
||||||
bool match_compare(const std::string& input, const std::string& text, const bool exact)
|
bool match_compare(const std::string& input, const std::string& text, const bool exact)
|
||||||
{
|
{
|
||||||
if (exact && text == input) return true;
|
if (exact && text == input) return true;
|
||||||
|
@ -90,6 +90,7 @@ namespace utils::string
|
|||||||
std::string dump_hex(const std::string& data, const std::string& separator = " ");
|
std::string dump_hex(const std::string& data, const std::string& separator = " ");
|
||||||
|
|
||||||
std::string get_clipboard_data();
|
std::string get_clipboard_data();
|
||||||
|
void set_clipboard_data(const std::string& text);
|
||||||
|
|
||||||
void strip(const char* in, char* out, int max);
|
void strip(const char* in, char* out, int max);
|
||||||
|
|
||||||
@ -98,5 +99,7 @@ namespace utils::string
|
|||||||
|
|
||||||
std::string replace(std::string str, const std::string& from, const std::string& to);
|
std::string replace(std::string str, const std::string& from, const std::string& to);
|
||||||
|
|
||||||
|
std::string truncate(const std::string& text, const size_t length, const std::string& end);
|
||||||
|
|
||||||
bool match_compare(const std::string& input, const std::string& text, const bool exact);
|
bool match_compare(const std::string& input, const std::string& text, const bool exact);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user