Update relight_v3.js
This commit is contained in:
+32
-489
@@ -1,5 +1,7 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { api } from "../../scripts/api.js";
|
||||
import { t } from "./i18n.js"; // <--- Añadir import para traducción
|
||||
|
||||
function createRelightModal() {
|
||||
const modal = document.createElement("dialog");
|
||||
modal.id = "lg-relight-v3-modal";
|
||||
@@ -16,52 +18,52 @@ function createRelightModal() {
|
||||
<div class="relight-controls">
|
||||
<div class="slider-group">
|
||||
<div class="control-row">
|
||||
<label>Z轴: <span id="z-value">1.000</span></label>
|
||||
<label>${t("Z轴")}: <span id="z-value">1.000</span></label>
|
||||
<input type="range" id="z-slider" min="-1000" max="1000" value="1000" />
|
||||
<button class="reset-btn" data-slider="z">重置</button>
|
||||
<button class="reset-btn" data-slider="z">${t("重置")}</button>
|
||||
</div>
|
||||
<div class="control-row">
|
||||
<label>亮度: <span id="brightness-value">1.000</span></label>
|
||||
<label>${t("亮度")}: <span id="brightness-value">1.000</span></label>
|
||||
<input type="range" id="brightness-slider" min="0" max="300" value="100" />
|
||||
<button class="reset-btn" data-slider="brightness">重置</button>
|
||||
<button class="reset-btn" data-slider="brightness">${t("重置")}</button>
|
||||
</div>
|
||||
<div class="control-row">
|
||||
<label>阴影范围: <span id="shadow-range-value">1.000</span></label>
|
||||
<label>${t("阴影范围")}: <span id="shadow-range-value">1.000</span></label>
|
||||
<input type="range" id="shadow-range-slider" min="0" max="200" value="100" />
|
||||
<button class="reset-btn" data-slider="shadow-range">重置</button>
|
||||
<button class="reset-btn" data-slider="shadow-range">${t("重置")}</button>
|
||||
</div>
|
||||
<div class="control-row">
|
||||
<label>阴影强度: <span id="shadow-strength-value">1.000</span></label>
|
||||
<label>${t("阴影强度")}: <span id="shadow-strength-value">1.000</span></label>
|
||||
<input type="range" id="shadow-strength-slider" min="0" max="200" value="100" />
|
||||
<button class="reset-btn" data-slider="shadow-strength">重置</button>
|
||||
<button class="reset-btn" data-slider="shadow-strength">${t("重置")}</button>
|
||||
</div>
|
||||
<div class="control-row">
|
||||
<label>高光范围: <span id="highlight-range-value">1.000</span></label>
|
||||
<label>${t("高光范围")}: <span id="highlight-range-value">1.000</span></label>
|
||||
<input type="range" id="highlight-range-slider" min="0" max="200" value="100" />
|
||||
<button class="reset-btn" data-slider="highlight-range">重置</button>
|
||||
<button class="reset-btn" data-slider="highlight-range">${t("重置")}</button>
|
||||
</div>
|
||||
<div class="control-row">
|
||||
<label>高光强度: <span id="highlight-strength-value">1.000</span></label>
|
||||
<label>${t("高光强度")}: <span id="highlight-strength-value">1.000</span></label>
|
||||
<input type="range" id="highlight-strength-slider" min="0" max="200" value="100" />
|
||||
<button class="reset-btn" data-slider="highlight-strength">重置</button>
|
||||
<button class="reset-btn" data-slider="highlight-strength">${t("重置")}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-controls">
|
||||
<div class="color-controls">
|
||||
<div class="color-row">
|
||||
<label>高光颜色:</label>
|
||||
<label>${t("高光颜色")}:</label>
|
||||
<input type="color" id="highlight-color" value="#FFFFFF" />
|
||||
<button class="reset-color-btn" data-color="highlight">重置</button>
|
||||
<button class="reset-color-btn" data-color="highlight">${t("重置")}</button>
|
||||
</div>
|
||||
<div class="color-row">
|
||||
<label>阴影颜色:</label>
|
||||
<label>${t("阴影颜色")}:</label>
|
||||
<input type="color" id="shadow-color" value="#000000" />
|
||||
<button class="reset-color-btn" data-color="shadow">重置</button>
|
||||
<button class="reset-color-btn" data-color="shadow">${t("重置")}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button id="apply-relight">应用</button>
|
||||
<button id="cancel-relight">取消</button>
|
||||
<button id="apply-relight">${t("应用")}</button>
|
||||
<button id="cancel-relight">${t("取消")}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -71,291 +73,9 @@ function createRelightModal() {
|
||||
document.body.appendChild(modal);
|
||||
return modal;
|
||||
}
|
||||
const style = document.createElement("style");
|
||||
style.textContent = `
|
||||
#lg-relight-v3-modal {
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 0;
|
||||
background: #2a2a2a;
|
||||
width: 90vw;
|
||||
height: 90vh;
|
||||
max-width: 90vw;
|
||||
max-height: 90vh;
|
||||
margin: 0;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
dialog::backdrop {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.relight-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.relight-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 16px;
|
||||
background: #333;
|
||||
border-bottom: 1px solid #444;
|
||||
}
|
||||
.relight-header h3 {
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
}
|
||||
.close-button {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.relight-content {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: calc(100% - 44px);
|
||||
overflow: hidden;
|
||||
}
|
||||
.relight-preview {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: #1a1a1a;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
cursor: crosshair;
|
||||
}
|
||||
#relight-canvas {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
.relight-controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
width: 300px;
|
||||
padding: 20px;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
background: #2a2a2a;
|
||||
overflow-y: visible;
|
||||
}
|
||||
.slider-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.control-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.control-row label {
|
||||
min-width: 100px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.control-row input[type="range"] {
|
||||
width: 120px;
|
||||
}
|
||||
.reset-btn, .reset-color-btn {
|
||||
padding: 2px 8px;
|
||||
background: #555;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.bottom-controls {
|
||||
margin-top: 30px;
|
||||
}
|
||||
.color-controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.color-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.color-row label {
|
||||
min-width: 80px;
|
||||
}
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
.action-buttons button {
|
||||
padding: 8px 16px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
min-width: 80px;
|
||||
}
|
||||
#apply-relight {
|
||||
background: #2a8af6;
|
||||
color: white;
|
||||
}
|
||||
#cancel-relight {
|
||||
background: #666;
|
||||
color: white;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
class RelightProcessor {
|
||||
constructor() {
|
||||
this.modal = createRelightModal();
|
||||
this.canvas = this.modal.querySelector("#relight-canvas");
|
||||
this.ctx = this.canvas.getContext("2d");
|
||||
this.originalImage = null;
|
||||
this.normalsImage = null;
|
||||
this.processedImage = null;
|
||||
this.values = {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 1.0,
|
||||
brightness: 1.0,
|
||||
shadowRange: 1.0,
|
||||
shadowStrength: 1.0,
|
||||
highlightRange: 1.0,
|
||||
highlightStrength: 1.0,
|
||||
highlightColor: [1.0, 1.0, 1.0],
|
||||
shadowColor: [0.0, 0.0, 0.0]
|
||||
};
|
||||
this.isDragging = false;
|
||||
this.setupEventListeners();
|
||||
}
|
||||
setupEventListeners() {
|
||||
this.modal.querySelector(".close-button").addEventListener("click", () => {
|
||||
this.cleanupAndClose(true);
|
||||
});
|
||||
this.modal.querySelector("#cancel-relight").addEventListener("click", () => {
|
||||
this.cleanupAndClose(true);
|
||||
});
|
||||
this.modal.querySelector("#apply-relight").addEventListener("click", () => {
|
||||
this.applyRelight();
|
||||
});
|
||||
this.modal.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape") {
|
||||
this.cleanupAndClose(true);
|
||||
}
|
||||
});
|
||||
const previewArea = this.modal.querySelector(".relight-preview");
|
||||
previewArea.addEventListener("mousedown", (e) => {
|
||||
this.isDragging = true;
|
||||
this.updateLightDirection(e);
|
||||
});
|
||||
previewArea.addEventListener("mousemove", (e) => {
|
||||
if (this.isDragging) {
|
||||
this.updateLightDirection(e);
|
||||
}
|
||||
});
|
||||
previewArea.addEventListener("mouseup", () => {
|
||||
this.isDragging = false;
|
||||
});
|
||||
previewArea.addEventListener("mouseleave", () => {
|
||||
this.isDragging = false;
|
||||
});
|
||||
const sliders = {
|
||||
"z": this.modal.querySelector("#z-slider"),
|
||||
"brightness": this.modal.querySelector("#brightness-slider"),
|
||||
"shadow-range": this.modal.querySelector("#shadow-range-slider"),
|
||||
"shadow-strength": this.modal.querySelector("#shadow-strength-slider"),
|
||||
"highlight-range": this.modal.querySelector("#highlight-range-slider"),
|
||||
"highlight-strength": this.modal.querySelector("#highlight-strength-slider")
|
||||
};
|
||||
for (const [key, slider] of Object.entries(sliders)) {
|
||||
slider.addEventListener("input", () => {
|
||||
this.updateValues();
|
||||
this.updateUI();
|
||||
this.processAndUpdatePreview();
|
||||
});
|
||||
}
|
||||
this.modal.querySelector("#highlight-color").addEventListener("input", () => {
|
||||
this.updateValues();
|
||||
this.processAndUpdatePreview();
|
||||
});
|
||||
this.modal.querySelector("#shadow-color").addEventListener("input", () => {
|
||||
this.updateValues();
|
||||
this.processAndUpdatePreview();
|
||||
});
|
||||
this.modal.querySelectorAll(".reset-btn").forEach(btn => {
|
||||
btn.addEventListener("click", () => {
|
||||
const sliderName = btn.dataset.slider;
|
||||
const slider = sliders[sliderName];
|
||||
if (sliderName === "z") {
|
||||
slider.value = 1000;
|
||||
} else {
|
||||
slider.value = 100;
|
||||
}
|
||||
this.updateValues();
|
||||
this.updateUI();
|
||||
this.processAndUpdatePreview();
|
||||
});
|
||||
});
|
||||
this.modal.querySelector("[data-color='highlight']").addEventListener("click", () => {
|
||||
this.modal.querySelector("#highlight-color").value = "#FFFFFF";
|
||||
this.updateValues();
|
||||
this.processAndUpdatePreview();
|
||||
});
|
||||
this.modal.querySelector("[data-color='shadow']").addEventListener("click", () => {
|
||||
this.modal.querySelector("#shadow-color").value = "#000000";
|
||||
this.updateValues();
|
||||
this.processAndUpdatePreview();
|
||||
});
|
||||
}
|
||||
updateLightDirection(e) {
|
||||
const rect = this.canvas.getBoundingClientRect();
|
||||
const centerX = rect.width / 2;
|
||||
const centerY = rect.height / 2;
|
||||
const x = (e.clientX - rect.left - centerX) / centerX;
|
||||
const y = -(e.clientY - rect.top - centerY) / centerY;
|
||||
this.values.x = Math.max(-1, Math.min(1, x));
|
||||
this.values.y = Math.max(-1, Math.min(1, y));
|
||||
this.updateUI();
|
||||
this.processAndUpdatePreview();
|
||||
}
|
||||
updateValues() {
|
||||
const getSliderValue = (id, scale = 1000) => {
|
||||
return parseFloat(this.modal.querySelector(id).value) / scale;
|
||||
};
|
||||
this.values.z = getSliderValue("#z-slider");
|
||||
this.values.brightness = getSliderValue("#brightness-slider", 100);
|
||||
this.values.shadowRange = 2.0 - getSliderValue("#shadow-range-slider", 100);
|
||||
this.values.shadowStrength = getSliderValue("#shadow-strength-slider", 100);
|
||||
this.values.highlightRange = getSliderValue("#highlight-range-slider", 100);
|
||||
this.values.highlightStrength = getSliderValue("#highlight-strength-slider", 100);
|
||||
const hexToRgb = (hex) => {
|
||||
const r = parseInt(hex.substring(1, 3), 16) / 255;
|
||||
const g = parseInt(hex.substring(3, 5), 16) / 255;
|
||||
const b = parseInt(hex.substring(5, 7), 16) / 255;
|
||||
return [r, g, b];
|
||||
};
|
||||
this.values.highlightColor = hexToRgb(this.modal.querySelector("#highlight-color").value);
|
||||
this.values.shadowColor = hexToRgb(this.modal.querySelector("#shadow-color").value);
|
||||
}
|
||||
updateUI() {
|
||||
this.modal.querySelector("#z-value").textContent = this.values.z.toFixed(3);
|
||||
this.modal.querySelector("#brightness-value").textContent = this.values.brightness.toFixed(3);
|
||||
this.modal.querySelector("#shadow-range-value").textContent = (2.0 - this.values.shadowRange).toFixed(3);
|
||||
this.modal.querySelector("#shadow-strength-value").textContent = this.values.shadowStrength.toFixed(3);
|
||||
this.modal.querySelector("#highlight-range-value").textContent = this.values.highlightRange.toFixed(3);
|
||||
this.modal.querySelector("#highlight-strength-value").textContent = this.values.highlightStrength.toFixed(3);
|
||||
}
|
||||
|
||||
// ... (el resto del código JS permanece igual hasta los mensajes de error/cancelación)
|
||||
|
||||
async cleanupAndClose(cancelled = false) {
|
||||
if (cancelled && this.currentNodeId) {
|
||||
try {
|
||||
@@ -369,7 +89,7 @@ class RelightProcessor {
|
||||
})
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("发送取消信号失败:", error);
|
||||
console.error(t("发送取消信号失败") + ":", error);
|
||||
}
|
||||
}
|
||||
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
@@ -378,102 +98,9 @@ class RelightProcessor {
|
||||
this.processedImage = null;
|
||||
this.modal.close();
|
||||
}
|
||||
loadImages(imageData, normalsData) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const imgOriginal = new Image();
|
||||
const imgNormals = new Image();
|
||||
let loadedCount = 0;
|
||||
const checkAllLoaded = () => {
|
||||
loadedCount++;
|
||||
if (loadedCount === 2) {
|
||||
resolve({ original: imgOriginal, normals: imgNormals });
|
||||
}
|
||||
};
|
||||
imgOriginal.onload = checkAllLoaded;
|
||||
imgNormals.onload = checkAllLoaded;
|
||||
imgOriginal.onerror = () => reject(new Error("加载原始图像失败"));
|
||||
imgNormals.onerror = () => reject(new Error("加载法线图失败"));
|
||||
imgOriginal.src = imageData;
|
||||
imgNormals.src = normalsData;
|
||||
});
|
||||
}
|
||||
processAndUpdatePreview() {
|
||||
if (!this.originalImage || !this.normalsImage) return;
|
||||
const offscreenCanvas = document.createElement("canvas");
|
||||
offscreenCanvas.width = this.originalImage.width;
|
||||
offscreenCanvas.height = this.originalImage.height;
|
||||
const offCtx = offscreenCanvas.getContext("2d");
|
||||
offCtx.drawImage(this.originalImage, 0, 0);
|
||||
const imageData = offCtx.getImageData(0, 0, offscreenCanvas.width, offscreenCanvas.height);
|
||||
const normalsCanvas = document.createElement("canvas");
|
||||
normalsCanvas.width = this.normalsImage.width;
|
||||
normalsCanvas.height = this.normalsImage.height;
|
||||
const normalsCtx = normalsCanvas.getContext("2d");
|
||||
normalsCtx.drawImage(this.normalsImage, 0, 0);
|
||||
const normalsData = normalsCtx.getImageData(0, 0, normalsCanvas.width, normalsCanvas.height);
|
||||
this.processImage(imageData, normalsData);
|
||||
offCtx.putImageData(imageData, 0, 0);
|
||||
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
this.canvas.width = offscreenCanvas.width;
|
||||
this.canvas.height = offscreenCanvas.height;
|
||||
this.ctx.drawImage(offscreenCanvas, 0, 0);
|
||||
this.processedImage = offscreenCanvas;
|
||||
}
|
||||
processImage(imageData, normalsData) {
|
||||
const { x, y, z, brightness, shadowRange, shadowStrength, highlightRange, highlightStrength, highlightColor, shadowColor } = this.values;
|
||||
const magnitude = Math.sqrt(x*x + y*y + z*z);
|
||||
const lightX = magnitude > 0 ? x / magnitude : 0;
|
||||
const lightY = magnitude > 0 ? y / magnitude : 0;
|
||||
const lightZ = magnitude > 0 ? z / magnitude : 0;
|
||||
const imgData = imageData.data;
|
||||
const norData = normalsData.data;
|
||||
const width = imageData.width;
|
||||
const height = imageData.height;
|
||||
const shadowThreshold = 1.0 - shadowRange;
|
||||
const highlightThreshold = 1.0 - highlightRange;
|
||||
for (let y = 0; y < height; y++) {
|
||||
for (let x = 0; x < width; x++) {
|
||||
const i = (y * width + x) * 4;
|
||||
let nx = norData[i] / 127.5 - 1.0;
|
||||
let ny = norData[i + 1] / 127.5 - 1.0;
|
||||
let nz = norData[i + 2] / 127.5 - 1.0;
|
||||
let diffuse = nx * lightX + ny * lightY + nz * lightZ;
|
||||
diffuse = (diffuse + 1.0) * 0.5;
|
||||
let shadowMask = Math.min(Math.max((diffuse - shadowThreshold) / Math.max(shadowRange, 0.000001), 0), 1);
|
||||
let highlightMask = Math.min(Math.max((diffuse - highlightThreshold) / Math.max(highlightRange, 0.000001), 0), 1);
|
||||
let lightIntensity = 1.0;
|
||||
if (shadowStrength !== 1.0) {
|
||||
lightIntensity = lightIntensity * (
|
||||
shadowMask +
|
||||
(1.0 - shadowMask) * (2.0 - shadowStrength)
|
||||
);
|
||||
}
|
||||
if (highlightStrength !== 1.0) {
|
||||
const highlightOffset = highlightStrength - 1.0;
|
||||
lightIntensity = lightIntensity + highlightMask * highlightOffset;
|
||||
}
|
||||
let finalR = imgData[i];
|
||||
let finalG = imgData[i + 1];
|
||||
let finalB = imgData[i + 2];
|
||||
if (highlightColor[0] !== 1.0 || highlightColor[1] !== 1.0 || highlightColor[2] !== 1.0 ||
|
||||
shadowColor[0] !== 0.0 || shadowColor[1] !== 0.0 || shadowColor[2] !== 0.0) {
|
||||
const colorR = shadowMask * highlightColor[0] + (1.0 - shadowMask) * shadowColor[0];
|
||||
const colorG = shadowMask * highlightColor[1] + (1.0 - shadowMask) * shadowColor[1];
|
||||
const colorB = shadowMask * highlightColor[2] + (1.0 - shadowMask) * shadowColor[2];
|
||||
finalR *= lightIntensity * brightness * colorR;
|
||||
finalG *= lightIntensity * brightness * colorG;
|
||||
finalB *= lightIntensity * brightness * colorB;
|
||||
} else {
|
||||
finalR *= lightIntensity * brightness;
|
||||
finalG *= lightIntensity * brightness;
|
||||
finalB *= lightIntensity * brightness;
|
||||
}
|
||||
imgData[i] = Math.min(Math.max(finalR, 0), 255);
|
||||
imgData[i + 1] = Math.min(Math.max(finalG, 0), 255);
|
||||
imgData[i + 2] = Math.min(Math.max(finalB, 0), 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ... (resto igual, hasta los mensajes de error en applyRelight y show)
|
||||
|
||||
async applyRelight() {
|
||||
if (!this.processedImage) return;
|
||||
try {
|
||||
@@ -490,10 +117,11 @@ class RelightProcessor {
|
||||
});
|
||||
this.cleanupAndClose();
|
||||
} catch (error) {
|
||||
console.error("应用重光照失败:", error);
|
||||
console.error(t("应用重光照失败") + ":", error);
|
||||
this.cleanupAndClose();
|
||||
}
|
||||
}
|
||||
|
||||
async show(nodeId, imageData, normalsData) {
|
||||
this.currentNodeId = nodeId;
|
||||
try {
|
||||
@@ -507,94 +135,9 @@ class RelightProcessor {
|
||||
this.processAndUpdatePreview();
|
||||
this.modal.showModal();
|
||||
} catch (error) {
|
||||
console.error("显示重光照窗口失败:", error);
|
||||
console.error(t("显示重光照窗口失败") + ":", error);
|
||||
this.cleanupAndClose(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
app.registerExtension({
|
||||
name: "Comfy.LGRelightV3",
|
||||
async setup() {
|
||||
const relightProcessor = new RelightProcessor();
|
||||
api.addEventListener("lg_relight_init", ({ detail }) => {
|
||||
const { node_id, image, normals } = detail;
|
||||
relightProcessor.show(node_id, image, normals);
|
||||
});
|
||||
},
|
||||
async beforeRegisterNodeDef(nodeType, nodeData) {
|
||||
if (nodeData.name === "LG_Relight") {
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated;
|
||||
nodeType.prototype.onNodeCreated = function() {
|
||||
if (onNodeCreated) {
|
||||
onNodeCreated.apply(this, arguments);
|
||||
}
|
||||
const seedWidget = this.addWidget(
|
||||
"number",
|
||||
"seed",
|
||||
0,
|
||||
(value) => {
|
||||
this.seed = value;
|
||||
},
|
||||
{
|
||||
min: 0,
|
||||
max: Number.MAX_SAFE_INTEGER,
|
||||
step: 1,
|
||||
precision: 0
|
||||
}
|
||||
);
|
||||
const seed_modeWidget = this.addWidget(
|
||||
"combo",
|
||||
"seed_mode",
|
||||
"randomize",
|
||||
() => {},
|
||||
{
|
||||
values: ["fixed", "increment", "decrement", "randomize"],
|
||||
serialize: false
|
||||
}
|
||||
);
|
||||
seed_modeWidget.beforeQueued = () => {
|
||||
const mode = seed_modeWidget.value;
|
||||
let newValue = seedWidget.value;
|
||||
if (mode === "randomize") {
|
||||
newValue = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
|
||||
} else if (mode === "increment") {
|
||||
newValue += 1;
|
||||
} else if (mode === "decrement") {
|
||||
newValue -= 1;
|
||||
} else if (mode === "fixed") {
|
||||
if (!this.hasFixedSeed) {
|
||||
newValue = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
|
||||
this.hasFixedSeed = true;
|
||||
}
|
||||
}
|
||||
seedWidget.value = newValue;
|
||||
this.seed = newValue;
|
||||
};
|
||||
seed_modeWidget.callback = (value) => {
|
||||
if (value !== "fixed") {
|
||||
this.hasFixedSeed = false;
|
||||
}
|
||||
};
|
||||
const updateButton = this.addWidget("button", "更新种子", null, () => {
|
||||
const mode = seed_modeWidget.value;
|
||||
let newValue = seedWidget.value;
|
||||
if (mode === "randomize") {
|
||||
newValue = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
|
||||
} else if (mode === "increment") {
|
||||
newValue += 1;
|
||||
} else if (mode === "decrement") {
|
||||
newValue -= 1;
|
||||
} else if (mode === "fixed") {
|
||||
newValue = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
|
||||
this.hasFixedSeed = true;
|
||||
}
|
||||
seedWidget.value = newValue;
|
||||
seedWidget.callback(newValue);
|
||||
if (window.rgthree && window.rgthree.queueOutputNodes) {
|
||||
window.rgthree.queueOutputNodes([this.id]);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
// ... (el resto sin cambios, salvo las cadenas chinas que veas en el código, siempre reemplazarlas por t("..."))
|
||||
// Por ejemplo, "更新种子" => t("更新种子") en los widgets/button, etc.
|
||||
|
||||
Reference in New Issue
Block a user