Initial voice HUD indicator setup
This commit is contained in:
parent
848b11399f
commit
34bb0b5422
@ -1,4 +1,6 @@
|
|||||||
{
|
{
|
||||||
|
"universeScriptContexts" : { "opensb" : ["/scripts/universeClient/opensb.lua"] },
|
||||||
|
|
||||||
// Disables scissoring and letterboxing on vanilla and modded warp cinematics
|
// Disables scissoring and letterboxing on vanilla and modded warp cinematics
|
||||||
"warpCinematicBase" : {
|
"warpCinematicBase" : {
|
||||||
"scissor" : false,
|
"scissor" : false,
|
||||||
|
BIN
assets/opensb/interface/voicechat/indicator/back.png
Normal file
BIN
assets/opensb/interface/voicechat/indicator/back.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 611 B |
BIN
assets/opensb/interface/voicechat/indicator/front.png
Normal file
BIN
assets/opensb/interface/voicechat/indicator/front.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/opensb/interface/voicechat/indicator/front_muted.png
Normal file
BIN
assets/opensb/interface/voicechat/indicator/front_muted.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
29
assets/opensb/scripts/universeClient/opensb.lua
Normal file
29
assets/opensb/scripts/universeClient/opensb.lua
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
submodules = {}
|
||||||
|
|
||||||
|
require "/scripts/universeClient/opensb/voice_manager.lua"
|
||||||
|
|
||||||
|
local submodules, type = submodules, type
|
||||||
|
local function call(func, ...)
|
||||||
|
if type(func) == "function" then
|
||||||
|
return func(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function init(...)
|
||||||
|
script.setUpdateDelta(1)
|
||||||
|
for i, module in pairs(submodules) do
|
||||||
|
call(module.init, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function update(...)
|
||||||
|
for i, module in pairs(submodules) do
|
||||||
|
call(module.update, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function uninit(...)
|
||||||
|
for i, module in pairs(submodules) do
|
||||||
|
call(module.uninit, ...)
|
||||||
|
end
|
||||||
|
end
|
216
assets/opensb/scripts/universeClient/opensb/voice_manager.lua
Normal file
216
assets/opensb/scripts/universeClient/opensb/voice_manager.lua
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
-- Manages the voice HUD indicators and click-to-mute/unmute.
|
||||||
|
|
||||||
|
local fmt = string.format
|
||||||
|
local sqrt = math.sqrt
|
||||||
|
|
||||||
|
local module = {}
|
||||||
|
submodules.voice_manager = module
|
||||||
|
|
||||||
|
--constants
|
||||||
|
local INDICATOR_PATH = "/interface/voicechat/indicator/"
|
||||||
|
local BACK_INDICATOR_IMAGE = INDICATOR_PATH .. "back.png"
|
||||||
|
local FRONT_INDICATOR_IMAGE = INDICATOR_PATH .. "front.png"
|
||||||
|
local FRONT_MUTED_INDICATOR_IMAGE = INDICATOR_PATH .. "front_muted.png"
|
||||||
|
local INDICATOR_SIZE = {300, 48}
|
||||||
|
local LINE_PADDING = 12
|
||||||
|
local LINE_WIDTH = 296
|
||||||
|
local LINE_WIDTH_PADDED = LINE_WIDTH - LINE_PADDING
|
||||||
|
local LINE_COLOR = {50, 210, 255, 255}
|
||||||
|
local FONT_DIRECTIVES = "?border=1;333;3337?border=1;333;3330"
|
||||||
|
local NAME_PREFIX = "^noshadow,white,set;"
|
||||||
|
|
||||||
|
local canvas
|
||||||
|
|
||||||
|
local linePaddingDrawable = {
|
||||||
|
image = BACK_INDICATOR_IMAGE,
|
||||||
|
position = {0, 0},
|
||||||
|
color = LINE_COLOR,
|
||||||
|
centered = false
|
||||||
|
}
|
||||||
|
|
||||||
|
local function getLinePadding(a, b)
|
||||||
|
linePaddingDrawable.image = BACK_INDICATOR_IMAGE .. fmt("?crop=%i;%i;%i;%i?fade=fff;1", a, 0, b, INDICATOR_SIZE[2])
|
||||||
|
linePaddingDrawable.position[1] = a
|
||||||
|
return linePaddingDrawable;
|
||||||
|
end
|
||||||
|
|
||||||
|
local lineDrawable = {
|
||||||
|
line = {{LINE_PADDING, 24}, {10, 24}},
|
||||||
|
width = 48,
|
||||||
|
color = LINE_COLOR
|
||||||
|
}
|
||||||
|
|
||||||
|
local function drawTheLine(pos, value)
|
||||||
|
local width = math.floor((LINE_WIDTH * value) + 0.5)
|
||||||
|
LINE_COLOR[4] = 255 * math.min(1, sqrt(width / 350))
|
||||||
|
if width > 0 then
|
||||||
|
canvas:drawDrawable(getLinePadding(0, math.min(12, width)), pos)
|
||||||
|
if width > 12 then
|
||||||
|
lineDrawable.line[2][1] = math.min(width, LINE_WIDTH_PADDED)
|
||||||
|
canvas:drawDrawable(lineDrawable, pos)
|
||||||
|
if width > LINE_WIDTH_PADDED then
|
||||||
|
canvas:drawDrawable(getLinePadding(LINE_WIDTH_PADDED, width), pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local drawable = {
|
||||||
|
image = BACK_INDICATOR_IMAGE,
|
||||||
|
centered = false
|
||||||
|
}
|
||||||
|
|
||||||
|
local textPositioning = {
|
||||||
|
position = {0, 0},
|
||||||
|
horizontalAnchor = "left",
|
||||||
|
verticalAnchor = "mid"
|
||||||
|
}
|
||||||
|
|
||||||
|
local hoveredSpeaker = nil
|
||||||
|
local hoveredSpeakerIndex = 1
|
||||||
|
local hoveredSpeakerPosition = {0, 0}
|
||||||
|
local function mouseOverSpeaker(mouse, pos, expand)
|
||||||
|
expand = tonumber(expand) or 0
|
||||||
|
return (mouse[1] > pos[1] - expand and mouse[1] < pos[1] + 300 + expand)
|
||||||
|
and (mouse[2] > pos[2] - expand and mouse[2] < pos[2] + 48 + expand)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function drawSpeakerBar(mouse, pos, speaker, i)
|
||||||
|
drawable.image = BACK_INDICATOR_IMAGE
|
||||||
|
canvas:drawDrawable(drawable, pos)
|
||||||
|
drawTheLine(pos, 1 - math.sqrt(math.min(1, math.max(0, speaker.loudness / -50))))
|
||||||
|
local hovering = not speaker.isLocal and mouseOverSpeaker(mouse, pos)
|
||||||
|
|
||||||
|
textPositioning.position = {pos[1] + 49, pos[2] + 24}
|
||||||
|
textPositioning.horizontalAnchor = "left"
|
||||||
|
local text = NAME_PREFIX ..
|
||||||
|
(hovering and (speaker.muted and "^#31d2f7;Unmute^reset; " or "^#f43030;Mute^reset; ") or "")
|
||||||
|
.. speaker.name
|
||||||
|
canvas:drawText(text, textPositioning, 16, nil, nil, nil, FONT_DIRECTIVES)
|
||||||
|
drawable.image = speaker.muted and FRONT_MUTED_INDICATOR_IMAGE or FRONT_INDICATOR_IMAGE
|
||||||
|
canvas:drawDrawable(drawable, pos)
|
||||||
|
|
||||||
|
if hovering then
|
||||||
|
hoveredSpeaker = speaker
|
||||||
|
hoveredSpeakerIndex = i
|
||||||
|
hoveredSpeakerPosition = pos
|
||||||
|
--if input.key("LShift") then
|
||||||
|
-- textPositioning.position = {pos[1] + 288, pos[2] + 24}
|
||||||
|
-- textPositioning.horizontalAnchor = "right"
|
||||||
|
-- canvas:drawText("^#fff7;" .. tostring(speaker.speakerId), textPositioning, 16, nil, nil, nil, FONT_DIRECTIVES)
|
||||||
|
--end
|
||||||
|
--
|
||||||
|
--if input.mouseDown("MouseLeft") then
|
||||||
|
-- local muted = not voice.muted(speaker.speakerId)
|
||||||
|
-- interface.queueMessage((muted and "^#f43030;Muted^reset; " or "^#31d2f7;Unmuted^reset; ") .. speaker.name, 4, 0.5)
|
||||||
|
-- voice.setMuted(speaker.speakerId, muted)
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local speakersTime = {}
|
||||||
|
|
||||||
|
local function simulateSpeakers()
|
||||||
|
local speakers = {}
|
||||||
|
for i = 2, 5 + math.floor((math.sin(os.clock()) * 4) + .5) do
|
||||||
|
speakers[i] = {
|
||||||
|
speakerId = i,
|
||||||
|
entityId = -65536 * i,
|
||||||
|
name = "Player " .. i,
|
||||||
|
loudness = -48 + 48 * math.sin(os.clock() + (i * 0.5)),
|
||||||
|
muted = false
|
||||||
|
}
|
||||||
|
end
|
||||||
|
return speakers
|
||||||
|
end
|
||||||
|
|
||||||
|
local function drawIndicators()
|
||||||
|
canvas:clear()
|
||||||
|
local screenSize = canvas:size()
|
||||||
|
local mousePosition = canvas:mousePosition()
|
||||||
|
sb.setLogMap("mousePosition", sb.printJson(mousePosition))
|
||||||
|
local basePos = {screenSize[1] - 350, 50}
|
||||||
|
|
||||||
|
-- sort it ourselves for now
|
||||||
|
local speakersRemaining, speakersSorted = {}, {}
|
||||||
|
local hoveredSpeakerId = nil
|
||||||
|
if hoveredSpeaker then
|
||||||
|
if not mouseOverSpeaker(mousePosition, hoveredSpeakerPosition, 16) then
|
||||||
|
hoveredSpeaker = nil
|
||||||
|
else
|
||||||
|
hoveredSpeakerId = hoveredSpeaker.speakerId
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--local speakers = voice.speakers()
|
||||||
|
local speakers = { -- just testing before implementing voice lua functions
|
||||||
|
{
|
||||||
|
speakerId = 1,
|
||||||
|
entityId = -65536,
|
||||||
|
loudness = -96 + math.random() * 96,
|
||||||
|
muted = false,
|
||||||
|
name = "theres a pipe bomb up my ass"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local sortI = 0
|
||||||
|
local now = os.clock()
|
||||||
|
for i, speaker in pairs(speakers) do
|
||||||
|
local speakerId = speaker.speakerId
|
||||||
|
speakersRemaining[speakerId] = true
|
||||||
|
local t = speakersTime[speakerId]
|
||||||
|
if not t then
|
||||||
|
t = now
|
||||||
|
speakersTime[speakerId] = t
|
||||||
|
end
|
||||||
|
speaker.startTime = t
|
||||||
|
if speakerId == hoveredSpeakerId then
|
||||||
|
hoveredSpeaker = speaker
|
||||||
|
else
|
||||||
|
sortI = sortI + 1
|
||||||
|
speakersSorted[sortI] = speaker
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, v in pairs(speakersTime) do
|
||||||
|
if not speakersRemaining[i] then
|
||||||
|
speakersTime[i] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
table.sort(speakersSorted, function(a, b)
|
||||||
|
if a.startTime == b.startTime then
|
||||||
|
return a.speakerId < b.speakerId
|
||||||
|
else
|
||||||
|
return a.startTime < b.startTime
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
if hoveredSpeaker then
|
||||||
|
local len = #speakersSorted
|
||||||
|
if hoveredSpeakerIndex > len then
|
||||||
|
for i = len + 1, hoveredSpeakerIndex - 1 do
|
||||||
|
speakersSorted[i] = false
|
||||||
|
end
|
||||||
|
speakersSorted[hoveredSpeakerIndex] = hoveredSpeaker
|
||||||
|
else
|
||||||
|
table.insert(speakersSorted, hoveredSpeakerIndex, hoveredSpeaker)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, v in pairs(speakersSorted) do
|
||||||
|
if v then
|
||||||
|
local entityId = v.entityId
|
||||||
|
local loudness = v.loudness
|
||||||
|
local pos = {basePos[1], basePos[2] + (i - 1) * 52}
|
||||||
|
drawSpeakerBar(mousePosition, pos, v, i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function module.init()
|
||||||
|
canvas = interface.bindCanvas("voice", true)
|
||||||
|
end
|
||||||
|
|
||||||
|
function module.update()
|
||||||
|
drawIndicators()
|
||||||
|
end
|
@ -614,6 +614,7 @@ void ClientApplication::changeState(MainAppState newState) {
|
|||||||
m_worldPainter = make_shared<WorldPainter>();
|
m_worldPainter = make_shared<WorldPainter>();
|
||||||
m_mainInterface = make_shared<MainInterface>(m_universeClient, m_worldPainter, m_cinematicOverlay);
|
m_mainInterface = make_shared<MainInterface>(m_universeClient, m_worldPainter, m_cinematicOverlay);
|
||||||
m_universeClient->setLuaCallbacks("interface", LuaBindings::makeInterfaceCallbacks(m_mainInterface.get()));
|
m_universeClient->setLuaCallbacks("interface", LuaBindings::makeInterfaceCallbacks(m_mainInterface.get()));
|
||||||
|
m_universeClient->startLua();
|
||||||
|
|
||||||
m_mainMixer->setWorldPainter(m_worldPainter);
|
m_mainMixer->setWorldPainter(m_worldPainter);
|
||||||
|
|
||||||
|
@ -27,6 +27,11 @@ LuaCallbacks LuaBindings::makeInterfaceCallbacks(MainInterface* mainInterface) {
|
|||||||
return GuiContext::singleton().interfaceScale();
|
return GuiContext::singleton().interfaceScale();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
callbacks.registerCallback("queueMessage", [mainInterface](String const& message, Maybe<float> cooldown, Maybe<float> springState) {
|
||||||
|
mainInterface->queueMessage(message, cooldown, springState.value(0));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
return callbacks;
|
return callbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +62,8 @@ namespace Star {
|
|||||||
|
|
||||||
GuiMessage::GuiMessage() : message(), cooldown(), springState() {}
|
GuiMessage::GuiMessage() : message(), cooldown(), springState() {}
|
||||||
|
|
||||||
GuiMessage::GuiMessage(String const& message, float cooldown)
|
GuiMessage::GuiMessage(String const& message, float cooldown, float spring)
|
||||||
: message(message), cooldown(cooldown), springState(0) {}
|
: message(message), cooldown(cooldown), springState(spring) {}
|
||||||
|
|
||||||
MainInterface::MainInterface(UniverseClientPtr client, WorldPainterPtr painter, CinematicPtr cinematicOverlay) {
|
MainInterface::MainInterface(UniverseClientPtr client, WorldPainterPtr painter, CinematicPtr cinematicOverlay) {
|
||||||
m_state = Running;
|
m_state = Running;
|
||||||
@ -369,6 +369,9 @@ bool MainInterface::handleInputEvent(InputEvent const& event) {
|
|||||||
player->endTrigger();
|
player->endTrigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& pair : m_canvases)
|
||||||
|
pair.second->sendEvent(event);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -863,11 +866,15 @@ void MainInterface::doChat(String const& chat, bool addToHistory) {
|
|||||||
m_chat->addHistory(chat);
|
m_chat->addHistory(chat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainInterface::queueMessage(String const& message) {
|
void MainInterface::queueMessage(String const& message, Maybe<float> cooldown, float spring) {
|
||||||
auto guiMessage = make_shared<GuiMessage>(message, m_config->messageTime);
|
auto guiMessage = make_shared<GuiMessage>(message, cooldown.value(m_config->messageTime), spring);
|
||||||
m_messages.append(guiMessage);
|
m_messages.append(guiMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainInterface::queueMessage(String const& message) {
|
||||||
|
queueMessage(message, m_config->messageTime, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
void MainInterface::queueJoinRequest(pair<String, RpcPromiseKeeper<P2PJoinRequestReply>> request)
|
void MainInterface::queueJoinRequest(pair<String, RpcPromiseKeeper<P2PJoinRequestReply>> request)
|
||||||
{
|
{
|
||||||
m_queuedJoinRequests.push_back(request);
|
m_queuedJoinRequests.push_back(request);
|
||||||
@ -927,18 +934,21 @@ void MainInterface::warpTo(WarpAction const& warpAction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CanvasWidgetPtr MainInterface::fetchCanvas(String const& canvasName, bool ignoreInterfaceScale) {
|
CanvasWidgetPtr MainInterface::fetchCanvas(String const& canvasName, bool ignoreInterfaceScale) {
|
||||||
|
CanvasWidgetPtr canvas;
|
||||||
|
|
||||||
if (auto canvasPtr = m_canvases.ptr(canvasName))
|
if (auto canvasPtr = m_canvases.ptr(canvasName))
|
||||||
return *canvasPtr;
|
canvas = *canvasPtr;
|
||||||
else {
|
else {
|
||||||
CanvasWidgetPtr canvas = m_canvases.emplace(canvasName, make_shared<CanvasWidget>()).first->second;
|
m_canvases.emplace(canvasName, canvas = make_shared<CanvasWidget>());
|
||||||
canvas->setPosition(Vec2I());
|
canvas->setPosition(Vec2I());
|
||||||
if (ignoreInterfaceScale)
|
if (ignoreInterfaceScale)
|
||||||
canvas->setSize(Vec2I(m_guiContext->windowSize()));
|
canvas->setSize(Vec2I(m_guiContext->windowSize()));
|
||||||
else
|
else
|
||||||
canvas->setSize(Vec2I(m_guiContext->windowInterfaceSize()));
|
canvas->setSize(Vec2I(m_guiContext->windowInterfaceSize()));
|
||||||
canvas->setIgnoreInterfaceScale(ignoreInterfaceScale);
|
|
||||||
return canvas;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
canvas->setIgnoreInterfaceScale(ignoreInterfaceScale);
|
||||||
|
return canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
PanePtr MainInterface::createEscapeDialog() {
|
PanePtr MainInterface::createEscapeDialog() {
|
||||||
|
@ -49,7 +49,7 @@ STAR_CLASS(MainInterface);
|
|||||||
|
|
||||||
struct GuiMessage {
|
struct GuiMessage {
|
||||||
GuiMessage();
|
GuiMessage();
|
||||||
GuiMessage(String const& message, float cooldown);
|
GuiMessage(String const& message, float cooldown, float spring = 0);
|
||||||
|
|
||||||
String message;
|
String message;
|
||||||
float cooldown;
|
float cooldown;
|
||||||
@ -105,7 +105,9 @@ public:
|
|||||||
|
|
||||||
void doChat(String const& chat, bool addToHistory);
|
void doChat(String const& chat, bool addToHistory);
|
||||||
|
|
||||||
|
void queueMessage(String const& message, Maybe<float> cooldown, float spring);
|
||||||
void queueMessage(String const& message);
|
void queueMessage(String const& message);
|
||||||
|
|
||||||
void queueItemPickupText(ItemPtr const& item);
|
void queueItemPickupText(ItemPtr const& item);
|
||||||
void queueJoinRequest(pair<String, RpcPromiseKeeper<P2PJoinRequestReply>> request);
|
void queueJoinRequest(pair<String, RpcPromiseKeeper<P2PJoinRequestReply>> request);
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ UniverseClient::UniverseClient(PlayerStoragePtr playerStorage, StatisticsPtr sta
|
|||||||
m_playerStorage = move(playerStorage);
|
m_playerStorage = move(playerStorage);
|
||||||
m_statistics = move(statistics);
|
m_statistics = move(statistics);
|
||||||
m_pause = false;
|
m_pause = false;
|
||||||
|
m_luaRoot = make_shared<LuaRoot>();
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +87,7 @@ Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowA
|
|||||||
return String(strf("Join failed! Server does not support connections with protocol version {}", StarProtocolVersion));
|
return String(strf("Join failed! Server does not support connections with protocol version {}", StarProtocolVersion));
|
||||||
|
|
||||||
connection.pushSingle(make_shared<ClientConnectPacket>(Root::singleton().assets()->digest(), allowAssetsMismatch, m_mainPlayer->uuid(), m_mainPlayer->name(),
|
connection.pushSingle(make_shared<ClientConnectPacket>(Root::singleton().assets()->digest(), allowAssetsMismatch, m_mainPlayer->uuid(), m_mainPlayer->name(),
|
||||||
m_mainPlayer->species(), m_playerStorage->loadShipData(m_mainPlayer->uuid()), ShipUpgrades(m_mainPlayer->shipUpgrades()),
|
m_mainPlayer->species(), m_playerStorage->loadShipData(m_mainPlayer->uuid()), m_mainPlayer->shipUpgrades(),
|
||||||
m_mainPlayer->log()->introComplete(), account));
|
m_mainPlayer->log()->introComplete(), account));
|
||||||
connection.sendAll(timeout);
|
connection.sendAll(timeout);
|
||||||
|
|
||||||
@ -219,8 +220,11 @@ void UniverseClient::update() {
|
|||||||
|
|
||||||
m_statistics->update();
|
m_statistics->update();
|
||||||
|
|
||||||
if (!m_pause)
|
if (!m_pause) {
|
||||||
m_worldClient->update();
|
m_worldClient->update();
|
||||||
|
for (auto& p : m_scriptContexts)
|
||||||
|
p.second->update();
|
||||||
|
}
|
||||||
m_connection->push(m_worldClient->getOutgoingPackets());
|
m_connection->push(m_worldClient->getOutgoingPackets());
|
||||||
|
|
||||||
if (!m_pause)
|
if (!m_pause)
|
||||||
@ -444,6 +448,28 @@ void UniverseClient::setLuaCallbacks(String const& groupName, LuaCallbacks const
|
|||||||
m_worldClient->setLuaCallbacks(groupName, callbacks);
|
m_worldClient->setLuaCallbacks(groupName, callbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UniverseClient::startLua() {
|
||||||
|
auto assets = Root::singleton().assets();
|
||||||
|
for (auto& p : assets->json("/client.config:universeScriptContexts").toObject()) {
|
||||||
|
auto scriptComponent = make_shared<ScriptComponent>();
|
||||||
|
scriptComponent->setLuaRoot(m_luaRoot);
|
||||||
|
scriptComponent->setScripts(jsonToStringList(p.second.toArray()));
|
||||||
|
|
||||||
|
for (auto& pair : m_luaCallbacks)
|
||||||
|
scriptComponent->addCallbacks(pair.first, pair.second);
|
||||||
|
|
||||||
|
m_scriptContexts.set(p.first, scriptComponent);
|
||||||
|
scriptComponent->init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniverseClient::stopLua() {
|
||||||
|
for (auto& p : m_scriptContexts)
|
||||||
|
p.second->uninit();
|
||||||
|
|
||||||
|
m_scriptContexts.clear();
|
||||||
|
}
|
||||||
|
|
||||||
ClockConstPtr UniverseClient::universeClock() const {
|
ClockConstPtr UniverseClient::universeClock() const {
|
||||||
return m_universeClock;
|
return m_universeClock;
|
||||||
}
|
}
|
||||||
@ -539,6 +565,8 @@ void UniverseClient::handlePackets(List<PacketPtr> const& packets) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UniverseClient::reset() {
|
void UniverseClient::reset() {
|
||||||
|
stopLua();
|
||||||
|
|
||||||
m_universeClock.reset();
|
m_universeClock.reset();
|
||||||
m_worldClient.reset();
|
m_worldClient.reset();
|
||||||
m_celestialDatabase.reset();
|
m_celestialDatabase.reset();
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "StarAiTypes.hpp"
|
#include "StarAiTypes.hpp"
|
||||||
#include "StarSky.hpp"
|
#include "StarSky.hpp"
|
||||||
#include "StarUniverseConnection.hpp"
|
#include "StarUniverseConnection.hpp"
|
||||||
|
#include "StarLuaComponents.hpp"
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
@ -29,8 +30,8 @@ STAR_CLASS(CelestialDatabase);
|
|||||||
STAR_CLASS(JsonRpcInterface);
|
STAR_CLASS(JsonRpcInterface);
|
||||||
STAR_CLASS(TeamClient);
|
STAR_CLASS(TeamClient);
|
||||||
STAR_CLASS(QuestManager);
|
STAR_CLASS(QuestManager);
|
||||||
|
|
||||||
STAR_CLASS(UniverseClient);
|
STAR_CLASS(UniverseClient);
|
||||||
|
STAR_CLASS(LuaRoot);
|
||||||
|
|
||||||
class UniverseClient {
|
class UniverseClient {
|
||||||
public:
|
public:
|
||||||
@ -86,6 +87,8 @@ public:
|
|||||||
uint16_t maxPlayers();
|
uint16_t maxPlayers();
|
||||||
|
|
||||||
void setLuaCallbacks(String const& groupName, LuaCallbacks const& callbacks);
|
void setLuaCallbacks(String const& groupName, LuaCallbacks const& callbacks);
|
||||||
|
void startLua();
|
||||||
|
void stopLua();
|
||||||
|
|
||||||
ClockConstPtr universeClock() const;
|
ClockConstPtr universeClock() const;
|
||||||
CelestialLogConstPtr celestialLog() const;
|
CelestialLogConstPtr celestialLog() const;
|
||||||
@ -141,6 +144,12 @@ private:
|
|||||||
List<ChatReceivedMessage> m_pendingMessages;
|
List<ChatReceivedMessage> m_pendingMessages;
|
||||||
|
|
||||||
Maybe<String> m_disconnectReason;
|
Maybe<String> m_disconnectReason;
|
||||||
|
|
||||||
|
LuaRootPtr m_luaRoot;
|
||||||
|
|
||||||
|
typedef LuaUpdatableComponent<LuaBaseComponent> ScriptComponent;
|
||||||
|
typedef shared_ptr<ScriptComponent> ScriptComponentPtr;
|
||||||
|
StringMap<ScriptComponentPtr> m_scriptContexts;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -88,20 +88,21 @@ bool CanvasWidget::sendEvent(InputEvent const& event) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto& context = GuiContext::singleton();
|
auto& context = GuiContext::singleton();
|
||||||
|
int interfaceScale = m_ignoreInterfaceScale ? 1 : context.interfaceScale();
|
||||||
if (auto mouseButtonDown = event.ptr<MouseButtonDownEvent>()) {
|
if (auto mouseButtonDown = event.ptr<MouseButtonDownEvent>()) {
|
||||||
if (inMember(*context.mousePosition(event)) && m_captureMouse) {
|
if (inMember(*context.mousePosition(event, interfaceScale)) && m_captureMouse) {
|
||||||
m_clickEvents.append({*context.mousePosition(event) - screenPosition(), mouseButtonDown->mouseButton, true});
|
m_clickEvents.append({*context.mousePosition(event, interfaceScale) - screenPosition(), mouseButtonDown->mouseButton, true});
|
||||||
m_clickEvents.limitSizeBack(MaximumEventBuffer);
|
m_clickEvents.limitSizeBack(MaximumEventBuffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (auto mouseButtonUp = event.ptr<MouseButtonUpEvent>()) {
|
} else if (auto mouseButtonUp = event.ptr<MouseButtonUpEvent>()) {
|
||||||
if (m_captureMouse) {
|
if (m_captureMouse) {
|
||||||
m_clickEvents.append({*context.mousePosition(event) - screenPosition(), mouseButtonUp->mouseButton, false});
|
m_clickEvents.append({*context.mousePosition(event, interfaceScale) - screenPosition(), mouseButtonUp->mouseButton, false});
|
||||||
m_clickEvents.limitSizeBack(MaximumEventBuffer);
|
m_clickEvents.limitSizeBack(MaximumEventBuffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (event.is<MouseMoveEvent>()) {
|
} else if (event.is<MouseMoveEvent>()) {
|
||||||
m_mousePosition = *context.mousePosition(event) - screenPosition();
|
m_mousePosition = *context.mousePosition(event, interfaceScale) - screenPosition();
|
||||||
return false;
|
return false;
|
||||||
} else if (auto keyDown = event.ptr<KeyDownEvent>()) {
|
} else if (auto keyDown = event.ptr<KeyDownEvent>()) {
|
||||||
if (m_captureKeyboard) {
|
if (m_captureKeyboard) {
|
||||||
@ -258,7 +259,7 @@ void CanvasWidget::renderTriangles(Vec2F const& renderingOffset, List<tuple<Vec2
|
|||||||
void CanvasWidget::renderText(Vec2F const& renderingOffset, String const& s, TextPositioning const& position, unsigned fontSize, Vec4B const& color, FontMode mode, float lineSpacing, String const& font, String const& directives) {
|
void CanvasWidget::renderText(Vec2F const& renderingOffset, String const& s, TextPositioning const& position, unsigned fontSize, Vec4B const& color, FontMode mode, float lineSpacing, String const& font, String const& directives) {
|
||||||
auto& context = GuiContext::singleton();
|
auto& context = GuiContext::singleton();
|
||||||
context.setFontProcessingDirectives(directives);
|
context.setFontProcessingDirectives(directives);
|
||||||
context.setFontSize(fontSize);
|
context.setFontSize(fontSize, m_ignoreInterfaceScale ? 1 : context.interfaceScale());
|
||||||
context.setFontColor(color);
|
context.setFontColor(color);
|
||||||
context.setFontMode(mode);
|
context.setFontMode(mode);
|
||||||
context.setFont(font);
|
context.setFont(font);
|
||||||
|
@ -98,9 +98,9 @@ void GuiContext::setInterfaceScale(int interfaceScale) {
|
|||||||
m_interfaceScale = interfaceScale;
|
m_interfaceScale = interfaceScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe<Vec2I> GuiContext::mousePosition(InputEvent const& event) const {
|
Maybe<Vec2I> GuiContext::mousePosition(InputEvent const& event, int pixelRatio) const {
|
||||||
auto getInterfacePosition = [this](Vec2I pos) {
|
auto getInterfacePosition = [pixelRatio](Vec2I pos) {
|
||||||
return Vec2I(pos) / interfaceScale();
|
return Vec2I(pos) / pixelRatio;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (auto mouseMoveEvent = event.ptr<MouseMoveEvent>())
|
if (auto mouseMoveEvent = event.ptr<MouseMoveEvent>())
|
||||||
@ -115,6 +115,10 @@ Maybe<Vec2I> GuiContext::mousePosition(InputEvent const& event) const {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Maybe<Vec2I> GuiContext::mousePosition(InputEvent const& event) const {
|
||||||
|
return mousePosition(event, interfaceScale());
|
||||||
|
}
|
||||||
|
|
||||||
Set<InterfaceAction> GuiContext::actions(InputEvent const& event) const {
|
Set<InterfaceAction> GuiContext::actions(InputEvent const& event) const {
|
||||||
return m_keyBindings.actions(event);
|
return m_keyBindings.actions(event);
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ public:
|
|||||||
int interfaceScale() const;
|
int interfaceScale() const;
|
||||||
void setInterfaceScale(int interfaceScale);
|
void setInterfaceScale(int interfaceScale);
|
||||||
|
|
||||||
|
Maybe<Vec2I> mousePosition(InputEvent const& event, int pixelRatio) const;
|
||||||
Maybe<Vec2I> mousePosition(InputEvent const& event) const;
|
Maybe<Vec2I> mousePosition(InputEvent const& event) const;
|
||||||
|
|
||||||
Set<InterfaceAction> actions(InputEvent const& event) const;
|
Set<InterfaceAction> actions(InputEvent const& event) const;
|
||||||
|
@ -25,13 +25,14 @@ LuaMethods<CanvasWidgetPtr> LuaUserDataMethods<CanvasWidgetPtr>::make() {
|
|||||||
|
|
||||||
methods.registerMethodWithSignature<void, CanvasWidgetPtr>("clear", mem_fn(&CanvasWidget::clear));
|
methods.registerMethodWithSignature<void, CanvasWidgetPtr>("clear", mem_fn(&CanvasWidget::clear));
|
||||||
|
|
||||||
methods.registerMethod("drawDrawable", [](CanvasWidgetPtr canvasWidget, Drawable drawable) {
|
methods.registerMethod("drawDrawable", [](CanvasWidgetPtr canvasWidget, Drawable drawable, Maybe<Vec2F> screenPos) {
|
||||||
canvasWidget->drawDrawable(move(drawable), Vec2F());
|
canvasWidget->drawDrawable(move(drawable), screenPos.value(Vec2F()));
|
||||||
});
|
});
|
||||||
|
|
||||||
methods.registerMethod("drawDrawables", [](CanvasWidgetPtr canvasWidget, List<Drawable> drawables) {
|
methods.registerMethod("drawDrawables", [](CanvasWidgetPtr canvasWidget, List<Drawable> drawables, Maybe<Vec2F> screenPos) {
|
||||||
|
Vec2F pos = screenPos.value(Vec2F());
|
||||||
for (auto& drawable : drawables)
|
for (auto& drawable : drawables)
|
||||||
canvasWidget->drawDrawable(move(drawable), Vec2F());
|
canvasWidget->drawDrawable(move(drawable), pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
methods.registerMethod("drawImage",
|
methods.registerMethod("drawImage",
|
||||||
|
Loading…
Reference in New Issue
Block a user