mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2025-12-20 11:09:21 +01:00
Rendering support for fucking W I D E characters
This commit is contained in:
parent
a575a74b8d
commit
cdbb421e7e
@ -131,7 +131,7 @@ for i = 1, #modules do
|
|||||||
object.draw = moduleDraw
|
object.draw = moduleDraw
|
||||||
object.eventHandler = moduleEventHandler
|
object.eventHandler = moduleEventHandler
|
||||||
|
|
||||||
leftPanel.width = math.max(leftPanel.width, unicode.len(result.name) + 14)
|
leftPanel.width = math.max(leftPanel.width, unicode.wlen(result.name) + 14)
|
||||||
else
|
else
|
||||||
error("Failed to execute module " .. modules[i] .. ": " .. tostring(result))
|
error("Failed to execute module " .. modules[i] .. ": " .. tostring(result))
|
||||||
end
|
end
|
||||||
|
|||||||
@ -550,7 +550,7 @@ local function pressableDraw(pressable)
|
|||||||
screen.drawRectangle(pressable.x, pressable.y, pressable.width, pressable.height, background, text, " ")
|
screen.drawRectangle(pressable.x, pressable.y, pressable.width, pressable.height, background, text, " ")
|
||||||
end
|
end
|
||||||
|
|
||||||
screen.drawText(math.floor(pressable.x + pressable.width / 2 - unicode.len(pressable.text) / 2), math.floor(pressable.y + pressable.height / 2), text, pressable.text)
|
screen.drawText(math.floor(pressable.x + pressable.width / 2 - unicode.wlen(pressable.text) / 2), math.floor(pressable.y + pressable.height / 2), text, pressable.text)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function pressableHandlePress(workspace, pressable, ...)
|
local function pressableHandlePress(workspace, pressable, ...)
|
||||||
@ -672,7 +672,7 @@ local function buttonGetColors(button)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function buttonDrawText(button, textColor)
|
local function buttonDrawText(button, textColor)
|
||||||
screen.drawText(math.floor(button.x + button.width / 2 - unicode.len(button.text) / 2), math.floor(button.y + button.height / 2), textColor, button.text)
|
screen.drawText(math.floor(button.x + button.width / 2 - unicode.wlen(button.text) / 2), math.floor(button.y + button.height / 2), textColor, button.text)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function buttonDraw(button)
|
local function buttonDraw(button)
|
||||||
@ -741,7 +741,7 @@ local function buttonCreate(x, y, width, height, backgroundColor, textColor, bac
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function adaptiveButtonCreate(x, y, xOffset, yOffset, backgroundColor, textColor, backgroundPressedColor, textPressedColor, text)
|
local function adaptiveButtonCreate(x, y, xOffset, yOffset, backgroundColor, textColor, backgroundPressedColor, textPressedColor, text)
|
||||||
return buttonCreate(x, y, unicode.len(text) + xOffset * 2, yOffset * 2 + 1, backgroundColor, textColor, backgroundPressedColor, textPressedColor, text)
|
return buttonCreate(x, y, unicode.wlen(text) + xOffset * 2, yOffset * 2 + 1, backgroundColor, textColor, backgroundPressedColor, textPressedColor, text)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GUI.button(...)
|
function GUI.button(...)
|
||||||
@ -848,7 +848,7 @@ local function drawLabel(object)
|
|||||||
object.height,
|
object.height,
|
||||||
object.horizontalAlignment,
|
object.horizontalAlignment,
|
||||||
object.verticalAlignment,
|
object.verticalAlignment,
|
||||||
unicode.len(object.text),
|
unicode.wlen(object.text),
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
screen.drawText(math.floor(xText), math.floor(yText), object.colors.text, object.text)
|
screen.drawText(math.floor(xText), math.floor(yText), object.colors.text, object.text)
|
||||||
@ -910,7 +910,7 @@ local function drawProgressBar(object)
|
|||||||
|
|
||||||
if object.showValue then
|
if object.showValue then
|
||||||
local stringValue = (object.valuePrefix or "") .. object.value .. (object.valuePostfix or "")
|
local stringValue = (object.valuePrefix or "") .. object.value .. (object.valuePostfix or "")
|
||||||
screen.drawText(math.floor(object.x + object.width / 2 - unicode.len(stringValue) / 2), object.y + 1, object.colors.value, stringValue)
|
screen.drawText(math.floor(object.x + object.width / 2 - unicode.wlen(stringValue) / 2), object.y + 1, object.colors.value, stringValue)
|
||||||
end
|
end
|
||||||
|
|
||||||
return object
|
return object
|
||||||
@ -1013,7 +1013,7 @@ local function codeViewDraw(codeView)
|
|||||||
local y, toLine, colorScheme, patterns = codeView.y, codeView.fromLine + codeView.height - 1, codeView.syntaxColorScheme, codeView.syntaxPatterns
|
local y, toLine, colorScheme, patterns = codeView.y, codeView.fromLine + codeView.height - 1, codeView.syntaxColorScheme, codeView.syntaxPatterns
|
||||||
|
|
||||||
-- Line numbers bar and code area
|
-- Line numbers bar and code area
|
||||||
codeView.lineNumbersWidth = unicode.len(tostring(toLine)) + 2
|
codeView.lineNumbersWidth = unicode.wlen(tostring(toLine)) + 2
|
||||||
codeView.codeAreaPosition = codeView.x + codeView.lineNumbersWidth
|
codeView.codeAreaPosition = codeView.x + codeView.lineNumbersWidth
|
||||||
codeView.codeAreaWidth = codeView.width - codeView.lineNumbersWidth
|
codeView.codeAreaWidth = codeView.width - codeView.lineNumbersWidth
|
||||||
|
|
||||||
@ -1033,7 +1033,7 @@ local function codeViewDraw(codeView)
|
|||||||
screen.drawRectangle(codeView.codeAreaPosition, y, codeView.codeAreaWidth, 1, codeView.highlights[line], colorScheme.text, " ")
|
screen.drawRectangle(codeView.codeAreaPosition, y, codeView.codeAreaWidth, 1, codeView.highlights[line], colorScheme.text, " ")
|
||||||
end
|
end
|
||||||
|
|
||||||
screen.drawText(codeView.codeAreaPosition - unicode.len(text) - 1, y, colorScheme.lineNumbersText, text)
|
screen.drawText(codeView.codeAreaPosition - unicode.wlen(text) - 1, y, colorScheme.lineNumbersText, text)
|
||||||
|
|
||||||
y = y + 1
|
y = y + 1
|
||||||
else
|
else
|
||||||
@ -1295,21 +1295,21 @@ local function drawChart(object)
|
|||||||
for y = object.y + object.height - 3, object.y + 1, -chartHeight * object.yAxisValueInterval do
|
for y = object.y + object.height - 3, object.y + 1, -chartHeight * object.yAxisValueInterval do
|
||||||
local stringValue = getAxisValue(value, object.yAxisPostfix, object.roundValues)
|
local stringValue = getAxisValue(value, object.yAxisPostfix, object.roundValues)
|
||||||
|
|
||||||
yAxisValueMaxWidth = math.max(yAxisValueMaxWidth, unicode.len(stringValue))
|
yAxisValueMaxWidth = math.max(yAxisValueMaxWidth, unicode.wlen(stringValue))
|
||||||
table.insert(yAxisValues, {y = math.ceil(y), value = stringValue})
|
table.insert(yAxisValues, {y = math.ceil(y), value = stringValue})
|
||||||
value = value + dy * object.yAxisValueInterval
|
value = value + dy * object.yAxisValueInterval
|
||||||
end
|
end
|
||||||
|
|
||||||
local stringValue = getAxisValue(yMax, object.yAxisPostfix, object.roundValues)
|
local stringValue = getAxisValue(yMax, object.yAxisPostfix, object.roundValues)
|
||||||
table.insert(yAxisValues, {y = object.y, value = stringValue})
|
table.insert(yAxisValues, {y = object.y, value = stringValue})
|
||||||
yAxisValueMaxWidth = math.max(yAxisValueMaxWidth, unicode.len(stringValue))
|
yAxisValueMaxWidth = math.max(yAxisValueMaxWidth, unicode.wlen(stringValue))
|
||||||
|
|
||||||
local chartWidth = object.width - (object.showYAxisValues and yAxisValueMaxWidth + 2 or 0)
|
local chartWidth = object.width - (object.showYAxisValues and yAxisValueMaxWidth + 2 or 0)
|
||||||
local chartX = object.x + object.width - chartWidth
|
local chartX = object.x + object.width - chartWidth
|
||||||
|
|
||||||
for i = 1, #yAxisValues do
|
for i = 1, #yAxisValues do
|
||||||
if object.showYAxisValues then
|
if object.showYAxisValues then
|
||||||
screen.drawText(chartX - unicode.len(yAxisValues[i].value) - 2, yAxisValues[i].y, object.colors.axisValue, yAxisValues[i].value)
|
screen.drawText(chartX - unicode.wlen(yAxisValues[i].value) - 2, yAxisValues[i].y, object.colors.axisValue, yAxisValues[i].value)
|
||||||
end
|
end
|
||||||
screen.drawText(chartX, yAxisValues[i].y, object.colors.helpers, string.rep("─", chartWidth))
|
screen.drawText(chartX, yAxisValues[i].y, object.colors.helpers, string.rep("─", chartWidth))
|
||||||
end
|
end
|
||||||
@ -1319,11 +1319,11 @@ local function drawChart(object)
|
|||||||
value = xMin
|
value = xMin
|
||||||
for x = chartX, chartX + chartWidth - 2, chartWidth * object.xAxisValueInterval do
|
for x = chartX, chartX + chartWidth - 2, chartWidth * object.xAxisValueInterval do
|
||||||
local stringValue = getAxisValue(value, object.xAxisPostfix, object.roundValues)
|
local stringValue = getAxisValue(value, object.xAxisPostfix, object.roundValues)
|
||||||
screen.drawText(math.floor(x - unicode.len(stringValue) / 2), object.y + object.height - 1, object.colors.axisValue, stringValue)
|
screen.drawText(math.floor(x - unicode.wlen(stringValue) / 2), object.y + object.height - 1, object.colors.axisValue, stringValue)
|
||||||
value = value + dx * object.xAxisValueInterval
|
value = value + dx * object.xAxisValueInterval
|
||||||
end
|
end
|
||||||
local value = getAxisValue(xMax, object.xAxisPostfix, object.roundValues)
|
local value = getAxisValue(xMax, object.xAxisPostfix, object.roundValues)
|
||||||
screen.drawText(object.x + object.width - unicode.len(value), object.y + object.height - 1, object.colors.axisValue, value)
|
screen.drawText(object.x + object.width - unicode.wlen(value), object.y + object.height - 1, object.colors.axisValue, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Axis lines
|
-- Axis lines
|
||||||
@ -1418,13 +1418,13 @@ local function sliderDraw(object)
|
|||||||
|
|
||||||
if object.showMaximumAndMinimumValues then
|
if object.showMaximumAndMinimumValues then
|
||||||
local stringMaximumValue, stringMinimumValue = tostring(object.roundValues and math.floor(object.maximumValue) or number.roundToDecimalPlaces(object.maximumValue, 2)), tostring(object.roundValues and math.floor(object.minimumValue) or number.roundToDecimalPlaces(object.minimumValue, 2))
|
local stringMaximumValue, stringMinimumValue = tostring(object.roundValues and math.floor(object.maximumValue) or number.roundToDecimalPlaces(object.maximumValue, 2)), tostring(object.roundValues and math.floor(object.minimumValue) or number.roundToDecimalPlaces(object.minimumValue, 2))
|
||||||
screen.drawText(object.x - unicode.len(stringMinimumValue) - 1, object.y, object.colors.value, stringMinimumValue)
|
screen.drawText(object.x - unicode.wlen(stringMinimumValue) - 1, object.y, object.colors.value, stringMinimumValue)
|
||||||
screen.drawText(object.x + object.width + 1, object.y, object.colors.value, stringMaximumValue)
|
screen.drawText(object.x + object.width + 1, object.y, object.colors.value, stringMaximumValue)
|
||||||
end
|
end
|
||||||
|
|
||||||
if object.currentValuePrefix or object.currentValuePostfix then
|
if object.currentValuePrefix or object.currentValuePostfix then
|
||||||
local stringCurrentValue = (object.currentValuePrefix or "") .. (object.roundValues and math.floor(object.value) or number.roundToDecimalPlaces(object.value, 2)) .. (object.currentValuePostfix or "")
|
local stringCurrentValue = (object.currentValuePrefix or "") .. (object.roundValues and math.floor(object.value) or number.roundToDecimalPlaces(object.value, 2)) .. (object.currentValuePostfix or "")
|
||||||
screen.drawText(math.floor(object.x + object.width / 2 - unicode.len(stringCurrentValue) / 2), object.y + 1, object.colors.value, stringCurrentValue)
|
screen.drawText(math.floor(object.x + object.width / 2 - unicode.wlen(stringCurrentValue) / 2), object.y + 1, object.colors.value, stringCurrentValue)
|
||||||
end
|
end
|
||||||
|
|
||||||
local activeWidth = number.round((object.value - object.minimumValue) / (object.maximumValue - object.minimumValue) * object.width)
|
local activeWidth = number.round((object.value - object.minimumValue) / (object.maximumValue - object.minimumValue) * object.width)
|
||||||
@ -2029,7 +2029,7 @@ end
|
|||||||
|
|
||||||
local function filesystemDialogAddExtensionFilter(filesystemDialog, extension)
|
local function filesystemDialogAddExtensionFilter(filesystemDialog, extension)
|
||||||
filesystemDialog.extensionComboBox:addItem(extension)
|
filesystemDialog.extensionComboBox:addItem(extension)
|
||||||
filesystemDialog.extensionComboBox.width = math.max(filesystemDialog.extensionComboBox.width, unicode.len(extension) + 3)
|
filesystemDialog.extensionComboBox.width = math.max(filesystemDialog.extensionComboBox.width, unicode.wlen(extension) + 3)
|
||||||
filesystemDialog.extensionComboBox.localX = filesystemDialog.cancelButton.localX - filesystemDialog.extensionComboBox.width - 2
|
filesystemDialog.extensionComboBox.localX = filesystemDialog.cancelButton.localX - filesystemDialog.extensionComboBox.width - 2
|
||||||
filesystemDialog.filesystemTree:addExtensionFilter(extension)
|
filesystemDialog.filesystemTree:addExtensionFilter(extension)
|
||||||
|
|
||||||
@ -2704,7 +2704,7 @@ local function textBoxDraw(object)
|
|||||||
1,
|
1,
|
||||||
object.horizontalAlignment,
|
object.horizontalAlignment,
|
||||||
object.verticalAlignment,
|
object.verticalAlignment,
|
||||||
unicode.len(line),
|
unicode.wlen(line),
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -3611,7 +3611,7 @@ end
|
|||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function textUpdate(object)
|
local function textUpdate(object)
|
||||||
object.width = unicode.len(object.text)
|
object.width = unicode.wlen(object.text)
|
||||||
|
|
||||||
return object
|
return object
|
||||||
end
|
end
|
||||||
@ -3684,7 +3684,7 @@ local function listUpdate(list)
|
|||||||
-- Размеры хуйни
|
-- Размеры хуйни
|
||||||
if list.cells[1][1].direction == GUI.DIRECTION_HORIZONTAL then
|
if list.cells[1][1].direction == GUI.DIRECTION_HORIZONTAL then
|
||||||
if list.offsetMode then
|
if list.offsetMode then
|
||||||
child.width, child.height = list.itemSize * 2 + unicode.len(child.text), list.height
|
child.width, child.height = list.itemSize * 2 + unicode.wlen(child.text), list.height
|
||||||
else
|
else
|
||||||
child.width, child.height = list.itemSize, list.height
|
child.width, child.height = list.itemSize, list.height
|
||||||
end
|
end
|
||||||
@ -3819,7 +3819,7 @@ end
|
|||||||
---------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function keyAndValueUpdate(object)
|
local function keyAndValueUpdate(object)
|
||||||
object.keyLength, object.valueLength = unicode.len(object.key), unicode.len(object.value)
|
object.keyLength, object.valueLength = unicode.wlen(object.key), unicode.wlen(object.value)
|
||||||
object.width = object.keyLength + object.valueLength
|
object.width = object.keyLength + object.valueLength
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3931,8 +3931,9 @@ local function dropDownMenuItemDraw(item)
|
|||||||
end
|
end
|
||||||
|
|
||||||
screen.drawText(item.x + 1, yText, textColor, item.text)
|
screen.drawText(item.x + 1, yText, textColor, item.text)
|
||||||
|
|
||||||
if item.shortcut then
|
if item.shortcut then
|
||||||
screen.drawText(item.x + item.width - unicode.len(item.shortcut) - 1, yText, textColor, item.shortcut)
|
screen.drawText(item.x + item.width - unicode.wlen(item.shortcut) - 1, yText, textColor, item.shortcut)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
screen.drawText(item.x, yText, item.parent.parent.colors.separator, string.rep("─", item.width))
|
screen.drawText(item.x, yText, item.parent.parent.colors.separator, string.rep("─", item.width))
|
||||||
@ -4182,9 +4183,10 @@ local function contextMenuUpdate(menu)
|
|||||||
local widestItem, widestShortcut = 0, 0
|
local widestItem, widestShortcut = 0, 0
|
||||||
for i = 1, #menu.itemsContainer.children do
|
for i = 1, #menu.itemsContainer.children do
|
||||||
if menu.itemsContainer.children[i].type == 1 then
|
if menu.itemsContainer.children[i].type == 1 then
|
||||||
widestItem = math.max(widestItem, unicode.len(menu.itemsContainer.children[i].text))
|
widestItem = math.max(widestItem, unicode.wlen(menu.itemsContainer.children[i].text))
|
||||||
|
|
||||||
if menu.itemsContainer.children[i].shortcut then
|
if menu.itemsContainer.children[i].shortcut then
|
||||||
widestShortcut = math.max(widestShortcut, unicode.len(menu.itemsContainer.children[i].shortcut))
|
widestShortcut = math.max(widestShortcut, unicode.wlen(menu.itemsContainer.children[i].shortcut))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -4596,7 +4598,7 @@ local function menuDraw(menu)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function menuAddItem(menu, text, textColor)
|
local function menuAddItem(menu, text, textColor)
|
||||||
local item = menu:addChild(pressable(1, 1, unicode.len(text) + 2, 1, nil, textColor or menu.colors.default.text, menu.colors.selected.background, menu.colors.selected.text, 0x0, 0x0, text))
|
local item = menu:addChild(pressable(1, 1, unicode.wlen(text) + 2, 1, nil, textColor or menu.colors.default.text, menu.colors.selected.background, menu.colors.selected.text, 0x0, 0x0, text))
|
||||||
item.eventHandler = pressableEventHandler
|
item.eventHandler = pressableEventHandler
|
||||||
|
|
||||||
return item
|
return item
|
||||||
|
|||||||
@ -22,16 +22,18 @@ local
|
|||||||
|
|
||||||
unicodeLen,
|
unicodeLen,
|
||||||
unicodeSub,
|
unicodeSub,
|
||||||
|
unicodeWlen,
|
||||||
|
unicodeWlenCache,
|
||||||
|
|
||||||
bufferWidth,
|
bufferWidth,
|
||||||
bufferHeight,
|
bufferHeight,
|
||||||
|
|
||||||
currentFrameBackgrounds,
|
currentFrameBackgrounds,
|
||||||
currentFrameForegrounds,
|
currentFrameForegrounds,
|
||||||
currentFrameSymbols,
|
currentFrameChars,
|
||||||
newFrameBackgrounds,
|
newFrameBackgrounds,
|
||||||
newFrameForegrounds,
|
newFrameForegrounds,
|
||||||
newFrameSymbols,
|
newFrameChars,
|
||||||
|
|
||||||
drawLimitX1,
|
drawLimitX1,
|
||||||
drawLimitX2,
|
drawLimitX2,
|
||||||
@ -56,7 +58,9 @@ local
|
|||||||
color.integerToRGB,
|
color.integerToRGB,
|
||||||
|
|
||||||
unicode.len,
|
unicode.len,
|
||||||
unicode.sub;
|
unicode.sub,
|
||||||
|
unicode.wlen,
|
||||||
|
{};
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -65,11 +69,11 @@ local function getIndex(x, y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function getCurrentFrameTables()
|
local function getCurrentFrameTables()
|
||||||
return currentFrameBackgrounds, currentFrameForegrounds, currentFrameSymbols
|
return currentFrameBackgrounds, currentFrameForegrounds, currentFrameChars
|
||||||
end
|
end
|
||||||
|
|
||||||
local function getNewFrameTables()
|
local function getNewFrameTables()
|
||||||
return newFrameBackgrounds, newFrameForegrounds, newFrameSymbols
|
return newFrameBackgrounds, newFrameForegrounds, newFrameChars
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
@ -93,7 +97,7 @@ local function flush(width, height)
|
|||||||
width, height = componentInvoke(GPUAddress, "getResolution")
|
width, height = componentInvoke(GPUAddress, "getResolution")
|
||||||
end
|
end
|
||||||
|
|
||||||
currentFrameBackgrounds, currentFrameForegrounds, currentFrameSymbols, newFrameBackgrounds, newFrameForegrounds, newFrameSymbols = {}, {}, {}, {}, {}, {}
|
currentFrameBackgrounds, currentFrameForegrounds, currentFrameChars, newFrameBackgrounds, newFrameForegrounds, newFrameChars = {}, {}, {}, {}, {}, {}
|
||||||
bufferWidth = width
|
bufferWidth = width
|
||||||
bufferHeight = height
|
bufferHeight = height
|
||||||
|
|
||||||
@ -106,8 +110,8 @@ local function flush(width, height)
|
|||||||
currentFrameForegrounds[i] = 0xFEFEFE
|
currentFrameForegrounds[i] = 0xFEFEFE
|
||||||
newFrameForegrounds[i] = 0xFEFEFE
|
newFrameForegrounds[i] = 0xFEFEFE
|
||||||
|
|
||||||
currentFrameSymbols[i] = " "
|
currentFrameChars[i] = " "
|
||||||
newFrameSymbols[i] = " "
|
newFrameChars[i] = " "
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -199,31 +203,62 @@ end
|
|||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function rawSet(index, background, foreground, symbol)
|
local function rawSet(index, background, foreground, char)
|
||||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, foreground, symbol
|
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = background, foreground, char
|
||||||
end
|
end
|
||||||
|
|
||||||
local function rawGet(index)
|
local function rawGet(index)
|
||||||
return newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index]
|
return newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index]
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get(x, y)
|
local function get(x, y)
|
||||||
if x >= 1 and y >= 1 and x <= bufferWidth and y <= bufferHeight then
|
if x >= 1 and y >= 1 and x <= bufferWidth and y <= bufferHeight then
|
||||||
local index = bufferWidth * (y - 1) + x
|
local index = bufferWidth * (y - 1) + x
|
||||||
return newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index]
|
|
||||||
|
return newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index]
|
||||||
else
|
else
|
||||||
return 0x000000, 0x000000, " "
|
return 0x000000, 0x000000, " "
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function set(x, y, background, foreground, symbol)
|
local function set(x, y, background, foreground, char)
|
||||||
if x >= drawLimitX1 and y >= drawLimitY1 and x <= drawLimitX2 and y <= drawLimitY2 then
|
if x < drawLimitX1 or y < drawLimitY1 or x > drawLimitX2 or y > drawLimitY2 then
|
||||||
local index = bufferWidth * (y - 1) + x
|
return
|
||||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, foreground, symbol
|
end
|
||||||
|
|
||||||
|
local
|
||||||
|
index,
|
||||||
|
charWlen =
|
||||||
|
bufferWidth * (y - 1) + x,
|
||||||
|
unicodeWlenCache[char]
|
||||||
|
|
||||||
|
if not charWlen then
|
||||||
|
charWlen = unicodeWlen(char)
|
||||||
|
unicodeWlenCache[char] = charWlen
|
||||||
|
end
|
||||||
|
|
||||||
|
newFrameBackgrounds[index],
|
||||||
|
newFrameForegrounds[index],
|
||||||
|
newFrameChars[index] =
|
||||||
|
background,
|
||||||
|
foreground,
|
||||||
|
char
|
||||||
|
|
||||||
|
index = index + 1
|
||||||
|
|
||||||
|
for i = 2, charWlen do
|
||||||
|
newFrameBackgrounds[index],
|
||||||
|
newFrameForegrounds[index],
|
||||||
|
newFrameChars[index] =
|
||||||
|
background,
|
||||||
|
foreground,
|
||||||
|
" "
|
||||||
|
|
||||||
|
index = index + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function drawRectangle(x, y, width, height, background, foreground, symbol, transparency)
|
local function drawRectangle(x, y, width, height, background, foreground, char, transparency)
|
||||||
local temp
|
local temp
|
||||||
|
|
||||||
-- Clipping left
|
-- Clipping left
|
||||||
@ -272,7 +307,7 @@ local function drawRectangle(x, y, width, height, background, foreground, symbol
|
|||||||
for i = 1, width do
|
for i = 1, width do
|
||||||
newFrameBackgrounds[temp],
|
newFrameBackgrounds[temp],
|
||||||
newFrameForegrounds[temp],
|
newFrameForegrounds[temp],
|
||||||
newFrameSymbols[temp] = background, foreground, symbol
|
newFrameChars[temp] = background, foreground, char
|
||||||
|
|
||||||
temp = temp + 1
|
temp = temp + 1
|
||||||
end
|
end
|
||||||
@ -361,7 +396,7 @@ local function blur(x, y, width, height, radius, color, transparency)
|
|||||||
|
|
||||||
newFrameBackgrounds[screenIndex] = colorRGBToInteger(r, g, b)
|
newFrameBackgrounds[screenIndex] = colorRGBToInteger(r, g, b)
|
||||||
newFrameForegrounds[screenIndex] = 0x0
|
newFrameForegrounds[screenIndex] = 0x0
|
||||||
newFrameSymbols[screenIndex] = " "
|
newFrameChars[screenIndex] = " "
|
||||||
|
|
||||||
screenIndex = screenIndex + 1
|
screenIndex = screenIndex + 1
|
||||||
end
|
end
|
||||||
@ -383,7 +418,7 @@ local function copy(x, y, width, height)
|
|||||||
index = bufferWidth * (j - 1) + i
|
index = bufferWidth * (j - 1) + i
|
||||||
tableInsert(copyArray, newFrameBackgrounds[index])
|
tableInsert(copyArray, newFrameBackgrounds[index])
|
||||||
tableInsert(copyArray, newFrameForegrounds[index])
|
tableInsert(copyArray, newFrameForegrounds[index])
|
||||||
tableInsert(copyArray, newFrameSymbols[index])
|
tableInsert(copyArray, newFrameChars[index])
|
||||||
else
|
else
|
||||||
tableInsert(copyArray, 0x0)
|
tableInsert(copyArray, 0x0)
|
||||||
tableInsert(copyArray, 0x0)
|
tableInsert(copyArray, 0x0)
|
||||||
@ -405,7 +440,7 @@ local function paste(startX, startY, picture)
|
|||||||
if x >= drawLimitX1 and x <= drawLimitX2 then
|
if x >= drawLimitX1 and x <= drawLimitX2 then
|
||||||
newFrameBackgrounds[screenIndex] = picture[pictureIndex]
|
newFrameBackgrounds[screenIndex] = picture[pictureIndex]
|
||||||
newFrameForegrounds[screenIndex] = picture[pictureIndex + 1]
|
newFrameForegrounds[screenIndex] = picture[pictureIndex + 1]
|
||||||
newFrameSymbols[screenIndex] = picture[pictureIndex + 2]
|
newFrameChars[screenIndex] = picture[pictureIndex + 2]
|
||||||
end
|
end
|
||||||
|
|
||||||
screenIndex, pictureIndex = screenIndex + 1, pictureIndex + 3
|
screenIndex, pictureIndex = screenIndex + 1, pictureIndex + 3
|
||||||
@ -517,37 +552,56 @@ local function rasterizePolygon(centerX, centerY, startX, startY, countOfEdges,
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function drawLine(x1, y1, x2, y2, background, foreground, symbol)
|
local function drawLine(x1, y1, x2, y2, background, foreground, char)
|
||||||
rasterizeLine(x1, y1, x2, y2, function(x, y)
|
rasterizeLine(x1, y1, x2, y2, function(x, y)
|
||||||
set(x, y, background, foreground, symbol)
|
set(x, y, background, foreground, char)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function drawEllipse(centerX, centerY, radiusX, radiusY, background, foreground, symbol)
|
local function drawEllipse(centerX, centerY, radiusX, radiusY, background, foreground, char)
|
||||||
rasterizeEllipse(centerX, centerY, radiusX, radiusY, function(x, y)
|
rasterizeEllipse(centerX, centerY, radiusX, radiusY, function(x, y)
|
||||||
set(x, y, background, foreground, symbol)
|
set(x, y, background, foreground, char)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function drawPolygon(centerX, centerY, radiusX, radiusY, background, foreground, countOfEdges, symbol)
|
local function drawPolygon(centerX, centerY, radiusX, radiusY, background, foreground, countOfEdges, char)
|
||||||
rasterizePolygon(centerX, centerY, radiusX, radiusY, countOfEdges, function(x, y)
|
rasterizePolygon(centerX, centerY, radiusX, radiusY, countOfEdges, function(x, y)
|
||||||
set(x, y, background, foreground, symbol)
|
set(x, y, background, foreground, char)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function drawText(x, y, textColor, data, transparency)
|
local function drawText(x, y, textColor, text, transparency)
|
||||||
if y >= drawLimitY1 and y <= drawLimitY2 then
|
if y < drawLimitY1 or y > drawLimitY2 then
|
||||||
local charIndex, screenIndex = 1, bufferWidth * (y - 1) + x
|
return
|
||||||
|
end
|
||||||
|
|
||||||
for charIndex = 1, unicodeLen(data) do
|
local
|
||||||
if x >= drawLimitX1 and x <= drawLimitX2 then
|
charIndex,
|
||||||
|
screenIndex,
|
||||||
|
|
||||||
|
char,
|
||||||
|
charWlen =
|
||||||
|
1,
|
||||||
|
bufferWidth * (y - 1) + x
|
||||||
|
|
||||||
|
for charIndex = 1, unicodeLen(text) do
|
||||||
|
char = unicodeSub(text, charIndex, charIndex)
|
||||||
|
charWlen = unicodeWlenCache[char]
|
||||||
|
|
||||||
|
if not charWlen then
|
||||||
|
charWlen = unicodeWlen(char)
|
||||||
|
unicodeWlenCache[char] = charWlen
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, charWlen do
|
||||||
|
if x >= drawLimitX1 and x + charWlen - 1 <= drawLimitX2 then
|
||||||
if transparency then
|
if transparency then
|
||||||
newFrameForegrounds[screenIndex] = colorBlend(newFrameBackgrounds[screenIndex], textColor, transparency)
|
newFrameForegrounds[screenIndex] = colorBlend(newFrameBackgrounds[screenIndex], textColor, transparency)
|
||||||
else
|
else
|
||||||
newFrameForegrounds[screenIndex] = textColor
|
newFrameForegrounds[screenIndex] = textColor
|
||||||
end
|
end
|
||||||
|
|
||||||
newFrameSymbols[screenIndex] = unicodeSub(data, charIndex, charIndex)
|
newFrameChars[screenIndex] = i == 1 and char or " "
|
||||||
end
|
end
|
||||||
|
|
||||||
x, screenIndex = x + 1, screenIndex + 1
|
x, screenIndex = x + 1, screenIndex + 1
|
||||||
@ -592,11 +646,11 @@ local function drawImage(x, y, picture, blendForeground)
|
|||||||
background,
|
background,
|
||||||
foreground,
|
foreground,
|
||||||
alpha,
|
alpha,
|
||||||
symbol = bufferWidth * (y - 1) + x, bufferWidth - clippedImageWidth, (imageWidth - clippedImageWidth) * 4
|
char = bufferWidth * (y - 1) + x, bufferWidth - clippedImageWidth, (imageWidth - clippedImageWidth) * 4
|
||||||
|
|
||||||
for j = 1, clippedImageHeight do
|
for j = 1, clippedImageHeight do
|
||||||
for i = 1, clippedImageWidth do
|
for i = 1, clippedImageWidth do
|
||||||
alpha, symbol = picture[pictureIndex + 2], picture[pictureIndex + 3]
|
alpha, char = picture[pictureIndex + 2], picture[pictureIndex + 3]
|
||||||
|
|
||||||
-- If it's fully transparent pixel
|
-- If it's fully transparent pixel
|
||||||
if alpha == 0 then
|
if alpha == 0 then
|
||||||
@ -611,11 +665,11 @@ local function drawImage(x, y, picture, blendForeground)
|
|||||||
newFrameForegrounds[screenIndex] = picture[pictureIndex + 1]
|
newFrameForegrounds[screenIndex] = picture[pictureIndex + 1]
|
||||||
end
|
end
|
||||||
-- If it's not transparent with whitespace
|
-- If it's not transparent with whitespace
|
||||||
elseif symbol ~= " " then
|
elseif char ~= " " then
|
||||||
newFrameForegrounds[screenIndex] = picture[pictureIndex + 1]
|
newFrameForegrounds[screenIndex] = picture[pictureIndex + 1]
|
||||||
end
|
end
|
||||||
|
|
||||||
newFrameSymbols[screenIndex] = symbol
|
newFrameChars[screenIndex] = char
|
||||||
|
|
||||||
screenIndex, pictureIndex = screenIndex + 1, pictureIndex + 4
|
screenIndex, pictureIndex = screenIndex + 1, pictureIndex + 4
|
||||||
end
|
end
|
||||||
@ -640,35 +694,35 @@ end
|
|||||||
|
|
||||||
local function semiPixelRawSet(index, color, yPercentTwoEqualsZero)
|
local function semiPixelRawSet(index, color, yPercentTwoEqualsZero)
|
||||||
local upperPixel, lowerPixel, bothPixel = "▀", "▄", " "
|
local upperPixel, lowerPixel, bothPixel = "▀", "▄", " "
|
||||||
local background, foreground, symbol = newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index]
|
local background, foreground, char = newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index]
|
||||||
|
|
||||||
if yPercentTwoEqualsZero then
|
if yPercentTwoEqualsZero then
|
||||||
if symbol == upperPixel then
|
if char == upperPixel then
|
||||||
if color == foreground then
|
if color == foreground then
|
||||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = color, foreground, bothPixel
|
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = color, foreground, bothPixel
|
||||||
else
|
else
|
||||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = color, foreground, symbol
|
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = color, foreground, char
|
||||||
end
|
end
|
||||||
elseif symbol == bothPixel then
|
elseif char == bothPixel then
|
||||||
if color ~= background then
|
if color ~= background then
|
||||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, color, lowerPixel
|
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = background, color, lowerPixel
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, color, lowerPixel
|
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = background, color, lowerPixel
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if symbol == lowerPixel then
|
if char == lowerPixel then
|
||||||
if color == foreground then
|
if color == foreground then
|
||||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = color, foreground, bothPixel
|
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = color, foreground, bothPixel
|
||||||
else
|
else
|
||||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = color, foreground, symbol
|
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = color, foreground, char
|
||||||
end
|
end
|
||||||
elseif symbol == bothPixel then
|
elseif char == bothPixel then
|
||||||
if color ~= background then
|
if color ~= background then
|
||||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, color, upperPixel
|
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = background, color, upperPixel
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, color, upperPixel
|
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = background, color, upperPixel
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -765,51 +819,168 @@ end
|
|||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function update(force)
|
local function update(force)
|
||||||
local index, indexStepOnEveryLine, changes = bufferWidth * (drawLimitY1 - 1) + drawLimitX1, (bufferWidth - drawLimitX2 + drawLimitX1 - 1), {}
|
local
|
||||||
local x, equalChars, equalCharsIndex, charX, charIndex, currentForeground
|
index,
|
||||||
local currentFrameBackground, currentFrameForeground, currentFrameSymbol, changesCurrentFrameBackground, changesCurrentFrameBackgroundCurrentFrameForeground
|
indexStepOnEveryLine,
|
||||||
local changesCurrentFrameBackgroundCurrentFrameForegroundIndex
|
changes,
|
||||||
|
|
||||||
|
x,
|
||||||
|
|
||||||
|
charX,
|
||||||
|
charIndex,
|
||||||
|
charWlen,
|
||||||
|
|
||||||
|
equalChars,
|
||||||
|
equalCharsIndex,
|
||||||
|
|
||||||
|
currentFrameBackground,
|
||||||
|
currentFrameForeground,
|
||||||
|
currentFrameChar,
|
||||||
|
newFrameChar,
|
||||||
|
newFrameForeground,
|
||||||
|
newFrameBackground,
|
||||||
|
|
||||||
|
changesCurrentFrameBackground,
|
||||||
|
changesCurrentFrameBackgroundCurrentFrameForeground,
|
||||||
|
changesCurrentFrameBackgroundCurrentFrameForegroundIndex,
|
||||||
|
|
||||||
|
currentForeground =
|
||||||
|
bufferWidth * (drawLimitY1 - 1) + drawLimitX1,
|
||||||
|
(bufferWidth - drawLimitX2 + drawLimitX1 - 1),
|
||||||
|
{}
|
||||||
|
|
||||||
for y = drawLimitY1, drawLimitY2 do
|
for y = drawLimitY1, drawLimitY2 do
|
||||||
x = drawLimitX1
|
x = drawLimitX1
|
||||||
|
|
||||||
while x <= drawLimitX2 do
|
while x <= drawLimitX2 do
|
||||||
-- Determine if some pixel data was changed (or if <force> argument was passed)
|
-- Determine if some pixel data was changed (or if <force> argument was passed)
|
||||||
|
currentFrameBackground,
|
||||||
|
currentFrameForeground,
|
||||||
|
currentFrameChar =
|
||||||
|
currentFrameBackgrounds[index],
|
||||||
|
currentFrameForegrounds[index],
|
||||||
|
currentFrameChars[index]
|
||||||
|
|
||||||
|
newFrameBackground,
|
||||||
|
newFrameForeground,
|
||||||
|
newFrameChar =
|
||||||
|
newFrameBackgrounds[index],
|
||||||
|
newFrameForegrounds[index],
|
||||||
|
newFrameChars[index]
|
||||||
|
|
||||||
if
|
if
|
||||||
currentFrameBackgrounds[index] ~= newFrameBackgrounds[index] or
|
currentFrameBackground ~= newFrameBackground or
|
||||||
currentFrameForegrounds[index] ~= newFrameForegrounds[index] or
|
currentFrameForeground ~= newFrameForeground or
|
||||||
currentFrameSymbols[index] ~= newFrameSymbols[index] or
|
currentFrameChar ~= newFrameChar or
|
||||||
force
|
force
|
||||||
then
|
then
|
||||||
-- Make pixel at both frames equal
|
-- Make pixel at both frames equal
|
||||||
currentFrameBackground, currentFrameForeground, currentFrameSymbol = newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index]
|
currentFrameBackgrounds[index],
|
||||||
currentFrameBackgrounds[index] = currentFrameBackground
|
currentFrameForegrounds[index],
|
||||||
currentFrameForegrounds[index] = currentFrameForeground
|
currentFrameChars[index],
|
||||||
currentFrameSymbols[index] = currentFrameSymbol
|
|
||||||
|
currentFrameBackground,
|
||||||
|
currentFrameForeground,
|
||||||
|
currentFrameChar =
|
||||||
|
newFrameBackground,
|
||||||
|
newFrameForeground,
|
||||||
|
newFrameChar,
|
||||||
|
|
||||||
|
newFrameBackground,
|
||||||
|
newFrameForeground,
|
||||||
|
newFrameChar
|
||||||
|
|
||||||
-- Look for pixels with equal chars from right of current pixel
|
-- Look for pixels with equal chars from right of current pixel
|
||||||
equalChars, equalCharsIndex, charX, charIndex = {currentFrameSymbol}, 2, x + 1, index + 1
|
charWlen = unicodeWlenCache[currentFrameChar]
|
||||||
|
|
||||||
|
if not charWlen then
|
||||||
|
charWlen = unicodeWlen(currentFrameChar)
|
||||||
|
unicodeWlenCache[currentFrameChar] = charWlen
|
||||||
|
end
|
||||||
|
|
||||||
|
charX,
|
||||||
|
charIndex,
|
||||||
|
equalChars,
|
||||||
|
equalCharsIndex =
|
||||||
|
x + 1,
|
||||||
|
index + 1,
|
||||||
|
{ currentFrameChar },
|
||||||
|
2
|
||||||
|
|
||||||
|
for i = 2, charWlen do
|
||||||
|
currentFrameBackgrounds[charIndex],
|
||||||
|
currentFrameForegrounds[charIndex],
|
||||||
|
currentFrameChars[charIndex],
|
||||||
|
|
||||||
|
charX,
|
||||||
|
charIndex =
|
||||||
|
newFrameBackground,
|
||||||
|
newFrameForeground,
|
||||||
|
" ",
|
||||||
|
|
||||||
|
charX + 1,
|
||||||
|
charIndex + 1
|
||||||
|
end
|
||||||
|
|
||||||
while charX <= drawLimitX2 do
|
while charX <= drawLimitX2 do
|
||||||
|
newFrameBackground,
|
||||||
|
newFrameForeground,
|
||||||
|
newFrameChar =
|
||||||
|
newFrameBackgrounds[charIndex],
|
||||||
|
newFrameForegrounds[charIndex],
|
||||||
|
newFrameChars[charIndex]
|
||||||
|
|
||||||
-- Pixels becomes equal only if they have same background and (whitespace char or same foreground)
|
-- Pixels becomes equal only if they have same background and (whitespace char or same foreground)
|
||||||
if
|
if
|
||||||
currentFrameBackground == newFrameBackgrounds[charIndex] and
|
newFrameBackground == currentFrameBackground
|
||||||
(
|
and (
|
||||||
newFrameSymbols[charIndex] == " " or
|
newFrameForeground == currentFrameForeground
|
||||||
currentFrameForeground == newFrameForegrounds[charIndex]
|
or newFrameChar == " "
|
||||||
)
|
)
|
||||||
then
|
then
|
||||||
-- Make pixel at both frames equal
|
charWlen = unicodeWlenCache[newFrameChar]
|
||||||
currentFrameBackgrounds[charIndex] = newFrameBackgrounds[charIndex]
|
|
||||||
currentFrameForegrounds[charIndex] = newFrameForegrounds[charIndex]
|
|
||||||
currentFrameSymbols[charIndex] = newFrameSymbols[charIndex]
|
|
||||||
|
|
||||||
equalChars[equalCharsIndex], equalCharsIndex = currentFrameSymbols[charIndex], equalCharsIndex + 1
|
if not charWlen then
|
||||||
|
charWlen = unicodeWlen(newFrameChar)
|
||||||
|
unicodeWlenCache[newFrameChar] = charWlen
|
||||||
|
end
|
||||||
|
|
||||||
|
currentFrameBackgrounds[charIndex],
|
||||||
|
currentFrameForegrounds[charIndex],
|
||||||
|
currentFrameChars[charIndex],
|
||||||
|
|
||||||
|
charX,
|
||||||
|
charIndex,
|
||||||
|
|
||||||
|
equalChars[equalCharsIndex],
|
||||||
|
equalCharsIndex =
|
||||||
|
newFrameBackground,
|
||||||
|
newFrameForeground,
|
||||||
|
newFrameChar,
|
||||||
|
|
||||||
|
charX + 1,
|
||||||
|
charIndex + 1,
|
||||||
|
|
||||||
|
newFrameChar,
|
||||||
|
equalCharsIndex + 1
|
||||||
|
|
||||||
|
for i = 2, charWlen do
|
||||||
|
currentFrameBackgrounds[charIndex],
|
||||||
|
currentFrameForegrounds[charIndex],
|
||||||
|
currentFrameChars[charIndex],
|
||||||
|
|
||||||
|
charX,
|
||||||
|
charIndex =
|
||||||
|
newFrameBackground,
|
||||||
|
newFrameForeground,
|
||||||
|
" ",
|
||||||
|
|
||||||
|
charX + 1,
|
||||||
|
charIndex + 1
|
||||||
|
end
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
charX, charIndex = charX + 1, charIndex + 1
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Group pixels that need to be drawn by background and foreground
|
-- Group pixels that need to be drawn by background and foreground
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user