diff --git a/apps/openmw-mp/CMakeLists.txt b/apps/openmw-mp/CMakeLists.txt index 0cbec0f67..8a7a3cda2 100644 --- a/apps/openmw-mp/CMakeLists.txt +++ b/apps/openmw-mp/CMakeLists.txt @@ -57,6 +57,7 @@ set(SERVER CellState.cpp Object.cpp stacktrace.cpp + Window.cpp Script/CommandController.cpp Script/EventController.cpp Script/LuaState.cpp Script/luaUtils.cpp ) @@ -95,7 +96,7 @@ set(PROCESSORS_PLAYER processors/player/ProcessorPlayerResurrect.hpp processors/player/ProcessorPlayerShapeshift.hpp processors/player/ProcessorPlayerSkill.hpp processors/player/ProcessorPlayerSpeech.hpp processors/player/ProcessorPlayerSpellbook.hpp processors/player/ProcessorPlayerStatsDynamic.hpp - processors/player/ProcessorPlayerTopic.hpp + processors/player/ProcessorPlayerTopic.hpp processors/player/ProcessorGUIWindow.hpp ) source_group(tes3mp-server\\processors\\player FILES ${PROCESSORS_PLAYER}) diff --git a/apps/openmw-mp/GUI.cpp b/apps/openmw-mp/GUI.cpp index 6182fa37e..f7ef25fc4 100644 --- a/apps/openmw-mp/GUI.cpp +++ b/apps/openmw-mp/GUI.cpp @@ -3,11 +3,9 @@ // #include - -#include "Networking.hpp" - #include "GUI.hpp" #include "Player.hpp" +#include "Networking.hpp" void GUI::Init(LuaState &lua) { @@ -18,8 +16,11 @@ void GUI::Init(LuaState &lua) "passwordDialog", &GUI::passwordDialog, "listBox", &GUI::listBox, "setMapVisibility", &GUI::setMapVisibility, - "setMapVisibilityAll", &GUI::setMapVisibilityAll + "setMapVisibilityAll", &GUI::setMapVisibilityAll, + "createWindow", &GUI::createWindow, + "deleteWindow", &GUI::deleteWindow ); + Window::Init(lua); } GUI::GUI(Player *player): player(player), changed(false) @@ -100,3 +101,45 @@ void GUI::setMapVisibilityAll(unsigned short targetPID, unsigned short state) { LOG_MESSAGE(Log::LOG_WARN, "stub"); } + +std::shared_ptr GUI::createWindow(short x, short y, sol::function fn, sol::this_environment te) +{ + int id = 0; + + for(auto &window : windows) + { + if(window.second == nullptr) + { + id = window.first; + break; + } + } + + if(id == 0) + id = lastWindowId++; + + auto window = std::make_shared(player, id); + window->setSize(x, y); + window->setCallback(fn); + + windows[id] = window; + return window; +} + +void GUI::deleteWindow(std::shared_ptr window) +{ + auto it = windows.find(window->getID()); + if(it != windows.end()) + { + it->second = nullptr; + } +} + +void GUI::onGUIWindowAction() +{ + auto it = windows.find(player->guiWindow.id); + if(it != windows.end() && it->second != nullptr) + { + it->second->call(player->guiWindow); + } +} diff --git a/apps/openmw-mp/GUI.hpp b/apps/openmw-mp/GUI.hpp index 4a8ec984c..d059e7b1a 100644 --- a/apps/openmw-mp/GUI.hpp +++ b/apps/openmw-mp/GUI.hpp @@ -4,6 +4,8 @@ #pragma once +#include "Window.hpp" + class LuaState; class Player; @@ -28,9 +30,15 @@ public: //state 0 - disallow, 1 - allow void setMapVisibility(unsigned short targetPID, unsigned short affectedPID, unsigned short state); void setMapVisibilityAll(unsigned short targetPID, unsigned short state); + + std::shared_ptr createWindow(short x, short y, sol::function fn, sol::this_environment te); + void deleteWindow(std::shared_ptr window); + void onGUIWindowAction(); private: Player *player; bool changed; + std::unordered_map> windows; + int lastWindowId; }; diff --git a/apps/openmw-mp/Window.cpp b/apps/openmw-mp/Window.cpp new file mode 100644 index 000000000..2e5324167 --- /dev/null +++ b/apps/openmw-mp/Window.cpp @@ -0,0 +1,215 @@ +// +// Created by koncord on 21.11.17. +// + +#include +#include "Player.hpp" +#include "Window.hpp" +#include "Networking.hpp" + +using namespace std; +using namespace mwmp; + +void Window::Init(LuaState &lua) +{ + lua.getState()->new_usertype("Window", + "addButton", &Window::addButton, + "addLabel", &Window::addLabel, + "addEditBox", &Window::addEditBox, + "addPassiveListBox", &Window::addPassiveListBox, + "addActiveListBox", &Window::addActiveListBox, + "addSlider", &Window::addSlider, + "show", &Window::show, + "clear", &Window::clear, + "setCallback", &Window::setCallback + + ); +} + +Window::Window(Player *player, int id) : player(player) +{ + guiWindow.id = id; +} + +Window::~Window() +{ + +} + +void Window::show() +{ + printf("Trying to show window: %d\n", guiWindow.id); + if (guiWindow.widgets.empty()) + return; + + auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_WINDOW); + + player->guiWindow = guiWindow; + + packet->setPlayer(player); + packet->Send(false); +} + +void Window::clear() +{ + guiWindow.widgets.clear(); +} + +int Window::getID() +{ + return guiWindow.id; +} + +void Window::call(const BasePlayer::GUIWindow &window) +{ + sol::table table = Networking::get().getState().getState()->create_table(); + + auto fnTypeToStr = [](const BasePlayer::GUIWindow::WidgetType &type) { + switch (type) + { + + case BasePlayer::GUIWindow::WidgetType::Button: + return "Button"; + case BasePlayer::GUIWindow::WidgetType::Editbox: + return "Editbox"; + case BasePlayer::GUIWindow::WidgetType::Label: + return "Label"; + case BasePlayer::GUIWindow::WidgetType::ListBoxActive: + return "ListBoxActive"; + case BasePlayer::GUIWindow::WidgetType::ListBoxPassive: + return "ListBoxPassive"; + case BasePlayer::GUIWindow::WidgetType::Slider: + return "Slider"; + } + }; + + for (const auto &widget : window.widgets) + { + + sol::table w = table.create(widget.name); + + w.add(fnTypeToStr(widget.type)); + if (!widget.data.empty()) + w.add(widget.data[0]); + } + callback.call(this, player, table); +} + +void Window::setCallback(sol::function callback) +{ + /*int id = 0; + for(auto &&cb : callbacks) + { + if(cb.second.get() == nullptr) + id = cb.first; + } + if(id == 0) + id = lastId++; + callbacks[id] = make_unique(callback);*/ + this->callback = callback; +} + +void Window::setSize(short width, short height) +{ + guiWindow.width = width; + guiWindow.height = height; +} + +void Window::addButton(short x, short y, const std::string &label, sol::optional active) +{ + BasePlayer::GUIWindow::Widget widget; + widget.posX = x; + widget.posY = y; + widget.name = label; + widget.type = BasePlayer::GUIWindow::WidgetType::Button; + if(active) + widget.disabled = !active.value(); + else + widget.disabled = false; + guiWindow.widgets.push_back(widget); +} + +void Window::addEditBox(short x, short y, short w, short h, const std::string &id, sol::optional active) +{ + BasePlayer::GUIWindow::Widget widget; + widget.posX = x; + widget.posY = y; + widget.width = w; + widget.height = h; + widget.name = id; + widget.type = BasePlayer::GUIWindow::WidgetType::Editbox; + if(active) + widget.disabled = !active.value(); + else + widget.disabled = false; + guiWindow.widgets.push_back(widget); +} + +void Window::addLabel(short x, short y, const std::string &label) +{ + BasePlayer::GUIWindow::Widget widget; + widget.posX = x; + widget.posY = y; + widget.name = label; + widget.type = BasePlayer::GUIWindow::WidgetType::Label; + guiWindow.widgets.push_back(widget); +} + +void Window::addPassiveListBox(short x, short y, short w, short h, const std::string &id, sol::table data, + sol::optional active) +{ + BasePlayer::GUIWindow::Widget widget; + widget.posX = x; + widget.posY = y; + widget.width = w; + widget.height = h; + widget.name = id; + widget.type = BasePlayer::GUIWindow::WidgetType::ListBoxPassive; + + if(active) + widget.disabled = !active.value(); + else + widget.disabled = false; + + for (const auto &item : data) + widget.data.push_back(item.second.as()); + + guiWindow.widgets.push_back(widget); +} + +void Window::addActiveListBox(short x, short y, short w, short h, const std::string &id, sol::table data, + sol::optional active) +{ + BasePlayer::GUIWindow::Widget widget; + widget.posX = x; + widget.posY = y; + widget.width = w; + widget.height = h; + widget.name = id; + widget.type = BasePlayer::GUIWindow::WidgetType::ListBoxActive; + if(active) + widget.disabled = !active.value(); + else + widget.disabled = false; + + for (const auto &item : data) + widget.data.push_back(item.second.as()); + + guiWindow.widgets.push_back(widget); +} + +void Window::addSlider(short x, short y, short w, short h, const std::string &id, sol::optional active) +{ + BasePlayer::GUIWindow::Widget widget; + widget.posX = x; + widget.posY = y; + widget.width = w; + widget.height = h; + widget.name = id; + widget.type = BasePlayer::GUIWindow::WidgetType::Slider; + if(active) + widget.disabled = !active.value(); + else + widget.disabled = false; + guiWindow.widgets.push_back(widget); +} diff --git a/apps/openmw-mp/Window.hpp b/apps/openmw-mp/Window.hpp new file mode 100644 index 000000000..c655088c1 --- /dev/null +++ b/apps/openmw-mp/Window.hpp @@ -0,0 +1,45 @@ +// +// Created by koncord on 21.11.17. +// + +#pragma once + +#include +#include + +class Player; + +class Window +{ +public: + static void Init(LuaState &lua); +public: + Window(Player *player, int id); + ~Window(); + + + void setSize(short x, short y); + void setCallback(sol::function); + + int getID(); + + void show(); + void clear(); + + void call(const mwmp::BasePlayer::GUIWindow &window); + + void addButton(short x, short y, const std::string &label, sol::optional active); + void addLabel(short x, short y, const std::string &label); + void addEditBox(short x, short y, short w, short h, const std::string &id, sol::optional active); + void addPassiveListBox(short x, short y, short w, short h,const std::string &id, sol::table data, sol::optional active); + void addActiveListBox(short x, short y, short w, short h,const std::string &id, sol::table data, sol::optional active); + void addSlider(short x, short y, short w, short h,const std::string &id, sol::optional active); +private: + Player *player; + bool changed; + + sol::function callback; + mwmp::BasePlayer::GUIWindow guiWindow; +}; + + diff --git a/apps/openmw-mp/processors/ProcessorInitializer.cpp b/apps/openmw-mp/processors/ProcessorInitializer.cpp index 95bb57224..2eba8e4a1 100644 --- a/apps/openmw-mp/processors/ProcessorInitializer.cpp +++ b/apps/openmw-mp/processors/ProcessorInitializer.cpp @@ -9,6 +9,7 @@ #include "PlayerProcessor.hpp" #include "player/ProcessorChatMsg.hpp" #include "player/ProcessorGUIMessageBox.hpp" +#include "player/ProcessorGUIWindow.hpp" #include "player/ProcessorGameWeather.hpp" #include "player/ProcessorPlayerCharGen.hpp" #include "player/ProcessorPlayerAnimFlags.hpp" @@ -78,6 +79,7 @@ void ProcessorInitializer() { PlayerProcessor::AddProcessor(new ProcessorChatMsg()); PlayerProcessor::AddProcessor(new ProcessorGUIMessageBox()); + PlayerProcessor::AddProcessor(new ProcessorGUIWindow()); PlayerProcessor::AddProcessor(new ProcessorGameWeather()); PlayerProcessor::AddProcessor(new ProcessorPlayerCharGen()); PlayerProcessor::AddProcessor(new ProcessorPlayerAnimFlags()); diff --git a/apps/openmw-mp/processors/player/ProcessorGUIWindow.hpp b/apps/openmw-mp/processors/player/ProcessorGUIWindow.hpp new file mode 100644 index 000000000..05c7845db --- /dev/null +++ b/apps/openmw-mp/processors/player/ProcessorGUIWindow.hpp @@ -0,0 +1,28 @@ +// +// Created by koncord on 23.11.17. +// + +#pragma once + +#include "../PlayerProcessor.hpp" + +namespace mwmp +{ + + class ProcessorGUIWindow : public PlayerProcessor + { + public: + ProcessorGUIWindow() + { + BPP_INIT(ID_GUI_WINDOW) + } + + void Do(PlayerPacket &packet, std::shared_ptr player) override + { + DEBUG_PRINTF(strPacketID.c_str()); + + player->getGUI().onGUIWindowAction(); + } + }; +} +