diff --git a/js/combo_clone.js b/js/combo_clone.js index 9c84664..5d63618 100644 --- a/js/combo_clone.js +++ b/js/combo_clone.js @@ -1,6 +1,9 @@ import { shared } from "./shared.js" +import { Logger } from "./use_everywhere_utilities.js" function update_me(node) { + Logger.log_problem(`Reseting combo clone node ${node.id}`) + node.IS_COMBO_CLONE = true node.widgets[0].options.values = [...node.properties.comboclone.options] node.outputs[0].type = "COMBO" node.outputs[0].label = node.properties.comboclone.name @@ -10,20 +13,24 @@ export function reset_comboclone_on_load(node) { if (node.properties?.comboclone) update_me(node) } -export function comboclone_on_connection(node, link_info) { +export function comboclone_on_connection(node, link_info, connect) { if (shared.graph_being_configured) return - if (!link_info) return - const target_node = node.graph.getNodeById(link_info.target_id) - const input_name = target_node?.inputs[link_info.target_slot].name - const widget = target_node?.widgets?.find((w)=>(w.name==input_name)) - - if (widget?.type=="combo" && widget?.options?.values) { - node.properties.comboclone = { - options : [...widget.options.values], - name : input_name + if (connect) { + if (!link_info) return + const target_node = node.graph.getNodeById(link_info.target_id) + const input_name = target_node?.inputs[link_info.target_slot].name + const widget = target_node?.widgets?.find((w)=>(w.name==input_name)) + + if (widget?.type=="combo" && widget?.options?.values) { + node.properties.comboclone = { + options : [...widget.options.values], + name : input_name + } + update_me(node) + node.widgets[0].value = widget.value + link_info.type = "COMBO" } - update_me(node) - node.widgets[0].value = widget.value - link_info.type = "COMBO" + } else { + let a; } } \ No newline at end of file diff --git a/js/connections.js b/js/connections.js index acb9351..b2539b0 100644 --- a/js/connections.js +++ b/js/connections.js @@ -1,38 +1,131 @@ import { link_is_from_subgraph_input, get_subgraph_input_type, node_graph } from "./use_everywhere_subgraph_utils.js" -import { get_real_node } from "./use_everywhere_utilities.js"; +import { get_real_node, is_UEnode, Logger } from "./use_everywhere_utilities.js"; import { app } from "../../scripts/app.js"; import { i18n } from "./i18n.js"; -/* -Called by onConnectionsChange for a UE_Node when side == 1 (input). +import { shared } from "./shared.js"; +import { reset_comboclone_on_load } from "./combo_clone.js"; -*/ -export function input_changed(node, slot, connect, link_info) { +function get_type(node, link_info) { var type = null - if (connect && link_info) { + if (link_info) { if (link_is_from_subgraph_input(link_info)) { // input slot of subgraph type = get_subgraph_input_type(node_graph(node), link_info.origin_slot) } else { type = get_real_node(link_info.origin_id, node_graph(node))?.outputs[link_info.origin_slot]?.type } - }; - type = type || '*' - if (type=='*' && link_info && connect) type = link_info.type - - node.inputs[slot].type = type; - if (link_info) link_info.type = type - - if (type=='*') { - node.inputs[slot].label = i18n('anything'); - node.inputs[slot].color_on = undefined; + if (type != link_info.type && link_info.type != '*') { + Logger.log_problem(`Type detected from upstream, ${type} != type on link_info ${link_info.type}`) + } } else { + Logger.log_problem(`input_changed with connect true, graph_being_configured false, and no link_info`) + } + type = type || '*' + if (type!='*' && link_info) link_info.type = type + if (type=='*' && link_info) type = link_info.type + return type +} + +/* +Called by onConnectionsChange for a UE_Node when side == 1 (input). +*/ + +export function input_changed(node, slot, connect, link_info) { + if (shared.graph_being_configured) return + + if (connect) { + const type = get_type(node, link_info) if (app.ui.settings.getSettingValue("Use Everywhere.Options.use_output_name") && link_info) { - if (!node.inputs[slot].label || node.inputs[slot].label==i18n('anything')) { - const out_slot = app.graph.getNodeById(link_info.origin_id)?.outputs[link_info.origin_slot] - node.inputs[slot].label = out_slot?.label || out_slot?.localized_name || out_slot?.name || type; - } + const out_slot = node.graph.getNodeById(link_info.origin_id)?.outputs[link_info.origin_slot] + node.inputs[slot].label = out_slot?.label || out_slot?.localized_name || out_slot?.name || i18n(type); } else { - node.inputs[slot].label = type; + node.inputs[slot].label = i18n(type); } node.inputs[slot].color_on = app.canvas.default_connection_color_byType[type]; + node.inputs[slot].type = type + } else { + node.inputs[slot].label = i18n('anything'); + node.inputs[slot].color_on = undefined; + node.inputs[slot].type = '*' } + fix_inputs(node) +} + +function store_input_state(node) { + return + node.properties.ue_properties.input_state = [] + node.inputs.filter((inputslot)=>(inputslot.type!='*')).forEach((input)=>{ + node.properties.ue_properties.input_state.push( { + type : input.type, + label : input.label, + color_on : input.color_on + } ) + }) +} + +function restore_input_state(node) { + return + if (node.properties.ue_properties.input_state) { + while (node.inputs.length < node.properties.ue_properties.input_state.length+1) add_new_input(node) + while (node.inputs.length > node.properties.ue_properties.input_state.length+1) { + if (!remove_excess_input(node)) return + } + node.properties.ue_properties.input_state.forEach((state, i) => { + Object.assign(node.inputs[i], state) + }) + } else { + Logger.log_problem(`restore_input_state called for a node with no stored input state`) + } +} + +export function restore_input_states(graph) { + graph.nodes.forEach((node) => { + reset_comboclone_on_load(node) + if (node.properties.ue_properties?.input_state) restore_input_state(node) + if (is_UEnode(node)) fix_inputs(node) + if (node.subgraph) restore_input_states(node.subgraph) + }) +} + +function add_new_input(node) { + node.properties.ue_properties.next_input_index = (node.properties.ue_properties.next_input_index || 10) + 1 + node.addInput(`anything${node.properties.ue_properties.next_input_index}`, "*", {label:i18n('anything')}) +} + +function remove_excess_input(node) { + const idx = node.inputs.findIndex((inputslot)=>(inputslot.type=='*')) + if (idx>=0) { + try { + Logger.log_info(`Removing excess anything input from node ${node.id}`) + node.removeInput(idx) + return true + } catch (e) { Logger.log_error(e) } + } else { Logger.log_problem(`Something very odd happened in fix_inputs for ${node.id}`) } + return false +} + +/* +This is called in various places (node load, creation, link change) to ensure there is exactly one empty input +*/ +export function fix_inputs(node) { + if (!node.graph) return // node has been deleted prior to the fix + if (shared.graph_being_configured) return + if (node.properties.ue_properties.fixed_inputs) return store_input_state(node) + + + const empty_inputs = node.inputs.filter((inputslot)=>(inputslot.type=='*')) + var excess_inputs = empty_inputs.length - 1 + + if (excess_inputs<0) { + try { + Logger.log_info(`Adding new anything input to node ${node.id}`) + add_new_input(node) + fix_inputs(node) + } catch (e) { + Logger.log_error(e) + } + } else if (excess_inputs>0) { + if (remove_excess_input(node)) fix_inputs(node) + } + + store_input_state(node) } \ No newline at end of file diff --git a/js/ue_properties.js b/js/ue_properties.js index 539d995..0b75177 100644 --- a/js/ue_properties.js +++ b/js/ue_properties.js @@ -1,6 +1,7 @@ -import { VERSION, version_at_least, fix_inputs, create } from "./use_everywhere_utilities.js" +import { VERSION, version_at_least, create } from "./use_everywhere_utilities.js" import { i18n, i18n_functional, GROUP_RESTRICTION_OPTIONS, COLOR_RESTRICTION_OPTIONS } from "./i18n.js"; import { shared } from "./shared.js"; +import { fix_inputs } from "./connections.js"; const ALL_REGEXES = ['title', 'input', 'prompt', 'negative', 'group'] diff --git a/js/use_everywhere.js b/js/use_everywhere.js index 882ee21..2ced502 100644 --- a/js/use_everywhere.js +++ b/js/use_everywhere.js @@ -3,7 +3,7 @@ import { api } from "../../scripts/api.js"; import { shared } from "./shared.js"; -import { is_UEnode, inject, Logger, defineProperty, graphConverter, fix_inputs, create } from "./use_everywhere_utilities.js"; +import { is_UEnode, inject, Logger, defineProperty, graphConverter, create } from "./use_everywhere_utilities.js"; import { indicate_restriction } from "./use_everywhere_ui.js"; import { LinkRenderController } from "./use_everywhere_ui.js"; import { GraphAnalyser } from "./use_everywhere_graph_analysis.js"; @@ -11,11 +11,11 @@ import { canvas_menu_settings, SETTINGS, add_extra_menu_items } from "./use_ever import { add_debug } from "./ue_debug.js"; import { settingsCache } from "./use_everywhere_cache.js"; import { convert_to_links } from "./use_everywhere_apply.js"; -import { visible_graph } from "./use_everywhere_subgraph_utils.js"; +import { master_graph, visible_graph } from "./use_everywhere_subgraph_utils.js"; import { any_restrictions, setup_ue_properties_oncreate, setup_ue_properties_onload } from "./ue_properties.js"; import { edit_restrictions } from "./ue_properties_editor.js"; import { language_changed } from "./i18n.js"; -import { input_changed } from "./connections.js"; +import { input_changed, fix_inputs, restore_input_states } from "./connections.js"; import { reset_comboclone_on_load, comboclone_on_connection } from "./combo_clone.js"; /* @@ -66,7 +66,7 @@ app.registerExtension({ */ const onConnectionsChange = nodeType.prototype.onConnectionsChange; nodeType.prototype.onConnectionsChange = function (side,slot,connect,link_info,output) { - if (this.IS_COMBO_CLONE && connect) comboclone_on_connection(this, link_info) + if (this.IS_COMBO_CLONE) comboclone_on_connection(this, link_info, connect) if (this.IS_UE && side==1) { // side 1 is input input_changed(this, slot, connect, link_info) @@ -140,8 +140,6 @@ app.registerExtension({ } } setup_ue_properties_onload(node) - - if (node.IS_COMBO_CLONE) reset_comboclone_on_load(node) }, async setup() { @@ -364,6 +362,7 @@ app.registerExtension({ graphConverter.remove_saved_ue_links_recursively(app.graph) //convert_old_nodes(app.graph) shared.graph_being_configured = false + restore_input_states(master_graph()) } }); diff --git a/js/use_everywhere_utilities.js b/js/use_everywhere_utilities.js index b0a0f86..75d4dec 100644 --- a/js/use_everywhere_utilities.js +++ b/js/use_everywhere_utilities.js @@ -337,43 +337,10 @@ export function get_connection(node, i) { const graph = node_graph(node) const in_link = node?.inputs[i]?.link; if (in_link) { - return { link:handle_bypass(graph.links[in_link], node.inputs[i].type, graph), type:node.inputs[i].type } + var llink = graph.links[in_link] + llink = handle_bypass(llink, llink.type) + return { link:llink, type:llink.type } } else { return { link:undefined, type:undefined } } } - - -/* -This is called in various places (node load, creation, link change) to ensure there is exactly one empty input -*/ -export function fix_inputs(node) { - if (!node.graph) return // node has been deleted prior to the fix - if (node.properties.ue_properties.fixed_inputs) return - if (shared.graph_being_configured) return - - const empty_inputs = node.inputs.filter((inputslot)=>(inputslot.type=='*')) - var excess_inputs = empty_inputs.length - 1 - - if (excess_inputs<0) { - try { - node.properties.ue_properties.next_input_index = (node.properties.ue_properties.next_input_index || 10) + 1 - node.addInput(`anything${node.properties.ue_properties.next_input_index}`, "*", {label:i18n('anything')}) - fix_inputs(node) - } catch (e) { - Logger.log_error(e) - } - } else if (excess_inputs>0) { - const idx = node.inputs.findIndex((inputslot)=>(inputslot.type=='*')) - if (idx>=0) { - try { - node.removeInput(idx) - fix_inputs(node) - } catch (e) { - Logger.log_error(e) - } - } else { - Logger.log_problem(`Something very odd happened in fix_inputs for ${node.id}`) - } - } -} \ No newline at end of file