diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-07-17 22:20:39 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-07-17 22:20:39 +1000 |
commit | 34bb0b54222c1c0f3450c56e76f89f192d77374b (patch) | |
tree | 09e119625d066d16e3a81a8f6c0c424c4159f058 /assets/opensb/scripts | |
parent | 848b11399f2e34d7f1e0523e214287bfdcc5816c (diff) |
Initial voice HUD indicator setup
Diffstat (limited to 'assets/opensb/scripts')
-rw-r--r-- | assets/opensb/scripts/universeClient/opensb.lua | 29 | ||||
-rw-r--r-- | assets/opensb/scripts/universeClient/opensb/voice_manager.lua | 216 |
2 files changed, 245 insertions, 0 deletions
diff --git a/assets/opensb/scripts/universeClient/opensb.lua b/assets/opensb/scripts/universeClient/opensb.lua new file mode 100644 index 0000000..c1b4dea --- /dev/null +++ b/assets/opensb/scripts/universeClient/opensb.lua @@ -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
\ No newline at end of file diff --git a/assets/opensb/scripts/universeClient/opensb/voice_manager.lua b/assets/opensb/scripts/universeClient/opensb/voice_manager.lua new file mode 100644 index 0000000..c07a8c2 --- /dev/null +++ b/assets/opensb/scripts/universeClient/opensb/voice_manager.lua @@ -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
\ No newline at end of file |