diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 083beb8..c9c65d9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -116,7 +116,7 @@ jobs: run: | # Create all 4 profile packages ./scripts/create-profile-packages.sh - + # Verify all packages were created VERSION="${{ steps.version.outputs.version }}" for profile in minimal slim default full; do @@ -155,7 +155,7 @@ jobs: 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 "minimal=$MINIMAL_CHECKSUM" >> $GITHUB_OUTPUT echo "slim=$SLIM_CHECKSUM" >> $GITHUB_OUTPUT echo "default=$DEFAULT_CHECKSUM" >> $GITHUB_OUTPUT @@ -184,7 +184,7 @@ jobs: | 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` | | **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` | diff --git a/FlexLove.lua b/FlexLove.lua index 195ae8e..0ef60fe 100644 --- a/FlexLove.lua +++ b/FlexLove.lua @@ -149,6 +149,18 @@ function flexlove.init(config) NinePatch.init({ ErrorHandler = flexlove._ErrorHandler }) 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 Units.init({ Context = Context, ErrorHandler = flexlove._ErrorHandler }) Color.init({ ErrorHandler = flexlove._ErrorHandler }) @@ -439,9 +451,31 @@ function flexlove.endFrame() stateUpdate._cursorVisible = element._cursorVisible stateUpdate._cursorBlinkPaused = element._cursorBlinkPaused 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 - 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 diff --git a/modules/Blur.lua b/modules/Blur.lua index 80fed26..1dcb0c8 100644 --- a/modules/Blur.lua +++ b/modules/Blur.lua @@ -5,8 +5,10 @@ local Cache = { canvases = {}, quads = {}, blurInstances = {}, -- Cache blur instances by quality + blurredCanvases = {}, -- Cache pre-blurred canvases for immediate mode MAX_CANVAS_SIZE = 20, MAX_QUAD_SIZE = 20, + MAX_BLURRED_CANVAS_CACHE = 50, -- Maximum cached blurred canvases INTENSITY_THRESHOLD = 5, -- Skip blur below this intensity } @@ -121,11 +123,93 @@ function Cache.releaseQuad(quad) 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 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.quads = {} Cache.blurInstances = {} + Cache.blurredCanvases = {} end -- ============================================================================ @@ -411,11 +495,129 @@ function Blur.clearCache() Cache.clear() 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 ----@param deps table Dependencies: { ErrorHandler = ErrorHandler? } +---@param deps table Dependencies: { ErrorHandler = ErrorHandler?, immediateModeOptimizations = boolean? } function Blur.init(deps) if type(deps) == "table" then Blur._ErrorHandler = deps.ErrorHandler + Blur._immediateModeOptimizations = deps.immediateModeOptimizations or false end end diff --git a/modules/Renderer.lua b/modules/Renderer.lua index 91387f3..526cbeb 100644 --- a/modules/Renderer.lua +++ b/modules/Renderer.lua @@ -425,7 +425,9 @@ function Renderer:draw(element, backdropCanvas) if self.backdropBlur and self.backdropBlur.intensity > 0 and backdropCanvas then local blurInstance = self:getBlurInstance() 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 diff --git a/modules/types.lua b/modules/types.lua index fdfae2b..86c7a7c 100644 --- a/modules/types.lua +++ b/modules/types.lua @@ -185,4 +185,5 @@ local TransformProps ---@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 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 = {} diff --git a/scripts/create-profile-packages.sh b/scripts/create-profile-packages.sh index 26180b2..a63e58a 100755 --- a/scripts/create-profile-packages.sh +++ b/scripts/create-profile-packages.sh @@ -40,16 +40,16 @@ get_description() { get_modules() { case "$1" in 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) - 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) - 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) - 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 } diff --git a/scripts/test-release-locally.sh b/scripts/test-release-locally.sh new file mode 100755 index 0000000..b6f2c91 --- /dev/null +++ b/scripts/test-release-locally.sh @@ -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 "" diff --git a/testing/__tests__/blur_test.lua b/testing/__tests__/blur_test.lua index 6ce4f70..dfabb76 100644 --- a/testing/__tests__/blur_test.lua +++ b/testing/__tests__/blur_test.lua @@ -86,14 +86,18 @@ function TestBlur:testNewWithNilProps() end 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 blur2 = Blur.new({quality = 5}) luaunit.assertNotNil(blur1.shader) luaunit.assertNotNil(blur2.shader) - -- Shaders should be different objects even if same quality - luaunit.assertNotEquals(blur1.shader, blur2.shader) + -- Shaders should be the same object when quality matches (cached) + 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 -- ============================================================================