Dear ImGui moontalk
This commit is contained in:
parent
e000381786
commit
47738e21ae
252
client/moontalk-imgui.cpp
Normal file
252
client/moontalk-imgui.cpp
Normal file
@ -0,0 +1,252 @@
|
||||
/* moontalk-imgui.cpp - Dear ImGui frontend
|
||||
* written by an Anon. https://boards.4chan.org/g/thread/98813374#p98826333
|
||||
*/
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_stdlib.h>
|
||||
#include <imgui_impl_sdl2.h>
|
||||
#include <imgui_impl_sdlrenderer2.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
#define SERV "7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion"
|
||||
#define PORT "50000"
|
||||
|
||||
static int moontalk_fd = -1;
|
||||
static std::mutex inqueue_lock;
|
||||
static std::queue<std::string> inqueue;
|
||||
static std::vector<std::string> moontalk_lines;
|
||||
|
||||
int tcp_connect(const char* addr, const char *port)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
struct addrinfo* res;
|
||||
int status = getaddrinfo(addr, port, &hints, &res);
|
||||
if (status != 0)
|
||||
errx(1, "getaddrinfo: %s", gai_strerror(status));
|
||||
|
||||
int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (fd < 0)
|
||||
err(1, "socket");
|
||||
|
||||
if (connect(fd, res->ai_addr, res->ai_addrlen))
|
||||
err(1, "socket");
|
||||
|
||||
freeaddrinfo(res);
|
||||
return fd;
|
||||
}
|
||||
|
||||
void moontalk_send(const std::string& line)
|
||||
{
|
||||
char timebuf[256];
|
||||
|
||||
time_t t = time(NULL);;
|
||||
struct tm * tm;
|
||||
tm = gmtime(&t);
|
||||
strftime(timebuf, sizeof(timebuf), "<%Y/%m/%d %H:%M:%S ", tm);
|
||||
|
||||
|
||||
std::string out;
|
||||
out += timebuf;
|
||||
out += line;
|
||||
if (line.at(line.size()-1) != '\n') out.push_back('\n');
|
||||
|
||||
send(moontalk_fd, out.data(), out.size(), 0);
|
||||
printf("send %s", out.c_str());
|
||||
}
|
||||
|
||||
void read_loop()
|
||||
{
|
||||
char buffer[4096];
|
||||
size_t pos = 0;
|
||||
|
||||
for (;;) {
|
||||
ssize_t r = read(moontalk_fd, buffer + pos, sizeof(buffer) - pos);
|
||||
if (r < 0) {
|
||||
if (r == EINTR)
|
||||
continue;
|
||||
err(1, "read");
|
||||
}
|
||||
pos += r;
|
||||
|
||||
// scan lines and push them to inqueue
|
||||
size_t start = 0;
|
||||
size_t end = 0;
|
||||
while (end < pos) {
|
||||
if (buffer[end] == '\n') {
|
||||
std::string line = {buffer + start, buffer + end+1};
|
||||
|
||||
inqueue_lock.lock();
|
||||
inqueue.push(std::move(line));
|
||||
inqueue_lock.unlock();
|
||||
|
||||
start = end+1;
|
||||
end = end+1;
|
||||
} else {
|
||||
end++;
|
||||
}
|
||||
}
|
||||
if (start != 0) {
|
||||
memmove(buffer, buffer+start, pos-start);
|
||||
pos -= start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ui()
|
||||
{
|
||||
static std::string input;
|
||||
|
||||
if (ImGui::Begin("Chat")) {
|
||||
for (auto& line : moontalk_lines) {
|
||||
ImGui::TextUnformatted(line.c_str());
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (ImGui::Begin("Input")) {
|
||||
ImGui::InputText("Input", &input);
|
||||
if (ImGui::Button("Send")) {
|
||||
moontalk_send(input);
|
||||
input.clear();
|
||||
}
|
||||
|
||||
// TODO or make it separate window and handle the layout on docking layer
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
|
||||
err(1, "SDL_Init: %s", SDL_GetError());
|
||||
|
||||
// From 2.0.18: Enable native IME.
|
||||
#ifdef SDL_HINT_IME_SHOW_UI
|
||||
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
|
||||
#endif
|
||||
|
||||
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
SDL_Window* window = SDL_CreateWindow("moontalk", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
|
||||
if (!window)
|
||||
err(1, "SDL_CreateWindow: %s", SDL_GetError());
|
||||
|
||||
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
|
||||
if (renderer == nullptr)
|
||||
err(1, "SDL_CreateRenderer: %s", SDL_GetError());
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
|
||||
// io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
|
||||
//io.ConfigViewportsNoAutoMerge = true;
|
||||
//io.ConfigViewportsNoTaskBarIcon = true;
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
|
||||
ImGui_ImplSDLRenderer2_Init(renderer);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
// setup
|
||||
fprintf(stderr, "Connecting...\n");
|
||||
moontalk_fd = tcp_connect(SERV, PORT);
|
||||
fprintf(stderr, "Connected\n");
|
||||
|
||||
std::thread t(read_loop);
|
||||
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
if (event.type == SDL_QUIT)
|
||||
done = true;
|
||||
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
|
||||
done = true;
|
||||
}
|
||||
|
||||
inqueue_lock.lock();
|
||||
if (!inqueue.empty()) {
|
||||
std::string line = std::move(inqueue.front());
|
||||
inqueue.pop();
|
||||
moontalk_lines.push_back(std::move(line));
|
||||
}
|
||||
inqueue_lock.unlock();
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplSDLRenderer2_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport());
|
||||
|
||||
ui();
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
SDL_RenderSetScale(renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 1);
|
||||
SDL_RenderClear(renderer);
|
||||
ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData());
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
ImGui_ImplSDLRenderer2_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
|
||||
close(moontalk_fd);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user