Round 8: preset UX improvements, lock file, auto-save
- Preset combobox now reflects current preset correctly - Selecting different preset in Config auto-loads it on OK - Preset buttons changed to: New, Clone, Rename, Delete (removed Save/Load) - New creates preset with default values - Clone copies current preset state to new name - Rename changes preset name and updates file associations - Delete removes preset (Default protected) and switches to Default - Window titles show preset: "AniPhallow (PresetName)" - Lock file prevents duplicate plugin instances - Auto-save (saveAll) called on every state-modifying action - addPresetName/removePresetName helpers for sorted preset list
This commit is contained in:
parent
9e3a2702dc
commit
67edfb0b1d
304
aniphallow.lua
304
aniphallow.lua
|
|
@ -34,6 +34,7 @@ local GB_COLS = 16 -- tiles per row in optimized image (128px = GB standard)
|
||||||
local PRESETS_DIR = app.fs.joinPath(app.fs.userConfigPath, "aniphallow_presets")
|
local PRESETS_DIR = app.fs.joinPath(app.fs.userConfigPath, "aniphallow_presets")
|
||||||
local MASTER_FILE = app.fs.joinPath(app.fs.userConfigPath, "aniphallow_master.ini")
|
local MASTER_FILE = app.fs.joinPath(app.fs.userConfigPath, "aniphallow_master.ini")
|
||||||
local OLD_PREFS_FILE = app.fs.joinPath(app.fs.userConfigPath, "aniphallow_prefs.ini")
|
local OLD_PREFS_FILE = app.fs.joinPath(app.fs.userConfigPath, "aniphallow_prefs.ini")
|
||||||
|
local LOCK_FILE = app.fs.joinPath(app.fs.userConfigPath, "aniphallow.lock")
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
-- State
|
-- State
|
||||||
|
|
@ -226,6 +227,23 @@ local function resetToDefaults()
|
||||||
S.selectedFrame = 0
|
S.selectedFrame = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
-- Preset name helpers
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
local function addPresetName(name)
|
||||||
|
for _, n in ipairs(knownPresetNames) do
|
||||||
|
if n == name then return end
|
||||||
|
end
|
||||||
|
table.insert(knownPresetNames, name)
|
||||||
|
table.sort(knownPresetNames, function(a, b) return a:lower() < b:lower() end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function removePresetName(name)
|
||||||
|
for i, n in ipairs(knownPresetNames) do
|
||||||
|
if n == name then table.remove(knownPresetNames, i); return end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
-- Preset system: save/load preset files and master file
|
-- Preset system: save/load preset files and master file
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
@ -1225,6 +1243,13 @@ local function buildOptimizedImage(img, tiles, compress, silhouette, silhouetteC
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
-- Lock file helpers
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
local function removeLockFile()
|
||||||
|
os.remove(LOCK_FILE)
|
||||||
|
end
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
-- Preview Window (primary window)
|
-- Preview Window (primary window)
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
@ -1275,7 +1300,7 @@ openPreviewWindow = function()
|
||||||
pvHeight = math.max(pvHeight, 40)
|
pvHeight = math.max(pvHeight, 40)
|
||||||
|
|
||||||
previewDlg = Dialog{
|
previewDlg = Dialog{
|
||||||
title = "AniPhallow Preview",
|
title = "AniPhallow (" .. S.currentPreset .. ")",
|
||||||
onclose = function()
|
onclose = function()
|
||||||
if previewTimer then pcall(function() previewTimer:stop() end) end
|
if previewTimer then pcall(function() previewTimer:stop() end) end
|
||||||
if pvRefreshTimer then pcall(function() pvRefreshTimer:stop() end) end
|
if pvRefreshTimer then pcall(function() pvRefreshTimer:stop() end) end
|
||||||
|
|
@ -1284,6 +1309,8 @@ openPreviewWindow = function()
|
||||||
previewDlg = nil
|
previewDlg = nil
|
||||||
S.previewWindowOpen = false
|
S.previewWindowOpen = false
|
||||||
saveAll()
|
saveAll()
|
||||||
|
-- If main dialog is also closed, remove lock
|
||||||
|
if not mainDlg then removeLockFile() end
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1474,6 +1501,9 @@ openPreviewWindow = function()
|
||||||
pcall(function() mainDlg:close() end)
|
pcall(function() mainDlg:close() end)
|
||||||
openMainDialog()
|
openMainDialog()
|
||||||
end
|
end
|
||||||
|
-- Reopen preview to update title
|
||||||
|
pcall(function() previewDlg:close() end)
|
||||||
|
openPreviewWindow()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -1521,6 +1551,7 @@ openMainDialog = function()
|
||||||
if gridY < 0 or gridY + S.tileH > S.sourceImage.height then return end
|
if gridY < 0 or gridY + S.tileH > S.sourceImage.height then return end
|
||||||
if not S.anims[name] then S.anims[name] = {} end
|
if not S.anims[name] then S.anims[name] = {} end
|
||||||
table.insert(S.anims[name], { x = gridX, y = gridY, flipped = flipped, offX = 0, offY = 0 })
|
table.insert(S.anims[name], { x = gridX, y = gridY, flipped = flipped, offX = 0, offY = 0 })
|
||||||
|
saveAll()
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -1560,7 +1591,7 @@ openMainDialog = function()
|
||||||
local viewH = math.min(contentH, SOURCE_VIEWPORT_H)
|
local viewH = math.min(contentH, SOURCE_VIEWPORT_H)
|
||||||
|
|
||||||
dlg = Dialog{
|
dlg = Dialog{
|
||||||
title = "AniPhallow - Animation Builder",
|
title = "AniPhallow (" .. S.currentPreset .. ")",
|
||||||
onclose = function()
|
onclose = function()
|
||||||
if mainAnimTimer then pcall(function() mainAnimTimer:stop() end) end
|
if mainAnimTimer then pcall(function() mainAnimTimer:stop() end) end
|
||||||
if mainRefreshTimer then pcall(function() mainRefreshTimer:stop() end) end
|
if mainRefreshTimer then pcall(function() mainRefreshTimer:stop() end) end
|
||||||
|
|
@ -1568,6 +1599,8 @@ openMainDialog = function()
|
||||||
mainRefreshTimer = nil
|
mainRefreshTimer = nil
|
||||||
mainDlg = nil
|
mainDlg = nil
|
||||||
saveAll()
|
saveAll()
|
||||||
|
-- If preview is also closed, remove lock
|
||||||
|
if not previewDlg then removeLockFile() end
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
mainDlg = dlg
|
mainDlg = dlg
|
||||||
|
|
@ -1599,151 +1632,168 @@ openMainDialog = function()
|
||||||
-- Presets section
|
-- Presets section
|
||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
d:separator{ text = "Presets" }
|
d:separator{ text = "Presets" }
|
||||||
local presetNames = getAllPresetNames()
|
d:combobox{ id = "presetSelect", option = S.currentPreset, options = getAllPresetNames() }
|
||||||
d:combobox{ id = "presetList", label = "Preset:", option = S.currentPreset, options = presetNames }
|
d:button{ id = "presetNew", text = "New", onclick = function()
|
||||||
d:button{ id = "btnPresetSave", text = "Save", onclick = function()
|
local nd = Dialog{ title = "New Preset" }
|
||||||
local saveDlg = Dialog{ title = "Save Preset" }
|
nd:entry{ id = "name", label = "Name:", text = "" }
|
||||||
saveDlg:entry{ id = "name", label = "Name:", text = S.currentPreset }
|
nd:button{ id = "ok", text = "OK" }
|
||||||
saveDlg:button{ id = "ok", text = "Save" }
|
nd:button{ text = "Cancel" }
|
||||||
saveDlg:button{ text = "Cancel" }
|
nd:show()
|
||||||
saveDlg:show()
|
if nd.data.ok and nd.data.name and nd.data.name ~= "" then
|
||||||
if saveDlg.data.ok then
|
local newName = nd.data.name
|
||||||
local pname = saveDlg.data.name
|
-- Check if exists
|
||||||
if pname and pname ~= "" then
|
|
||||||
-- Check if name exists and differs from current
|
|
||||||
if pname ~= S.currentPreset then
|
|
||||||
-- Check if preset already exists
|
|
||||||
local exists = false
|
local exists = false
|
||||||
for _, n in ipairs(knownPresetNames) do
|
for _, n in ipairs(getAllPresetNames()) do
|
||||||
if n == pname then exists = true; break end
|
if n == newName then exists = true; break end
|
||||||
end
|
end
|
||||||
if exists then
|
if exists then
|
||||||
local confirm = app.alert{
|
local r = app.alert{ title = "Overwrite?", text = "Preset '" .. newName .. "' already exists. Overwrite?", buttons = {"Overwrite", "Cancel"} }
|
||||||
title = "Overwrite Preset",
|
if r ~= 1 then return end
|
||||||
text = "Preset '" .. pname .. "' already exists. Overwrite?",
|
|
||||||
buttons = { "Overwrite", "Cancel" }
|
|
||||||
}
|
|
||||||
if confirm ~= 1 then return end
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
S.currentPreset = pname
|
|
||||||
-- Add to known names if new
|
|
||||||
local found = false
|
|
||||||
for _, n in ipairs(knownPresetNames) do
|
|
||||||
if n == pname then found = true; break end
|
|
||||||
end
|
|
||||||
if not found then
|
|
||||||
table.insert(knownPresetNames, pname)
|
|
||||||
end
|
|
||||||
-- Associate with current file
|
|
||||||
if app.sprite and app.sprite.filename and app.sprite.filename ~= "" then
|
|
||||||
filePresetMap[app.sprite.filename] = pname
|
|
||||||
end
|
|
||||||
saveAll()
|
|
||||||
-- Update combobox
|
|
||||||
pcall(function()
|
|
||||||
d:modify{ id = "presetList", options = getAllPresetNames(), option = S.currentPreset }
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end }
|
|
||||||
d:button{ id = "btnPresetLoad", text = "Load", onclick = function()
|
|
||||||
local selectedPreset = d.data.presetList
|
|
||||||
if selectedPreset and selectedPreset ~= "" then
|
|
||||||
-- Save current preset first
|
-- Save current preset first
|
||||||
savePreset(S.currentPreset)
|
savePreset(S.currentPreset)
|
||||||
-- Load the new preset
|
-- Reset to defaults and save as new preset
|
||||||
loadPreset(selectedPreset)
|
resetToDefaults()
|
||||||
S.currentPreset = selectedPreset
|
S.currentPreset = newName
|
||||||
-- Associate with current file
|
addPresetName(newName)
|
||||||
if app.sprite and app.sprite.filename and app.sprite.filename ~= "" then
|
savePreset(newName)
|
||||||
filePresetMap[app.sprite.filename] = selectedPreset
|
local currentFile = app.sprite and app.sprite.filename or ""
|
||||||
end
|
if currentFile ~= "" then filePresetMap[currentFile] = newName end
|
||||||
saveMaster()
|
saveMaster()
|
||||||
-- Close config dialog and reopen main dialog
|
-- Close config and reopen main
|
||||||
d:close()
|
d:close()
|
||||||
if mainDlg then
|
if mainDlg then pcall(function() mainDlg:close() end) end
|
||||||
pcall(function() mainDlg:close() end)
|
|
||||||
end
|
|
||||||
openMainDialog()
|
openMainDialog()
|
||||||
|
-- Reopen preview to update title
|
||||||
|
if previewDlg then
|
||||||
|
pcall(function() previewDlg:close() end)
|
||||||
|
openPreviewWindow()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end }
|
end }
|
||||||
d:button{ id = "btnPresetClone", text = "Clone", onclick = function()
|
d:button{ id = "presetClone", text = "Clone", onclick = function()
|
||||||
local cloneDlg = Dialog{ title = "Clone Preset" }
|
local cd = Dialog{ title = "Clone Preset" }
|
||||||
cloneDlg:entry{ id = "name", label = "New name:", text = S.currentPreset .. "_copy" }
|
cd:entry{ id = "name", label = "New name:", text = S.currentPreset .. "_copy" }
|
||||||
cloneDlg:button{ id = "ok", text = "Clone" }
|
cd:button{ id = "ok", text = "Clone" }
|
||||||
cloneDlg:button{ text = "Cancel" }
|
cd:button{ text = "Cancel" }
|
||||||
cloneDlg:show()
|
cd:show()
|
||||||
if cloneDlg.data.ok then
|
if cd.data.ok and cd.data.name and cd.data.name ~= "" then
|
||||||
local newName = cloneDlg.data.name
|
local newName = cd.data.name
|
||||||
if newName and newName ~= "" then
|
|
||||||
-- Check if name already exists
|
-- Check if name already exists
|
||||||
local exists = false
|
local exists = false
|
||||||
for _, n in ipairs(knownPresetNames) do
|
for _, n in ipairs(getAllPresetNames()) do
|
||||||
if n == newName then exists = true; break end
|
if n == newName then exists = true; break end
|
||||||
end
|
end
|
||||||
if exists then
|
if exists then
|
||||||
app.alert("Preset '" .. newName .. "' already exists.")
|
app.alert("Preset '" .. newName .. "' already exists.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- Save current state as the new preset
|
-- Save current state as the new preset (clone)
|
||||||
savePreset(newName)
|
savePreset(newName)
|
||||||
table.insert(knownPresetNames, newName)
|
addPresetName(newName)
|
||||||
S.currentPreset = newName
|
S.currentPreset = newName
|
||||||
-- Associate with current file
|
local currentFile = app.sprite and app.sprite.filename or ""
|
||||||
if app.sprite and app.sprite.filename and app.sprite.filename ~= "" then
|
if currentFile ~= "" then filePresetMap[currentFile] = newName end
|
||||||
filePresetMap[app.sprite.filename] = newName
|
|
||||||
end
|
|
||||||
saveMaster()
|
saveMaster()
|
||||||
-- Update combobox
|
-- Close config and reopen main
|
||||||
pcall(function()
|
d:close()
|
||||||
d:modify{ id = "presetList", options = getAllPresetNames(), option = S.currentPreset }
|
if mainDlg then pcall(function() mainDlg:close() end) end
|
||||||
end)
|
openMainDialog()
|
||||||
|
-- Reopen preview to update title
|
||||||
|
if previewDlg then
|
||||||
|
pcall(function() previewDlg:close() end)
|
||||||
|
openPreviewWindow()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end }
|
end }
|
||||||
d:button{ id = "btnPresetDelete", text = "Delete", onclick = function()
|
d:button{ id = "presetRename", text = "Rename", onclick = function()
|
||||||
local selectedPreset = d.data.presetList
|
if S.currentPreset == "Default" then
|
||||||
if not selectedPreset or selectedPreset == "" then return end
|
app.alert("Cannot rename the Default preset.")
|
||||||
if selectedPreset == "Default" then
|
return
|
||||||
|
end
|
||||||
|
local rd = Dialog{ title = "Rename Preset" }
|
||||||
|
rd:entry{ id = "name", label = "New name:", text = S.currentPreset }
|
||||||
|
rd:button{ id = "ok", text = "OK" }
|
||||||
|
rd:button{ text = "Cancel" }
|
||||||
|
rd:show()
|
||||||
|
if rd.data.ok and rd.data.name and rd.data.name ~= "" then
|
||||||
|
local newName = rd.data.name
|
||||||
|
if newName == S.currentPreset then return end
|
||||||
|
-- Check if name already exists
|
||||||
|
local exists = false
|
||||||
|
for _, n in ipairs(getAllPresetNames()) do
|
||||||
|
if n == newName then exists = true; break end
|
||||||
|
end
|
||||||
|
if exists then
|
||||||
|
app.alert("Preset '" .. newName .. "' already exists.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local oldName = S.currentPreset
|
||||||
|
-- Rename the preset file
|
||||||
|
local oldPath = app.fs.joinPath(PRESETS_DIR, oldName .. ".ini")
|
||||||
|
local newPath = app.fs.joinPath(PRESETS_DIR, newName .. ".ini")
|
||||||
|
os.rename(oldPath, newPath)
|
||||||
|
-- Update known names
|
||||||
|
removePresetName(oldName)
|
||||||
|
addPresetName(newName)
|
||||||
|
-- Update file associations
|
||||||
|
for filepath, preset in pairs(filePresetMap) do
|
||||||
|
if preset == oldName then
|
||||||
|
filePresetMap[filepath] = newName
|
||||||
|
end
|
||||||
|
end
|
||||||
|
S.currentPreset = newName
|
||||||
|
saveMaster()
|
||||||
|
-- Close config and reopen main
|
||||||
|
d:close()
|
||||||
|
if mainDlg then pcall(function() mainDlg:close() end) end
|
||||||
|
openMainDialog()
|
||||||
|
-- Reopen preview to update title
|
||||||
|
if previewDlg then
|
||||||
|
pcall(function() previewDlg:close() end)
|
||||||
|
openPreviewWindow()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end }
|
||||||
|
d:button{ id = "presetDelete", text = "Delete", onclick = function()
|
||||||
|
if S.currentPreset == "Default" then
|
||||||
app.alert("Cannot delete the Default preset.")
|
app.alert("Cannot delete the Default preset.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local confirm = app.alert{
|
local confirm = app.alert{
|
||||||
title = "Delete Preset",
|
title = "Delete Preset",
|
||||||
text = "Delete preset '" .. selectedPreset .. "'?",
|
text = "Delete preset '" .. S.currentPreset .. "'?",
|
||||||
buttons = { "Delete", "Cancel" }
|
buttons = { "Delete", "Cancel" }
|
||||||
}
|
}
|
||||||
if confirm ~= 1 then return end
|
if confirm ~= 1 then return end
|
||||||
|
local deleteName = S.currentPreset
|
||||||
-- Delete the preset file
|
-- Delete the preset file
|
||||||
local path = app.fs.joinPath(PRESETS_DIR, selectedPreset .. ".ini")
|
local path = app.fs.joinPath(PRESETS_DIR, deleteName .. ".ini")
|
||||||
os.remove(path)
|
os.remove(path)
|
||||||
-- Remove from known names
|
-- Remove from known names
|
||||||
for i, n in ipairs(knownPresetNames) do
|
removePresetName(deleteName)
|
||||||
if n == selectedPreset then
|
|
||||||
table.remove(knownPresetNames, i)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Remove file associations pointing to this preset
|
-- Remove file associations pointing to this preset
|
||||||
for filepath, preset in pairs(filePresetMap) do
|
for filepath, preset in pairs(filePresetMap) do
|
||||||
if preset == selectedPreset then
|
if preset == deleteName then
|
||||||
filePresetMap[filepath] = nil
|
filePresetMap[filepath] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- If current preset was deleted, switch to Default
|
-- Switch to Default
|
||||||
if S.currentPreset == selectedPreset then
|
|
||||||
loadPreset("Default")
|
loadPreset("Default")
|
||||||
S.currentPreset = "Default"
|
S.currentPreset = "Default"
|
||||||
if app.sprite and app.sprite.filename and app.sprite.filename ~= "" then
|
if app.sprite and app.sprite.filename and app.sprite.filename ~= "" then
|
||||||
filePresetMap[app.sprite.filename] = nil
|
filePresetMap[app.sprite.filename] = nil
|
||||||
end
|
end
|
||||||
end
|
|
||||||
saveMaster()
|
saveMaster()
|
||||||
-- Update combobox
|
-- Close config and reopen main
|
||||||
pcall(function()
|
d:close()
|
||||||
d:modify{ id = "presetList", options = getAllPresetNames(), option = S.currentPreset }
|
if mainDlg then pcall(function() mainDlg:close() end) end
|
||||||
end)
|
openMainDialog()
|
||||||
|
-- Reopen preview to update title
|
||||||
|
if previewDlg then
|
||||||
|
pcall(function() previewDlg:close() end)
|
||||||
|
openPreviewWindow()
|
||||||
|
end
|
||||||
end }
|
end }
|
||||||
|
|
||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
|
|
@ -1806,6 +1856,28 @@ openMainDialog = function()
|
||||||
local plv = d.data.previewLayoutValue
|
local plv = d.data.previewLayoutValue
|
||||||
if plv < 1 then plv = 1 elseif plv > 20 then plv = 20 end
|
if plv < 1 then plv = 1 elseif plv > 20 then plv = 20 end
|
||||||
S.previewLayoutValue = plv
|
S.previewLayoutValue = plv
|
||||||
|
-- Check if preset changed via combobox
|
||||||
|
local selectedPreset = d.data.presetSelect
|
||||||
|
local presetChanged = false
|
||||||
|
if selectedPreset and selectedPreset ~= S.currentPreset then
|
||||||
|
savePreset(S.currentPreset) -- Save current first
|
||||||
|
loadPreset(selectedPreset) -- Load new
|
||||||
|
S.currentPreset = selectedPreset
|
||||||
|
local currentFile = app.sprite and app.sprite.filename or ""
|
||||||
|
if currentFile ~= "" then filePresetMap[currentFile] = selectedPreset end
|
||||||
|
presetChanged = true
|
||||||
|
end
|
||||||
|
saveAll()
|
||||||
|
if presetChanged then
|
||||||
|
dlg:close()
|
||||||
|
openMainDialog()
|
||||||
|
-- Reopen preview to update title
|
||||||
|
if previewDlg then
|
||||||
|
pcall(function() previewDlg:close() end)
|
||||||
|
openPreviewWindow()
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -2198,6 +2270,7 @@ openMainDialog = function()
|
||||||
S.selectedFrame = #frames
|
S.selectedFrame = #frames
|
||||||
end
|
end
|
||||||
if #frames == 0 then S.selectedFrame = 0 end
|
if #frames == 0 then S.selectedFrame = 0 end
|
||||||
|
saveAll()
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -2225,6 +2298,7 @@ openMainDialog = function()
|
||||||
local frame = table.remove(frames, from)
|
local frame = table.remove(frames, from)
|
||||||
table.insert(frames, to, frame)
|
table.insert(frames, to, frame)
|
||||||
S.selectedFrame = to
|
S.selectedFrame = to
|
||||||
|
saveAll()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
S.frameDragging = false
|
S.frameDragging = false
|
||||||
|
|
@ -2251,6 +2325,7 @@ openMainDialog = function()
|
||||||
local frames = S.anims[name]
|
local frames = S.anims[name]
|
||||||
if not frames or S.selectedFrame > #frames then return end
|
if not frames or S.selectedFrame > #frames then return end
|
||||||
frames[S.selectedFrame].flipped = not frames[S.selectedFrame].flipped
|
frames[S.selectedFrame].flipped = not frames[S.selectedFrame].flipped
|
||||||
|
saveAll()
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
@ -2264,6 +2339,7 @@ openMainDialog = function()
|
||||||
local frames = S.anims[name]
|
local frames = S.anims[name]
|
||||||
if not frames or S.selectedFrame > #frames then return end
|
if not frames or S.selectedFrame > #frames then return end
|
||||||
frames[S.selectedFrame].flippedV = not frames[S.selectedFrame].flippedV
|
frames[S.selectedFrame].flippedV = not frames[S.selectedFrame].flippedV
|
||||||
|
saveAll()
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
@ -2279,6 +2355,7 @@ openMainDialog = function()
|
||||||
local idx = S.selectedFrame
|
local idx = S.selectedFrame
|
||||||
frames[idx], frames[idx - 1] = frames[idx - 1], frames[idx]
|
frames[idx], frames[idx - 1] = frames[idx - 1], frames[idx]
|
||||||
S.selectedFrame = idx - 1
|
S.selectedFrame = idx - 1
|
||||||
|
saveAll()
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
@ -2294,6 +2371,7 @@ openMainDialog = function()
|
||||||
local idx = S.selectedFrame
|
local idx = S.selectedFrame
|
||||||
frames[idx], frames[idx + 1] = frames[idx + 1], frames[idx]
|
frames[idx], frames[idx + 1] = frames[idx + 1], frames[idx]
|
||||||
S.selectedFrame = idx + 1
|
S.selectedFrame = idx + 1
|
||||||
|
saveAll()
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
@ -2336,6 +2414,7 @@ openMainDialog = function()
|
||||||
S.selectedFrame = #frames
|
S.selectedFrame = #frames
|
||||||
end
|
end
|
||||||
if #frames == 0 then S.selectedFrame = 0 end
|
if #frames == 0 then S.selectedFrame = 0 end
|
||||||
|
saveAll()
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
@ -2353,6 +2432,7 @@ openMainDialog = function()
|
||||||
local frames = S.anims[name]
|
local frames = S.anims[name]
|
||||||
if not frames or S.selectedFrame > #frames then return end
|
if not frames or S.selectedFrame > #frames then return end
|
||||||
frames[S.selectedFrame].offY = (frames[S.selectedFrame].offY or 0) - 1
|
frames[S.selectedFrame].offY = (frames[S.selectedFrame].offY or 0) - 1
|
||||||
|
saveAll()
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
@ -2365,6 +2445,7 @@ openMainDialog = function()
|
||||||
local frames = S.anims[name]
|
local frames = S.anims[name]
|
||||||
if not frames or S.selectedFrame > #frames then return end
|
if not frames or S.selectedFrame > #frames then return end
|
||||||
frames[S.selectedFrame].offY = (frames[S.selectedFrame].offY or 0) + 1
|
frames[S.selectedFrame].offY = (frames[S.selectedFrame].offY or 0) + 1
|
||||||
|
saveAll()
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
@ -2377,6 +2458,7 @@ openMainDialog = function()
|
||||||
local frames = S.anims[name]
|
local frames = S.anims[name]
|
||||||
if not frames or S.selectedFrame > #frames then return end
|
if not frames or S.selectedFrame > #frames then return end
|
||||||
frames[S.selectedFrame].offX = (frames[S.selectedFrame].offX or 0) - 1
|
frames[S.selectedFrame].offX = (frames[S.selectedFrame].offX or 0) - 1
|
||||||
|
saveAll()
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
@ -2389,6 +2471,7 @@ openMainDialog = function()
|
||||||
local frames = S.anims[name]
|
local frames = S.anims[name]
|
||||||
if not frames or S.selectedFrame > #frames then return end
|
if not frames or S.selectedFrame > #frames then return end
|
||||||
frames[S.selectedFrame].offX = (frames[S.selectedFrame].offX or 0) + 1
|
frames[S.selectedFrame].offX = (frames[S.selectedFrame].offX or 0) + 1
|
||||||
|
saveAll()
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
@ -2402,6 +2485,7 @@ openMainDialog = function()
|
||||||
if not frames or S.selectedFrame > #frames then return end
|
if not frames or S.selectedFrame > #frames then return end
|
||||||
frames[S.selectedFrame].offX = 0
|
frames[S.selectedFrame].offX = 0
|
||||||
frames[S.selectedFrame].offY = 0
|
frames[S.selectedFrame].offY = 0
|
||||||
|
saveAll()
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
@ -2482,6 +2566,7 @@ openMainDialog = function()
|
||||||
width = math.min(S.gbOptImage.width * z, SOURCE_VIEWPORT_W),
|
width = math.min(S.gbOptImage.width * z, SOURCE_VIEWPORT_W),
|
||||||
height = math.min(S.gbOptImage.height * z, GB_OPT_H) }
|
height = math.min(S.gbOptImage.height * z, GB_OPT_H) }
|
||||||
end
|
end
|
||||||
|
saveAll()
|
||||||
dlg:repaint()
|
dlg:repaint()
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
@ -3117,6 +3202,7 @@ openMainDialog = function()
|
||||||
if not path or path == "" then return end
|
if not path or path == "" then return end
|
||||||
|
|
||||||
S.gbLastSavePath = path
|
S.gbLastSavePath = path
|
||||||
|
saveAll()
|
||||||
|
|
||||||
local optW = S.gbOptImage.width
|
local optW = S.gbOptImage.width
|
||||||
local optH = S.gbOptImage.height
|
local optH = S.gbOptImage.height
|
||||||
|
|
@ -3171,6 +3257,11 @@ openMainDialog = function()
|
||||||
S.currentPreset = presetForFile
|
S.currentPreset = presetForFile
|
||||||
pcall(function() dlg:close() end)
|
pcall(function() dlg:close() end)
|
||||||
openMainDialog()
|
openMainDialog()
|
||||||
|
-- Reopen preview to update title
|
||||||
|
if previewDlg then
|
||||||
|
pcall(function() previewDlg:close() end)
|
||||||
|
openPreviewWindow()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -3190,12 +3281,17 @@ local function run()
|
||||||
app.alert("No sprite is open.")
|
app.alert("No sprite is open.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- Toggle: if already running, close everything
|
-- Check if already running via lock file
|
||||||
if previewDlg then
|
local lockF = io.open(LOCK_FILE, "r")
|
||||||
pcall(function() previewDlg:close() end)
|
if lockF then
|
||||||
if mainDlg then pcall(function() mainDlg:close() end) end
|
lockF:close()
|
||||||
|
app.alert("AniPhallow is already running.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
-- Create lock file
|
||||||
|
local lf = io.open(LOCK_FILE, "w")
|
||||||
|
if lf then lf:write("running"); lf:close() end
|
||||||
|
|
||||||
S.currentTab = "Animations"
|
S.currentTab = "Animations"
|
||||||
refreshSource()
|
refreshSource()
|
||||||
-- Always open preview window on launch
|
-- Always open preview window on launch
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue