2个脚本整合。一个批量渲染序列帧工具、一个批量生成GIF工具。 批量渲染完成后 去掉渲染完成提示 去掉打开文件夹 直接自动批量生成GIF,GIF输出目录 默认为 批量渲染序列帧文件夹 的 父目录。接下来我会给两个脚本。 脚本1:try(destroyDialog renderSeqRollout)catch()
rollout renderSeqRollout "批量渲染序列帧工具 V5.4" width:423 height:500
(
-- 单场景渲染控件
groupBox grpSingle "单场景渲染设置" width:390 height:70 pos:[15, 10]
checkbox chk_useActiveRange "使用时间滑块范围" checked:true align:#left offset:[10,-50] across:2
checkbox chk_openFolder "渲染后打开文件夹" checked:true align:#right offset:[-120,-50]
spinner spn_startFrame "起始帧:" range:[-99999,99999,0] type:#integer fieldWidth:50 offset:[10,0] across:2
spinner spn_endFrame "结束帧:" range:[-99999,99999,100] type:#integer fieldWidth:50 offset:[-90,0]
-- 渲染尺寸设置
groupBox grpRenderSize "渲染尺寸设置" width:390 height:90 pos:[15, 85]
checkbox chk_customSize "使用自定义尺寸" checked:false align:#left offset:[10,-30]
checkbox chk_lockAspect "锁定宽高比" checked:false align:#right offset:[-120,-30] across:2
spinner spn_width "宽度:" range:[1,10000,renderWidth] type:#integer fieldWidth:50 offset:[10,0] across:2
spinner spn_height "高度:" range:[1,10000,renderHeight] type:#integer fieldWidth:50 offset:[-90,0]
-- 批量渲染控件
groupBox grpBatch "批量渲染设置" width:390 height:200 pos:[15, 180]
checkbox chk_batchMode "批量渲染模式" checked:false align:#left offset:[10,-185]
label lbl_batchPath "当前文件夹路径:" align:#left offset:[10,10] across:2
editText edt_batchPath "" width:230 height:20 align:#right offset:[-150,8] readOnly:true
button btn_refresh "刷新" width:50 height:20 align:#right offset:[-90,-25]
listBox lst_files "MAX文件列表" height:6 width:370 pos:[20, 265]
-- 通用控件
button btn_render "渲染序列帧" width:390 height:40 pos:[15, 405]
progressBar pb_progress "进度条:" color:(color 0 128 255) height:15 pos:[10, 455]
label lbl_status "状态: 准备就绪" align:#left offset:[0,5] pos:[15, 475]
-- 局部变量
local frameCount = 0
local renderedFrames = 0
local outputDir = ""
local outputPattern = ""
local sceneName = ""
local batchFiles = #()
local currentBatchIndex = 1
local batchTotalFiles = 0
local originalScenePath = ""
local originalSceneFile = ""
local aspectRatio = 1.0 -- 用于存储宽高比
-- 扫描当前文件夹中的MAX文件
fn scanMaxFiles =
(
local currentPath = maxFilePath
if currentPath != "" then
(
edt_batchPath.text = currentPath
batchFiles = getFiles (currentPath + "\\*.max")
lst_files.items = for f in batchFiles collect filenameFromPath f
lbl_status.text = "状态: 找到 " + (batchFiles.count as string) + " 个MAX文件"
)
else
(
lbl_status.text = "状态: 场景未保存,请先保存场景"
edt_batchPath.text = ""
lst_files.items = #()
)
)
-- 初始化时设置正确的帧范围和渲染尺寸
on renderSeqRollout open do
(
spn_startFrame.value = animationRange.start.frame as integer
spn_endFrame.value = animationRange.end.frame as integer
spn_width.value = renderWidth
spn_height.value = renderHeight
-- 计算初始宽高比
if renderHeight > 0 do aspectRatio = renderWidth as float / renderHeight as float
-- 设置控件状态
spn_startFrame.enabled = not chk_useActiveRange.checked
spn_endFrame.enabled = not chk_useActiveRange.checked
spn_width.enabled = chk_customSize.checked
spn_height.enabled = chk_customSize.checked
scanMaxFiles() -- 自动扫描当前文件夹
)
on chk_useActiveRange changed state do
(
spn_startFrame.enabled = not state
spn_endFrame.enabled = not state
if state do
(
spn_startFrame.value = animationRange.start.frame as integer
spn_endFrame.value = animationRange.end.frame as integer
)
)
-- 自定义尺寸复选框事件
on chk_customSize changed state do
(
spn_width.enabled = state
spn_height.enabled = state
chk_lockAspect.enabled = state
)
-- 更新宽高比锁定
fn updateAspectLock =
(
if chk_lockAspect.checked and spn_height.value > 0 do
(
aspectRatio = spn_width.value as float / spn_height.value as float
)
)
-- 宽度变化事件
on spn_width changed val do
(
if chk_lockAspect.checked and aspectRatio > 0 and chk_customSize.checked then
(
local newHeight = (val / aspectRatio) as integer
if newHeight > 0 do
(
spn_height.value = newHeight
)
)
else
(
updateAspectLock()
)
)
-- 高度变化事件
on spn_height changed val do
(
if chk_lockAspect.checked and aspectRatio > 0 and chk_customSize.checked then
(
local newWidth = (val * aspectRatio) as integer
if newWidth > 0 do
(
spn_width.value = newWidth
)
)
else
(
updateAspectLock()
)
)
-- 锁定宽高比复选框事件
on chk_lockAspect changed state do
(
if state and spn_height.value > 0 do
(
aspectRatio = spn_width.value as float / spn_height.value as float
)
)
-- 获取时间滑块的实际范围
fn getActualTimeRange =
(
local actualStart = animationRange.start.frame as integer
local actualEnd = animationRange.end.frame as integer
return #(actualStart, actualEnd)
)
-- 刷新文件列表按钮事件
on btn_refresh pressed do
(
scanMaxFiles()
)
-- 渲染单帧函数
fn renderSingleFrame frameIndex =
(
-- 设置当前帧
sliderTime = frameIndex
-- 生成当前帧的文件名
frameNumber = formattedPrint frameIndex format:"06d"
frameFile = substituteString outputPattern "######" frameNumber
-- 执行渲染(禁用所有窗口)
render outputfile:frameFile vfb:false progressbar:false quiet:true
-- 更新进度
renderedFrames += 1
pb_progress.value = (100.0 * renderedFrames / frameCount)
lbl_status.text = "状态: 渲染中 (" + renderedFrames as string + "/" + frameCount as string + ")"
)
-- 渲染当前场景
fn renderCurrentScene =
(
-- 检查场景是否保存
if maxFileName == "" then
(
lbl_status.text = "状态: 错误 - 场景未保存!"
messageBox "请先保存场景文件!" title:"错误"
return false
)
-- 获取场景信息
sceneName = getFilenameFile maxFileName
local scenePath = maxFilePath
-- 创建输出目录
outputDir = scenePath + sceneName
if not doesFileExist outputDir then
(
makeDir outputDir
lbl_status.text = "状态: 创建目录 - " + outputDir
)
-- 获取实际时间范围
local actualRange = getActualTimeRange()
-- 设置渲染范围
local startFrame, endFrame
if chk_useActiveRange.checked then
(
startFrame = actualRange[1]
endFrame = actualRange[2]
)
else
(
startFrame = spn_startFrame.value
endFrame = spn_endFrame.value
)
-- 计算帧数
frameCount = endFrame - startFrame + 1
if frameCount <= 0 then
(
lbl_status.text = "状态: 错误 - 无效帧范围!"
messageBox "帧范围无效!起始帧不能大于结束帧。" title:"错误"
return false
)
-- 创建输出文件名模式(JPG格式)
outputPattern = outputDir + "\\" + sceneName + "_" + "######.jpg"
-- 保存当前渲染器设置
local oldRenderer = renderers.current
-- 将渲染器设置为Scanline Renderer
renderers.current = Default_Scanline_Renderer()
-- 检查渲染器
if renderers.current == undefined then
(
lbl_status.text = "状态: 错误 - 没有激活的渲染器!"
messageBox "没有激活的渲染器!请选择渲染器。" title:"错误"
return false
)
-- 保存当前渲染设置
local oldOutput = rendOutputFilename
local oldSaveFile = rendSaveFile
local oldTimeType = rendTimeType
local oldNThFrame = rendNThFrame
local oldStart = rendStart
local oldEnd = rendEnd
-- 保存当前渲染尺寸
local oldWidth = renderWidth
local oldHeight = renderHeight
-- 如果启用自定义尺寸,设置新的渲染尺寸
if chk_customSize.checked then
(
renderWidth = spn_width.value
renderHeight = spn_height.value
)
-- 设置渲染参数
rendOutputFilename = outputPattern
rendSaveFile = true
rendTimeType = 3 -- 渲染范围
rendNThFrame = 1 -- 每帧渲染
rendStart = startFrame
rendEnd = endFrame
-- 提交渲染设置
renderSceneDialog.update()
renderSceneDialog.commit()
-- 逐帧渲染
renderedFrames = 0
local success = true
for f = startFrame to endFrame do
(
try
(
renderSingleFrame f
)
catch
(
lbl_status.text = "状态: 错误 - 渲染帧 " + f as string + " 时失败"
messageBox ("渲染帧 " + f as string + " 时失败:\n" + getCurrentException()) title:"渲染错误"
success = false
exit
)
)
-- 恢复原始渲染设置
rendOutputFilename = oldOutput
rendSaveFile = oldSaveFile
rendTimeType = oldTimeType
rendNThFrame = oldNThFrame
rendStart = oldStart
rendEnd = oldEnd
renderers.current = oldRenderer
-- 恢复原始渲染尺寸
renderWidth = oldWidth
renderHeight = oldHeight
renderSceneDialog.commit()
return success
)
-- 渲染按钮事件
on btn_render pressed do
(
-- 重置状态
pb_progress.value = 0
renderedFrames = 0
setWaitCursor()
if chk_batchMode.checked then
(
-- 批量渲染模式
if batchFiles.count == 0 then
(
lbl_status.text = "状态: 错误 - 未找到MAX文件!"
messageBox "当前文件夹中没有找到MAX文件!" title:"错误"
return false
)
-- 保存当前场景信息
originalScenePath = maxFilePath
originalSceneFile = maxFileName
batchTotalFiles = batchFiles.count
currentBatchIndex = 1
lbl_status.text = "状态: 开始批量渲染 (" + batchTotalFiles as string + " 个文件)..."
for i = 1 to batchFiles.count do
(
local currentFile = batchFiles[i]
currentBatchIndex = i
-- 更新文件进度
pb_progress.value = (100.0 * (i-1) / batchTotalFiles)
lbl_status.text = "状态: 正在渲染文件 " + i as string + "/" + batchTotalFiles as string + ": " + filenameFromPath currentFile
-- 加载MAX文件
loadMaxFile currentFile quiet:true
-- 渲染当前场景
local success = renderCurrentScene()
if not success then
(
messageBox ("渲染失败: " + currentFile) title:"错误"
exit
)
)
-- 恢复原始场景
if originalSceneFile != "" then
(
local originalFilePath = originalScenePath + originalSceneFile
if doesFileExist originalFilePath then
(
loadMaxFile originalFilePath quiet:true
lbl_status.text = "状态: 已恢复原始场景"
)
)
pb_progress.value = 100
lbl_status.text = "状态: 批量渲染完成! (" + batchTotalFiles as string + " 个文件)"
messageBox ("批量渲染成功完成!\n共渲染了 " + batchTotalFiles as string + " 个场景") title:"渲染成功"
)
else
(
-- 单场景渲染模式
lbl_status.text = "状态: 开始渲染当前场景..."
local success = renderCurrentScene()
if success then
(
pb_progress.value = 100
lbl_status.text = "状态: 渲染完成! (" + frameCount as string + " 帧)"
-- 可选:打开输出目录
if chk_openFolder.checked and doesFileExist outputDir then
(
shellLaunch "explorer.exe" outputDir
)
messageBox ("渲染成功完成!\n共渲染了 " + frameCount as string + " 帧\n输出目录: " + outputDir) title:"渲染成功"
)
else
(
pb_progress.value = 0
)
)
setArrowCursor()
)
)
createdialog renderSeqRollout 脚本2:rollout gifMakerRollout "GIF生成工具 - 多文件夹处理" width:400 height:420
(
-- UI控件声明
groupBox grpSettings "设置" pos:[10,10] width:380 height:200
editText edtFFmpegPath "FFmpeg路径:" pos:[20,35] fieldWidth:300 labelOnTop:true text:"" -- 初始为空
button btnBrowseFFmpeg "浏览..." pos:[330,35] width:40 height:20
editText edtParentFolder "父文件夹路径:" pos:[20,75] fieldWidth:300 labelOnTop:true text:(getDir #export + "\\") -- 默认导出目录
button btnBrowseParentFolder "浏览..." pos:[330,75] width:40 height:20
label lblPatternHint "图片序列格式:" pos:[20,115] width:100 height:20
dropdownlist ddlPattern "序列格式" pos:[20,135] width:300 height:40 items:#("自动检测序列帧", "手动输入格式...")
editText edtCustomPattern "" pos:[20,175] fieldWidth:300 height:20 visible:false
button btnTestPattern "测试格式" pos:[330,175] width:40 height:20 visible:false
groupBox grpAnimation "动画设置" pos:[10,220] width:380 height:80
spinner spnFrameRate "帧率 (fps):" pos:[20,240] range:[1,60,30] type:#integer fieldWidth:50
spinner spnSpeedFactor "速度因子:" pos:[150,240] range:[0.1,10.0,1.0] type:#float scale:0.1 fieldWidth:50
label lblSpeedHint "1.0=正常 | 2.0=2倍速 | 0.5=半速" pos:[210,240] width:150 height:20
checkbox chkAutoOpen "生成后打开文件夹" pos:[20,280] checked:true
progressBar pbProgress "" pos:[10,310] width:380 height:20 value:0 color:(color 0 255 0)
label lblStatus "" pos:[10,335] width:380 height:20
button btnGenerate "批量生成GIF" pos:[100,360] width:100 height:30
button btnCancel "取消" pos:[220,360] width:100 height:30
-- 自动查找脚本目录下的FFmpeg
fn findFFmpegInScriptDir =
(
-- 获取脚本文件路径
local scriptPath = getSourceFileName()
if scriptPath == undefined do return ""
-- 获取脚本所在目录
local scriptDir = getFilenamePath scriptPath
-- 检查常见位置
local possiblePaths = #(
scriptDir + "ffmpeg.exe", -- 直接在脚本目录
scriptDir + "ffmpeg\\bin\\ffmpeg.exe", -- 在ffmpeg子目录
scriptDir + "bin\\ffmpeg.exe", -- 在bin子目录
scriptDir + "tools\\ffmpeg.exe" -- 在tools子目录
)
-- 查找存在的路径
for path in possiblePaths do
(
if doesFileExist path do return path
)
return ""
)
-- 辅助函数:验证路径是否存在
fn validatePath path isFile:false =
(
if path == "" do
(
messageBox "路径不能为空!" title:"错误"
return false
)
if isFile then
(
if not doesFileExist path then
(
messageBox ("路径不存在: \n" + path) title:"错误"
return false
)
)
else
(
if not doesDirectoryExist path then
(
messageBox ("文件夹不存在: \n" + path) title:"错误"
return false
)
)
return true
)
-- 获取图片分辨率 - 更可靠的方法
fn getImageResolution imgPath =
(
if doesFileExist imgPath then
(
try
(
-- 使用openBitmap方法获取分辨率
local bmp = openBitmap imgPath
if bmp != undefined then
(
local w = bmp.width
local h = bmp.height
close bmp
return [w, h]
)
)
catch
(
format "无法读取图片分辨率: %\n" imgPath
)
)
return [0,0]
)
-- 检测序列帧模式并获取分辨率
fn detectSequencePatternAndResolution folderPath =
(
local sequenceFiles = #()
if not doesDirectoryExist folderPath do return #("", [0,0])
-- 获取所有图片文件
imgFiles = getFiles (folderPath + "*.jpg")
join imgFiles (getFiles (folderPath + "*.jpeg"))
join imgFiles (getFiles (folderPath + "*.png"))
join imgFiles (getFiles (folderPath + "*.bmp"))
join imgFiles (getFiles (folderPath + "*.tga"))
join imgFiles (getFiles (folderPath + "*.tif"))
join imgFiles (getFiles (folderPath + "*.tiff"))
if imgFiles.count == 0 do return #("", [0,0])
-- 按文件名排序
sort imgFiles
-- 分析文件名模式
patterns = #()
resolutions = #()
for i = 1 to imgFiles.count do
(
fileName = filenameFromPath imgFiles[i]
baseName = getFilenameFile fileName
fileExt = getFilenameType fileName
-- 查找数字序列部分
digits = ""
prefix = ""
suffix = ""
digitCount = 0
digitStart = 0
-- 查找数字序列
for j = baseName.count to 1 by -1 do
(
char = baseName[j]
if (findString "0123456789" char) != undefined then
(
digits = char + digits
digitCount += 1
digitStart = j
)
else
(
if digitCount > 0 do exit
)
)
-- 如果找到数字序列
if digitCount > 0 then
(
prefix = substring baseName 1 (digitStart - 1)
suffix = substring baseName (digitStart + digitCount) -1
-- 生成序列模式
pattern = prefix + "%0" + (digitCount as string) + "d" + suffix + fileExt
append patterns pattern
-- 获取图片分辨率(只取第一张)
if i == 1 then
(
resolution = getImageResolution imgFiles[i]
append resolutions resolution
)
)
)
if patterns.count == 0 do return #("", [0,0])
-- 找出最常见的模式
patternCounts = #()
for p in patterns do
(
index = findItem patternCounts p
if index == 0 then
(
append patternCounts p
append patternCounts 1
)
else
(
patternCounts[index+1] += 1
)
)
-- 选择出现次数最多的模式
maxCount = 0
bestPattern = ""
for i = 1 to patternCounts.count by 2 do
(
if patternCounts[i+1] > maxCount then
(
maxCount = patternCounts[i+1]
bestPattern = patternCounts[i]
)
)
-- 转换为FFmpeg格式 (使用两个%表示单个%)
if bestPattern != "" do
(
bestPattern = substituteString bestPattern "%0" "%%0"
)
-- 返回最佳模式和分辨率
return #(bestPattern, resolutions[1])
)
-- 测试序列格式
fn testSequencePattern folderPath pattern =
(
if not doesDirectoryExist folderPath do return false
-- 转换为搜索模式
searchPattern = substituteString pattern "%%0" "*"
searchPattern = substituteString searchPattern "d" "*"
-- 查找匹配文件
matchedFiles = getFiles (folderPath + searchPattern)
return matchedFiles.count > 0
)
-- 浏览FFmpeg路径
on btnBrowseFFmpeg pressed do
(
local path = getOpenFileName caption:"选择FFmpeg可执行文件" \
filename:edtFFmpegPath.text \
types:"可执行文件(*.exe)|*.exe"
if path != undefined do edtFFmpegPath.text = path
)
-- 浏览父文件夹
on btnBrowseParentFolder pressed do
(
local path = getSavePath caption:"选择父文件夹" \
initialDir:edtParentFolder.text
if path != undefined do
(
folderPath = path + "\\"
edtParentFolder.text = folderPath
)
)
-- 序列格式下拉列表改变事件
on ddlPattern selected sel do
(
if sel == 2 then
(
edtCustomPattern.visible = true
btnTestPattern.visible = true
edtCustomPattern.text = "例如: image_%%03d.jpg"
)
else
(
edtCustomPattern.visible = false
btnTestPattern.visible = false
)
)
-- 测试序列格式按钮
on btnTestPattern pressed do
(
folderPath = edtParentFolder.text
if not doesDirectoryExist folderPath do
(
messageBox "文件夹不存在!" title:"错误"
return false
)
-- 获取第一个子文件夹进行测试
subFolders = getDirectories (folderPath + "*")
if subFolders.count == 0 do
(
messageBox "父文件夹中没有子文件夹!" title:"错误"
return false
)
testFolder = subFolders[1]
pattern = edtCustomPattern.text
if testSequencePattern testFolder pattern then
(
messageBox ("格式有效!\n在第一个子文件夹中检测到匹配文件。") title:"测试结果"
)
else
(
messageBox ("未找到匹配文件!\n请检查格式是否正确。") title:"测试结果"
)
)
-- 生成GIF (使用setpts滤镜实现真正的速度控制)
on btnGenerate pressed do
(
-- 获取UI中的值
ffmpegPath = edtFFmpegPath.text
parentFolder = edtParentFolder.text
frameRate = spnFrameRate.value
speedFactor = spnSpeedFactor.value
-- 获取序列格式
if ddlPattern.selection == 1 then
(
useAutoPattern = true
)
else
(
useAutoPattern = false
manualPattern = edtCustomPattern.text
)
-- 验证FFmpeg路径
if ffmpegPath == "" do
(
messageBox "请设置FFmpeg路径!" title:"错误"
return false
)
if not validatePath ffmpegPath isFile:true do return false
if not validatePath parentFolder do return false
-- 确保文件夹以反斜杠结尾
if not matchPattern parentFolder pattern:"*\\" do parentFolder += "\\"
-- 获取所有子文件夹
subFolders = getDirectories (parentFolder + "*")
if subFolders.count == 0 do
(
messageBox "父文件夹中没有子文件夹!" title:"错误"
return false
)
-- 初始化进度条
pbProgress.value = 0
pbProgress.color = (color 0 255 0)
lblStatus.text = "准备开始处理..."
totalFolders = subFolders.count
processedFolders = 0
skippedFolders = 0
generatedGifs = #()
-- 处理每个子文件夹
for folder in subFolders do
(
-- 更新状态
folderName = getFilenameFile (trimRight folder "\\")
lblStatus.text = "处理中: " + folderName
processedFolders += 1
pbProgress.value = (100.0 * processedFolders / totalFolders)
-- 强制更新UI
windows.processPostedMessages()
-- 检测序列模式并获取分辨率
local patternAndRes
if useAutoPattern then
(
patternAndRes = detectSequencePatternAndResolution folder
imgPattern = patternAndRes[1]
resolution = patternAndRes[2]
if imgPattern == "" then
(
format "跳过文件夹 [%] - 未检测到序列帧\n" folderName
skippedFolders += 1
continue
)
if resolution.x == 0 or resolution.y == 0 then
(
format "跳过文件夹 [%] - 无法获取分辨率\n" folderName
skippedFolders += 1
continue
)
)
else
(
imgPattern = manualPattern
-- 尝试获取第一张图片的分辨率
searchPattern = substituteString imgPattern "%%0" "000"
searchPattern = substituteString searchPattern "d" "*"
imgFiles = getFiles (folder + searchPattern)
if imgFiles.count > 0 then
(
resolution = getImageResolution imgFiles[1]
if resolution.x == 0 or resolution.y == 0 then
(
format "跳过文件夹 [%] - 无法获取分辨率\n" folderName
skippedFolders += 1
continue
)
)
else
(
format "跳过文件夹 [%] - 没有匹配的图片文件\n" folderName
skippedFolders += 1
continue
)
)
-- 构建输入输出路径
fullInputPath = folder + imgPattern
fullOutputPath = parentFolder + folderName + ".gif"
-- 删除已存在的GIF文件以确保覆盖
if doesFileExist fullOutputPath do
(
deleteFile fullOutputPath
format "已删除旧文件: %\n" fullOutputPath
)
-- 使用setpts滤镜实现真正的速度控制
setptsFilter = "setpts=PTS/" + (speedFactor as string)
scaleFilter = "scale=" + (resolution.x as string) + ":" + (resolution.y as string) + ":flags=lanczos"
-- 构建完整的ffmpeg命令
ffmpegCmd = "\"" + ffmpegPath + "\" -y -framerate " + (frameRate as string) + \
" -i \"" + fullInputPath + "\" " + \
"-vf \"" + setptsFilter + "," + scaleFilter + "\" " + \
"-r " + (frameRate as string) + " " + \
"-loop 0 \"" + fullOutputPath + "\""
-- 输出命令到监听器以便调试
format "处理文件夹 [%]:\n命令: %\n" folderName ffmpegCmd
lblStatus.text = "处理中: " + folderName + " (" + resolution.x as string + "x" + resolution.y as string + ")"
-- 创建临时批处理文件
tempBatFile = getDir #temp + "\\make_gif_" + (random 1 10000) as string + ".bat"
batContent = "@echo off\n" + ffmpegCmd
-- 创建并写入批处理文件
success = false
f = createFile tempBatFile
if f != undefined then
(
format "%" batContent to:f
close f
success = true
)
else
(
format "无法创建临时批处理文件!\n"
)
-- 执行批处理文件 (隐藏窗口)
if success do
(
exitCode = HiddenDosCommand ("\"" + tempBatFile + "\"")
format "退出代码: %\n" exitCode
-- 检查输出文件是否存在
if doesFileExist fullOutputPath then
(
append generatedGifs fullOutputPath
format "成功生成GIF: %\n" fullOutputPath
)
else
(
format "生成GIF失败: %\n" fullOutputPath
)
-- 清理临时文件
if doesFileExist tempBatFile do deleteFile tempBatFile
)
)
-- 完成进度条
pbProgress.value = 100
lblStatus.text = "处理完成! 已生成 " + (generatedGifs.count as string) + " 个GIF"
-- 如果需要,打开输出文件夹
if chkAutoOpen.checked and generatedGifs.count > 0 do
(
shellLaunch "explorer.exe" ("/e,\"" + parentFolder + "\"")
)
messageBox ("成功生成 " + (generatedGifs.count as string) + " 个GIF!\n跳过 " + (skippedFolders as string) + " 个文件夹。") title:"完成"
)
-- 取消按钮
on btnCancel pressed do
(
DestroyDialog gifMakerRollout
)
-- 初始化UI
on gifMakerRollout open do
(
ddlPattern.items = #("自动检测序列帧", "手动输入格式...")
-- 自动查找FFmpeg路径
local autoFFmpegPath = findFFmpegInScriptDir()
if autoFFmpegPath != "" then
(
edtFFmpegPath.text = autoFFmpegPath
format "自动设置FFmpeg路径: %\n" autoFFmpegPath
)
else
(
messageBox "请设置FFmpeg路径!\n点击'浏览...'按钮选择ffmpeg.exe文件。" title:"提示"
)
)
)
-- 创建UI窗口
CreateDialog gifMakerRollout
最新发布