mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 07:05:43 -03:00
feat(trigger-word-toggle): add strength value support for trigger words
- Extract and preserve strength values from trigger words in format "(word:strength)" - Maintain strength formatting when filtering active trigger words in both group and individual modes - Update active state tracking to handle strength-modified words correctly - Ensure backward compatibility with existing trigger word formats
This commit is contained in:
@@ -63,7 +63,22 @@ class TriggerWordToggle:
|
|||||||
trigger_data = json.loads(trigger_data)
|
trigger_data = json.loads(trigger_data)
|
||||||
|
|
||||||
# Create dictionaries to track active state of words or groups
|
# Create dictionaries to track active state of words or groups
|
||||||
active_state = {item['text']: item.get('active', False) for item in trigger_data}
|
# Also track strength values for each trigger word
|
||||||
|
active_state = {}
|
||||||
|
strength_map = {}
|
||||||
|
|
||||||
|
for item in trigger_data:
|
||||||
|
text = item['text']
|
||||||
|
active = item.get('active', False)
|
||||||
|
# Extract strength if it's in the format "(word:strength)"
|
||||||
|
strength_match = re.match(r'\((.+):([\d.]+)\)', text)
|
||||||
|
if strength_match:
|
||||||
|
original_word = strength_match.group(1)
|
||||||
|
strength = float(strength_match.group(2))
|
||||||
|
active_state[original_word] = active
|
||||||
|
strength_map[original_word] = strength
|
||||||
|
else:
|
||||||
|
active_state[text] = active
|
||||||
|
|
||||||
if group_mode:
|
if group_mode:
|
||||||
# Split by two or more consecutive commas to get groups
|
# Split by two or more consecutive commas to get groups
|
||||||
@@ -71,19 +86,60 @@ class TriggerWordToggle:
|
|||||||
# Remove leading/trailing whitespace from each group
|
# Remove leading/trailing whitespace from each group
|
||||||
groups = [group.strip() for group in groups]
|
groups = [group.strip() for group in groups]
|
||||||
|
|
||||||
# Filter groups: keep those not in toggle_trigger_words or those that are active
|
# Process groups: keep those not in toggle_trigger_words or those that are active
|
||||||
filtered_groups = [group for group in groups if group not in active_state or active_state[group]]
|
filtered_groups = []
|
||||||
|
for group in groups:
|
||||||
|
# Check if this group contains any words that are in the active_state
|
||||||
|
group_words = [word.strip() for word in group.split(',')]
|
||||||
|
active_group_words = []
|
||||||
|
|
||||||
|
for word in group_words:
|
||||||
|
# Remove any existing strength formatting for comparison
|
||||||
|
word_comparison = re.sub(r'\((.+):([\d.]+)\)', r'\1', word).strip()
|
||||||
|
|
||||||
|
if word_comparison not in active_state or active_state[word_comparison]:
|
||||||
|
# If this word has a strength value, use that instead of the original
|
||||||
|
if word_comparison in strength_map:
|
||||||
|
active_group_words.append(f"({word_comparison}:{strength_map[word_comparison]:.2f})")
|
||||||
|
else:
|
||||||
|
# Preserve existing strength formatting if the word was previously modified
|
||||||
|
# Check if the original word had strength formatting
|
||||||
|
strength_match = re.match(r'\((.+):([\d.]+)\)', word)
|
||||||
|
if strength_match:
|
||||||
|
active_group_words.append(word)
|
||||||
|
else:
|
||||||
|
active_group_words.append(word)
|
||||||
|
|
||||||
|
if active_group_words:
|
||||||
|
filtered_groups.append(', '.join(active_group_words))
|
||||||
|
|
||||||
if filtered_groups:
|
if filtered_groups:
|
||||||
filtered_triggers = ', '.join(filtered_groups)
|
filtered_triggers = ', '.join(filtered_groups)
|
||||||
else:
|
else:
|
||||||
filtered_triggers = ""
|
filtered_triggers = ""
|
||||||
else:
|
else:
|
||||||
# Original behavior for individual words mode
|
# Normal mode: split by commas and treat each word as a separate tag
|
||||||
original_words = [word.strip() for word in trigger_words.split(',')]
|
original_words = [word.strip() for word in trigger_words.split(',')]
|
||||||
# Filter out empty strings
|
# Filter out empty strings
|
||||||
original_words = [word for word in original_words if word]
|
original_words = [word for word in original_words if word]
|
||||||
filtered_words = [word for word in original_words if word not in active_state or active_state[word]]
|
|
||||||
|
filtered_words = []
|
||||||
|
for word in original_words:
|
||||||
|
# Remove any existing strength formatting for comparison
|
||||||
|
word_comparison = re.sub(r'\((.+):([\d.]+)\)', r'\1', word).strip()
|
||||||
|
|
||||||
|
if word_comparison not in active_state or active_state[word_comparison]:
|
||||||
|
# If this word has a strength value, use that instead of the original
|
||||||
|
if word_comparison in strength_map:
|
||||||
|
filtered_words.append(f"({word_comparison}:{strength_map[word_comparison]:.2f})")
|
||||||
|
else:
|
||||||
|
# Preserve existing strength formatting if the word was previously modified
|
||||||
|
# Check if the original word had strength formatting
|
||||||
|
strength_match = re.match(r'\((.+):([\d.]+)\)', word)
|
||||||
|
if strength_match:
|
||||||
|
filtered_words.append(word)
|
||||||
|
else:
|
||||||
|
filtered_words.append(word)
|
||||||
|
|
||||||
if filtered_words:
|
if filtered_words:
|
||||||
filtered_triggers = ', '.join(filtered_words)
|
filtered_triggers = ', '.join(filtered_words)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { forwardMiddleMouseToCanvas } from "./utils.js";
|
import { forwardMiddleMouseToCanvas } from "./utils.js";
|
||||||
|
|
||||||
export function addTagsWidget(node, name, opts, callback) {
|
export function addTagsWidget(node, name, opts, callback, wheelSensitivity = 0.02) {
|
||||||
// Create container for tags
|
// Create container for tags
|
||||||
const container = document.createElement("div");
|
const container = document.createElement("div");
|
||||||
container.className = "comfy-tags-container";
|
container.className = "comfy-tags-container";
|
||||||
@@ -78,13 +78,19 @@ export function addTagsWidget(node, name, opts, callback) {
|
|||||||
|
|
||||||
let tagCount = 0;
|
let tagCount = 0;
|
||||||
normalizedTags.forEach((tagData, index) => {
|
normalizedTags.forEach((tagData, index) => {
|
||||||
const { text, active, highlighted } = tagData;
|
const { text, active, highlighted, strength } = tagData;
|
||||||
const tagEl = document.createElement("div");
|
const tagEl = document.createElement("div");
|
||||||
tagEl.className = "comfy-tag";
|
tagEl.className = "comfy-tag";
|
||||||
|
|
||||||
updateTagStyle(tagEl, active, highlighted);
|
updateTagStyle(tagEl, active, highlighted, strength);
|
||||||
|
|
||||||
tagEl.textContent = text;
|
// Set the text content to include strength if present
|
||||||
|
// Always show strength if it has been modified to avoid layout shift
|
||||||
|
if (strength !== undefined && strength !== null) {
|
||||||
|
tagEl.textContent = `${text}:${strength.toFixed(2)}`;
|
||||||
|
} else {
|
||||||
|
tagEl.textContent = text;
|
||||||
|
}
|
||||||
tagEl.title = text; // Set tooltip for full content
|
tagEl.title = text; // Set tooltip for full content
|
||||||
|
|
||||||
// Add click handler to toggle state
|
// Add click handler to toggle state
|
||||||
@@ -97,7 +103,8 @@ export function addTagsWidget(node, name, opts, callback) {
|
|||||||
updateTagStyle(
|
updateTagStyle(
|
||||||
tagEl,
|
tagEl,
|
||||||
updatedTags[index].active,
|
updatedTags[index].active,
|
||||||
updatedTags[index].highlighted
|
updatedTags[index].highlighted,
|
||||||
|
updatedTags[index].strength
|
||||||
);
|
);
|
||||||
|
|
||||||
tagEl.dataset.active = updatedTags[index].active ? "true" : "false";
|
tagEl.dataset.active = updatedTags[index].active ? "true" : "false";
|
||||||
@@ -106,6 +113,50 @@ export function addTagsWidget(node, name, opts, callback) {
|
|||||||
widget.value = updatedTags;
|
widget.value = updatedTags;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add mouse wheel handler to adjust strength
|
||||||
|
tagEl.addEventListener("wheel", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
// Only adjust strength if the mouse is over the tag
|
||||||
|
const updatedTags = [...widget.value];
|
||||||
|
let currentStrength = updatedTags[index].strength;
|
||||||
|
|
||||||
|
// If no strength is set, default to 1.0
|
||||||
|
if (currentStrength === undefined || currentStrength === null) {
|
||||||
|
currentStrength = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust strength based on scroll direction
|
||||||
|
// DeltaY < 0 is scroll up, deltaY > 0 is scroll down
|
||||||
|
if (e.deltaY < 0) {
|
||||||
|
// Scroll up: increase strength by wheelSensitivity
|
||||||
|
currentStrength += wheelSensitivity;
|
||||||
|
} else {
|
||||||
|
// Scroll down: decrease strength by wheelSensitivity
|
||||||
|
currentStrength -= wheelSensitivity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure strength doesn't go below 0
|
||||||
|
currentStrength = Math.max(0, currentStrength);
|
||||||
|
|
||||||
|
// Update the strength value
|
||||||
|
updatedTags[index].strength = currentStrength;
|
||||||
|
|
||||||
|
// Update the tag display to show the strength value
|
||||||
|
// Always show strength once it has been modified to avoid layout shift
|
||||||
|
tagEl.textContent = `${updatedTags[index].text}:${currentStrength.toFixed(2)}`;
|
||||||
|
|
||||||
|
updateTagStyle(
|
||||||
|
tagEl,
|
||||||
|
updatedTags[index].active,
|
||||||
|
updatedTags[index].highlighted,
|
||||||
|
updatedTags[index].strength
|
||||||
|
);
|
||||||
|
|
||||||
|
widget.value = updatedTags;
|
||||||
|
});
|
||||||
|
|
||||||
rowContainer.appendChild(tagEl);
|
rowContainer.appendChild(tagEl);
|
||||||
tagCount++;
|
tagCount++;
|
||||||
});
|
});
|
||||||
@@ -137,7 +188,7 @@ export function addTagsWidget(node, name, opts, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Helper function to update tag style based on active state
|
// Helper function to update tag style based on active state
|
||||||
function updateTagStyle(tagEl, active, highlighted = false) {
|
function updateTagStyle(tagEl, active, highlighted = false, strength = null) {
|
||||||
const baseStyles = {
|
const baseStyles = {
|
||||||
padding: "3px 10px", // Adjusted vertical padding to balance text
|
padding: "3px 10px", // Adjusted vertical padding to balance text
|
||||||
borderRadius: "6px",
|
borderRadius: "6px",
|
||||||
@@ -178,6 +229,14 @@ export function addTagsWidget(node, name, opts, callback) {
|
|||||||
backgroundImage: "none",
|
backgroundImage: "none",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Additional styles for tags with modified strength
|
||||||
|
const strengthStyles = (strength !== null && strength !== undefined && strength !== 1.0)
|
||||||
|
? {
|
||||||
|
border: "1px solid rgba(255, 215, 0, 0.7)", // Gold border for modified strength
|
||||||
|
backgroundImage: "linear-gradient(120deg, rgba(255,215,0,0.1), rgba(255,215,0,0.05))",
|
||||||
|
}
|
||||||
|
: {};
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
Object.assign(tagEl.style, {
|
Object.assign(tagEl.style, {
|
||||||
...baseStyles,
|
...baseStyles,
|
||||||
@@ -185,6 +244,7 @@ export function addTagsWidget(node, name, opts, callback) {
|
|||||||
color: "white",
|
color: "white",
|
||||||
borderColor: "rgba(66, 153, 225, 0.9)",
|
borderColor: "rgba(66, 153, 225, 0.9)",
|
||||||
...highlightStyles,
|
...highlightStyles,
|
||||||
|
...strengthStyles,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Object.assign(tagEl.style, {
|
Object.assign(tagEl.style, {
|
||||||
@@ -193,6 +253,7 @@ export function addTagsWidget(node, name, opts, callback) {
|
|||||||
color: "rgba(226, 232, 240, 0.8)",
|
color: "rgba(226, 232, 240, 0.8)",
|
||||||
borderColor: "rgba(226, 232, 240, 0.2)",
|
borderColor: "rgba(226, 232, 240, 0.2)",
|
||||||
...highlightStyles,
|
...highlightStyles,
|
||||||
|
...strengthStyles,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,57 @@ import { api } from "../../scripts/api.js";
|
|||||||
import { CONVERTED_TYPE, getNodeFromGraph } from "./utils.js";
|
import { CONVERTED_TYPE, getNodeFromGraph } from "./utils.js";
|
||||||
import { addTagsWidget } from "./tags_widget.js";
|
import { addTagsWidget } from "./tags_widget.js";
|
||||||
|
|
||||||
|
// Setting ID for wheel sensitivity
|
||||||
|
const TRIGGER_WORD_WHEEL_SENSITIVITY_ID = "loramanager.trigger_word_wheel_sensitivity";
|
||||||
|
const TRIGGER_WORD_WHEEL_SENSITIVITY_DEFAULT = 0.02;
|
||||||
|
|
||||||
|
// Get the wheel sensitivity setting value
|
||||||
|
const getWheelSensitivity = (() => {
|
||||||
|
let settingsUnavailableLogged = false;
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const settingManager = app?.extensionManager?.setting;
|
||||||
|
if (!settingManager || typeof settingManager.get !== "function") {
|
||||||
|
if (!settingsUnavailableLogged) {
|
||||||
|
console.warn("LoRA Manager: settings API unavailable, using default wheel sensitivity.");
|
||||||
|
settingsUnavailableLogged = true;
|
||||||
|
}
|
||||||
|
return TRIGGER_WORD_WHEEL_SENSITIVITY_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const value = settingManager.get(TRIGGER_WORD_WHEEL_SENSITIVITY_ID);
|
||||||
|
return value ?? TRIGGER_WORD_WHEEL_SENSITIVITY_DEFAULT;
|
||||||
|
} catch (error) {
|
||||||
|
if (!settingsUnavailableLogged) {
|
||||||
|
console.warn("LoRA Manager: unable to read wheel sensitivity setting, using default.", error);
|
||||||
|
settingsUnavailableLogged = true;
|
||||||
|
}
|
||||||
|
return TRIGGER_WORD_WHEEL_SENSITIVITY_DEFAULT;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
// TriggerWordToggle extension for ComfyUI
|
// TriggerWordToggle extension for ComfyUI
|
||||||
app.registerExtension({
|
app.registerExtension({
|
||||||
name: "LoraManager.TriggerWordToggle",
|
name: "LoraManager.TriggerWordToggle",
|
||||||
|
|
||||||
|
settings: [
|
||||||
|
{
|
||||||
|
id: TRIGGER_WORD_WHEEL_SENSITIVITY_ID,
|
||||||
|
name: "Trigger Word Wheel Sensitivity",
|
||||||
|
type: "slider",
|
||||||
|
attrs: {
|
||||||
|
min: 0.01,
|
||||||
|
max: 0.1,
|
||||||
|
step: 0.01,
|
||||||
|
},
|
||||||
|
defaultValue: TRIGGER_WORD_WHEEL_SENSITIVITY_DEFAULT,
|
||||||
|
tooltip: "Mouse wheel sensitivity for adjusting trigger word strength (default: 0.02)",
|
||||||
|
category: ["LoRA Manager", "Trigger Word Toggle", "Wheel Sensitivity"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
// Add message handler to listen for messages from Python
|
// Add message handler to listen for messages from Python
|
||||||
api.addEventListener("trigger_word_update", (event) => {
|
api.addEventListener("trigger_word_update", (event) => {
|
||||||
@@ -26,10 +73,13 @@ app.registerExtension({
|
|||||||
|
|
||||||
// Wait for node to be properly initialized
|
// Wait for node to be properly initialized
|
||||||
requestAnimationFrame(async () => {
|
requestAnimationFrame(async () => {
|
||||||
|
// Get the wheel sensitivity setting
|
||||||
|
const wheelSensitivity = getWheelSensitivity();
|
||||||
|
|
||||||
// Get the widget object directly from the returned object
|
// Get the widget object directly from the returned object
|
||||||
const result = addTagsWidget(node, "toggle_trigger_words", {
|
const result = addTagsWidget(node, "toggle_trigger_words", {
|
||||||
defaultVal: []
|
defaultVal: []
|
||||||
});
|
}, null, wheelSensitivity);
|
||||||
|
|
||||||
node.tagWidget = result.widget;
|
node.tagWidget = result.widget;
|
||||||
|
|
||||||
@@ -134,6 +184,24 @@ app.registerExtension({
|
|||||||
node.applyTriggerHighlightState?.();
|
node.applyTriggerHighlightState?.();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Override the serializeValue method to properly format trigger words with strength
|
||||||
|
const originalSerializeValue = result.widget.serializeValue;
|
||||||
|
result.widget.serializeValue = function() {
|
||||||
|
const value = this.value || [];
|
||||||
|
// Transform the values to include strength in the proper format
|
||||||
|
const transformedValue = value.map(tag => {
|
||||||
|
// If strength is defined (even if it's 1.0), format as {text: "(original_text:strength)", ...}
|
||||||
|
if (tag.strength !== undefined && tag.strength !== null) {
|
||||||
|
return {
|
||||||
|
...tag,
|
||||||
|
text: `(${tag.text}:${tag.strength.toFixed(2)})`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return tag;
|
||||||
|
});
|
||||||
|
return transformedValue;
|
||||||
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -157,59 +225,74 @@ app.registerExtension({
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Update tags display based on group mode
|
// Update tags display based on group mode
|
||||||
updateTagsBasedOnMode(node, message, groupMode) {
|
updateTagsBasedOnMode(node, message, groupMode) {
|
||||||
if (!node.tagWidget) return;
|
if (!node.tagWidget) return;
|
||||||
|
|
||||||
const existingTags = node.tagWidget.value || [];
|
const existingTags = node.tagWidget.value || [];
|
||||||
const existingTagMap = {};
|
const existingTagMap = {};
|
||||||
|
|
||||||
// Create a map of existing tags and their active states
|
// Create a map of existing tags and their active states and strengths
|
||||||
existingTags.forEach(tag => {
|
existingTags.forEach(tag => {
|
||||||
existingTagMap[tag.text] = tag.active;
|
existingTagMap[tag.text] = {
|
||||||
|
active: tag.active,
|
||||||
|
strength: tag.strength
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get default active state from the widget
|
||||||
|
const defaultActive = node.widgets[1] ? node.widgets[1].value : true;
|
||||||
|
|
||||||
|
let tagArray = [];
|
||||||
|
|
||||||
|
if (groupMode) {
|
||||||
|
if (message.trim() === '') {
|
||||||
|
tagArray = [];
|
||||||
|
}
|
||||||
|
// Group mode: split by ',,' and treat each group as a single tag
|
||||||
|
else if (message.includes(',,')) {
|
||||||
|
const groups = message.split(/,{2,}/); // Match 2 or more consecutive commas
|
||||||
|
tagArray = groups
|
||||||
|
.map(group => group.trim())
|
||||||
|
.filter(group => group)
|
||||||
|
.map(group => {
|
||||||
|
// Check if this group already exists with strength info
|
||||||
|
const existing = existingTagMap[group];
|
||||||
|
return {
|
||||||
|
text: group,
|
||||||
|
// Use existing values if available, otherwise use defaults
|
||||||
|
active: existing ? existing.active : defaultActive,
|
||||||
|
strength: existing ? existing.strength : null
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// If no ',,' delimiter, treat the entire message as one group
|
||||||
|
const existing = existingTagMap[message.trim()];
|
||||||
|
tagArray = [{
|
||||||
|
text: message.trim(),
|
||||||
|
// Use existing values if available, otherwise use defaults
|
||||||
|
active: existing ? existing.active : defaultActive,
|
||||||
|
strength: existing ? existing.strength : null
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Normal mode: split by commas and treat each word as a separate tag
|
||||||
|
tagArray = message
|
||||||
|
.split(',')
|
||||||
|
.map(word => word.trim())
|
||||||
|
.filter(word => word)
|
||||||
|
.map(word => {
|
||||||
|
// Check if this word already exists with strength info
|
||||||
|
const existing = existingTagMap[word];
|
||||||
|
return {
|
||||||
|
text: word,
|
||||||
|
// Use existing values if available, otherwise use defaults
|
||||||
|
active: existing ? existing.active : defaultActive,
|
||||||
|
strength: existing ? existing.strength : null
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get default active state from the widget
|
|
||||||
const defaultActive = node.widgets[1] ? node.widgets[1].value : true;
|
|
||||||
|
|
||||||
let tagArray = [];
|
|
||||||
|
|
||||||
if (groupMode) {
|
|
||||||
if (message.trim() === '') {
|
|
||||||
tagArray = [];
|
|
||||||
}
|
|
||||||
// Group mode: split by ',,' and treat each group as a single tag
|
|
||||||
else if (message.includes(',,')) {
|
|
||||||
const groups = message.split(/,{2,}/); // Match 2 or more consecutive commas
|
|
||||||
tagArray = groups
|
|
||||||
.map(group => group.trim())
|
|
||||||
.filter(group => group)
|
|
||||||
.map(group => ({
|
|
||||||
text: group,
|
|
||||||
// Use defaultActive only for new tags
|
|
||||||
active: existingTagMap[group] !== undefined ? existingTagMap[group] : defaultActive
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
// If no ',,' delimiter, treat the entire message as one group
|
|
||||||
tagArray = [{
|
|
||||||
text: message.trim(),
|
|
||||||
// Use defaultActive only for new tags
|
|
||||||
active: existingTagMap[message.trim()] !== undefined ? existingTagMap[message.trim()] : defaultActive
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Normal mode: split by commas and treat each word as a separate tag
|
|
||||||
tagArray = message
|
|
||||||
.split(',')
|
|
||||||
.map(word => word.trim())
|
|
||||||
.filter(word => word)
|
|
||||||
.map(word => ({
|
|
||||||
text: word,
|
|
||||||
// Use defaultActive only for new tags
|
|
||||||
active: existingTagMap[word] !== undefined ? existingTagMap[word] : defaultActive
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
node.tagWidget.value = tagArray;
|
|
||||||
node.applyTriggerHighlightState?.();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node.tagWidget.value = tagArray;
|
||||||
|
node.applyTriggerHighlightState?.();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user