release fix and blur improvements
This commit is contained in:
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -184,7 +184,7 @@ jobs:
|
|||||||
|
|
||||||
| Profile | Size | Description | Package |
|
| Profile | Size | Description | Package |
|
||||||
|---------|------|-------------|---------|
|
|---------|------|-------------|---------|
|
||||||
| **Minimal** | ~60% | Core functionality only | `flexlove-minimal-v${{ steps.version.outputs.version }}.zip` |
|
| **Minimal** | ~70% | Core functionality only | `flexlove-minimal-v${{ steps.version.outputs.version }}.zip` |
|
||||||
| **Slim** | ~80% | + Animation and Image support | `flexlove-slim-v${{ steps.version.outputs.version }}.zip` |
|
| **Slim** | ~80% | + Animation and Image support | `flexlove-slim-v${{ steps.version.outputs.version }}.zip` |
|
||||||
| **Default** | ~95% | + Theme and Blur effects | `flexlove-default-v${{ steps.version.outputs.version }}.zip` |
|
| **Default** | ~95% | + Theme and Blur effects | `flexlove-default-v${{ steps.version.outputs.version }}.zip` |
|
||||||
| **Full** | 100% | All modules including debugging tools | `flexlove-full-v${{ steps.version.outputs.version }}.zip` |
|
| **Full** | 100% | All modules including debugging tools | `flexlove-full-v${{ steps.version.outputs.version }}.zip` |
|
||||||
|
|||||||
36
FlexLove.lua
36
FlexLove.lua
@@ -149,6 +149,18 @@ function flexlove.init(config)
|
|||||||
NinePatch.init({ ErrorHandler = flexlove._ErrorHandler })
|
NinePatch.init({ ErrorHandler = flexlove._ErrorHandler })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Initialize Blur module with immediate mode optimization config
|
||||||
|
if ModuleLoader.isModuleLoaded(modulePath .. "modules.Blur") then
|
||||||
|
local blurOptimizations = config.immediateModeBlurOptimizations
|
||||||
|
if blurOptimizations == nil then
|
||||||
|
blurOptimizations = true -- Default to enabled
|
||||||
|
end
|
||||||
|
Blur.init({
|
||||||
|
ErrorHandler = flexlove._ErrorHandler,
|
||||||
|
immediateModeOptimizations = blurOptimizations and config.immediateMode or false
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
-- Initialize required modules
|
-- Initialize required modules
|
||||||
Units.init({ Context = Context, ErrorHandler = flexlove._ErrorHandler })
|
Units.init({ Context = Context, ErrorHandler = flexlove._ErrorHandler })
|
||||||
Color.init({ ErrorHandler = flexlove._ErrorHandler })
|
Color.init({ ErrorHandler = flexlove._ErrorHandler })
|
||||||
@@ -440,8 +452,30 @@ function flexlove.endFrame()
|
|||||||
stateUpdate._cursorBlinkPaused = element._cursorBlinkPaused
|
stateUpdate._cursorBlinkPaused = element._cursorBlinkPaused
|
||||||
stateUpdate._cursorBlinkPauseTimer = element._cursorBlinkPauseTimer
|
stateUpdate._cursorBlinkPauseTimer = element._cursorBlinkPauseTimer
|
||||||
|
|
||||||
|
-- Track blur-related properties for cache invalidation
|
||||||
|
if element.backdropBlur or element.contentBlur then
|
||||||
|
stateUpdate._blurX = element.x
|
||||||
|
stateUpdate._blurY = element.y
|
||||||
|
stateUpdate._blurWidth = element._borderBoxWidth or (element.width + element.padding.left + element.padding.right)
|
||||||
|
stateUpdate._blurHeight = element._borderBoxHeight or (element.height + element.padding.top + element.padding.bottom)
|
||||||
|
if element.backdropBlur then
|
||||||
|
stateUpdate._backdropBlurIntensity = element.backdropBlur.intensity
|
||||||
|
stateUpdate._backdropBlurQuality = element.backdropBlur.quality
|
||||||
|
end
|
||||||
|
if element.contentBlur then
|
||||||
|
stateUpdate._contentBlurIntensity = element.contentBlur.intensity
|
||||||
|
stateUpdate._contentBlurQuality = element.contentBlur.quality
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Use optimized update that only changes modified values
|
-- Use optimized update that only changes modified values
|
||||||
StateManager.updateStateIfChanged(element.id, stateUpdate)
|
-- Returns true if state was changed (meaning blur cache needs invalidation)
|
||||||
|
local stateChanged = StateManager.updateStateIfChanged(element.id, stateUpdate)
|
||||||
|
|
||||||
|
-- Invalidate blur cache if blur-related properties changed
|
||||||
|
if stateChanged and (element.backdropBlur or element.contentBlur) and Blur then
|
||||||
|
Blur.clearElementCache(element.id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
204
modules/Blur.lua
204
modules/Blur.lua
@@ -5,8 +5,10 @@ local Cache = {
|
|||||||
canvases = {},
|
canvases = {},
|
||||||
quads = {},
|
quads = {},
|
||||||
blurInstances = {}, -- Cache blur instances by quality
|
blurInstances = {}, -- Cache blur instances by quality
|
||||||
|
blurredCanvases = {}, -- Cache pre-blurred canvases for immediate mode
|
||||||
MAX_CANVAS_SIZE = 20,
|
MAX_CANVAS_SIZE = 20,
|
||||||
MAX_QUAD_SIZE = 20,
|
MAX_QUAD_SIZE = 20,
|
||||||
|
MAX_BLURRED_CANVAS_CACHE = 50, -- Maximum cached blurred canvases
|
||||||
INTENSITY_THRESHOLD = 5, -- Skip blur below this intensity
|
INTENSITY_THRESHOLD = 5, -- Skip blur below this intensity
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,11 +123,93 @@ function Cache.releaseQuad(quad)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Generate cache key for blurred canvas
|
||||||
|
---@param elementId string Element ID
|
||||||
|
---@param x number X position
|
||||||
|
---@param y number Y position
|
||||||
|
---@param width number Width
|
||||||
|
---@param height number Height
|
||||||
|
---@param intensity number Blur intensity
|
||||||
|
---@param quality number Blur quality
|
||||||
|
---@param isBackdrop boolean Whether this is backdrop blur
|
||||||
|
---@return string key Cache key
|
||||||
|
function Cache.generateBlurCacheKey(elementId, x, y, width, height, intensity, quality, isBackdrop)
|
||||||
|
return string.format("%s:%d:%d:%d:%d:%d:%d:%s", elementId, x, y, width, height, intensity, quality, tostring(isBackdrop))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get cached blurred canvas
|
||||||
|
---@param key string Cache key
|
||||||
|
---@return love.Canvas|nil canvas Cached canvas or nil
|
||||||
|
function Cache.getBlurredCanvas(key)
|
||||||
|
local entry = Cache.blurredCanvases[key]
|
||||||
|
if entry then
|
||||||
|
entry.lastUsed = os.time()
|
||||||
|
return entry.canvas
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Store blurred canvas in cache
|
||||||
|
---@param key string Cache key
|
||||||
|
---@param canvas love.Canvas Canvas to cache
|
||||||
|
function Cache.setBlurredCanvas(key, canvas)
|
||||||
|
-- Limit cache size
|
||||||
|
local count = 0
|
||||||
|
for _ in pairs(Cache.blurredCanvases) do
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if count >= Cache.MAX_BLURRED_CANVAS_CACHE then
|
||||||
|
-- Remove oldest entry
|
||||||
|
local oldestKey = nil
|
||||||
|
local oldestTime = math.huge
|
||||||
|
for k, v in pairs(Cache.blurredCanvases) do
|
||||||
|
if v.lastUsed < oldestTime then
|
||||||
|
oldestTime = v.lastUsed
|
||||||
|
oldestKey = k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if oldestKey then
|
||||||
|
if Cache.blurredCanvases[oldestKey].canvas then
|
||||||
|
Cache.blurredCanvases[oldestKey].canvas:release()
|
||||||
|
end
|
||||||
|
Cache.blurredCanvases[oldestKey] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Cache.blurredCanvases[key] = {
|
||||||
|
canvas = canvas,
|
||||||
|
lastUsed = os.time(),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Clear blurred canvas cache for specific element
|
||||||
|
---@param elementId string Element ID to clear cache for
|
||||||
|
function Cache.clearBlurredCanvasesForElement(elementId)
|
||||||
|
for key, entry in pairs(Cache.blurredCanvases) do
|
||||||
|
if key:match("^" .. elementId .. ":") then
|
||||||
|
if entry.canvas then
|
||||||
|
entry.canvas:release()
|
||||||
|
end
|
||||||
|
Cache.blurredCanvases[key] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Clear all caches
|
--- Clear all caches
|
||||||
function Cache.clear()
|
function Cache.clear()
|
||||||
|
-- Release all blurred canvases
|
||||||
|
for _, entry in pairs(Cache.blurredCanvases) do
|
||||||
|
if entry.canvas then
|
||||||
|
entry.canvas:release()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Cache.canvases = {}
|
Cache.canvases = {}
|
||||||
Cache.quads = {}
|
Cache.quads = {}
|
||||||
Cache.blurInstances = {}
|
Cache.blurInstances = {}
|
||||||
|
Cache.blurredCanvases = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
@@ -411,11 +495,129 @@ function Blur.clearCache()
|
|||||||
Cache.clear()
|
Cache.clear()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Apply backdrop blur with caching support
|
||||||
|
---@param intensity number Blur intensity (0-100)
|
||||||
|
---@param x number X position
|
||||||
|
---@param y number Y position
|
||||||
|
---@param width number Width of region
|
||||||
|
---@param height number Height of region
|
||||||
|
---@param backdropCanvas love.Canvas Canvas containing the backdrop content
|
||||||
|
---@param elementId string|nil Element ID for caching (nil disables caching)
|
||||||
|
function Blur:applyBackdropCached(intensity, x, y, width, height, backdropCanvas, elementId)
|
||||||
|
-- If caching is disabled or no element ID, fall back to regular apply
|
||||||
|
if not Blur._immediateModeOptimizations or not elementId then
|
||||||
|
return self:applyBackdrop(intensity, x, y, width, height, backdropCanvas)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Generate cache key
|
||||||
|
local cacheKey = Cache.generateBlurCacheKey(elementId, x, y, width, height, intensity, self.quality, true)
|
||||||
|
|
||||||
|
-- Check cache
|
||||||
|
local cachedCanvas = Cache.getBlurredCanvas(cacheKey)
|
||||||
|
if cachedCanvas then
|
||||||
|
-- Draw cached blur
|
||||||
|
local prevCanvas = love.graphics.getCanvas()
|
||||||
|
local prevShader = love.graphics.getShader()
|
||||||
|
local prevColor = { love.graphics.getColor() }
|
||||||
|
local prevBlendMode = love.graphics.getBlendMode()
|
||||||
|
|
||||||
|
love.graphics.setCanvas(prevCanvas)
|
||||||
|
love.graphics.setShader()
|
||||||
|
love.graphics.setBlendMode(prevBlendMode)
|
||||||
|
love.graphics.draw(cachedCanvas, x, y)
|
||||||
|
|
||||||
|
love.graphics.setShader(prevShader)
|
||||||
|
love.graphics.setColor(unpack(prevColor))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Not cached, render and cache
|
||||||
|
if not backdropCanvas then
|
||||||
|
if Blur._ErrorHandler then
|
||||||
|
Blur._ErrorHandler:warn("Blur", "applyBackdrop requires a backdrop canvas.")
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if intensity <= 0 or width <= 0 or height <= 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Early exit for very low intensity (optimization)
|
||||||
|
if intensity < Cache.INTENSITY_THRESHOLD then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
intensity = math.max(0, math.min(100, intensity))
|
||||||
|
|
||||||
|
local passes = math.ceil(intensity / 20)
|
||||||
|
passes = math.max(1, math.min(5, passes))
|
||||||
|
|
||||||
|
local canvas1 = Cache.getCanvas(width, height)
|
||||||
|
local canvas2 = Cache.getCanvas(width, height)
|
||||||
|
|
||||||
|
local prevCanvas = love.graphics.getCanvas()
|
||||||
|
local prevShader = love.graphics.getShader()
|
||||||
|
local prevColor = { love.graphics.getColor() }
|
||||||
|
local prevBlendMode = love.graphics.getBlendMode()
|
||||||
|
|
||||||
|
love.graphics.setCanvas(canvas1)
|
||||||
|
love.graphics.clear()
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
love.graphics.setBlendMode("alpha", "premultiplied")
|
||||||
|
|
||||||
|
local backdropWidth, backdropHeight = backdropCanvas:getDimensions()
|
||||||
|
local quad = Cache.getQuad(x, y, width, height, backdropWidth, backdropHeight)
|
||||||
|
love.graphics.draw(backdropCanvas, quad, 0, 0)
|
||||||
|
|
||||||
|
love.graphics.setShader(self.shader)
|
||||||
|
|
||||||
|
for i = 1, passes do
|
||||||
|
love.graphics.setCanvas(canvas2)
|
||||||
|
love.graphics.clear()
|
||||||
|
self.shader:send("direction", { 1 / width, 0 })
|
||||||
|
love.graphics.draw(canvas1, 0, 0)
|
||||||
|
|
||||||
|
love.graphics.setCanvas(canvas1)
|
||||||
|
love.graphics.clear()
|
||||||
|
self.shader:send("direction", { 0, 1 / height })
|
||||||
|
love.graphics.draw(canvas2, 0, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Cache the result
|
||||||
|
local cachedResult = love.graphics.newCanvas(width, height)
|
||||||
|
love.graphics.setCanvas(cachedResult)
|
||||||
|
love.graphics.clear()
|
||||||
|
love.graphics.setShader()
|
||||||
|
love.graphics.setBlendMode("alpha", "premultiplied")
|
||||||
|
love.graphics.draw(canvas1, 0, 0)
|
||||||
|
Cache.setBlurredCanvas(cacheKey, cachedResult)
|
||||||
|
|
||||||
|
love.graphics.setCanvas(prevCanvas)
|
||||||
|
love.graphics.setShader()
|
||||||
|
love.graphics.setBlendMode(prevBlendMode)
|
||||||
|
love.graphics.draw(canvas1, x, y)
|
||||||
|
|
||||||
|
love.graphics.setShader(prevShader)
|
||||||
|
love.graphics.setColor(unpack(prevColor))
|
||||||
|
|
||||||
|
Cache.releaseCanvas(canvas1)
|
||||||
|
Cache.releaseCanvas(canvas2)
|
||||||
|
Cache.releaseQuad(quad)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Clear blur cache for specific element
|
||||||
|
---@param elementId string Element ID
|
||||||
|
function Blur.clearElementCache(elementId)
|
||||||
|
Cache.clearBlurredCanvasesForElement(elementId)
|
||||||
|
end
|
||||||
|
|
||||||
--- Initialize Blur module with dependencies
|
--- Initialize Blur module with dependencies
|
||||||
---@param deps table Dependencies: { ErrorHandler = ErrorHandler? }
|
---@param deps table Dependencies: { ErrorHandler = ErrorHandler?, immediateModeOptimizations = boolean? }
|
||||||
function Blur.init(deps)
|
function Blur.init(deps)
|
||||||
if type(deps) == "table" then
|
if type(deps) == "table" then
|
||||||
Blur._ErrorHandler = deps.ErrorHandler
|
Blur._ErrorHandler = deps.ErrorHandler
|
||||||
|
Blur._immediateModeOptimizations = deps.immediateModeOptimizations or false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -425,7 +425,9 @@ function Renderer:draw(element, backdropCanvas)
|
|||||||
if self.backdropBlur and self.backdropBlur.intensity > 0 and backdropCanvas then
|
if self.backdropBlur and self.backdropBlur.intensity > 0 and backdropCanvas then
|
||||||
local blurInstance = self:getBlurInstance()
|
local blurInstance = self:getBlurInstance()
|
||||||
if blurInstance then
|
if blurInstance then
|
||||||
self._Blur.applyBackdrop(blurInstance, self.backdropBlur.intensity, element.x, element.y, borderBoxWidth, borderBoxHeight, backdropCanvas)
|
-- Use cached blur in immediate mode if element has an ID
|
||||||
|
local elementId = element.id and element.id ~= "" and element.id or nil
|
||||||
|
blurInstance:applyBackdropCached(self.backdropBlur.intensity, element.x, element.y, borderBoxWidth, borderBoxHeight, backdropCanvas, elementId)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -185,4 +185,5 @@ local TransformProps
|
|||||||
---@field gcMemoryThreshold number? -- Memory threshold in MB before forcing GC (default: 100)
|
---@field gcMemoryThreshold number? -- Memory threshold in MB before forcing GC (default: 100)
|
||||||
---@field gcInterval number? -- Frames between GC steps in periodic mode (default: 60)
|
---@field gcInterval number? -- Frames between GC steps in periodic mode (default: 60)
|
||||||
---@field gcStepSize number? -- Work units per GC step, higher = more aggressive (default: 200)
|
---@field gcStepSize number? -- Work units per GC step, higher = more aggressive (default: 200)
|
||||||
|
---@field immediateModeBlurOptimizations boolean? -- Cache blur canvases in immediate mode to avoid re-rendering each frame (default: true)
|
||||||
local FlexLoveConfig = {}
|
local FlexLoveConfig = {}
|
||||||
|
|||||||
@@ -40,16 +40,16 @@ get_description() {
|
|||||||
get_modules() {
|
get_modules() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
minimal)
|
minimal)
|
||||||
echo "utils.lua Units.lua Context.lua StateManager.lua ErrorHandler.lua Color.lua InputEvent.lua TextEditor.lua LayoutEngine.lua Renderer.lua EventHandler.lua ScrollManager.lua Element.lua RoundedRect.lua Grid.lua GestureRecognizer.lua ModuleLoader.lua"
|
echo "utils.lua Units.lua Context.lua StateManager.lua ErrorHandler.lua Color.lua InputEvent.lua TextEditor.lua LayoutEngine.lua Renderer.lua EventHandler.lua ScrollManager.lua Element.lua RoundedRect.lua Grid.lua ModuleLoader.lua types.lua"
|
||||||
;;
|
;;
|
||||||
slim)
|
slim)
|
||||||
echo "utils.lua Units.lua Context.lua StateManager.lua ErrorHandler.lua Color.lua InputEvent.lua TextEditor.lua LayoutEngine.lua Renderer.lua EventHandler.lua ScrollManager.lua Element.lua RoundedRect.lua Grid.lua GestureRecognizer.lua Animation.lua ImageRenderer.lua ImageScaler.lua ImageCache.lua ModuleLoader.lua"
|
echo "utils.lua Units.lua Context.lua StateManager.lua ErrorHandler.lua Color.lua InputEvent.lua TextEditor.lua LayoutEngine.lua Renderer.lua EventHandler.lua ScrollManager.lua Element.lua RoundedRect.lua Grid.lua ModuleLoader.lua types.lua Animation.lua NinePatch.lua ImageRenderer.lua ImageScaler.lua ImageCache.lua"
|
||||||
;;
|
;;
|
||||||
default)
|
default)
|
||||||
echo "utils.lua Units.lua Context.lua StateManager.lua ErrorHandler.lua Color.lua InputEvent.lua TextEditor.lua LayoutEngine.lua Renderer.lua EventHandler.lua ScrollManager.lua Element.lua RoundedRect.lua Grid.lua GestureRecognizer.lua Animation.lua NinePatch.lua ImageRenderer.lua ImageScaler.lua ImageCache.lua Theme.lua Blur.lua ModuleLoader.lua"
|
echo "utils.lua Units.lua Context.lua StateManager.lua ErrorHandler.lua Color.lua InputEvent.lua TextEditor.lua LayoutEngine.lua Renderer.lua EventHandler.lua ScrollManager.lua Element.lua RoundedRect.lua Grid.lua ModuleLoader.lua types.lua Animation.lua NinePatch.lua ImageRenderer.lua ImageScaler.lua ImageCache.lua Theme.lua Blur.lua GestureRecognizer.lua"
|
||||||
;;
|
;;
|
||||||
full)
|
full)
|
||||||
echo "utils.lua Units.lua Context.lua StateManager.lua ErrorHandler.lua Color.lua InputEvent.lua TextEditor.lua LayoutEngine.lua Renderer.lua EventHandler.lua ScrollManager.lua Element.lua RoundedRect.lua Grid.lua GestureRecognizer.lua Animation.lua NinePatch.lua ImageRenderer.lua ImageScaler.lua ImageCache.lua Theme.lua Blur.lua Performance.lua ModuleLoader.lua"
|
echo "utils.lua Units.lua Context.lua StateManager.lua ErrorHandler.lua Color.lua InputEvent.lua TextEditor.lua LayoutEngine.lua Renderer.lua EventHandler.lua ScrollManager.lua Element.lua RoundedRect.lua Grid.lua ModuleLoader.lua types.lua Animation.lua NinePatch.lua ImageRenderer.lua ImageScaler.lua ImageCache.lua Theme.lua Blur.lua GestureRecognizer.lua Performance.lua MemoryScanner.lua"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|||||||
169
scripts/test-release-locally.sh
Executable file
169
scripts/test-release-locally.sh
Executable file
@@ -0,0 +1,169 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Local test script for release workflow
|
||||||
|
# This simulates the key steps of .github/workflows/release.yml
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo -e "${BLUE}==================================${NC}"
|
||||||
|
echo -e "${BLUE}Local Release Workflow Test${NC}"
|
||||||
|
echo -e "${BLUE}==================================${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 1: Extract version
|
||||||
|
echo -e "${YELLOW}Step 1: Extract version from FlexLove.lua${NC}"
|
||||||
|
VERSION=$(grep -m 1 "_VERSION" FlexLove.lua | sed -E 's/.*"([^"]+)".*/\1/')
|
||||||
|
if [ -z "$VERSION" ]; then
|
||||||
|
echo -e "${RED}Error: Could not extract version${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ Version: ${VERSION}${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 2: Make scripts executable
|
||||||
|
echo -e "${YELLOW}Step 2: Make scripts executable${NC}"
|
||||||
|
chmod +x scripts/generate_docs.sh
|
||||||
|
chmod +x scripts/create-release.sh
|
||||||
|
chmod +x scripts/create-profile-packages.sh
|
||||||
|
chmod +x scripts/archive-docs.sh
|
||||||
|
echo -e "${GREEN}✓ Scripts are executable${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 3: Create release packages
|
||||||
|
echo -e "${YELLOW}Step 3: Create release packages${NC}"
|
||||||
|
./scripts/create-profile-packages.sh
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 4: Verify all packages were created
|
||||||
|
echo -e "${YELLOW}Step 4: Verify all packages${NC}"
|
||||||
|
for profile in minimal slim default full; do
|
||||||
|
if [ ! -f "releases/flexlove-${profile}-v${VERSION}.zip" ]; then
|
||||||
|
echo -e "${RED}✗ Error: ${profile} profile package was not created${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -f "releases/flexlove-${profile}-v${VERSION}.zip.sha256" ]; then
|
||||||
|
echo -e "${RED}✗ Error: ${profile} checksum file was not created${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
SIZE=$(du -h "releases/flexlove-${profile}-v${VERSION}.zip" | cut -f1)
|
||||||
|
echo -e "${GREEN}✓ ${profile} package verified (${SIZE})${NC}"
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 5: Verify checksums
|
||||||
|
echo -e "${YELLOW}Step 5: Verify checksums${NC}"
|
||||||
|
cd releases
|
||||||
|
if shasum -a 256 -c flexlove-*-v${VERSION}.zip.sha256 2>&1 | grep -q "OK"; then
|
||||||
|
shasum -a 256 -c flexlove-*-v${VERSION}.zip.sha256
|
||||||
|
echo -e "${GREEN}✓ All checksums verified${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Checksum verification failed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cd ..
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 6: Extract checksums for display
|
||||||
|
echo -e "${YELLOW}Step 6: Extract checksums for release notes${NC}"
|
||||||
|
MINIMAL_CHECKSUM=$(cat "releases/flexlove-minimal-v${VERSION}.zip.sha256" | cut -d ' ' -f 1)
|
||||||
|
SLIM_CHECKSUM=$(cat "releases/flexlove-slim-v${VERSION}.zip.sha256" | cut -d ' ' -f 1)
|
||||||
|
DEFAULT_CHECKSUM=$(cat "releases/flexlove-default-v${VERSION}.zip.sha256" | cut -d ' ' -f 1)
|
||||||
|
FULL_CHECKSUM=$(cat "releases/flexlove-full-v${VERSION}.zip.sha256" | cut -d ' ' -f 1)
|
||||||
|
|
||||||
|
echo -e "${BLUE}Minimal: ${MINIMAL_CHECKSUM}${NC}"
|
||||||
|
echo -e "${BLUE}Slim: ${SLIM_CHECKSUM}${NC}"
|
||||||
|
echo -e "${BLUE}Default: ${DEFAULT_CHECKSUM}${NC}"
|
||||||
|
echo -e "${BLUE}Full: ${FULL_CHECKSUM}${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 7: Check if pre-release
|
||||||
|
echo -e "${YELLOW}Step 7: Check if pre-release${NC}"
|
||||||
|
if [[ "$VERSION" =~ (alpha|beta|rc|dev) ]]; then
|
||||||
|
echo -e "${BLUE}This is a pre-release version${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}This is a stable release${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 8: Verify package contents
|
||||||
|
echo -e "${YELLOW}Step 8: Verify package contents${NC}"
|
||||||
|
TEMP_DIR=$(mktemp -d)
|
||||||
|
for profile in minimal slim default full; do
|
||||||
|
unzip -q "releases/flexlove-${profile}-v${VERSION}.zip" -d "${TEMP_DIR}/${profile}"
|
||||||
|
|
||||||
|
# Check FlexLove.lua exists
|
||||||
|
if [ ! -f "${TEMP_DIR}/${profile}/flexlove/FlexLove.lua" ]; then
|
||||||
|
echo -e "${RED}✗ ${profile}: Missing FlexLove.lua${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check LICENSE exists
|
||||||
|
if [ ! -f "${TEMP_DIR}/${profile}/flexlove/LICENSE" ]; then
|
||||||
|
echo -e "${RED}✗ ${profile}: Missing LICENSE${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check README exists
|
||||||
|
if [ ! -f "${TEMP_DIR}/${profile}/flexlove/README.md" ]; then
|
||||||
|
echo -e "${RED}✗ ${profile}: Missing README.md${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Count modules
|
||||||
|
MODULE_COUNT=$(find "${TEMP_DIR}/${profile}/flexlove/modules" -name "*.lua" | wc -l | tr -d ' ')
|
||||||
|
|
||||||
|
# Check themes for default and full
|
||||||
|
if [ "$profile" == "default" ] || [ "$profile" == "full" ]; then
|
||||||
|
if [ ! -d "${TEMP_DIR}/${profile}/flexlove/themes" ]; then
|
||||||
|
echo -e "${RED}✗ ${profile}: Missing themes directory${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify theme files
|
||||||
|
if [ ! -f "${TEMP_DIR}/${profile}/flexlove/themes/metal.example.lua" ]; then
|
||||||
|
echo -e "${RED}✗ ${profile}: Missing metal.example.lua${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -f "${TEMP_DIR}/${profile}/flexlove/themes/space.example.lua" ]; then
|
||||||
|
echo -e "${RED}✗ ${profile}: Missing space.example.lua${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -f "${TEMP_DIR}/${profile}/flexlove/themes/README.md" ]; then
|
||||||
|
echo -e "${RED}✗ ${profile}: Missing themes/README.md${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify no other files in themes
|
||||||
|
THEME_FILE_COUNT=$(find "${TEMP_DIR}/${profile}/flexlove/themes" -type f | wc -l | tr -d ' ')
|
||||||
|
if [ "$THEME_FILE_COUNT" != "3" ]; then
|
||||||
|
echo -e "${RED}✗ ${profile}: Expected 3 files in themes, found ${THEME_FILE_COUNT}${NC}"
|
||||||
|
find "${TEMP_DIR}/${profile}/flexlove/themes" -type f
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}✓ ${profile}: ${MODULE_COUNT} modules + themes verified${NC}"
|
||||||
|
else
|
||||||
|
# Verify no themes for minimal and slim
|
||||||
|
if [ -d "${TEMP_DIR}/${profile}/flexlove/themes" ]; then
|
||||||
|
echo -e "${RED}✗ ${profile}: Should not have themes directory${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ ${profile}: ${MODULE_COUNT} modules verified${NC}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
rm -rf "$TEMP_DIR"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo -e "${GREEN}==================================${NC}"
|
||||||
|
echo -e "${GREEN}✓ All tests passed!${NC}"
|
||||||
|
echo -e "${GREEN}==================================${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}Release packages are ready in: releases/${NC}"
|
||||||
|
echo -e "${BLUE}Version: v${VERSION}${NC}"
|
||||||
|
echo ""
|
||||||
@@ -86,14 +86,18 @@ function TestBlur:testNewWithNilProps()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function TestBlur:testNewCreatesUniqueShaders()
|
function TestBlur:testNewCreatesUniqueShaders()
|
||||||
-- Each instance should have its own shader
|
-- Blur instances with same quality should share cached shaders (optimization)
|
||||||
local blur1 = Blur.new({quality = 5})
|
local blur1 = Blur.new({quality = 5})
|
||||||
local blur2 = Blur.new({quality = 5})
|
local blur2 = Blur.new({quality = 5})
|
||||||
|
|
||||||
luaunit.assertNotNil(blur1.shader)
|
luaunit.assertNotNil(blur1.shader)
|
||||||
luaunit.assertNotNil(blur2.shader)
|
luaunit.assertNotNil(blur2.shader)
|
||||||
-- Shaders should be different objects even if same quality
|
-- Shaders should be the same object when quality matches (cached)
|
||||||
luaunit.assertNotEquals(blur1.shader, blur2.shader)
|
luaunit.assertEquals(blur1.shader, blur2.shader)
|
||||||
|
|
||||||
|
-- Different quality should result in different shaders
|
||||||
|
local blur3 = Blur.new({quality = 7})
|
||||||
|
luaunit.assertNotEquals(blur1.shader, blur3.shader)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user