154 lines
4.0 KiB
C++
154 lines
4.0 KiB
C++
/*
|
|
Copyright 2021 flyinghead
|
|
|
|
This file is part of Flycast.
|
|
|
|
Flycast is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Flycast is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
#pragma once
|
|
#include "types.h"
|
|
#include "gui.h"
|
|
#include "imgui.h"
|
|
#include "network/ggpo.h"
|
|
#include <chrono>
|
|
|
|
class Chat
|
|
{
|
|
std::vector<std::pair<ImVec4, std::string>> lines;
|
|
bool visible = false;
|
|
bool newMessage = false;
|
|
bool focus = false;
|
|
std::string localPlayerName;
|
|
std::string remotePlayerName;
|
|
|
|
const ImVec4 WHITE { 1, 1, 1, 1 };
|
|
const ImVec4 YELLOW { 1, 1, 0, 1 };
|
|
|
|
bool manual_open = false;
|
|
bool enable_timeout = false;
|
|
std::chrono::steady_clock::time_point launch_time;
|
|
|
|
std::string playerName(bool remote)
|
|
{
|
|
if (remote)
|
|
return !remotePlayerName.empty() ? remotePlayerName : config::ActAsServer ? "P2" : "P1";
|
|
else
|
|
return !localPlayerName.empty() ? localPlayerName : config::ActAsServer ? "P1" : "P2";
|
|
}
|
|
|
|
public:
|
|
void toggle_timeout()
|
|
{
|
|
if (config::GGPOChatTimeoutToggle && !manual_open)
|
|
{
|
|
enable_timeout = true;
|
|
launch_time = std::chrono::steady_clock::now();
|
|
}
|
|
}
|
|
|
|
void reset()
|
|
{
|
|
visible = false;
|
|
lines.clear();
|
|
}
|
|
|
|
void display()
|
|
{
|
|
auto timeout = std::chrono::seconds(config::GGPOChatTimeout.get());
|
|
|
|
if (enable_timeout &&
|
|
std::chrono::steady_clock::now() - launch_time > timeout)
|
|
{
|
|
visible = false;
|
|
enable_timeout = false;
|
|
manual_open = false;
|
|
}
|
|
|
|
if (!visible)
|
|
return;
|
|
|
|
ImguiStyleVar _(ImGuiStyleVar_WindowRounding, 0);
|
|
ImguiStyleVar _1(ImGuiStyleVar_WindowBorderSize, 0);
|
|
ImGui::SetNextWindowPos(ImVec2(settings.display.width / 2, settings.display.height) - ScaledVec2(200.f, 220.f), ImGuiCond_FirstUseEver);
|
|
ImGui::SetNextWindowSize(ScaledVec2(400, 220), ImGuiCond_FirstUseEver);
|
|
ImGui::SetNextWindowBgAlpha(0.7f);
|
|
ImGui::SetNextWindowFocus();
|
|
if (ImGui::Begin("Chat", &visible, ImGuiWindowFlags_NoScrollbar))
|
|
{
|
|
ImGui::BeginChild(ImGui::GetID("log"), ImVec2(0, -ImGui::GetStyle().ItemSpacing.x - ImGui::GetFontSize() - ImGui::GetStyle().FramePadding.x * 2),
|
|
ImGuiChildFlags_Border, ImGuiWindowFlags_DragScrolling);
|
|
ImGui::PushTextWrapPos(ImGui::GetContentRegionAvail().x);
|
|
for (const auto& p : lines)
|
|
ImGui::TextColored(p.first, "%s", p.second.c_str());
|
|
ImGui::PopTextWrapPos();
|
|
if (newMessage)
|
|
{
|
|
newMessage = false;
|
|
ImGui::SetScrollHereY(1.f);
|
|
}
|
|
ImGui::EndChild();
|
|
static char buf[512];
|
|
ImGui::SetNextItemWidth(-0.001f);
|
|
if (ImGui::InputText("##input", buf, sizeof(buf), ImGuiInputTextFlags_EnterReturnsTrue))
|
|
{
|
|
if (buf[0] != '\0')
|
|
{
|
|
ggpo::sendChatMessage(config::ActAsServer ? 0 : 1, buf);
|
|
std::string line = "<" + playerName(false) + "> " + std::string(buf);
|
|
lines.push_back(std::make_pair(WHITE, line));
|
|
buf[0] = '\0';
|
|
newMessage = true;
|
|
enable_timeout = false;
|
|
}
|
|
ImGui::SetKeyboardFocusHere(-1);
|
|
}
|
|
else if (focus)
|
|
{
|
|
ImGui::SetKeyboardFocusHere(-1);
|
|
focus = false;
|
|
}
|
|
ImGui::SetItemDefaultFocus();
|
|
}
|
|
ImGui::End();
|
|
}
|
|
|
|
void receive(int playerNum, const std::string& msg)
|
|
{
|
|
if (config::GGPOChat && !visible)
|
|
{
|
|
visible = true;
|
|
toggle_timeout();
|
|
}
|
|
std::string line = "<" + playerName(true) + "> " + msg;
|
|
lines.push_back(std::make_pair(YELLOW, line));
|
|
newMessage = true;
|
|
}
|
|
|
|
void toggle(bool manual = false)
|
|
{
|
|
visible = !visible;
|
|
focus = visible;
|
|
if (manual)
|
|
manual_open = manual;
|
|
}
|
|
|
|
void setLocalPlayerName(const std::string& name) {
|
|
localPlayerName = name;
|
|
}
|
|
|
|
void setRemotePlayerName(const std::string& name) {
|
|
remotePlayerName = name;
|
|
}
|
|
};
|