Support for chat message (WIP)

This commit is contained in:
Nemirtingas 2019-08-03 12:58:48 +02:00
parent 2a373bbf79
commit 4f9e67d700
6 changed files with 138 additions and 11 deletions

View file

@ -2816,6 +2816,8 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const
{ {
ImU32 color_bkp = col;
if (!text_end) if (!text_end)
text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls.
@ -2871,6 +2873,34 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
while (s < text_end) while (s < text_end)
{ {
if (*s == 1)
{
++s;
unsigned char color[4];
for (int i = 0; i < 4; ++i, s+=2)
{
if (s[0] >= '0' && s[0] <= '9')
color[i] = (s[0] - '0') * 16;
else if (s[0] >= 'a' && s[0] <= 'f')
color[i] = (s[0] - 'a' + 10) * 16;
else if (s[0] >= 'A' && s[0] <= 'F')
color[i] = (s[0] - 'A' + 10) * 16;
if (s[1] >= '0' && s[1] <= '9')
color[i] += (s[1] - '0');
else if (s[1] >= 'a' && s[1] <= 'f')
color[i] += (s[1] - 'a' + 10);
else if (s[1] >= 'A' && s[1] <= 'F')
color[i] += (s[1] - 'A' + 10);
}
col = ImColor(color[0], color[1], color[2], color[3]);
continue;
}
if (word_wrap_enabled) if (word_wrap_enabled)
{ {
// Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature. // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.

View file

@ -185,6 +185,17 @@ message Friend_Messages {
} }
} }
message Steam_Messages {
enum Types {
FRIEND_CHAT = 0;
}
Types type = 1;
oneof message_data {
bytes message = 2;
}
}
message Common_Message { message Common_Message {
uint64 source_id = 1; uint64 source_id = 1;
uint64 dest_id = 2; uint64 dest_id = 2;
@ -200,6 +211,7 @@ message Common_Message {
Friend_Messages friend_messages = 11; Friend_Messages friend_messages = 11;
Network_Old network_old = 12; Network_Old network_old = 12;
Networking_Sockets networking_sockets = 13; Networking_Sockets networking_sockets = 13;
Steam_Messages steam_messages = 14;
} }
uint32 source_ip = 128; uint32 source_ip = 128;

View file

@ -533,6 +533,11 @@ void Networking::do_callbacks_message(Common_Message *msg)
PRINT_DEBUG("has_networking_sockets\n"); PRINT_DEBUG("has_networking_sockets\n");
run_callbacks(CALLBACK_ID_NETWORKING_SOCKETS, msg); run_callbacks(CALLBACK_ID_NETWORKING_SOCKETS, msg);
} }
if (msg->has_steam_messages()) {
PRINT_DEBUG("has_steam_messages\n");
run_callbacks(CALLBACK_ID_STEAM_MESSAGES, msg);
}
} }
bool Networking::handle_tcp(Common_Message *msg, struct TCP_Socket &socket) bool Networking::handle_tcp(Common_Message *msg, struct TCP_Socket &socket)

View file

@ -60,6 +60,7 @@ enum Callback_Ids {
CALLBACK_ID_AUTH_TICKET, CALLBACK_ID_AUTH_TICKET,
CALLBACK_ID_FRIEND_MESSAGES, CALLBACK_ID_FRIEND_MESSAGES,
CALLBACK_ID_NETWORKING_SOCKETS, CALLBACK_ID_NETWORKING_SOCKETS,
CALLBACK_ID_STEAM_MESSAGES,
CALLBACK_IDS_MAX CALLBACK_IDS_MAX
}; };

View file

@ -3,6 +3,7 @@
#include <thread> #include <thread>
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <cctype>
#include <imgui.h> #include <imgui.h>
#include <impls/imgui_impl_win32.h> #include <impls/imgui_impl_win32.h>
@ -98,6 +99,7 @@ Steam_Overlay::Steam_Overlay(Settings* settings, SteamCallResults* callback_resu
overlay_state_changed(false) overlay_state_changed(false)
{ {
run_every_runcb->add(&Steam_Overlay::steam_overlay_run_every_runcb, this); run_every_runcb->add(&Steam_Overlay::steam_overlay_run_every_runcb, this);
this->network->setCallback(CALLBACK_ID_STEAM_MESSAGES, settings->get_local_steam_id(), &Steam_Overlay::steam_overlay_callback, this);
} }
Steam_Overlay::~Steam_Overlay() Steam_Overlay::~Steam_Overlay()
@ -105,6 +107,12 @@ Steam_Overlay::~Steam_Overlay()
run_every_runcb->remove(&Steam_Overlay::steam_overlay_run_every_runcb, this); run_every_runcb->remove(&Steam_Overlay::steam_overlay_run_every_runcb, this);
} }
void Steam_Overlay::steam_overlay_callback(void* object, Common_Message* msg)
{
Steam_Overlay* _this = reinterpret_cast<Steam_Overlay*>(object);
_this->Callback(msg);
}
void Steam_Overlay::steam_overlay_run_every_runcb(void* object) void Steam_Overlay::steam_overlay_run_every_runcb(void* object)
{ {
Steam_Overlay* _this = reinterpret_cast<Steam_Overlay*>(object); Steam_Overlay* _this = reinterpret_cast<Steam_Overlay*>(object);
@ -262,6 +270,7 @@ void Steam_Overlay::FriendConnect(Friend _friend)
{ {
std::lock_guard<std::recursive_mutex> lock(global_mutex); std::lock_guard<std::recursive_mutex> lock(global_mutex);
friends[_friend].window_state = window_state_none; friends[_friend].window_state = window_state_none;
memset(friends[_friend].chat_input, 0, max_chat_len);
} }
void Steam_Overlay::FriendDisconnect(Friend _friend) void Steam_Overlay::FriendDisconnect(Friend _friend)
@ -296,13 +305,13 @@ void Steam_Overlay::BuildFriendWindow(Friend const& frd, friend_window_state& st
return; return;
bool show = true; bool show = true;
ImGui::SetNextWindowSizeConstraints({ 160.0,90.0 }, { 9999.0, 9999.0 });
if (ImGui::Begin(frd.name().c_str(), &show)) if (ImGui::Begin(frd.name().c_str(), &show))
{ {
// Fill this with the chat box and maybe the invitation // Fill this with the chat box and maybe the invitation
if (state.window_state & (window_state_lobby_invite | window_state_rich_invite)) if (state.window_state & (window_state_lobby_invite | window_state_rich_invite))
{ {
ImGui::LabelText("", "%s invited you to join the game.", frd.name().c_str()); ImGui::LabelText("##label", "%s invited you to join the game.", frd.name().c_str());
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Accept")) if (ImGui::Button("Accept"))
{ {
@ -314,6 +323,30 @@ void Steam_Overlay::BuildFriendWindow(Friend const& frd, friend_window_state& st
state.window_state &= ~(window_state_lobby_invite | window_state_rich_invite); state.window_state &= ~(window_state_lobby_invite | window_state_rich_invite);
} }
} }
ImGui::PushItemWidth(-1.0f);
ImGui::InputTextMultiline("##chat_history", &state.chat_history[0], state.chat_history.length(), { -1.0f, 0 }, ImGuiInputTextFlags_ReadOnly);
ImGui::PopItemWidth();
if (ImGui::InputText("##chat_line", state.chat_input, max_chat_len, ImGuiInputTextFlags_EnterReturnsTrue))
{
if (!(state.window_state & window_state_send_message))
{
has_friend_action.push(frd);
state.window_state |= window_state_send_message;
}
}
ImGui::SameLine();
if (ImGui::Button("Send"))
{
if (!(state.window_state & window_state_send_message))
{
has_friend_action.push(frd);
state.window_state |= window_state_send_message;
}
}
} }
// User closed the friend window // User closed the friend window
if (!show) if (!show)
@ -335,18 +368,17 @@ void Steam_Overlay::OverlayProc( int width, int height )
ImGui::SetNextWindowSize({ static_cast<float>(width), ImGui::SetNextWindowSize({ static_cast<float>(width),
static_cast<float>(height) }); static_cast<float>(height) });
bool open_overlay = show_overlay; if (ImGui::Begin("SteamOverlay", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBringToFrontOnFocus))
if (ImGui::Begin("SteamOverlay", &open_overlay, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBringToFrontOnFocus))
{ {
ImGui::LabelText("", "Username: %s(%llu) playing %u", ImGui::LabelText("##label", "Username: %s(%llu) playing %u",
settings->get_local_name(), settings->get_local_name(),
settings->get_local_steam_id().ConvertToUint64(), settings->get_local_steam_id().ConvertToUint64(),
settings->get_local_game_id().AppID()); settings->get_local_game_id().AppID());
ImGui::Spacing(); ImGui::Spacing();
ImGui::LabelText("", "Friends"); ImGui::LabelText("##label", "Friends");
ImGui::ListBoxHeader("", friend_size); ImGui::ListBoxHeader("##label", friend_size);
std::for_each(friends.begin(), friends.end(), [this]( auto& i) std::for_each(friends.begin(), friends.end(), [this]( auto& i)
{ {
ImGui::PushID(i.first.id()); ImGui::PushID(i.first.id());
@ -372,11 +404,25 @@ void Steam_Overlay::OverlayProc( int width, int height )
} }
ImGui::End(); ImGui::End();
ShowOverlay(open_overlay);
//ImGui::ShowDemoWindow(); //ImGui::ShowDemoWindow();
} }
void Steam_Overlay::Callback(Common_Message *msg)
{
if (msg->has_steam_messages())
{
Friend frd;
frd.set_id(msg->source_id());
auto friend_info = friends.find(frd);
if (friend_info != friends.end())
{
Steam_Messages const& steam_message = msg->steam_messages();
// Change color to cyan for friend
friend_info->second.chat_history.append("\x1", 1).append("00FFFFFF", 8).append(steam_message.message()).append("\n", 1);
}
}
}
void Steam_Overlay::RunCallbacks() void Steam_Overlay::RunCallbacks()
{ {
if (overlay_state_changed) if (overlay_state_changed)
@ -397,6 +443,31 @@ void Steam_Overlay::RunCallbacks()
if (friend_info != friends.end()) if (friend_info != friends.end())
{ {
uint64 friend_id = friend_info->first.id(); uint64 friend_id = friend_info->first.id();
// The user clicken on "Send"
if (friend_info->second.window_state & window_state_send_message)
{
char* input = friend_info->second.chat_input;
char* end_input = input + strlen(input);
char* printable_char = std::find_if(input, end_input, [](char c) {
return std::isgraph(c);
});
if (printable_char != end_input)
{
// Handle chat send
Common_Message msg;
Steam_Messages* steam_messages = new Steam_Messages;
steam_messages->set_type(Steam_Messages::FRIEND_CHAT);
steam_messages->set_message(friend_info->second.chat_input);
msg.set_allocated_steam_messages(steam_messages);
msg.set_source_id(settings->get_local_steam_id().ConvertToUint64());
msg.set_dest_id(friend_id);
network->sendTo(&msg, true);
friend_info->second.chat_history.append("\x1", 1).append("00FF00FF", 8).append(input).append("\n", 1);
}
*input = 0; // Reset the input field
friend_info->second.window_state &= ~window_state_send_message;
}
// The user clicked on "Invite" // The user clicked on "Invite"
if (friend_info->second.window_state & window_state_invite) if (friend_info->second.window_state & window_state_invite)
{ {

View file

@ -6,6 +6,8 @@
#include <map> #include <map>
#include <queue> #include <queue>
static constexpr size_t max_chat_len = 768;
enum window_state enum window_state
{ {
window_state_none = 0, window_state_none = 0,
@ -13,17 +15,20 @@ enum window_state
window_state_invite = 1<<1, window_state_invite = 1<<1,
window_state_join = 1<<2, window_state_join = 1<<2,
window_state_lobby_invite = 1<<3, window_state_lobby_invite = 1<<3,
window_state_rich_invite = 1<<4 window_state_rich_invite = 1<<4,
window_state_send_message = 1<<5,
}; };
struct friend_window_state struct friend_window_state
{ {
uint8 window_state; uint8 window_state;
union union // The invitation (if any)
{ {
uint64 lobbyId; uint64 lobbyId;
char connect[k_cchMaxRichPresenceValueLength]; char connect[k_cchMaxRichPresenceValueLength];
}; };
std::string chat_history;
char chat_input[max_chat_len];
}; };
struct Friend_Less struct Friend_Less
@ -70,6 +75,9 @@ class Steam_Overlay
static LRESULT WINAPI MyDispatchMessageW(const MSG* lpMsg); static LRESULT WINAPI MyDispatchMessageW(const MSG* lpMsg);
static void steam_overlay_run_every_runcb(void* object); static void steam_overlay_run_every_runcb(void* object);
static void steam_overlay_callback(void* object, Common_Message* msg);
void Callback(Common_Message* msg);
void RunCallbacks(); void RunCallbacks();
// Right click on friend // Right click on friend