// ==UserScript== // @name 叠帧快捷操作 // @namespace jjw666 // @version 1.3 // @description 快速设置叠帧范围并执行叠帧操作 // @author You // @match https://bdlabel-adsd.mychery.com/* // @grant none // @license All Rights Reserved // ==/UserScript== (function() { 'use strict'; // 等待DOM加载完成 function waitForElement(selector, timeout = 5000) { return new Promise((resolve, reject) => { const startTime = Date.now(); const checkInterval = setInterval(() => { const element = document.querySelector(selector); if (element) { clearInterval(checkInterval); resolve(element); } else if (Date.now() - startTime > timeout) { clearInterval(checkInterval); reject(new Error(`元素 ${selector} 未找到`)); } }, 500); }); } // 获取当前帧和总帧数 function getFrameInfo() { // 从第二段代码中获取当前帧 const currentFrameInput = document.querySelector('.style_frameNum__3XHKJ .ant-input-number-input'); const totalFramesSpan = document.querySelector('.style_frameListBtn__-odJ0 span'); let currentFrame = 15; // 默认值 let totalFrames = 40; // 默认值 if (currentFrameInput) { currentFrame = parseInt(currentFrameInput.value) || 15; } if (totalFramesSpan) { const match = totalFramesSpan.textContent.match(/\d+/); if (match) { totalFrames = parseInt(match[0]) || 40; } } return { currentFrame, totalFrames }; } // 获取叠帧输入框 function getFrameInputs() { const inputs = document.querySelectorAll('.Modals_content__1zhd- .ant-input-number .ant-input-number-input'); if (inputs.length >= 2) { return { startInput: inputs[0], endInput: inputs[1] }; } return null; } // 设置叠帧输入框的值 function setFrameValues(startFrame, endFrame) { const inputs = getFrameInputs(); if (!inputs) return; // 设置起始帧 const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set; nativeInputValueSetter.call(inputs.startInput, startFrame); inputs.startInput.dispatchEvent(new Event('input', { bubbles: true })); inputs.startInput.dispatchEvent(new Event('change', { bubbles: true })); inputs.startInput.dispatchEvent(new Event('blur', { bubbles: true })); // 设置结束帧 nativeInputValueSetter.call(inputs.endInput, endFrame); inputs.endInput.dispatchEvent(new Event('input', { bubbles: true })); inputs.endInput.dispatchEvent(new Event('change', { bubbles: true })); inputs.endInput.dispatchEvent(new Event('blur', { bubbles: true })); } // 重置输入框到默认值(第一个数为1,第二个数为总帧数) function resetFrameInputs() { const info = getFrameInfo(); // 重置为 1 到总帧数 setFrameValues(1, info.totalFrames); } // 点击叠帧按钮 function clickStackFrameButton() { const stackBtn = document.querySelector('.Modals_content__1zhd- .ant-btn-primary'); if (stackBtn) { stackBtn.click(); } } // 设置叠帧开关状态 function setStackToggle(enabled) { const switchBtn = document.querySelector('.Modals_content__1zhd- .ant-switch'); if (switchBtn) { const isChecked = switchBtn.getAttribute('aria-checked') === 'true'; if (isChecked !== enabled) { switchBtn.click(); } } } // 创建自定义按钮 function createButtons() { // 查找开关元素 const switchBtn = document.querySelector('.Modals_content__1zhd- .ant-switch'); if (!switchBtn) return; // 查找开关所在的容器 const switchContainer = switchBtn.closest('div[style*="display: flex; align-items: center;"]'); if (!switchContainer) return; // 检查是否已存在我们的按钮 if (document.getElementById('custom-frame-buttons')) return; // 创建按钮容器(放在开关后面) const btnContainer = document.createElement('div'); btnContainer.id = 'custom-frame-buttons'; btnContainer.style.cssText = ` display: inline-flex; gap: 4px; margin-left: 8px; align-items: center; `; // 创建分隔符 const separator = document.createElement('span'); separator.style.cssText = 'color: #d9d9d9; margin: 0 4px;'; separator.textContent = '|'; // 创建"当前→第一帧"按钮 (用 -1 表示) const btnToFirst = document.createElement('button'); btnToFirst.type = 'button'; btnToFirst.className = 'ant-btn ant-btn-text ant-btn-sm'; btnToFirst.style.cssText = ` color: #1890ff; padding: 0 4px; font-size: 12px; height: 22px; line-height: 22px; border: none; background: transparent; cursor: pointer; `; btnToFirst.textContent = '-1'; btnToFirst.title = '当前帧到第一帧'; btnToFirst.addEventListener('click', function(e) { e.stopPropagation(); const info = getFrameInfo(); setStackToggle(true); setFrameValues(1, info.currentFrame); setTimeout(clickStackFrameButton, 300); }); // 创建"当前→最后一帧"按钮 (用 1- 表示) const btnToEnd = document.createElement('button'); btnToEnd.type = 'button'; btnToEnd.className = 'ant-btn ant-btn-text ant-btn-sm'; btnToEnd.style.cssText = ` color: #52c41a; padding: 0 4px; font-size: 12px; height: 22px; line-height: 22px; border: none; background: transparent; cursor: pointer; `; btnToEnd.textContent = '1-'; btnToEnd.title = '当前帧到最后一帧'; btnToEnd.addEventListener('click', function(e) { e.stopPropagation(); const info = getFrameInfo(); setStackToggle(true); setFrameValues(info.currentFrame, info.totalFrames); setTimeout(clickStackFrameButton, 300); }); // 创建分隔符 const separator2 = document.createElement('span'); separator2.style.cssText = 'color: #d9d9d9; margin: 0 4px;'; separator2.textContent = '|'; // 创建"取消叠帧"按钮 (用 OFF 表示) const btnCancel = document.createElement('button'); btnCancel.type = 'button'; btnCancel.className = 'ant-btn ant-btn-text ant-btn-sm'; btnCancel.style.cssText = ` color: #ff4d4f; padding: 0 4px; font-size: 12px; height: 22px; line-height: 22px; border: none; background: transparent; cursor: pointer; `; btnCancel.textContent = 'OFF'; btnCancel.title = '取消叠帧'; btnCancel.addEventListener('click', function(e) { e.stopPropagation(); setStackToggle(false); resetFrameInputs(); }); // 添加元素到容器 btnContainer.appendChild(btnToFirst); btnContainer.appendChild(separator); btnContainer.appendChild(btnToEnd); btnContainer.appendChild(separator2); btnContainer.appendChild(btnCancel); // 将按钮容器插入到开关后面 switchContainer.appendChild(btnContainer); } // 监听叠帧对话框的出现 function observeStackDialog() { // 使用MutationObserver监听DOM变化 const observer = new MutationObserver(function(mutations) { const dialog = document.querySelector('.Modals_stackFrameContainer__19rT_'); if (dialog && dialog.style.display !== 'none') { // 对话框出现,创建按钮 setTimeout(createButtons, 500); } }); observer.observe(document.body, { childList: true, subtree: true, attributes: false }); // 初始检查 setTimeout(createButtons, 1000); } // 启动脚本 observeStackDialog(); // 也监听叠帧对话框内的变化,以便在切换时重新创建按钮 const dialogObserver = new MutationObserver(function(mutations) { const switchBtn = document.querySelector('.Modals_content__1zhd- .ant-switch'); if (switchBtn && !document.getElementById('custom-frame-buttons')) { createButtons(); } }); dialogObserver.observe(document.body, { childList: true, subtree: true, attributes: false }); console.log('叠帧快捷操作脚本已加载 - 简化版'); })();