Files
QRify/BrialQRify.rbxmx
T
2026-06-18 09:12:35 +08:00

674 lines
16 KiB
Plaintext

<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="Script" referent="RBX33E862322BCF41359DC4BE53FD912695">
<Properties>
<ProtectedString name="Source"><![CDATA[--[[
oooooooooo. o8o oooo .oooooo. ooooooooo. o8o .o88o.
`888' `Y8b `"' `888 d8P' `Y8b `888 `Y88. `"' 888 `"
888 888 oooo d8b oooo .oooo. 888 888 888 888 .d88' oooo o888oo oooo ooo
888oooo888' `888""8P `888 `P )88b 888 888 888 888ooo88P' `888 888 `88. .8'
888 `88b 888 888 .oP"888 888 888 888 888`88b. 888 888 `88..8'
888 .88P 888 888 d8( 888 888 `88b d88b 888 `88b. 888 888 `888'
o888bood8P' d888b o888o `Y888""8o o888o `Y8bood8P'Ybd' o888o o888o o888o o888o .8'
.o..P'
`Y8P'
By Hayes@Brial
--]]
-- Supports QR Version 1-4, Error Correction L, Byte mode
local toolbar = plugin:CreateToolbar("BrialQRify")
local button = toolbar:CreateButton("BrialQRify", "Generates a scannable QR code in StarterGui", "")
local widgetInfo = DockWidgetPluginGuiInfo.new(
Enum.InitialDockState.Float,
true, true,
420, 500,
420, 500
)
local widget = plugin:CreateDockWidgetPluginGui("BrialQRify", widgetInfo)
widget.Title = "BrialQRify"
widget.Enabled = false
local mainFrame = Instance.new("Frame")
mainFrame.Size = UDim2.new(1, 0, 1, 0)
mainFrame.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
mainFrame.BorderSizePixel = 0
mainFrame.Parent = widget
local title = Instance.new("TextLabel")
title.Size = UDim2.new(1, 0, 0, 40)
title.Position = UDim2.new(0, 0, 0, 0)
title.Text = "BrialQRify"
title.TextColor3 = Color3.fromRGB(255, 255, 255)
title.TextSize = 22
title.Font = Enum.Font.GothamBold
title.BackgroundTransparency = 1
title.Parent = mainFrame
local separator = Instance.new("Frame")
separator.Size = UDim2.new(1, -20, 0, 1)
separator.Position = UDim2.new(0, 10, 0, 40)
separator.BackgroundColor3 = Color3.fromRGB(60, 60, 60)
separator.BorderSizePixel = 0
separator.Parent = mainFrame
local function createRow(y, labelText, boxWidth)
local row = Instance.new("Frame")
row.Size = UDim2.new(1, -20, 0, 32)
row.Position = UDim2.new(0, 10, 0, y)
row.BackgroundTransparency = 1
row.Parent = mainFrame
local lbl = Instance.new("TextLabel")
lbl.Size = UDim2.new(0, 120, 1, 0)
lbl.Position = UDim2.new(0, 0, 0, 0)
lbl.Text = labelText
lbl.TextColor3 = Color3.fromRGB(200, 200, 200)
lbl.TextSize = 14
lbl.TextXAlignment = Enum.TextXAlignment.Right
lbl.BackgroundTransparency = 1
lbl.Parent = row
local box = Instance.new("TextBox")
box.Size = UDim2.new(0, boxWidth or 240, 1, 0)
box.Position = UDim2.new(0, 130, 0, 0)
box.Text = ""
box.TextColor3 = Color3.fromRGB(255, 255, 255)
box.TextSize = 14
box.Font = Enum.Font.Gotham
box.BackgroundColor3 = Color3.fromRGB(55, 55, 55)
box.BorderSizePixel = 0
box.ClearTextOnFocus = false
box.Parent = row
return box, row
end
local contentBox, contentRow = createRow(52, "Content:", 240)
contentBox.Text = "https://brial.cn/"
local fgBox, fgRow = createRow(94, "Foreground:", 120)
fgBox.Text = "0,0,0"
local bgBox, bgRow = createRow(136, "Background:", 120)
bgBox.Text = "255,255,255"
local pixelBox, pixelRow = createRow(178, "Pixel Size:", 80)
pixelBox.Text = "10"
local genBtn = Instance.new("TextButton")
genBtn.Size = UDim2.new(0, 200, 0, 38)
genBtn.Position = UDim2.new(0, 130, 0, 226)
genBtn.Text = "Generate QR Code"
genBtn.TextColor3 = Color3.fromRGB(255, 255, 255)
genBtn.TextSize = 16
genBtn.Font = Enum.Font.GothamBold
genBtn.BackgroundColor3 = Color3.fromRGB(0, 120, 215)
genBtn.BorderSizePixel = 0
genBtn.Parent = mainFrame
local previewLabel = Instance.new("TextLabel")
previewLabel.Size = UDim2.new(1, -20, 0, 20)
previewLabel.Position = UDim2.new(0, 10, 0, 280)
previewLabel.Text = "Preview"
previewLabel.TextColor3 = Color3.fromRGB(150, 150, 150)
previewLabel.TextSize = 12
previewLabel.TextXAlignment = Enum.TextXAlignment.Left
previewLabel.BackgroundTransparency = 1
previewLabel.Parent = mainFrame
local previewFrame = Instance.new("Frame")
previewFrame.Size = UDim2.new(1, -20, 0, 160)
previewFrame.Position = UDim2.new(0, 10, 0, 304)
previewFrame.BackgroundColor3 = Color3.fromRGB(220, 220, 220)
previewFrame.BorderSizePixel = 1
previewFrame.BorderColor3 = Color3.fromRGB(80, 80, 80)
previewFrame.ClipsDescendants = true
previewFrame.Parent = mainFrame
local previewPlaceholder = Instance.new("TextLabel")
previewPlaceholder.Size = UDim2.new(1, 0, 1, 0)
previewPlaceholder.Text = "QR code preview"
previewPlaceholder.TextColor3 = Color3.fromRGB(120, 120, 120)
previewPlaceholder.TextSize = 14
previewPlaceholder.BackgroundTransparency = 1
previewPlaceholder.Parent = previewFrame
local statusLabel = Instance.new("TextLabel")
statusLabel.Size = UDim2.new(1, -20, 0, 28)
statusLabel.Position = UDim2.new(0, 10, 1, -32)
statusLabel.Text = "Ready"
statusLabel.TextColor3 = Color3.fromRGB(150, 255, 150)
statusLabel.TextSize = 13
statusLabel.TextXAlignment = Enum.TextXAlignment.Left
statusLabel.BackgroundTransparency = 1
statusLabel.Parent = mainFrame
local QR = {}
local VERSION_INFO = {
[1] = {size = 21, data = 19, ec = 7, capacity = 17, align = nil},
[2] = {size = 25, data = 34, ec = 10, capacity = 32, align = {7, 19}},
[3] = {size = 29, data = 55, ec = 15, capacity = 53, align = {7, 23}},
[4] = {size = 33, data = 80, ec = 20, capacity = 78, align = {7, 27}},
}
local gfExp = {}
local gfLog = {}
do
local x = 1
for i = 0, 254 do
gfExp[i] = x
gfLog[x] = i
x = bit32.lshift(x, 1)
if x >= 256 then
x = bit32.bxor(x, 0x11D)
end
end
for i = 255, 511 do
gfExp[i] = gfExp[i - 255]
end
end
local function gfMul(a, b)
if a == 0 or b == 0 then
return 0
end
return gfExp[gfLog[a] + gfLog[b]]
end
local function getBit(num, i)
return bit32.band(bit32.rshift(num, i), 1) ~= 0
end
local function chooseVersion(byteCount)
for v = 1, 4 do
if byteCount <= VERSION_INFO[v].capacity then
return v
end
end
return nil
end
local function makeBytes(str)
local t = {}
for i = 1, #str do
t[#t + 1] = string.byte(str, i)
end
return t
end
local function appendBits(bits, value, count)
for i = count - 1, 0, -1 do
bits[#bits + 1] = getBit(value, i) and 1 or 0
end
end
local function makeDataCodewords(bytes, version)
local info = VERSION_INFO[version]
local bits = {}
appendBits(bits, 0x4, 4)
appendBits(bits, #bytes, 8)
for _, b in ipairs(bytes) do
appendBits(bits, b, 8)
end
local maxBits = info.data * 8
local terminator = math.min(4, maxBits - #bits)
appendBits(bits, 0, terminator)
while #bits % 8 ~= 0 do
bits[#bits + 1] = 0
end
local data = {}
for i = 1, #bits, 8 do
local v = 0
for j = 0, 7 do
v = bit32.bor(bit32.lshift(v, 1), bits[i + j])
end
data[#data + 1] = v
end
local pads = {0xEC, 0x11}
local p = 1
while #data < info.data do
data[#data + 1] = pads[p]
p = 3 - p
end
return data
end
local function reedSolomon(data, degree)
local gen = {1}
for i = 0, degree - 1 do
local nextGen = {}
for j = 1, #gen + 1 do
nextGen[j] = 0
end
for j = 1, #gen do
nextGen[j] = bit32.bxor(nextGen[j], gen[j])
nextGen[j + 1] = bit32.bxor(nextGen[j + 1], gfMul(gen[j], gfExp[i]))
end
gen = nextGen
end
local rem = {}
for i = 1, degree do
rem[i] = 0
end
for _, b in ipairs(data) do
local factor = bit32.bxor(b, rem[1])
for i = 1, degree - 1 do
rem[i] = rem[i + 1]
end
rem[degree] = 0
for i = 1, degree do
rem[i] = bit32.bxor(rem[i], gfMul(gen[i + 1], factor))
end
end
return rem
end
local function makeMatrix(size)
local matrix = {}
local reserved = {}
for y = 1, size do
matrix[y] = {}
reserved[y] = {}
for x = 1, size do
matrix[y][x] = false
reserved[y][x] = false
end
end
local function setModule(x, y, dark, isReserved)
matrix[y][x] = dark
if isReserved then
reserved[y][x] = true
end
end
return matrix, reserved, setModule
end
local function addFinder(setModule, size, x, y)
for dy = -1, 7 do
for dx = -1, 7 do
local xx = x + dx
local yy = y + dy
if xx >= 1 and xx <= size and yy >= 1 and yy <= size then
local dark =
(dx >= 0 and dx <= 6 and dy >= 0 and dy <= 6) and
(dx == 0 or dx == 6 or dy == 0 or dy == 6 or
(dx >= 2 and dx <= 4 and dy >= 2 and dy <= 4))
setModule(xx, yy, dark, true)
end
end
end
end
local function addAlignment(setModule, cx, cy)
for dy = -2, 2 do
for dx = -2, 2 do
local dist = math.max(math.abs(dx), math.abs(dy))
setModule(cx + dx, cy + dy, dist ~= 1, true)
end
end
end
local function addFunctionPatterns(matrix, reserved, setModule, version)
local size = VERSION_INFO[version].size
addFinder(setModule, size, 1, 1)
addFinder(setModule, size, size - 6, 1)
addFinder(setModule, size, 1, size - 6)
for i = 9, size - 8 do
local dark = i % 2 == 1
setModule(i, 7, dark, true)
setModule(7, i, dark, true)
end
local align = VERSION_INFO[version].align
if align then
for _, cy in ipairs(align) do
for _, cx in ipairs(align) do
local nearTL = cx <= 9 and cy <= 9
local nearTR = cx >= size - 8 and cy <= 9
local nearBL = cx <= 9 and cy >= size - 8
if not nearTL and not nearTR and not nearBL then
addAlignment(setModule, cx, cy)
end
end
end
end
setModule(9, size - 7, true, true)
for i = 1, 9 do
if i ~= 7 then
reserved[9][i] = true
reserved[i][9] = true
end
end
for i = size - 7, size do
reserved[9][i] = true
reserved[i][9] = true
end
end
local function makeFormatBits(mask)
local data = bit32.bor(bit32.lshift(1, 3), mask)
local rem = bit32.lshift(data, 10)
local gen = 0x537
for i = 14, 10, -1 do
if getBit(rem, i) then
rem = bit32.bxor(rem, bit32.lshift(gen, i - 10))
end
end
return bit32.bxor(bit32.bor(bit32.lshift(data, 10), rem), 0x5412)
end
local function drawFormatBits(matrix, mask)
local size = #matrix
local bits = makeFormatBits(mask)
local function set(x, y, bitIndex)
matrix[y][x] = getBit(bits, bitIndex)
end
for i = 0, 5 do
set(i + 1, 9, i)
end
set(8, 9, 6)
set(9, 9, 7)
set(9, 8, 8)
for i = 9, 14 do
set(15 - i, 9, i)
end
for i = 0, 7 do
set(9, size - i, i)
end
for i = 8, 14 do
set(size - 14 + i, 9, i)
end
matrix[size - 7][9] = true
end
local function maskCondition(mask, x, y)
local r = y - 1
local c = x - 1
if mask == 0 then
return (r + c) % 2 == 0
end
return false
end
function QR.generate(text)
local bytes = makeBytes(text)
local version = chooseVersion(#bytes)
if not version then
error("Content too long: maximum 78 bytes supported. Chinese characters typically use 3 bytes each.")
end
local info = VERSION_INFO[version]
local size = info.size
local matrix, reserved, setModule = makeMatrix(size)
addFunctionPatterns(matrix, reserved, setModule, version)
local data = makeDataCodewords(bytes, version)
local ec = reedSolomon(data, info.ec)
local all = {}
for _, v in ipairs(data) do
all[#all + 1] = v
end
for _, v in ipairs(ec) do
all[#all + 1] = v
end
local bits = {}
for _, b in ipairs(all) do
for i = 7, 0, -1 do
bits[#bits + 1] = getBit(b, i) and 1 or 0
end
end
local bitIndex = 1
local upward = true
local x = size
while x >= 1 do
if x == 7 then
x = x - 1
end
for i = 1, size do
local y = upward and (size - i + 1) or i
for dx = 0, 1 do
local xx = x - dx
if xx >= 1 and not reserved[y][xx] then
local bit = false
if bitIndex <= #bits then
bit = bits[bitIndex] == 1
bitIndex = bitIndex + 1
end
if maskCondition(0, xx, y) then
bit = not bit
end
matrix[y][xx] = bit
end
end
end
upward = not upward
x = x - 2
end
drawFormatBits(matrix, 0)
return matrix, version
end
local function parseColor(str)
local nums = {}
for n in string.gmatch(str, "%d+") do
nums[#nums + 1] = tonumber(n)
end
if #nums < 3 then
return nil
end
return Color3.fromRGB(
math.clamp(nums[1], 0, 255),
math.clamp(nums[2], 0, 255),
math.clamp(nums[3], 0, 255)
)
end
local function clearPreview()
for _, child in ipairs(previewFrame:GetChildren()) do
if child:IsA("Frame") and child ~= previewPlaceholder then
child:Destroy()
end
end
previewPlaceholder.Visible = true
end
local function drawQRCode(parent, matrix, fg, bg, pixel, quietZone)
local size = #matrix
local total = size + quietZone * 2
parent.BackgroundColor3 = bg
parent.Size = UDim2.new(0, total * pixel, 0, total * pixel)
for y = 1, size do
for x = 1, size do
if matrix[y][x] then
local p = Instance.new("Frame")
p.Size = UDim2.new(0, pixel, 0, pixel)
p.Position = UDim2.new(0, (x - 1 + quietZone) * pixel, 0, (y - 1 + quietZone) * pixel)
p.BackgroundColor3 = fg
p.BorderSizePixel = 0
p.Parent = parent
end
end
end
end
local function createQRInStarterGui(content, fg, bg, pixel)
local matrix, version = QR.generate(content)
local quietZone = 4
local size = #matrix
local total = size + quietZone * 2
local starterGui = game:GetService("StarterGui")
for _, child in ipairs(starterGui:GetChildren()) do
if child:IsA("ScreenGui") and string.sub(child.Name, 1, 8) == "QRCode_" then
child:Destroy()
end
end
local gui = Instance.new("ScreenGui")
gui.Name = "QRCode_" .. os.time()
gui.ResetOnSpawn = false
gui.IgnoreGuiInset = true
local container = Instance.new("Frame")
container.Name = "QRCode"
container.AnchorPoint = Vector2.new(0.5, 0.5)
container.Position = UDim2.new(0.5, 0, 0.5, 0)
container.BorderSizePixel = 0
container.Parent = gui
drawQRCode(container, matrix, fg, bg, pixel, quietZone)
gui.Parent = starterGui
return matrix, version, total * pixel
end
genBtn.MouseButton1Click:Connect(function()
local content = contentBox.Text
if content == "" then
statusLabel.Text = "Error: Please enter content"
statusLabel.TextColor3 = Color3.fromRGB(255, 100, 100)
return
end
local fg = parseColor(fgBox.Text)
local bg = parseColor(bgBox.Text)
if not fg then
statusLabel.Text = "Error: Invalid foreground color format (e.g. 0,0,0)"
statusLabel.TextColor3 = Color3.fromRGB(255, 100, 100)
return
end
if not bg then
statusLabel.Text = "Error: Invalid background color format (e.g. 255,255,255)"
statusLabel.TextColor3 = Color3.fromRGB(255, 100, 100)
return
end
if fg == bg then
statusLabel.Text = "Error: Foreground and background colors cannot be the same"
statusLabel.TextColor3 = Color3.fromRGB(255, 100, 100)
return
end
local pixel = tonumber(pixelBox.Text) or 10
pixel = math.clamp(math.floor(pixel), 4, 40)
local ok, resultOrErr, version, finalSize = pcall(function()
return createQRInStarterGui(content, fg, bg, pixel)
end)
if not ok then
statusLabel.Text = "Generation failed: " .. tostring(resultOrErr)
statusLabel.TextColor3 = Color3.fromRGB(255, 100, 100)
return
end
local matrix = resultOrErr
clearPreview()
previewPlaceholder.Visible = false
local previewSize = previewFrame.AbsoluteSize.Y
local previewPixel = math.floor(previewSize / (#matrix + 8))
if previewPixel < 1 then
previewPixel = 1
end
local previewContainer = Instance.new("Frame")
previewContainer.Position = UDim2.new(0.5, 0, 0.5, 0)
previewContainer.AnchorPoint = Vector2.new(0.5, 0.5)
previewContainer.BorderSizePixel = 0
previewContainer.Parent = previewFrame
drawQRCode(previewContainer, matrix, fg, bg, previewPixel, 4)
statusLabel.Text = "Generated: Version " .. tostring(version) .. ", Size " .. tostring(finalSize) .. "x" .. tostring(finalSize)
statusLabel.TextColor3 = Color3.fromRGB(150, 255, 150)
end)
button.Click:Connect(function()
widget.Enabled = not widget.Enabled
end)
print("BrialQRify loaded successfully")]]></ProtectedString>
<bool name="Disabled">false</bool>
<Content name="LinkedSource"><null></null></Content>
<token name="RunContext">0</token>
<string name="ScriptGuid">{BD223D70-4966-4F6F-A8A9-580F26EDC1D9}</string>
<BinaryString name="AttributesSerialize"></BinaryString>
<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
<bool name="DefinesCapabilities">false</bool>
<string name="Name">Main</string>
<int64 name="SourceAssetId">-1</int64>
<BinaryString name="Tags"></BinaryString>
</Properties>
</Item>
</roblox>