From 03362d2c6d3ef713677fa6e2cda7a0ace64728d8 Mon Sep 17 00:00:00 2001 From: moscovium Date: Wed, 26 Sep 2018 17:24:02 +0200 Subject: [PATCH] chat: theming support, hide chat when not needed, other minor changes --- .../[system]/chat-theme-gtao/__resource.lua | 10 ++ resources/[system]/chat-theme-gtao/shadow.js | 74 +++++++++++ resources/[system]/chat-theme-gtao/style.css | 116 ++++++++++++++++++ resources/[system]/chat/cl_chat.lua | 57 +++++++++ resources/[system]/chat/html/App.js | 85 +++++++++++++ resources/[system]/chat/html/index.css | 6 +- resources/[system]/chat/html/index.html | 72 ++++++----- 7 files changed, 385 insertions(+), 35 deletions(-) create mode 100644 resources/[system]/chat-theme-gtao/__resource.lua create mode 100644 resources/[system]/chat-theme-gtao/shadow.js create mode 100644 resources/[system]/chat-theme-gtao/style.css diff --git a/resources/[system]/chat-theme-gtao/__resource.lua b/resources/[system]/chat-theme-gtao/__resource.lua new file mode 100644 index 0000000..a9a6938 --- /dev/null +++ b/resources/[system]/chat-theme-gtao/__resource.lua @@ -0,0 +1,10 @@ +file 'style.css' +file 'shadow.js' + +chat_theme 'gtao' { + styleSheet = 'style.css', + script = 'shadow.js', + msgTemplates = { + default = '{0}{1}' + } +} \ No newline at end of file diff --git a/resources/[system]/chat-theme-gtao/shadow.js b/resources/[system]/chat-theme-gtao/shadow.js new file mode 100644 index 0000000..55d3176 --- /dev/null +++ b/resources/[system]/chat-theme-gtao/shadow.js @@ -0,0 +1,74 @@ +(function() { +var Filters = {} + +var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); +svg.setAttribute("style", "display:block;width:0px;height:0px"); +var defs = document.createElementNS("http://www.w3.org/2000/svg", "defs"); + +var blurFilter = document.createElementNS("http://www.w3.org/2000/svg", "filter"); +blurFilter.setAttribute("id", "svgBlurFilter"); +var feGaussianFilter = document.createElementNS("http://www.w3.org/2000/svg", "feGaussianBlur"); +feGaussianFilter.setAttribute("stdDeviation", "0 0"); +blurFilter.appendChild(feGaussianFilter); +defs.appendChild(blurFilter); +Filters._svgBlurFilter = feGaussianFilter; + +// Drop Shadow Filter +var dropShadowFilter = document.createElementNS("http://www.w3.org/2000/svg", "filter"); +dropShadowFilter.setAttribute("id", "svgDropShadowFilter"); +var feGaussianFilter = document.createElementNS("http://www.w3.org/2000/svg", "feGaussianBlur"); +feGaussianFilter.setAttribute("in", "SourceAlpha"); +feGaussianFilter.setAttribute("stdDeviation", "3"); +dropShadowFilter.appendChild(feGaussianFilter); +Filters._svgDropshadowFilterBlur = feGaussianFilter; + +var feOffset = document.createElementNS("http://www.w3.org/2000/svg", "feOffset"); +feOffset.setAttribute("dx", "0"); +feOffset.setAttribute("dy", "0"); +feOffset.setAttribute("result", "offsetblur"); +dropShadowFilter.appendChild(feOffset); +Filters._svgDropshadowFilterOffset = feOffset; + +var feFlood = document.createElementNS("http://www.w3.org/2000/svg", "feFlood"); +feFlood.setAttribute("flood-color", "rgba(0,0,0,1)"); +dropShadowFilter.appendChild(feFlood); +Filters._svgDropshadowFilterFlood = feFlood; + +var feComposite = document.createElementNS("http://www.w3.org/2000/svg", "feComposite"); +feComposite.setAttribute("in2", "offsetblur"); +feComposite.setAttribute("operator", "in"); +dropShadowFilter.appendChild(feComposite); +var feComposite = document.createElementNS("http://www.w3.org/2000/svg", "feComposite"); +feComposite.setAttribute("in2", "SourceAlpha"); +feComposite.setAttribute("operator", "out"); +feComposite.setAttribute("result", "outer"); +dropShadowFilter.appendChild(feComposite); + +var feMerge = document.createElementNS("http://www.w3.org/2000/svg", "feMerge"); +var feMergeNode = document.createElementNS("http://www.w3.org/2000/svg", "feMergeNode"); +feMerge.appendChild(feMergeNode); +var feMergeNode = document.createElementNS("http://www.w3.org/2000/svg", "feMergeNode"); +feMerge.appendChild(feMergeNode); +Filters._svgDropshadowMergeNode = feMergeNode; +dropShadowFilter.appendChild(feMerge); +defs.appendChild(dropShadowFilter); +svg.appendChild(defs); +document.documentElement.appendChild(svg); + +const blurScale = 1; +const scale = (document.body.clientWidth / 1280); + +Filters._svgDropshadowFilterBlur.setAttribute("stdDeviation", + 1 * blurScale + " " + + 1 * blurScale +); +Filters._svgDropshadowFilterOffset.setAttribute("dx", + String(Math.cos(45 * Math.PI / 180) * 1 * scale)); +Filters._svgDropshadowFilterOffset.setAttribute("dy", + String(Math.sin(45 * Math.PI / 180) * 1 * scale)); +Filters._svgDropshadowFilterFlood.setAttribute("flood-color", + 'rgba(0, 0, 0, 1)'); +Filters._svgDropshadowMergeNode.setAttribute("in", + "SourceGraphic"); + +})(); \ No newline at end of file diff --git a/resources/[system]/chat-theme-gtao/style.css b/resources/[system]/chat-theme-gtao/style.css new file mode 100644 index 0000000..661d2ee --- /dev/null +++ b/resources/[system]/chat-theme-gtao/style.css @@ -0,0 +1,116 @@ +* { + font-family: inherit; +} + +.chat-window { + --size: calc((((2.7vw / 1.77777) * 1.2)) * 6); + + position: absolute; + right: calc(1.56vw); + top: calc(50% - (var(--size) / 2)); + height: var(--size) !important; + + background: inherit !important; + + text-align: right; + + left: auto; + + user-select: none; +} + +@font-face { + font-family: 'Font2'; + src: url(https://runtime.fivem.net/temp/ChaletLondonNineteenSixty.otf?a); +} + +@font-face { + font-family: 'Font2_cond'; + src: url(https://runtime.fivem.net/temp/chaletcomprime-colognesixty-webfont.ttf?a); +} + +.msg { + font-family: Font2, sans-serif; + color: #fff; + + font-size: calc(1.8vw / 1.77777); /* 13px in 720p, calc'd by width */ + filter: url(#svgDropShadowFilter); + + line-height: calc((2.7vw / 1.77777) * 1.2); + + margin-bottom: 0; +} + +.chat-messages { + margin: 0; + height: 100%; +} + +.msg > span > span > b { + font-family: Font2_cond, sans-serif; + font-weight: normal; + + vertical-align: baseline; + padding-right: 11px; + + line-height: 1; + + font-size: calc(2.7vw / 1.77777); /* 13px in 720p, calc'd by width */ +} + +.msg > span > span > span { + vertical-align: baseline; +} + +.msg i:first-of-type { + font-style: normal; + color: #c0c0c0; +} + +.chat-input { + position: absolute; + right: calc(1.56vw); + bottom: calc(1.56vw); + + background: inherit !important; + + text-align: right; + + top: auto; + left: auto; + + height: auto; + + font-family: Font2, sans-serif; +} + +.chat-input > div { + background-color: rgba(0, 0, 0, .6); + padding: calc(0.15625vw / 2); +} + +.chat-input .prefix { + margin: 0; + margin-left: 0.7%; + margin-top: -0.1%; +} + +.chat-input > div + div { + position: absolute; + bottom: calc(1.65vh + 0.15625vw + 0.15625vw + 0.15625vw + (0.15625vw / 2)); + width: 99.6%; + + text-align: left; +} + +.suggestions { + border: calc(0.15625vw / 2) solid rgba(180, 180, 180, .6); + background: transparent; +} + +textarea { + background: transparent; + border: calc(0.15625vw / 2) solid rgba(180, 180, 180, .6); + padding: calc(0.15625vw / 2); + padding-left: calc(3.5% + (0.15625vw / 2)); +} \ No newline at end of file diff --git a/resources/[system]/chat/cl_chat.lua b/resources/[system]/chat/cl_chat.lua index 7173dbd..1a1eece 100644 --- a/resources/[system]/chat/cl_chat.lua +++ b/resources/[system]/chat/cl_chat.lua @@ -1,5 +1,7 @@ local chatInputActive = false local chatInputActivating = false +local chatHidden = true +local chatLoaded = false RegisterNetEvent('chatMessage') RegisterNetEvent('chat:addTemplate') @@ -132,16 +134,54 @@ local function refreshCommands() end end +local function refreshThemes() + local themes = {} + + for resIdx = 0, GetNumResources() - 1 do + local resource = GetResourceByFindIndex(resIdx) + + if GetResourceState(resource) == 'started' then + local numThemes = GetNumResourceMetadata(resource, 'chat_theme') + + if numThemes > 0 then + local themeName = GetResourceMetadata(resource, 'chat_theme') + local themeData = json.decode(GetResourceMetadata(resource, 'chat_theme_extra') or 'null') + + if themeName and themeData then + themeData.baseUrl = 'nui://' .. resource .. '/' + themes[themeName] = themeData + end + end + end + end + + SendNUIMessage({ + type = 'ON_UPDATE_THEMES', + themes = themes + }) +end + AddEventHandler('onClientResourceStart', function(resName) Wait(500) refreshCommands() + refreshThemes() +end) + +AddEventHandler('onClientResourceStop', function(resName) + Wait(500) + + refreshCommands() + refreshThemes() end) RegisterNUICallback('loaded', function(data, cb) TriggerServerEvent('chat:init'); refreshCommands() + refreshThemes() + + chatLoaded = true cb('ok') end) @@ -171,5 +211,22 @@ Citizen.CreateThread(function() chatInputActivating = false end end + + if chatLoaded then + local shouldBeHidden = false + + if IsScreenFadedOut() or IsPauseMenuActive() then + shouldBeHidden = true + end + + if (shouldBeHidden and not chatHidden) or (not shouldBeHidden and chatHidden) then + chatHidden = shouldBeHidden + + SendNUIMessage({ + type = 'ON_SCREEN_STATE_CHANGE', + shouldHide = shouldBeHidden + }) + end + end end end) diff --git a/resources/[system]/chat/html/App.js b/resources/[system]/chat/html/App.js index 4b38eb4..77769e1 100644 --- a/resources/[system]/chat/html/App.js +++ b/resources/[system]/chat/html/App.js @@ -6,6 +6,7 @@ window.APP = { style: CONFIG.style, showInput: false, showWindow: false, + shouldHide: true, backingSuggestions: [], removedSuggestions: [], templates: CONFIG.templates, @@ -13,6 +14,8 @@ window.APP = { messages: [], oldMessages: [], oldMessagesIndex: -1, + tplBackups: [], + msgTplBackups: [] }; }, destroyed() { @@ -48,6 +51,9 @@ window.APP = { }, }, methods: { + ON_SCREEN_STATE_CHANGE({ shouldHide }) { + this.shouldHide = shouldHide; + }, ON_OPEN() { this.showInput = true; this.showWindow = true; @@ -91,6 +97,85 @@ window.APP = { this.templates[template.id] = template.html; } }, + ON_UPDATE_THEMES({ themes }) { + this.removeThemes(); + + this.setThemes(themes); + }, + removeThemes() { + for (let i = 0; i < document.styleSheets.length; i++) { + const styleSheet = document.styleSheets[i]; + const node = styleSheet.ownerNode; + + if (node.getAttribute('data-theme')) { + node.parentNode.removeChild(node); + } + } + + this.tplBackups.reverse(); + + for (const [ elem, oldData ] of this.tplBackups) { + elem.innerText = oldData; + } + + this.tplBackups = []; + + this.msgTplBackups.reverse(); + + for (const [ id, oldData ] of this.msgTplBackups) { + this.templates[id] = oldData; + } + + this.msgTplBackups = []; + }, + setThemes(themes) { + for (const [ id, data ] of Object.entries(themes)) { + if (data.style) { + const style = document.createElement('style'); + style.type = 'text/css'; + style.setAttribute('data-theme', id); + style.appendChild(document.createTextNode(data.style)); + + document.head.appendChild(style); + } + + if (data.styleSheet) { + const link = document.createElement('link'); + link.rel = 'stylesheet'; + link.type = 'text/css'; + link.href = data.baseUrl + data.styleSheet; + link.setAttribute('data-theme', id); + + document.head.appendChild(link); + } + + if (data.templates) { + for (const [ tplId, tpl ] of Object.entries(data.templates)) { + const elem = document.getElementById(tplId); + + if (elem) { + this.tplBackups.push([ elem, elem.innerText ]); + elem.innerText = tpl; + } + } + } + + if (data.script) { + const script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = data.baseUrl + data.script; + + document.head.appendChild(script); + } + + if (data.msgTemplates) { + for (const [ tplId, tpl ] of Object.entries(data.msgTemplates)) { + this.msgTplBackups.push([ tplId, this.templates[tplId] ]); + this.templates[tplId] = tpl; + } + } + } + }, warn(msg) { this.messages.push({ args: [msg], diff --git a/resources/[system]/chat/html/index.css b/resources/[system]/chat/html/index.css index 96a8e3a..30f1699 100644 --- a/resources/[system]/chat/html/index.css +++ b/resources/[system]/chat/html/index.css @@ -103,7 +103,7 @@ textarea:focus, input:focus { list-style-type: none; padding: 0.5%; padding-left: 1.4%; - font-size: 1.1rem; + font-size: 1.65vh; box-sizing: border-box; color: white; background-color: rgba(44, 62, 80, 1.0); @@ -121,3 +121,7 @@ textarea:focus, input:focus { .suggestion { margin-bottom: 0.5%; } + +.hidden { + display: none; +} \ No newline at end of file diff --git a/resources/[system]/chat/html/index.html b/resources/[system]/chat/html/index.html index a0c43b2..6ce65dd 100644 --- a/resources/[system]/chat/html/index.html +++ b/resources/[system]/chat/html/index.html @@ -18,7 +18,7 @@