Merge branch 'rechat' of https://github.com/ANR2ME/ppsspp into ANR2ME-rechat

This commit is contained in:
Henrik Rydgård 2020-03-08 14:28:10 +01:00
commit 8f2a52ccab
20 changed files with 661 additions and 18 deletions

View File

@ -842,6 +842,7 @@ list(APPEND NativeAppSource
UI/DiscordIntegration.cpp
UI/NativeApp.cpp
UI/BackgroundAudio.cpp
UI/ChatScreen.cpp
UI/DevScreens.cpp
UI/DisplayLayoutEditor.cpp
UI/DisplayLayoutScreen.cpp

View File

@ -692,6 +692,7 @@ const KeyMap_IntStrPair psp_button_names[] = {
{VIRTKEY_AXIS_RIGHT_Y_MIN, "RightAn.Down"},
{VIRTKEY_AXIS_RIGHT_X_MIN, "RightAn.Left"},
{VIRTKEY_AXIS_RIGHT_X_MAX, "RightAn.Right"},
{VIRTKEY_OPENCHAT, "OpenChat" },
{VIRTKEY_AXIS_SWAP, "AxisSwap"},
{VIRTKEY_DEVMENU, "DevMenu"},

View File

@ -58,6 +58,7 @@ enum {
VIRTKEY_TEXTURE_REPLACE = 0x4000001A,
VIRTKEY_SCREENSHOT = 0x4000001B,
VIRTKEY_MUTE_TOGGLE = 0x4000001C,
VIRTKEY_OPENCHAT = 0x4000001D,
VIRTKEY_LAST,
VIRTKEY_COUNT = VIRTKEY_LAST - VIRTKEY_FIRST
};

View File

@ -920,7 +920,15 @@ static ConfigSetting controlSettings[] = {
static ConfigSetting networkSettings[] = {
ConfigSetting("EnableWlan", &g_Config.bEnableWlan, false, true, true),
ConfigSetting("EnableAdhocServer", &g_Config.bEnableAdhocServer, false, true, true),
ConfigSetting("EnableNetworkChat", &g_Config.bEnableNetworkChat, false, true, true),
ConfigSetting("ChatButtonPosition",&g_Config.iChatButtonPosition,BOTTOM_LEFT,true,true),
ConfigSetting("ChatScreenPosition",&g_Config.iChatScreenPosition,BOTTOM_LEFT,true,true),
ConfigSetting("EnableQuickChat", &g_Config.bEnableQuickChat, true, true, true),
ConfigSetting("QuickChat1", &g_Config.sQuickChat0, "Quick Chat 1", true, true),
ConfigSetting("QuickChat2", &g_Config.sQuickChat1, "Quick Chat 2", true, true),
ConfigSetting("QuickChat3", &g_Config.sQuickChat2, "Quick Chat 3", true, true),
ConfigSetting("QuickChat4", &g_Config.sQuickChat3, "Quick Chat 4", true, true),
ConfigSetting("QuickChat5", &g_Config.sQuickChat4, "Quick Chat 5", true, true),
ConfigSetting(false),
};

View File

@ -27,6 +27,17 @@
extern const char *PPSSPP_GIT_VERSION;
enum ChatPositions {
BOTTOM_LEFT = 0,
BOTTOM_CENTER = 1,
BOTOM_RIGHT = 2,
TOP_LEFT = 3,
TOP_CENTER = 4,
TOP_RIGHT = 5,
CENTER_LEFT = 6,
CENTER_RIGHT = 7,
};
namespace http {
class Download;
class Downloader;
@ -385,6 +396,17 @@ public:
bool bEnableAdhocServer;
int iWlanAdhocChannel;
bool bWlanPowerSave;
bool bEnableNetworkChat;
//for chat position , moveable buttons is better than this
int iChatButtonPosition;
int iChatScreenPosition;
bool bEnableQuickChat;
std::string sQuickChat0;
std::string sQuickChat1;
std::string sQuickChat2;
std::string sQuickChat3;
std::string sQuickChat4;
int iPSPModel;
int iFirmwareVersion;

View File

@ -55,6 +55,13 @@ std::recursive_mutex peerlock;
SceNetAdhocPdpStat * pdp[255];
SceNetAdhocPtpStat * ptp[255];
uint32_t localip;
std::vector<std::string> chatLog;
std::string name = "";
std::string incoming = "";
std::string message = "";
bool chatScreenVisible = false;
bool updateChatScreen = false;
int newChat = 0;
int isLocalMAC(const SceNetEtherAddr * addr) {
SceNetEtherAddr saddr;
@ -981,6 +988,45 @@ void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node) {
free(node);
}
void sendChat(std::string chatString) {
SceNetAdhocctlChatPacketC2S chat;
auto n = GetI18NCategory("Networking");
chat.base.opcode = OPCODE_CHAT;
//TODO check network inited, check send success or not, chatlog.pushback error on failed send, pushback error on not connected
if (friendFinderRunning)
{
// Send Chat to Server
if (!chatString.empty()) {
//maximum char allowed is 64 character for compability with original server (pro.coldbird.net)
message = chatString.substr(0, 60); // 64 return chat variable corrupted is it out of memory?
strcpy(chat.message, message.c_str());
//Send Chat Messages
int chatResult = send(metasocket, (const char *)&chat, sizeof(chat), 0);
NOTICE_LOG(SCENET, "Send Chat %s to Adhoc Server", chat.message);
name = g_Config.sNickName.c_str();
chatLog.push_back(name.substr(0, 8) + ": " + chat.message);
if (chatScreenVisible) {
updateChatScreen = true;
}
}
}
else {
chatLog.push_back(n->T("You're in Offline Mode, go to lobby or online hall"));
if (chatScreenVisible) {
updateChatScreen = true;
}
}
}
std::vector<std::string> getChatLog() {
// this log used by chat screen
if (chatLog.size() > 50) {
//erase the first 40 element limit the chatlog size
chatLog.erase(chatLog.begin(), chatLog.begin() + 40);
}
return chatLog;
}
int friendFinder(){
// Receive Buffer
int rxpos = 0;
@ -1024,13 +1070,6 @@ int friendFinder(){
}*/
}
// Send Chat Messages
//while(popFromOutbox(chat.message))
//{
// // Send Chat to Server
// sceNetInetSend(metasocket, (const char *)&chat, sizeof(chat), 0);
//}
// Wait for Incoming Data
int received = recv(metasocket, (char *)(rx + rxpos), sizeof(rx) - rxpos, 0);
@ -1078,14 +1117,23 @@ int friendFinder(){
if (rxpos >= (int)sizeof(SceNetAdhocctlChatPacketS2C)) {
// Cast Packet
SceNetAdhocctlChatPacketS2C * packet = (SceNetAdhocctlChatPacketS2C *)rx;
// Fix for Idiots that try to troll the "ME" Nametag
if (strcasecmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME");
// Add Incoming Chat to HUD
//printf("Receive chat message %s", packet->base.message);
DEBUG_LOG(SCENET, "Received chat message %s", packet->base.message);
NOTICE_LOG(SCENET, "Received chat message %s", packet->base.message);
incoming = "";
name = (char *)packet->name.data;
incoming.append(name.substr(0, 8));
incoming.append(": ");
incoming.append((char *)packet->base.message);
chatLog.push_back(incoming);
//im new to pointer btw :( doesn't know its safe or not this should update the chat screen when data coming
if (chatScreenVisible) {
updateChatScreen = true;
}
else {
if (newChat < 50) {
newChat += 1;
}
}
// Move RX Buffer
memmove(rx, rx + sizeof(SceNetAdhocctlChatPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlChatPacketS2C));
@ -1107,7 +1155,16 @@ int friendFinder(){
// Add User
addFriend(packet);
incoming = "";
incoming.append((char *)packet->name.data);
incoming.append(" Joined ");
//do we need ip?
//joined.append((char *)packet->ip);
chatLog.push_back(incoming);
//im new to pointer btw :( doesn't know its safe or not this should update the chat screen when data coming
if (chatScreenVisible) {
updateChatScreen = true;
}
// Update HUD User Count
#ifdef LOCALHOST_AS_PEER
setUserCount(getActivePeerCount());

View File

@ -847,6 +847,16 @@ SceNetAdhocMatchingMemberInternal* addMember(SceNetAdhocMatchingContext * contex
*/
void addFriend(SceNetAdhocctlConnectPacketS2C * packet);
/**
* Send chat or get that
* @param std::string ChatString
*/
void sendChat(std::string chatString);
std::vector<std::string> getChatLog();
extern bool chatScreenVisible;
extern bool updateChatScreen;
extern int newChat;
/*
* Find a Peer/Friend by MAC address
*/

263
UI/ChatScreen.cpp Normal file
View File

@ -0,0 +1,263 @@
#include "ui/ui_context.h"
#include "ui/view.h"
#include "ui/viewgroup.h"
#include "ui/ui.h"
#include "ChatScreen.h"
#include "Core/Config.h"
#include "Core/Host.h"
#include "Core/System.h"
#include "Common/LogManager.h"
#include "Core/HLE/proAdhoc.h"
#include "i18n/i18n.h"
#include <ctype.h>
#include "util/text/utf8.h"
void ChatMenu::CreatePopupContents(UI::ViewGroup *parent) {
using namespace UI;
auto n = GetI18NCategory("Networking");
LinearLayout *outer = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT,400));
scroll_ = outer->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0)));
LinearLayout *bottom = outer->Add(new LinearLayout(ORIENT_HORIZONTAL, new LayoutParams(FILL_PARENT, WRAP_CONTENT)));
#if defined(_WIN32) || defined(USING_QT_UI)
chatEdit_ = bottom->Add(new TextEdit("", n->T("Chat Here"), new LinearLayoutParams(1.0)));
#if defined(USING_WIN_UI)
//freeze the ui when using ctrl + C hotkey need workaround
if (g_Config.bBypassOSKWithKeyboard && !g_Config.bFullScreen)
{
std::wstring titleText = ConvertUTF8ToWString(n->T("Chat"));
std::wstring defaultText = ConvertUTF8ToWString(n->T("Chat Here"));
std::wstring inputChars;
if (System_InputBoxGetWString(titleText.c_str(), defaultText, inputChars)) {
//chatEdit_->SetText(ConvertWStringToUTF8(inputChars));
sendChat(ConvertWStringToUTF8(inputChars));
}
}
#endif
chatEdit_->OnEnter.Handle(this, &ChatMenu::OnSubmit);
#elif defined(__ANDROID__)
bottom->Add(new Button(n->T("Chat Here"),new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->OnClick.Handle(this, &ChatMenu::OnSubmit);
bottom->Add(new Button(n->T("Send")))->OnClick.Handle(this, &ChatMenu::OnSubmit);
#endif
if (g_Config.bEnableQuickChat) {
LinearLayout *quickChat = outer->Add(new LinearLayout(ORIENT_HORIZONTAL, new LayoutParams(FILL_PARENT, WRAP_CONTENT)));
quickChat->Add(new Button(n->T("1"), new LinearLayoutParams(1.0)))->OnClick.Handle(this, &ChatMenu::OnQuickChat1);
quickChat->Add(new Button(n->T("2"), new LinearLayoutParams(1.0)))->OnClick.Handle(this, &ChatMenu::OnQuickChat2);
quickChat->Add(new Button(n->T("3"), new LinearLayoutParams(1.0)))->OnClick.Handle(this, &ChatMenu::OnQuickChat3);
quickChat->Add(new Button(n->T("4"), new LinearLayoutParams(1.0)))->OnClick.Handle(this, &ChatMenu::OnQuickChat4);
quickChat->Add(new Button(n->T("5"), new LinearLayoutParams(1.0)))->OnClick.Handle(this, &ChatMenu::OnQuickChat5);
}
chatVert_ = scroll_->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
chatVert_->SetSpacing(0);
parent->Add(outer);
}
void ChatMenu::CreateViews() {
using namespace UI;
auto n = GetI18NCategory("Networking");
UIContext &dc = *screenManager()->getUIContext();
AnchorLayout *anchor = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
anchor->Overflow(false);
root_ = anchor;
float yres = screenManager()->getUIContext()->GetBounds().h;
switch (g_Config.iChatScreenPosition) {
// the chat screen size is still static 280x240 need a dynamic size based on device resolution
case 0:
box_ = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(PopupWidth(), FillVertical() ? yres - 30 : WRAP_CONTENT, 280, NONE, NONE, 240, true));
break;
case 1:
box_ = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(PopupWidth(), FillVertical() ? yres - 30 : WRAP_CONTENT, dc.GetBounds().centerX(), NONE, NONE, 240, true));
break;
case 2:
box_ = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(PopupWidth(), FillVertical() ? yres - 30 : WRAP_CONTENT, NONE, NONE, 280, 240, true));
break;
case 3:
box_ = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(PopupWidth(), FillVertical() ? yres - 30 : WRAP_CONTENT, 280, 240, NONE, NONE, true));
break;
case 4:
box_ = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(PopupWidth(), FillVertical() ? yres - 30 : WRAP_CONTENT, dc.GetBounds().centerX(), 240, NONE, NONE, true));
break;
case 5:
box_ = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(PopupWidth(), FillVertical() ? yres - 30 : WRAP_CONTENT, NONE, 240, 280, NONE, true));
break;
}
root_->Add(box_);
box_->SetBG(UI::Drawable(0x99303030));
box_->SetHasDropShadow(false);
View *title = new PopupHeader(n->T("Chat"));
box_->Add(title);
CreatePopupContents(box_);
#if defined(_WIN32) || defined(USING_QT_UI)
UI::EnableFocusMovement(true);
root_->SetDefaultFocusView(box_);
box_->SubviewFocused(chatEdit_);
root_->SetFocus();
#else
//root_->SetDefaultFocusView(box_);
//box_->SubviewFocused(scroll_);
//root_->SetFocus();
#endif
chatScreenVisible = true;
newChat = 0;
UpdateChat();
}
void ChatMenu::dialogFinished(const Screen *dialog, DialogResult result) {
UpdateUIState(UISTATE_INGAME);
}
UI::EventReturn ChatMenu::OnSubmit(UI::EventParams &e) {
#if defined(_WIN32) || defined(USING_QT_UI)
std::string chat = chatEdit_->GetText();
chatEdit_->SetText("");
chatEdit_->SetFocus();
sendChat(chat);
#elif defined(__ANDROID__)
System_SendMessage("inputbox", "Chat:");
#endif
return UI::EVENT_DONE;
}
UI::EventReturn ChatMenu::OnQuickChat1(UI::EventParams &e) {
sendChat(g_Config.sQuickChat0);
return UI::EVENT_DONE;
}
UI::EventReturn ChatMenu::OnQuickChat2(UI::EventParams &e) {
sendChat(g_Config.sQuickChat1);
return UI::EVENT_DONE;
}
UI::EventReturn ChatMenu::OnQuickChat3(UI::EventParams &e) {
sendChat(g_Config.sQuickChat2);
return UI::EVENT_DONE;
}
UI::EventReturn ChatMenu::OnQuickChat4(UI::EventParams &e) {
sendChat(g_Config.sQuickChat3);
return UI::EVENT_DONE;
}
UI::EventReturn ChatMenu::OnQuickChat5(UI::EventParams &e) {
sendChat(g_Config.sQuickChat4);
return UI::EVENT_DONE;
}
/*
maximum chat length in one message from server is only 64 character
need to split the chat to fit the static chat screen size
if the chat screen size become dynamic from device resolution
we need to change split function logic also.
*/
std::vector<std::string> Split(const std::string& str)
{
std::vector<std::string> ret;
int counter = 0;
int firstSentenceEnd = 0;
int secondSentenceEnd = 0;
int spliton = 45;
for (int i = 0; i<(int)str.length(); i++) {
if (isspace(str[i])) {
if (i < spliton) {
if(str[i-1]!=':')
firstSentenceEnd = i+1;
}
else if (i > spliton) {
firstSentenceEnd = spliton;
}
}
}
if (firstSentenceEnd == 0) {
firstSentenceEnd = spliton;
}
ret.push_back(str.substr(0, firstSentenceEnd));
ret.push_back(str.substr(firstSentenceEnd));
return ret;
}
void ChatMenu::UpdateChat() {
using namespace UI;
if (chatVert_ != NULL) {
chatVert_->Clear(); //read Access violation is proadhoc.cpp use NULL_->Clear() pointer?
std::vector<std::string> chatLog = getChatLog();
for (auto i : chatLog) {
//split long text
uint32_t namecolor = 0x29B6F6;
uint32_t textcolor = 0xFFFFFF;
uint32_t infocolor = 0xFDD835;
std::string name = g_Config.sNickName.c_str();
std::string displayname = i.substr(0, i.find(':'));
std::string chattext = i.substr(displayname.length());
if (name.substr(0, 8) == displayname) {
namecolor = 0xE53935;
}
if (i[displayname.length()] != ':') {
TextView *v = chatVert_->Add(new TextView(i, FLAG_DYNAMIC_ASCII, true));
v->SetTextColor(0xFF000000 | infocolor);
}
else {
LinearLayout *line = chatVert_->Add(new LinearLayout(ORIENT_HORIZONTAL, new LayoutParams(FILL_PARENT, FILL_PARENT)));
TextView *nameView = line->Add(new TextView(displayname, FLAG_DYNAMIC_ASCII, true));
nameView->SetTextColor(0xFF000000 | namecolor);
if (chattext.length() > 45) {
std::vector<std::string> splitted = Split(chattext);
std::string one = splitted[0];
std::string two = splitted[1];
TextView *oneview = line->Add(new TextView(one, FLAG_DYNAMIC_ASCII, true));
oneview->SetTextColor(0xFF000000 | textcolor);
TextView *twoview = chatVert_->Add(new TextView(two, FLAG_DYNAMIC_ASCII, true));
twoview->SetTextColor(0xFF000000 | textcolor);
}
else {
TextView *chatView = line->Add(new TextView(chattext, FLAG_DYNAMIC_ASCII, true));
chatView->SetTextColor(0xFF000000 | textcolor);
}
}
}
toBottom_ = true;
}
}
bool ChatMenu::touch(const TouchInput &touch) {
if (!box_ || (touch.flags & TOUCH_DOWN) == 0 || touch.id != 0) {
return UIDialogScreen::touch(touch);
}
if (!box_->GetBounds().Contains(touch.x, touch.y)){
screenManager()->finishDialog(this, DR_BACK);
}
return UIDialogScreen::touch(touch);
}
void ChatMenu::update() {
PopupScreen::update();
if (scroll_ && toBottom_) {
toBottom_ = false;
scroll_->ScrollToBottom();
}
if (updateChatScreen) {
UpdateChat();
updateChatScreen = false;
}
}
ChatMenu::~ChatMenu() {
chatScreenVisible = false;
}

27
UI/ChatScreen.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
#include "file/file_util.h"
#include "ui/ui_screen.h"
class ChatMenu : public PopupScreen {
public:
ChatMenu() : PopupScreen("Chat") , toBottom_(true) {}
~ChatMenu();
void CreatePopupContents(UI::ViewGroup *parent) override;
void CreateViews() override;
void dialogFinished(const Screen *dialog, DialogResult result) override;
bool touch(const TouchInput &touch) override;
void update() override;
void UpdateChat();
bool toBottom_;
private:
UI::EventReturn OnSubmit(UI::EventParams &e);
UI::EventReturn OnQuickChat1(UI::EventParams &e);
UI::EventReturn OnQuickChat2(UI::EventParams &e);
UI::EventReturn OnQuickChat3(UI::EventParams &e);
UI::EventReturn OnQuickChat4(UI::EventParams &e);
UI::EventReturn OnQuickChat5(UI::EventParams &e);
UI::TextEdit *chatEdit_;
UI::ScrollView *scroll_;
UI::LinearLayout *chatVert_;
UI::ViewGroup *box_;
};

View File

@ -62,6 +62,7 @@
#include "Core/SaveState.h"
#include "Core/MIPS/MIPS.h"
#include "Core/HLE/__sceAudio.h"
#include "Core/HLE/proAdhoc.h"
#include "UI/BackgroundAudio.h"
#include "UI/OnScreenDisplay.h"
@ -78,6 +79,7 @@
#include "UI/InstallZipScreen.h"
#include "UI/ProfilerDraw.h"
#include "UI/DiscordIntegration.h"
#include "UI/ChatScreen.h"
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
#include "Windows/MainWindow.h"
@ -87,6 +89,8 @@
static AVIDump avi;
#endif
UI::ChoiceWithValueDisplay *chatButtons;
static bool frameStep_;
static int lastNumFlips;
static bool startDumping;
@ -136,6 +140,7 @@ EmuScreen::EmuScreen(const std::string &filename)
coreState = CORE_STEPPING;
OnDevMenu.Handle(this, &EmuScreen::OnDevTools);
OnChatMenu.Handle(this, &EmuScreen::OnChat);
}
bool EmuScreen::bootAllowStorage(const std::string &filename) {
@ -438,6 +443,24 @@ void EmuScreen::sendMessage(const char *message, const char *value) {
} else {
gstate_c.skipDrawReason &= ~SKIPDRAW_WINDOW_MINIMIZED;
}
} else if (!strcmp(message, "chat screen")) {
#if defined(USING_WIN_UI)
//temporary workaround for hotkey its freeze the ui when open chat screen using hotkey and native keyboard is enable
if (g_Config.bBypassOSKWithKeyboard) {
osm.Show("Disable windows native keyboard options to use ctrl + c hotkey", 2.0f);
} else {
if (g_Config.bEnableNetworkChat) {
UI::EventParams e{};
OnChatMenu.Trigger(e);
}
}
#else
if (g_Config.bEnableNetworkChat) {
UI::EventParams e{};
OnChatMenu.Trigger(e);
}
#endif
}
}
@ -528,6 +551,13 @@ void EmuScreen::onVKeyDown(int virtualKeyCode) {
}
break;
case VIRTKEY_OPENCHAT:
if (g_Config.bEnableNetworkChat) {
UI::EventParams e{};
OnChatMenu.Trigger(e);
}
break;
case VIRTKEY_AXIS_SWAP:
KeyMap::SwapAxis();
break;
@ -976,6 +1006,40 @@ void EmuScreen::CreateViews() {
cardboardDisableButton_->OnClick.Handle(this, &EmuScreen::OnDisableCardboard);
cardboardDisableButton_->SetVisibility(V_GONE);
if (g_Config.bEnableNetworkChat) {
switch (g_Config.iChatButtonPosition) {
case 0:
chatButtons = new ChoiceWithValueDisplay(&newChat, sc->T("Chat"), new AnchorLayoutParams(130, WRAP_CONTENT, 80, NONE, NONE, 50, true));
break;
case 1:
chatButtons = new ChoiceWithValueDisplay(&newChat, sc->T("Chat"), new AnchorLayoutParams(130, WRAP_CONTENT, bounds.centerX(), NONE, NONE, 50, true));
break;
case 2:
chatButtons = new ChoiceWithValueDisplay(&newChat, sc->T("Chat"), new AnchorLayoutParams(130, WRAP_CONTENT, NONE, NONE, 80, 50, true));
break;
case 3:
chatButtons = new ChoiceWithValueDisplay(&newChat, sc->T("Chat"), new AnchorLayoutParams(130, WRAP_CONTENT, 80, 50, NONE, NONE, true));
break;
case 4:
chatButtons = new ChoiceWithValueDisplay(&newChat, sc->T("Chat"), new AnchorLayoutParams(130, WRAP_CONTENT, bounds.centerX(), 50, NONE, NONE, true));
break;
case 5:
chatButtons = new ChoiceWithValueDisplay(&newChat, sc->T("Chat"), new AnchorLayoutParams(130, WRAP_CONTENT, NONE, 50, 80, NONE, true));
break;
case 6:
chatButtons = new ChoiceWithValueDisplay(&newChat, sc->T("Chat"), new AnchorLayoutParams(130, WRAP_CONTENT, 80, bounds.centerY(), NONE, NONE, true));
break;
case 7:
chatButtons = new ChoiceWithValueDisplay(&newChat, sc->T("Chat"), new AnchorLayoutParams(130, WRAP_CONTENT, NONE, bounds.centerY(), 80, NONE, true));
break;
default:
chatButtons = new ChoiceWithValueDisplay(&newChat, sc->T("Chat"), new AnchorLayoutParams(130, WRAP_CONTENT, 80, NONE, NONE, 50, true));
break;
}
root_->Add(chatButtons)->OnClick.Handle(this, &EmuScreen::OnChat);
}
saveStatePreview_ = new AsyncImageFileView("", IS_FIXED, nullptr, new AnchorLayoutParams(bounds.centerX(), 100, NONE, NONE, true));
saveStatePreview_->SetFixedSize(160, 90);
saveStatePreview_->SetColor(0x90FFFFFF);
@ -1047,7 +1111,14 @@ UI::EventReturn EmuScreen::OnDisableCardboard(UI::EventParams &params) {
return UI::EVENT_DONE;
}
UI::EventReturn EmuScreen::OnChat(UI::EventParams& params) {
if (chatButtons->GetVisibility() == UI::V_VISIBLE) chatButtons->SetVisibility(UI::V_GONE);
screenManager()->push(new ChatMenu());
return UI::EVENT_DONE;
}
void EmuScreen::update() {
UIScreen::update();
if (bootPending_)
@ -1126,6 +1197,7 @@ void EmuScreen::update() {
}
}
}
}
void EmuScreen::checkPowerDown() {

View File

@ -52,6 +52,7 @@ protected:
void CreateViews() override;
UI::EventReturn OnDevTools(UI::EventParams &params);
UI::EventReturn OnDisableCardboard(UI::EventParams &params);
UI::EventReturn OnChat(UI::EventParams &params);
private:
void bootGame(const std::string &filename);
@ -71,7 +72,7 @@ private:
void checkPowerDown();
UI::Event OnDevMenu;
UI::Event OnChatMenu;
bool bootPending_;
std::string gamePath_;

View File

@ -669,6 +669,60 @@ void GameSettingsScreen::CreateViews() {
networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.sMACAddress, n->T("Change Mac Address"), (const char *)nullptr))->OnClick.Handle(this, &GameSettingsScreen::OnChangeMacAddress);
networkingSettings->Add(new PopupSliderChoice(&g_Config.iPortOffset, 0, 60000, n->T("Port offset", "Port offset(0 = PSP compatibility)"), 100, screenManager()));
networkingSettings->Add(new ItemHeader(ms->T("Chat")));
networkingSettings->Add(new CheckBox(&g_Config.bEnableNetworkChat, n->T("Enable network chat", "Enable network chat")));
static const char *chatButtonPositions[] = { "Bottom Left", "Bottom Center","Bottom Right","Top Left","Top Center", "Top Right","Center Left","Center Right" };
networkingSettings->Add(new PopupMultiChoice(&g_Config.iChatButtonPosition, n->T("Chat Button Position"), chatButtonPositions, 0, ARRAY_SIZE(chatButtonPositions), "Chat Button Position", screenManager()))->SetEnabledPtr(&g_Config.bEnableNetworkChat);
static const char *chatScreenPositions[] = { "Bottom Left", "Bottom Center","Bottom Right","Top Left","Top Center", "Top Right" };
networkingSettings->Add(new PopupMultiChoice(&g_Config.iChatScreenPosition, n->T("Chat Screen Position"), chatScreenPositions, 0, ARRAY_SIZE(chatScreenPositions), "Chat Screen Position", screenManager()))->SetEnabledPtr(&g_Config.bEnableNetworkChat);
networkingSettings->Add(new ItemHeader(co->T("QuickChat", "Quick Chat")));
networkingSettings->Add(new CheckBox(&g_Config.bEnableQuickChat, co->T("QuickChat", "Enable Quick Chat")));
#if !defined(MOBILE_DEVICE) && !defined(USING_QT_UI) // TODO: Add all platforms where KEY_CHAR support is added
PopupTextInputChoice *qc1 = networkingSettings->Add(new PopupTextInputChoice(&g_Config.sQuickChat0, sy->T("Quick Chat 1"), "", 32, screenManager()));
qc1->SetEnabledPtr(&g_Config.bEnableQuickChat);
PopupTextInputChoice *qc2 = networkingSettings->Add(new PopupTextInputChoice(&g_Config.sQuickChat1, sy->T("Quick Chat 2"), "", 32, screenManager()));
qc2->SetEnabledPtr(&g_Config.bEnableQuickChat);
PopupTextInputChoice *qc3 = networkingSettings->Add(new PopupTextInputChoice(&g_Config.sQuickChat2, sy->T("Quick Chat 3"), "", 32, screenManager()));
qc3->SetEnabledPtr(&g_Config.bEnableQuickChat);
PopupTextInputChoice *qc4 = networkingSettings->Add(new PopupTextInputChoice(&g_Config.sQuickChat3, sy->T("Quick Chat 4"), "", 32, screenManager()));
qc4->SetEnabledPtr(&g_Config.bEnableQuickChat);
PopupTextInputChoice *qc5 = networkingSettings->Add(new PopupTextInputChoice(&g_Config.sQuickChat4, sy->T("Quick Chat 5"), "", 32, screenManager()));
qc5->SetEnabledPtr(&g_Config.bEnableQuickChat);
#elif defined(USING_QT_UI)
Choice *qc1 = networkingSettings->Add(new Choice(sy->T("Quick Chat 1")));
qc1->SetEnabledPtr(&g_Config.bEnableQuickChat);
qc1->OnClick.Handle(this, &GameSettingsScreen::OnChangeQuickChat0);
Choice *qc2 = networkingSettings->Add(new Choice(sy->T("Quick Chat 2")));
qc2->SetEnabledPtr(&g_Config.bEnableQuickChat);
qc2->OnClick.Handle(this, &GameSettingsScreen::OnChangeQuickChat1);
Choice *qc3 = networkingSettings->Add(new Choice(sy->T("Quick Chat 3")));
qc3->SetEnabledPtr(&g_Config.bEnableQuickChat);
qc3->OnClick.Handle(this, &GameSettingsScreen::OnChangeQuickChat2);
Choice *qc4 = networkingSettings->Add(new Choice(sy->T("Quick Chat 4")));
qc4->SetEnabledPtr(&g_Config.bEnableQuickChat);
qc4->OnClick.Handle(this, &GameSettingsScreen::OnChangeQuickChat3);
Choice *qc5 = networkingSettings->Add(new Choice(sy->T("Quick Chat 5")));
qc5->SetEnabledPtr(&g_Config.bEnableQuickChat);
qc5->OnClick.Handle(this, &GameSettingsScreen::OnChangeQuickChat4);
#elif defined(__ANDROID__)
ChoiceWithValueDisplay *qc1 = networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.sQuickChat0, sy->T("Quick Chat 1"), (const char *)nullptr));
qc1->OnClick.Handle(this, &GameSettingsScreen::OnChangeQuickChat0);
qc1->SetEnabledPtr(&g_Config.bEnableQuickChat);
ChoiceWithValueDisplay *qc2 = networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.sQuickChat1, sy->T("Quick Chat 2"), (const char *)nullptr));
qc2->OnClick.Handle(this, &GameSettingsScreen::OnChangeQuickChat1);
qc2->SetEnabledPtr(&g_Config.bEnableQuickChat);
ChoiceWithValueDisplay *qc3 = networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.sQuickChat2, sy->T("Quick Chat 3"), (const char *)nullptr));
qc3->OnClick.Handle(this, &GameSettingsScreen::OnChangeQuickChat2);
qc3->SetEnabledPtr(&g_Config.bEnableQuickChat);
ChoiceWithValueDisplay *qc4 = networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.sQuickChat3, sy->T("Quick Chat 4"), (const char *)nullptr));
qc4->OnClick.Handle(this, &GameSettingsScreen::OnChangeQuickChat3);
qc4->SetEnabledPtr(&g_Config.bEnableQuickChat);
ChoiceWithValueDisplay *qc5 = networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.sQuickChat4, sy->T("Quick Chat 5"), (const char *)nullptr));
qc5->OnClick.Handle(this, &GameSettingsScreen::OnChangeQuickChat4);
qc5->SetEnabledPtr(&g_Config.bEnableQuickChat);
#endif
ViewGroup *toolsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
toolsScroll->SetTag("GameSettingsTools");
LinearLayout *tools = new LinearLayout(ORIENT_VERTICAL);
@ -1233,6 +1287,86 @@ UI::EventReturn GameSettingsScreen::OnAudioDevice(UI::EventParams &e) {
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnChangeQuickChat0(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
const size_t chat_len = 64;
char chat[chat_len];
memset(chat, 0, sizeof(chat));
if (System_InputBoxGetString("Enter Quick Chat 1", g_Config.sQuickChat0.c_str(), chat, chat_len)) {
g_Config.sQuickChat0 = chat;
}
#elif defined(__ANDROID__)
System_SendMessage("inputbox", ("quickchat0:" + g_Config.sQuickChat0).c_str());
#endif
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnChangeQuickChat1(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
const size_t chat_len = 64;
char chat[chat_len];
memset(chat, 0, sizeof(chat));
if (System_InputBoxGetString("Enter Quick Chat 2", g_Config.sQuickChat1.c_str(), chat, chat_len)) {
g_Config.sQuickChat1 = chat;
}
#elif defined(__ANDROID__)
System_SendMessage("inputbox", ("quickchat1:" + g_Config.sQuickChat1).c_str());
#endif
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnChangeQuickChat2(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
const size_t chat_len = 64;
char chat[chat_len];
memset(chat, 0, sizeof(chat));
if (System_InputBoxGetString("Enter Quick Chat 3", g_Config.sQuickChat2.c_str(), chat, chat_len)) {
g_Config.sQuickChat2 = chat;
}
#elif defined(__ANDROID__)
System_SendMessage("inputbox", ("quickchat2:" + g_Config.sQuickChat2).c_str());
#endif
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnChangeQuickChat3(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
const size_t chat_len = 64;
char chat[chat_len];
memset(chat, 0, sizeof(chat));
if (System_InputBoxGetString("Enter Quick Chat 4", g_Config.sQuickChat3.c_str(), chat, chat_len)) {
g_Config.sQuickChat3 = chat;
}
#elif defined(__ANDROID__)
System_SendMessage("inputbox", ("quickchat3:" + g_Config.sQuickChat3).c_str());
#endif
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnChangeQuickChat4(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
const size_t chat_len = 64;
char chat[chat_len];
memset(chat, 0, sizeof(chat));
if (System_InputBoxGetString("Enter Quick Chat 5", g_Config.sQuickChat4.c_str(), chat, chat_len)) {
g_Config.sQuickChat4 = chat;
}
#elif defined(__ANDROID__)
System_SendMessage("inputbox", ("quickchat4:" + g_Config.sQuickChat4).c_str());
#endif
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnChangeNickname(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
const size_t name_len = 256;

View File

@ -83,6 +83,11 @@ private:
UI::EventReturn OnPostProcShaderChange(UI::EventParams &e);
UI::EventReturn OnDeveloperTools(UI::EventParams &e);
UI::EventReturn OnRemoteISO(UI::EventParams &e);
UI::EventReturn OnChangeQuickChat0(UI::EventParams &e);
UI::EventReturn OnChangeQuickChat1(UI::EventParams &e);
UI::EventReturn OnChangeQuickChat2(UI::EventParams &e);
UI::EventReturn OnChangeQuickChat3(UI::EventParams &e);
UI::EventReturn OnChangeQuickChat4(UI::EventParams &e);
UI::EventReturn OnChangeNickname(UI::EventParams &e);
UI::EventReturn OnChangeproAdhocServerAddress(UI::EventParams &e);
UI::EventReturn OnChangeMacAddress(UI::EventParams &e);

View File

@ -86,6 +86,7 @@
#include "Core/HLE/sceCtrl.h"
#include "Core/HLE/sceUsbCam.h"
#include "Core/HLE/sceUsbGps.h"
#include "Core/HLE/proAdhoc.h"
#include "Core/Util/GameManager.h"
#include "Core/Util/AudioFormat.h"
#include "Core/WebServer.h"
@ -1103,6 +1104,29 @@ void HandleGlobalMessage(const std::string &msg, const std::string &value) {
g_Config.sRemoteISOSubdir = setString;
else if (inputboxValue[0] == "remoteiso_server")
g_Config.sLastRemoteISOServer = setString;
if (inputboxValue[0] == "quickchat0")
g_Config.sQuickChat0 = setString;
if (inputboxValue[0] == "quickchat1")
g_Config.sQuickChat1 = setString;
if (inputboxValue[0] == "quickchat2")
g_Config.sQuickChat2 = setString;
if (inputboxValue[0] == "quickchat3")
g_Config.sQuickChat3 = setString;
if (inputboxValue[0] == "quickchat4")
g_Config.sQuickChat4 = setString;
if (inputboxValue[0] == "nickname")
g_Config.sNickName = setString;
if (inputboxValue[0] == "Chat") {
if (inputboxValue.size() > 2)
{
std::string chatString = value;
chatString.erase(0, 5);
sendChat(chatString);
} else {
sendChat(setString);
}
}
inputboxValue.clear();
}
if (msg == "bgImage_updated") {

View File

@ -36,6 +36,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="BackgroundAudio.cpp" />
<ClCompile Include="ChatScreen.cpp" />
<ClCompile Include="ComboKeyMappingScreen.cpp" />
<ClCompile Include="ControlMappingScreen.cpp" />
<ClCompile Include="CwCheatScreen.cpp" />
@ -68,6 +69,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="BackgroundAudio.h" />
<ClInclude Include="ChatScreen.h" />
<ClInclude Include="ComboKeyMappingScreen.h" />
<ClInclude Include="ControlMappingScreen.h" />
<ClInclude Include="DevScreens.h" />

View File

@ -73,6 +73,9 @@
<ClCompile Include="GPUDriverTestScreen.cpp">
<Filter>Screens</Filter>
</ClCompile>
<ClCompile Include="ChatScreen.cpp">
<Filter>Screens</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GameInfoCache.h" />
@ -147,6 +150,9 @@
<ClInclude Include="GPUDriverTestScreen.h">
<Filter>Screens</Filter>
</ClInclude>
<ClInclude Include="ChatScreen.h">
<Filter>Screens</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Screens">

View File

@ -329,6 +329,7 @@ namespace MainWindow {
TranslateMenuItem(menu, ID_OPTIONS_SHOWFPS);
TranslateMenuItem(menu, ID_EMULATION_SOUND);
TranslateMenuItem(menu, ID_EMULATION_CHEATS, L"\tCtrl+T");
TranslateMenuItem(menu, ID_EMULATION_CHAT, L"\tCtrl+C");
// Help menu: it's translated in CreateHelpMenu.
CreateHelpMenu(menu);
@ -628,7 +629,11 @@ namespace MainWindow {
g_Config.bEnableCheats = !g_Config.bEnableCheats;
osm.ShowOnOff(gr->T("Cheats"), g_Config.bEnableCheats);
break;
case ID_EMULATION_CHAT:
if (GetUIState() == UISTATE_INGAME) {
NativeMessageReceived("chat screen", "");
}
break;
case ID_FILE_LOADSTATEFILE:
if (W32Util::BrowseForFileName(true, hWnd, L"Load state", 0, L"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0", L"ppst", fn)) {
SetCursor(LoadCursor(0, IDC_WAIT));

View File

@ -68,6 +68,7 @@ BEGIN
"W", ID_EMULATION_STOP, VIRTKEY, CONTROL, NOINVERT
"B", ID_EMULATION_RESET, VIRTKEY, CONTROL, NOINVERT
"T", ID_EMULATION_CHEATS, VIRTKEY, CONTROL, NOINVERT
"C", ID_EMULATION_CHAT, VIRTKEY, CONTROL, NOINVERT
"D", ID_DEBUG_DISASSEMBLY, VIRTKEY, CONTROL, NOINVERT
"G", ID_DEBUG_GEDEBUGGER, VIRTKEY, CONTROL, NOINVERT
"L", ID_DEBUG_LOG, VIRTKEY, CONTROL, NOINVERT
@ -648,6 +649,7 @@ BEGIN
MENUITEM "Enable Sound", ID_EMULATION_SOUND
MENUITEM "", 0, MFT_SEPARATOR
MENUITEM "Enable Cheats", ID_EMULATION_CHEATS
MENUITEM "Enable Chat", ID_EMULATION_CHAT
END
POPUP "Help", ID_HELP_MENU

View File

@ -370,6 +370,7 @@
#define IDC_GEDBG_STEPCOUNT_JUMP 40202
#define IDC_GEDBG_STEPCOUNT_COMBO 40203
#define ID_FILE_DUMP_VIDEO_OUTPUT 40204
#define ID_EMULATION_CHAT 40205
// Dummy option to let the buffered rendering hotkey cycle through all the options.
#define ID_OPTIONS_BUFFEREDRENDERINGDUMMY 40500

View File

@ -494,6 +494,7 @@ LOCAL_SRC_FILES := \
$(SRC)/android/jni/native-audio-so.cpp \
$(SRC)/UI/BackgroundAudio.cpp \
$(SRC)/UI/DiscordIntegration.cpp \
$(SRC)/UI/ChatScreen.cpp \
$(SRC)/UI/DevScreens.cpp \
$(SRC)/UI/DisplayLayoutEditor.cpp \
$(SRC)/UI/DisplayLayoutScreen.cpp \