diff --git a/fxmanifest.lua b/fxmanifest.lua index 5fa9b29..4acca46 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -50,6 +50,7 @@ client_scripts { 'modules/notify/**/client.lua', 'modules/dialogue/**/client/*.lua', 'modules/shops/**/client.lua', + 'modules/accessibility/client.lua', 'init.lua', } diff --git a/init.lua b/init.lua index 0bc21a1..3c6340b 100644 --- a/init.lua +++ b/init.lua @@ -99,6 +99,7 @@ Bridge.RegisterModule("Weather", Weather) Bridge.RegisterModule("Target", Target) Bridge.RegisterModule("Menu", Menu) Bridge.RegisterModule("Dialogue", Dialogue) +Bridge.RegisterModule("Accessibility", Accessibility) -- new Bridge.RegisterModule("Utility", cLib.Utility) Bridge.RegisterModule("Placeable", cLib.Placeable)--new diff --git a/locales/en.json b/locales/en.json index 6b04803..fef60d1 100644 --- a/locales/en.json +++ b/locales/en.json @@ -1,16 +1,45 @@ { - "locale-unit-test": "This is a test string", - "place_object_place": "[E] Place \n", - "place_object_cancel": "[X] Cancel \n", - "place_object_scroll_up": "[SCROLL UP] Turn right \n", - "place_object_scroll_down": "[SCROLL DOWN] Turn left", - "enter_text": "Enter Text", - "no_prop_defined": "You didnt define any object to place", - "Shops": {"NotEnoughMoney": "You dont have enough money to buy this item", "Input":"Amount Input", "PurchaseAmount":"Purchase Quanity","PurchasedItem": "You Have Purchased ", "CurrencySymbol": "$", "Confirm":"Confirm Purchase","AreYouSure":"Are you sure you want to purchase a ", "PayByCash": "Pay by cash", "PayByCard": "Pay by card" }, + "locale-unit-test": "This is a test string", + "place_object_place": "[E] Place \n", + "place_object_cancel": "[X] Cancel \n", + "place_object_scroll_up": "[SCROLL UP] Turn right \n", + "place_object_scroll_down": "[SCROLL DOWN] Turn left", + "enter_text": "Enter Text", + "no_prop_defined": "You didnt define any object to place", + "Shops": { + "NotEnoughMoney": "You dont have enough money to buy this item", + "Input": "Amount Input", + "PurchaseAmount": "Purchase Quanity", + "PurchasedItem": "You Have Purchased ", + "CurrencySymbol": "$", + "Confirm": "Confirm Purchase", + "AreYouSure": "Are you sure you want to purchase a ", + "PayByCash": "Pay by cash", + "PayByCard": "Pay by card" + }, + "UNITTEST": { + "UNITTESTA": "Im a %s %s", "UNITTEST": { - "UNITTESTA": "Im a %s %s", - "UNITTEST": { - "UNITTESTA": "\n.-._ _,-,\n`._`-._ _,-'_,'\n `._ `-._ _,-' _,'\n `._ `-._ __.-----.__ _,-' _,'\n `._ `#===\\\"\\\"\\\" \\\"\\\"\\\"===#' _,'\n `._/) ._ _. (\\_,'\n )*' **.__ __.** '*(\n # .==..__ \\\"\\\" \\\"\\\" __..==, #\n # `\\\"._(_). .(_)_.\\\"' #" - } - } -} \ No newline at end of file + "UNITTESTA": "\n.-._ _,-,\n`._`-._ _,-'_,'\n `._ `-._ _,-' _,'\n `._ `-._ __.-----.__ _,-' _,'\n `._ `#===\\\"\\\"\\\" \\\"\\\"\\\"===#' _,'\n `._/) ._ _. (\\_,'\n )*' **.__ __.** '*(\n # .==..__ \\\"\\\" \\\"\\\" __..==, #\n # `\\\"._(_). .(_)_.\\\"' #" + } + }, + "accessibility": { + "cb_command": "colourblindness", + "cb_title": "Colourblindness Options", + "cb_desc": "Select your type of colourblindness\nCurrent Colourblindness: %s", + "cb_none": "None", + "cb_updated": "Colourblindness has been updated to %s", + "cb_default_title": "No Colourblindness", + "cb_default_desc": "No colourblindness.\nThis is the default option.", + "cb_protanomaly_title": "Protanomaly", + "cb_protanomaly_desc": "Red-green color blindness.\nMakes certain shades of red look more green and less bright.\nThis type is mild and usually doesn’t get in the way of normal activities.", + "cb_deuteranomaly_title": "Deuteranomaly", + "cb_deuteranomaly_desc": "Red-green color blindness.\nIt makes certain shades of green look more red.\nThis type is mild and doesn’t usually get in the way of normal activities.", + "cb_dual_title": "Protanopia and Deuteranopia", + "cb_dual_desc": "Red-green color blindness.\nMakes someone unable to tell the difference between red and green at all.", + "cb_tritanopia_title": "Tritanopia", + "cb_tritanopia_desc": "Blue-yellow color blindness that makes someone unable to tell the difference between blue and green, purple and red, and yellow and pink.\nIt also makes colors look less bright.", + "cb_tritanomaly_title": "Tritanomaly", + "cb_tritanomaly_desc": "Blue-yellow color blindness makes it hard to tell the difference between blue and green and between yellow and red." + } +} diff --git a/locales/pt.json b/locales/pt.json index 498a81f..2c5e0a8 100644 --- a/locales/pt.json +++ b/locales/pt.json @@ -5,5 +5,24 @@ "place_object_scroll_up": "[SCROLL UP] Direita\n", "place_object_scroll_down": "[SCROLL DOWN] Esquerda", "enter_text": "Inserir Texto", - "no_prop_defined": "Não definiu nenhum objeto para colocar" + "no_prop_defined": "Não definiu nenhum objeto para colocar", + "accessibility": { + "cb_command": "daltônico", + "cb_title": "Opções de daltonismo", + "cb_desc": "Selecione seu tipo de daltonismo\nDaltonismo atual: %s", + "cb_none": "Nenhum", + "cb_updated": "O daltonismo foi atualizado para %s", + "cb_default_title": "Sem daltonismo", + "cb_default_desc": "Sem daltonismo.\nEsta é a opção padrão.", + "cb_protanomaly_title": "Protanomalia", + "cb_protanomaly_desc": "Daltonismo vermelho-verde.\nFaz com que certos tons de vermelho pareçam mais verdes e menos brilhantes.\nEste tipo é leve e geralmente não atrapalha as atividades normais.", + "cb_deuteranomaly_title": "Deuteranomalia", + "cb_deuteranomaly_desc": "Daltonismo vermelho-verde.\nFaz com que certos tons de verde pareçam mais vermelhos.\nEste tipo é leve e geralmente não atrapalha as atividades normais.", + "cb_dual_title": "Protanopia e Deuteranopia", + "cb_dual_desc": "Daltonismo vermelho-verde.\nFaz com que alguém não consiga distinguir entre vermelho e verde.", + "cb_tritanopia_title": "Tritanopia", + "cb_tritanopia_desc": "Daltonismo azul-amarelo que faz com que alguém não consiga distinguir a diferença entre azul e verde, roxo e vermelho, e amarelo e rosa.\nTambém faz com que as cores pareçam menos brilhantes.", + "cb_tritanomaly_title": "Tritanomalia", + "cb_tritanomaly_desc": "O daltonismo azul-amarelo dificulta a distinção entre azul e verde e entre amarelo e vermelho.", + } } \ No newline at end of file diff --git a/modules/accessibility/client.lua b/modules/accessibility/client.lua new file mode 100644 index 0000000..a284ca6 --- /dev/null +++ b/modules/accessibility/client.lua @@ -0,0 +1,210 @@ +local colourblind = GetResourceKvpString('colourblind') or "default" +local QB = false +if (BridgeClientConfig.MenuSystem == "auto" and GetResourceState("qb-menu") ~= "started") or (BridgeClientConfig.MenuSystem ~= "auto" and BridgeClientConfig.MenuSystem == "qb-menu") then + QB = true +end + +Accessibility = Accessibility or {} + +RegisterCommand(locale("accessibility.cb_command"), function() + Accessibility.updatecolourblindness() +end, false) + +Accessibility.updatecolourblindness = function() + local currentCB = locale("accessibility.cb_"..colourblind.."_title") + local cbIcon = "fas fa-eye-low-vision" + Menu.Open({ + id = 'colourblind_update', + title = locale("accessibility.cb_title"), + options = { + { + title = locale("accessibility.cb_title"), + description = locale("accessibility.cb_desc"):format(currentCB), + disabled = true, + }, + { + title = locale("accessibility.cb_default_title"), + description = locale("accessibility.cb_default_desc"), + icon = "fas fa-eye", + onSelect = function() + colourblind = "default" + SetResourceKvp('colourblind', colourblind) + Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000) + end + }, + { + title = locale("accessibility.cb_protanomaly_title"), + description = locale("accessibility.cb_protanomaly_desc"), + icon = cbIcon, + onSelect = function() + colourblind = "protanomaly" + SetResourceKvp('colourblind', colourblind) + Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000) + end + }, + { + title = locale("accessibility.cb_deuteranomaly_title"), + description = locale("accessibility.cb_deuteranomaly_desc"), + icon = cbIcon, + onSelect = function() + colourblind = "deuteranomaly" + SetResourceKvp('colourblind', colourblind) + Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000) + end + }, + { + title = locale('accessibility.cb_dual_title'), + description = locale("accessibility.cb_dual_desc"), + icon = cbIcon, + onSelect = function() + colourblind = "dual" + SetResourceKvp('colourblind', colourblind) + Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000) + end + }, + { + title = locale("accessibility.cb_tritanopia_title"), + description = locale("accessibility.cb_tritanopia_desc"), + icon = cbIcon, + onSelect = function() + colourblind = "tritanopia" + SetResourceKvp('colourblind', colourblind) + Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000) + end + }, + { + title = locale("accessibility.cb_tritanomaly_title"), + description = locale("accessibility.cb_tritanomaly_desc"), + icon = cbIcon, + onSelect = function() + colourblind = "tritanomaly" + SetResourceKvp('colourblind', colourblind) + Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000) + end + }, + }},QB) +end +Accessibility.hexToRgb = function(hex) + hex = hex:gsub("#", "") + local r,g,b = tonumber("0x" .. hex:sub(1, 2)),tonumber("0x" .. hex:sub(3, 4)),tonumber("0x" .. hex:sub(5, 6)) + return r, g, b +end + +Accessibility.rgbToHex = function(r, g, b) + return string.format("#%02x%02x%02x", r, g, b) +end + +Accessibility.rgbToHsl = function(r, g, b) + r = r / 255 + g = g / 255 + b = b / 255 + local max = math.max(r, g, b) + local min = math.min(r, g, b) + local h, s, l = 0, 0, (max + min) / 2 + + if max == min then + h, s = 0, 0 -- achromatic + else + local d = max - min + s = l > 0.5 and d / (2 - max - min) or d / (max + min) + if max == r then + h = (g - b) / d + (g < b and 6 or 0) + elseif max == g then + h = (b - r) / d + 2 + elseif max == b then + h = (r - g) / d + 4 + end + h = h / 6 + end + return h, s, l +end + +Accessibility.hslToRgb = function(h, s, l) + local r, g, b + if s == 0 then + r, g, b = l, l, l -- achromatic + else + local function hue2rgb(p, q, t) + if t < 0 then t = t + 1 end + if t > 1 then t = t - 1 end + if t < 1 / 6 then return p + (q - p) * 6 * t end + if t < 1 / 2 then return q end + if t < 2 / 3 then return p + (q - p) * (2 / 3 - t) * 6 end + return p + end + + local q = l < 0.5 and l * (1 + s) or l + s - l * s + local p = 2 * l - q + r = hue2rgb(p, q, h + 1 / 3) + g = hue2rgb(p, q, h) + b = hue2rgb(p, q, h - 1 / 3) + end + return math.floor(r * 255), math.floor(g * 255), math.floor(b * 255) +end + +Accessibility.adjustColourForColourblindness = function(num, returnAsRGB) + local r, g, b + if type(num) ~= "table" and num:match("^#%x%x%x%x%x%x$") then + r, g, b = Accessibility.hexToRgb(num) -- Convert hex to RGB + else + r, g, b = num.r, num.g, num.b -- If it's already RGB, use it directly + end + local h, s, l = Accessibility.rgbToHsl(r, g, b) -- Convert RGB to HSL + -- Adjust hue values based on colourblindness type + if colourblind == "protanomaly" then -- Red-blind + -- Shift towards blue/cyan + h = (h + 0.5) % 1 -- Shift by 180 degrees + elseif colourblind == "deuteranomaly" then -- Green-blind + -- Shift towards blue/magenta + h = (h + 0.33) % 1 -- Shift by 120 degrees + elseif colourblind == "dual" then -- Protanopia and Deuteranopia (Red-Green blind) + -- More significant shift towards blue/yellow + -- This is a more drastic shift to maximize contrast + if h < 0.166 then -- Reddish hues + h = 0.66 -- Shift to blue + elseif h < 0.5 then -- Greenish hues + h = 0.166 -- Shift to yellow + else + h = h -- Leave blue/purple hues alone + end + -- Increase saturation and lightness to make colours more distinct + s = math.min(s * 1.5, 1) + l = math.min(l * 1.2, 1) + elseif colourblind == "tritanopia" then -- Blue-blind + -- Shift towards red/yellow + h = (h + 0.16) % 1 -- Shift by 60 degrees + elseif colourblind == "tritanomaly" then + h = (h + 0.08) % 1 + end + + -- Convert back to RGB + r, g, b = Accessibility.hslToRgb(h, s, l) + if returnAsRGB then + return {r = r, g = g, b = b} + else + -- Convert back to HEX + local newHex = Accessibility.rgbToHex(r, g, b) + return newHex + end +end + +---@returns a colour adjusted for colourblindness in HEX if variable `returnAsRGB` is false +---@param colourName string Colour name in HEX format or RGB format +-- This is the trigger function for altering colours for colourblindness :D +Accessibility.getAdjustedColour = function(colourName, returnAsRGB) + local originalHex = colourName + if originalHex then + if colourblind == "default" then + if type(colourName) == "table" and not returnAsRGB then + return Accessibility.rgbToHex(colourName.r, colourName.g, colourName.b) + else + return originalHex + end + else + return Accessibility.adjustColourForColourblindness(originalHex, returnAsRGB) + end + else + Prints.Error("Invalid Colour Name^0] [^3"..colourName.."^0") + return "#FFFFFF" -- Default to white if the colour name is invalid + end +end \ No newline at end of file diff --git a/modules/menu/_qb-menu.lua b/modules/menu/_qb-menu.lua index 511495a..411fd0e 100644 --- a/modules/menu/_qb-menu.lua +++ b/modules/menu/_qb-menu.lua @@ -18,6 +18,7 @@ function OxToQBMenu(id, menu) header = v.title, txt = v.description, icon = v.icon, + disabled = v.disabled, } if v.onSelect then