Reset script panes on character swap
This commit is contained in:
parent
35fc2679de
commit
224ad2c2c0
@ -510,10 +510,23 @@ void ClientApplication::changeState(MainAppState newState) {
|
||||
m_universeClient->setLuaCallbacks("input", LuaBindings::makeInputCallbacks());
|
||||
m_universeClient->setLuaCallbacks("voice", LuaBindings::makeVoiceCallbacks());
|
||||
|
||||
m_universeClient->playerReloadCallback() = [&]() {
|
||||
if (auto paneManager = m_mainInterface->paneManager()) {
|
||||
if (auto inventory = paneManager->registeredPane<InventoryPane>(MainInterfacePanes::Inventory))
|
||||
inventory->clearChangedSlots();
|
||||
auto heldScriptPanes = make_shared<List<MainInterface::ScriptPaneInfo>>();
|
||||
|
||||
m_universeClient->playerReloadPreCallback() = [&, heldScriptPanes](bool resetInterface) {
|
||||
if (!resetInterface)
|
||||
return;
|
||||
|
||||
m_mainInterface->takeScriptPanes(*heldScriptPanes);
|
||||
};
|
||||
|
||||
m_universeClient->playerReloadCallback() = [&, heldScriptPanes](bool resetInterface) {
|
||||
auto paneManager = m_mainInterface->paneManager();
|
||||
if (auto inventory = paneManager->registeredPane<InventoryPane>(MainInterfacePanes::Inventory))
|
||||
inventory->clearChangedSlots();
|
||||
|
||||
if (resetInterface) {
|
||||
m_mainInterface->reviveScriptPanes(*heldScriptPanes);
|
||||
heldScriptPanes->clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
namespace Star {
|
||||
|
||||
BaseScriptPane::BaseScriptPane(Json config) : Pane() {
|
||||
BaseScriptPane::BaseScriptPane(Json config) : Pane(), m_rawConfig(config) {
|
||||
auto& root = Root::singleton();
|
||||
auto assets = root.assets();
|
||||
|
||||
@ -97,6 +97,9 @@ bool BaseScriptPane::sendEvent(InputEvent const& event) {
|
||||
return Pane::sendEvent(event);
|
||||
}
|
||||
|
||||
Json const& BaseScriptPane::config() const { return m_config; }
|
||||
Json const& BaseScriptPane::rawConfig() const { return m_rawConfig; }
|
||||
|
||||
PanePtr BaseScriptPane::createTooltip(Vec2I const& screenPosition) {
|
||||
auto result = m_script.invoke<Json>("createTooltip", screenPosition);
|
||||
if (result && !result.value().isNull()) {
|
||||
|
@ -25,12 +25,16 @@ public:
|
||||
void tick(float dt) override;
|
||||
|
||||
bool sendEvent(InputEvent const& event) override;
|
||||
|
||||
Json const& config() const;
|
||||
Json const& rawConfig() const;
|
||||
|
||||
PanePtr createTooltip(Vec2I const& screenPosition) override;
|
||||
Maybe<String> cursorOverride(Vec2I const& screenPosition) override;
|
||||
protected:
|
||||
virtual GuiReaderPtr reader();
|
||||
Json m_config;
|
||||
Json m_rawConfig;
|
||||
|
||||
GuiReaderPtr m_reader;
|
||||
|
||||
|
@ -498,22 +498,8 @@ void MainInterface::handleInteractAction(InteractAction interactAction) {
|
||||
m_paneManager.dismissPane(m_interactionScriptPanes[sourceEntity]);
|
||||
|
||||
ScriptPanePtr scriptPane = make_shared<ScriptPane>(m_client, interactAction.data, sourceEntity);
|
||||
// keep any number of script panes open with null source entities
|
||||
if (sourceEntity != NullEntityId)
|
||||
m_interactionScriptPanes[sourceEntity] = scriptPane;
|
||||
displayScriptPane(scriptPane, sourceEntity);
|
||||
|
||||
if (scriptPane->openWithInventory()) {
|
||||
m_paneManager.displayPane(PaneLayer::Window, scriptPane, [this](PanePtr const&) {
|
||||
if (auto player = m_client->mainPlayer())
|
||||
player->clearSwap();
|
||||
m_paneManager.dismissRegisteredPane(MainInterfacePanes::Inventory);
|
||||
});
|
||||
m_paneManager.displayRegisteredPane(MainInterfacePanes::Inventory);
|
||||
m_paneManager.bringPaneAdjacent(m_paneManager.registeredPane(MainInterfacePanes::Inventory),
|
||||
scriptPane, Root::singleton().assets()->json("/interface.config:bringAdjacentWindowGap").toFloat());
|
||||
} else {
|
||||
m_paneManager.displayPane(PaneLayer::Window, scriptPane);
|
||||
}
|
||||
} else if (interactAction.type == InteractActionType::Message) {
|
||||
m_client->mainPlayer()->receiveMessage(connectionForEntity(interactAction.entityId),
|
||||
interactAction.data.getString("messageType"), interactAction.data.getArray("messageArgs"));
|
||||
@ -952,6 +938,38 @@ CanvasWidgetPtr MainInterface::fetchCanvas(String const& canvasName, bool ignore
|
||||
return canvas;
|
||||
}
|
||||
|
||||
// For when the player swaps characters. We need to completely reload ScriptPanes,
|
||||
// because a lot of ScriptPanes do not expect the character to suddenly change and may break or spill data over.
|
||||
void MainInterface::takeScriptPanes(List<ScriptPaneInfo>& out) {
|
||||
m_paneManager.dismissWhere([&](PanePtr const& pane) {
|
||||
if (auto scriptPane = as<ScriptPane>(pane)) {
|
||||
if (scriptPane->isDismissed())
|
||||
return false;
|
||||
auto sourceEntityId = scriptPane->sourceEntityId();
|
||||
m_interactionScriptPanes.remove(sourceEntityId);
|
||||
auto& info = out.emplaceAppend();
|
||||
info.scriptPane = scriptPane;
|
||||
info.config = scriptPane->rawConfig();
|
||||
info.sourceEntityId = sourceEntityId;
|
||||
info.visible = scriptPane->visibility();
|
||||
info.position = scriptPane->relativePosition();
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void MainInterface::reviveScriptPanes(List<ScriptPaneInfo>& panes) {
|
||||
for (auto& info : panes) { // this is evil and stupid
|
||||
info.scriptPane->~ScriptPane();
|
||||
new(info.scriptPane.get()) ScriptPane(m_client, info.config, info.sourceEntityId);
|
||||
info.scriptPane->setVisibility(info.visible);
|
||||
displayScriptPane(info.scriptPane, info.sourceEntityId);
|
||||
info.scriptPane->setPosition(info.position);
|
||||
}
|
||||
}
|
||||
|
||||
PanePtr MainInterface::createEscapeDialog() {
|
||||
auto assets = Root::singleton().assets();
|
||||
|
||||
@ -1542,4 +1560,23 @@ bool MainInterface::overlayClick(Vec2I const& mousePos, MouseButton mouseButton)
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainInterface::displayScriptPane(ScriptPanePtr& scriptPane, EntityId sourceEntity) {
|
||||
// keep any number of script panes open with null source entities
|
||||
if (sourceEntity != NullEntityId)
|
||||
m_interactionScriptPanes[sourceEntity] = scriptPane;
|
||||
|
||||
if (scriptPane->openWithInventory()) {
|
||||
m_paneManager.displayPane(PaneLayer::Window, scriptPane, [this](PanePtr const&) {
|
||||
if (auto player = m_client->mainPlayer())
|
||||
player->clearSwap();
|
||||
m_paneManager.dismissRegisteredPane(MainInterfacePanes::Inventory);
|
||||
});
|
||||
m_paneManager.displayRegisteredPane(MainInterfacePanes::Inventory);
|
||||
m_paneManager.bringPaneAdjacent(m_paneManager.registeredPane(MainInterfacePanes::Inventory),
|
||||
scriptPane, Root::singleton().assets()->json("/interface.config:bringAdjacentWindowGap").toFloat());
|
||||
} else {
|
||||
m_paneManager.displayPane(PaneLayer::Window, scriptPane);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -119,6 +119,16 @@ public:
|
||||
|
||||
CanvasWidgetPtr fetchCanvas(String const& canvasName, bool ignoreInterfaceScale = false);
|
||||
|
||||
struct ScriptPaneInfo {
|
||||
ScriptPanePtr scriptPane;
|
||||
Json config;
|
||||
EntityId sourceEntityId;
|
||||
bool visible;
|
||||
Vec2I position;
|
||||
};
|
||||
|
||||
void takeScriptPanes(List<ScriptPaneInfo>& out);
|
||||
void reviveScriptPanes(List<ScriptPaneInfo>& panes);
|
||||
private:
|
||||
PanePtr createEscapeDialog();
|
||||
|
||||
@ -142,6 +152,8 @@ private:
|
||||
|
||||
bool overlayClick(Vec2I const& mousePos, MouseButton mouseButton);
|
||||
|
||||
void displayScriptPane(ScriptPanePtr& scriptPane, EntityId sourceEntity);
|
||||
|
||||
GuiContext* m_guiContext;
|
||||
MainInterfaceConfigConstPtr m_config;
|
||||
InterfaceCursor m_cursor;
|
||||
|
@ -88,4 +88,8 @@ bool ScriptPane::openWithInventory() const {
|
||||
return m_config.getBool("openWithInventory", false);
|
||||
}
|
||||
|
||||
EntityId ScriptPane::sourceEntityId() const {
|
||||
return m_sourceEntityId;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ public:
|
||||
|
||||
bool openWithInventory() const;
|
||||
|
||||
EntityId sourceEntityId() const;
|
||||
|
||||
LuaCallbacks makePaneCallbacks() override;
|
||||
private:
|
||||
UniverseClientPtr m_client;
|
||||
|
@ -477,7 +477,7 @@ void UniverseClient::stopLua() {
|
||||
m_scriptContexts.clear();
|
||||
}
|
||||
|
||||
bool UniverseClient::reloadPlayer(Json const& data, Uuid const& uuid) {
|
||||
bool UniverseClient::reloadPlayer(Json const& data, Uuid const& uuid, bool resetInterfaces) {
|
||||
auto player = mainPlayer();
|
||||
bool playerInWorld = player->inWorld();
|
||||
auto world = as<WorldClient>(player->world());
|
||||
@ -487,7 +487,7 @@ bool UniverseClient::reloadPlayer(Json const& data, Uuid const& uuid) {
|
||||
: connectionEntitySpace(world->connection()).first;
|
||||
|
||||
if (m_playerReloadPreCallback)
|
||||
m_playerReloadPreCallback();
|
||||
m_playerReloadPreCallback(resetInterfaces);
|
||||
|
||||
if (playerInWorld) {
|
||||
world->removeEntity(player->entityId(), false);
|
||||
@ -515,7 +515,7 @@ bool UniverseClient::reloadPlayer(Json const& data, Uuid const& uuid) {
|
||||
player->universeMap()->filterMappedObjects(coordinate, m_systemWorldClient->objectKeys());
|
||||
|
||||
if (m_playerReloadCallback)
|
||||
m_playerReloadCallback();
|
||||
m_playerReloadCallback(resetInterfaces);
|
||||
|
||||
if (exception)
|
||||
std::rethrow_exception(exception);
|
||||
@ -527,7 +527,7 @@ bool UniverseClient::switchPlayer(Uuid const& uuid) {
|
||||
if (uuid == mainPlayer()->uuid())
|
||||
return false;
|
||||
else if (auto data = m_playerStorage->maybeGetPlayerData(uuid))
|
||||
return reloadPlayer(*data, uuid);
|
||||
return reloadPlayer(*data, uuid, true);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@ -546,11 +546,11 @@ bool UniverseClient::switchPlayer(String const& name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UniverseClient::Callback& UniverseClient::playerReloadPreCallback() {
|
||||
UniverseClient::ReloadPlayerCallback& UniverseClient::playerReloadPreCallback() {
|
||||
return m_playerReloadPreCallback;
|
||||
}
|
||||
|
||||
UniverseClient::Callback& UniverseClient::playerReloadCallback() {
|
||||
UniverseClient::ReloadPlayerCallback& UniverseClient::playerReloadCallback() {
|
||||
return m_playerReloadCallback;
|
||||
}
|
||||
|
||||
|
@ -91,14 +91,15 @@ public:
|
||||
void startLua();
|
||||
void stopLua();
|
||||
|
||||
bool reloadPlayer(Json const& data, Uuid const& uuid);
|
||||
bool reloadPlayer(Json const& data, Uuid const& uuid, bool resetInterfaces = false);
|
||||
bool switchPlayer(Uuid const& uuid);
|
||||
bool switchPlayer(size_t index);
|
||||
bool switchPlayer(String const& name);
|
||||
|
||||
typedef std::function<void()> Callback;
|
||||
Callback& playerReloadPreCallback();
|
||||
Callback& playerReloadCallback();
|
||||
typedef std::function<void(bool)> ReloadPlayerCallback;
|
||||
ReloadPlayerCallback& playerReloadPreCallback();
|
||||
ReloadPlayerCallback& playerReloadCallback();
|
||||
|
||||
ClockConstPtr universeClock() const;
|
||||
CelestialLogConstPtr celestialLog() const;
|
||||
@ -161,8 +162,8 @@ private:
|
||||
typedef shared_ptr<ScriptComponent> ScriptComponentPtr;
|
||||
StringMap<ScriptComponentPtr> m_scriptContexts;
|
||||
|
||||
Callback m_playerReloadPreCallback;
|
||||
Callback m_playerReloadCallback;
|
||||
ReloadPlayerCallback m_playerReloadPreCallback;
|
||||
ReloadPlayerCallback m_playerReloadCallback;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -128,6 +128,23 @@ void PaneManager::setBackgroundWidget(WidgetPtr bg) {
|
||||
m_backgroundWidget = bg;
|
||||
}
|
||||
|
||||
void PaneManager::dismissWhere(function<bool(PanePtr const&)> func) {
|
||||
if (!func)
|
||||
return;
|
||||
|
||||
for (auto& layerPair : m_displayedPanes) {
|
||||
eraseWhere(layerPair.second, [&](auto& panePair) {
|
||||
if (func(panePair.first)) {
|
||||
panePair.first->dismissed();
|
||||
if (panePair.second)
|
||||
panePair.second(panePair.first);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
PanePtr PaneManager::keyboardCapturedPane() const {
|
||||
for (auto const& layerPair : m_displayedPanes) {
|
||||
for (auto const& panePair : layerPair.second) {
|
||||
|
@ -63,6 +63,8 @@ public:
|
||||
|
||||
void setBackgroundWidget(WidgetPtr bg);
|
||||
|
||||
void dismissWhere(function<bool(PanePtr const&)> func);
|
||||
|
||||
// Returns the pane that has captured the keyboard, if any.
|
||||
PanePtr keyboardCapturedPane() const;
|
||||
// Returns true if the current pane that has captured the keyboard is
|
||||
|
@ -219,6 +219,10 @@ void Widget::hide() {
|
||||
m_visible = false;
|
||||
}
|
||||
|
||||
bool Widget::visibility() const {
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
void Widget::toggleVisibility() {
|
||||
m_visible = !m_visible;
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
|
||||
virtual void show();
|
||||
virtual void hide();
|
||||
virtual bool visibility() const;
|
||||
virtual void toggleVisibility();
|
||||
virtual void setVisibility(bool visibility);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user