Update Files

This commit is contained in:
2025-01-22 16:18:30 +01:00
parent ed4603cf95
commit a36294b518
16718 changed files with 2960346 additions and 0 deletions

View File

@ -0,0 +1,12 @@
from lnx.logicnode.lnx_nodes import *
class IntFromBooleanNode(LnxLogicTreeNode):
"""Returns an int depending on the respective boolean state."""
bl_idname = 'LNIntFromBooleanNode'
bl_label = 'Boolean to Int'
lnx_version = 1
def lnx_init(self, context):
self.inputs.new('LnxBoolSocket', 'Bool')
self.outputs.new('LnxIntSocket', 'Int')

View File

@ -0,0 +1,17 @@
from lnx.logicnode.lnx_nodes import *
class VectorFromBooleanNode(LnxLogicTreeNode):
"""Returns a vector depending on the respective boolean state."""
bl_idname = 'LNVectorFromBooleanNode'
bl_label = 'Boolean to Vector'
lnx_version = 1
def lnx_init(self, context):
self.inputs.new('LnxBoolSocket', 'X')
self.inputs.new('LnxBoolSocket', '-X')
self.inputs.new('LnxBoolSocket', 'Y')
self.inputs.new('LnxBoolSocket', '-Y')
self.inputs.new('LnxBoolSocket', 'Z')
self.inputs.new('LnxBoolSocket', '-Z')
self.outputs.new('LnxVectorSocket', 'Vector')

View File

@ -0,0 +1,143 @@
import bpy
import lnx.utils
from lnx.logicnode.lnx_nodes import *
class CallGroupNode(LnxLogicTreeNode):
"""Calls the given group of nodes."""
bl_idname = 'LNCallGroupNode'
bl_label = 'Call Node Group'
lnx_section = 'group'
lnx_version = 3
def __init__(self):
self.register_id()
def lnx_init(self, context):
pass
# Function to add input sockets and re-link sockets
def update_inputs(self, tree, node, inp_sockets, in_links):
count = 0
for output in node.outputs:
_, c_socket = lnx.node_utils.output_get_connected_node(output)
if c_socket is not None:
current_socket = self.add_input(c_socket.bl_idname, output.name)
if(count < len(in_links)):
# Preserve default values in input sockets
inp_sockets[count].copy_defaults(current_socket)
for link in in_links[count]:
tree.links.new(link, current_socket)
else:
current_socket = self.add_input('LnxAnySocket', output.name)
current_socket.display_label = output.name
if(count < len(in_links)):
for link in in_links[count]:
tree.links.new(link, current_socket)
count = count + 1
# Function to add output sockets and re-link sockets
def update_outputs(self, tree, node, out_links):
count = 0
for input in node.inputs:
_, c_socket = lnx.node_utils.input_get_connected_node(input)
if c_socket is not None:
current_socket = self.add_output(c_socket.bl_idname, input.name)
if(count < len(out_links)):
for link in out_links[count]:
nlink = tree.links.new(current_socket, link)
nlink.is_valid = True
nlink.is_muted = False
else:
current_socket = self.add_output('LnxAnySocket', input.name)
current_socket.display_label = input.name
if(count < len(out_links)):
for link in out_links[count]:
tree.links.new(current_socket, link)
count = count + 1
def remove_tree(self):
self.group_tree = None
def update_sockets(self, context):
# List to store from and to sockets of connected nodes
from_socket_list = []
to_socket_list = []
inp_socket_list = []
tree = self.get_tree()
# Loop through each input socket
for inp in self.inputs:
link_per_socket = []
#Loop through each link to the socket
for link in inp.links:
link_per_socket.append(link.from_socket)
from_socket_list.append(link_per_socket)
inp_socket_list.append(inp)
# Loop through each output socket
for out in self.outputs:
link_per_socket = []
# Loop through each link to the socket
for link in out.links:
link_per_socket.append(link.to_socket)
to_socket_list.append(link_per_socket)
# Remove all output sockets
for output in self.outputs:
self.outputs.remove(output)
# Search for Group Input/Output
if self.group_tree is not None:
for node in self.group_tree.nodes:
if node.bl_idname == 'LNGroupInputsNode':
# Update input sockets
self.update_inputs(tree, node, inp_socket_list, from_socket_list)
break
for node in self.group_tree.nodes:
if node.bl_idname == 'LNGroupOutputsNode':
# Update output sockets
self.update_outputs(tree, node, to_socket_list)
break
#Remove all old input sockets after setting defaults
for inp in inp_socket_list:
self.inputs.remove(inp)
# Prperty to store group tree pointer
group_tree: PointerProperty(name='Group', type=bpy.types.NodeTree, update=update_sockets)
def draw_label(self) -> str:
if self.group_tree is not None:
return f'Group: {self.group_tree.name}'
return self.bl_label
# Draw node UI
def draw_buttons(self, context, layout):
col = layout.column()
row_name = col.row(align=True)
row_add = col.row(align=True)
row_ops = col.row()
if self.group_tree is None:
op = row_add.operator('lnx.add_group_tree', icon='PLUS', text='New Group')
op.node_index = self.get_id_str()
op = row_name.operator('lnx.search_group_tree', text='', icon='VIEWZOOM')
op.node_index = self.get_id_str()
if self.group_tree:
row_name.prop(self.group_tree, 'name', text='')
row_copy = row_name.split(align=True)
row_copy.alignment = 'CENTER'
fake_user = 1 if self.group_tree.use_fake_user else 0
op = row_copy.operator('lnx.copy_group_tree', text=str(self.group_tree.users - fake_user))
op.node_index = self.get_id_str()
row_name.prop(self.group_tree, 'use_fake_user', text='')
op = row_name.operator('lnx.unlink_group_tree', icon='X', text='')
op.node_index = self.get_id_str()
row_ops.enabled = not self.group_tree is None
op = row_ops.operator('lnx.edit_group_tree', icon='FULLSCREEN_ENTER', text='Edit tree')
op.node_index = self.get_id_str()
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
if self.lnx_version not in (0, 1, 2):
raise LookupError()
return node_tree.nodes.new('LNCallGroupNode')

View File

@ -0,0 +1,17 @@
from lnx.logicnode.lnx_nodes import *
class DefaultIfNullNode(LnxLogicTreeNode):
"""Returns the connected value only if it is not `null`, otherwise the `default` value is returned.
@input Value: the one that will be eventually null
@input Default: will be returned in case the primary value is null
"""
bl_idname = 'LNDefaultIfNullNode'
bl_label = 'Default if Null'
lnx_version = 1
def lnx_init(self, context):
self.inputs.new('LnxDynamicSocket', 'Value In')
self.inputs.new('LnxDynamicSocket', 'Default')
self.outputs.new('LnxDynamicSocket', 'Value Out')

View File

@ -0,0 +1,11 @@
from lnx.logicnode.lnx_nodes import *
class TimeNode(LnxLogicTreeNode):
"""Returns the application execution time and the delta time."""
bl_idname = 'LNTimeNode'
bl_label = 'Get Application Time'
lnx_version = 1
def lnx_init(self, context):
self.add_output('LnxFloatSocket', 'Time')
self.add_output('LnxFloatSocket', 'Delta')

View File

@ -0,0 +1,36 @@
from lnx.logicnode.lnx_nodes import *
class GetDebugConsoleSettings(LnxLogicTreeNode):
"""Return properties of the debug console.
@output Enabled: Whether the debug console is enabled.
@output Visible: Whether the debug console is visible,
or `false` if the debug console is disabled.
@output Hovered: Whether the debug console is hovered by the mouse cursor,
or `false` if the debug console is disabled.
@output UI Scale: The scaling factor of the debug console user interface,
or `1.0` if the debug console is disabled.
@output Position: The initial position of the debug console.
Possible values if the debug console is enabled: `"Left"`, `"Center"`, `"Right"`.
If the debug console is disabled, the returned value is an empty string `""`.
"""
bl_idname = 'LNGetDebugConsoleSettings'
bl_label = 'Get Debug Console Settings'
lnx_version = 2
def lnx_init(self, context):
self.add_output('LnxBoolSocket', 'Enabled')
self.add_output('LnxBoolSocket', 'Visible')
self.add_output('LnxBoolSocket', 'Hovered')
self.add_output('LnxFloatSocket', 'UI Scale')
self.add_output('LnxStringSocket', 'Position')
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
if self.lnx_version not in (0, 1):
raise LookupError()
return NodeReplacement(
'LNGetDebugConsoleSettings', self.lnx_version, 'LNGetDebugConsoleSettings', 2,
in_socket_mapping={}, out_socket_mapping={0: 1, 1: 3, 2: 4}
)

View File

@ -0,0 +1,15 @@
from lnx.logicnode.lnx_nodes import *
class DisplayInfoNode(LnxLogicTreeNode):
"""Returns the current display resolution.
@seeNode Get Window Resolution
"""
bl_idname = 'LNDisplayInfoNode'
bl_label = 'Get Display Resolution'
lnx_section = 'screen'
lnx_version = 1
def lnx_init(self, context):
self.add_output('LnxIntSocket', 'Width')
self.add_output('LnxIntSocket', 'Height')

View File

@ -0,0 +1,10 @@
from lnx.logicnode.lnx_nodes import *
class GetFPSNode(LnxLogicTreeNode):
"""Get the frames per second count."""
bl_idname = 'LNGetFPSNode'
bl_label = 'Get Frames Per Second'
lnx_version = 1
def lnx_init(self, context):
self.add_output('LnxIntSocket', 'Count')

View File

@ -0,0 +1,15 @@
from lnx.logicnode.lnx_nodes import *
class WindowInfoNode(LnxLogicTreeNode):
"""Returns the current window resolution.
@seeNode Get Display Resolution
"""
bl_idname = 'LNWindowInfoNode'
bl_label = 'Get Window Resolution'
lnx_section = 'screen'
lnx_version = 1
def lnx_init(self, context):
self.add_output('LnxIntSocket', 'Width')
self.add_output('LnxIntSocket', 'Height')

View File

@ -0,0 +1,217 @@
import bpy
import lnx.utils
import lnx.node_utils
from lnx.logicnode.lnx_nodes import *
import lnx.logicnode.miscellaneous.LN_call_group as LN_call_group
class GroupInputsNode(LnxLogicTreeNode):
"""Input for a node group."""
bl_idname = 'LNGroupInputsNode'
bl_label = 'Group Input Node'
lnx_section = 'group'
lnx_version = 3
def __init__(self):
self.register_id()
# Active socket selected
active_output: IntProperty(name='active_output', description='', default=0)
# Flag to store invalid links
invalid_link: BoolProperty(name='invalid_link', description='', default=False)
# Override copy prevention in certain situations such as copying entire group
copy_override: BoolProperty(name='copy override', description='', default=False)
def init(self, context):
tree = bpy.context.space_data.edit_tree
node_count = 0
for node in tree.nodes:
if node.bl_idname == 'LNGroupInputsNode':
node_count += 1
if node_count > 1:
lnx.log.warn("Only one group input node per node tree is allowed")
self.mute = True
else:
super().init(context)
# Prevent copying of group node
def copy(self, node):
if not self.copy_override:
self.mute = True
self.outputs.clear()
self.copy_override = False
def lnx_init(self, context):
if not self.mute:
self.add_socket()
# Called when link is created
def insert_link(self, link):
from_socket = link.from_socket
to_node = link.to_node
to_socket = None
# Recursively search for other socket in case of reroutes
if to_node.type == 'REROUTE':
_, to_socket = lnx.node_utils.output_get_connected_node(to_node.outputs[0])
else:
to_socket = link.to_socket
if to_socket is not None:
index = self.get_socket_index(from_socket)
# If socket connected to LnxAnySocket, link is invalid
if to_socket.bl_idname == 'LnxAnySocket':
self.invalid_link = True
else:
call_group_nodes = self.get_call_group_nodes()
for node in call_group_nodes:
# Change socket type according to the new link
node.change_input_socket(to_socket.bl_idname, index, link.from_socket.display_label)
# Use update method to remove invalid links
def update(self):
super().update()
if self.invalid_link:
self.remove_invalid_links()
# Called when name of the socket is changed
def socket_name_update(self, socket):
index = self.get_socket_index(socket)
# Update socket names of the related call group nodes
call_node_groups = self.get_call_group_nodes()
for node in call_node_groups:
inp_socket = node.inputs[index]
if inp_socket.bl_idname == 'LnxAnySocket':
inp_socket.display_label = socket.display_label
else:
inp_socket.name = socket.display_label
# Recursively search and remove invalid links
def remove_invalid_links(self):
for output in self.outputs:
for link in output.links:
if link.to_socket.bl_idname == 'LnxAnySocket':
tree = self.get_tree()
tree.links.remove(link)
break
self.invalid_link = False
# Function to move socket up and handle the same in related call group nodes
def move_socket_up(self):
if self.active_output > 0:
self.outputs.move(self.active_output, self.active_output - 1)
call_node_groups = self.get_call_group_nodes()
for nodes in call_node_groups:
nodes.inputs.move(self.active_output, self.active_output - 1)
self.active_output = self.active_output - 1
# Function to move socket down and handle the same in related call group nodes
def move_socket_down(self):
if self.active_output < len(self.outputs) - 1:
self.outputs.move(self.active_output, self.active_output + 1)
call_node_groups = self.get_call_group_nodes()
for nodes in call_node_groups:
nodes.inputs.move(self.active_output, self.active_output + 1)
self.active_output = self.active_output + 1
# Function to recursively get related call group nodes
def get_call_group_nodes(self):
call_group_nodes = []
# Return empty list if node is muted
if self.mute:
return call_group_nodes
for tree in bpy.data.node_groups:
if tree.bl_idname == "LnxLogicTreeType" or tree.bl_idname == "LnxGroupTree":
for node in tree.nodes:
if node.bl_idname == 'LNCallGroupNode':
if node.group_tree == self.get_tree():
call_group_nodes.append(node)
return call_group_nodes
# Function to add a socket and handle the same in the related call group nodes
def add_socket(self):
self.add_output('LnxAnySocket','')
call_group_nodes = self.get_call_group_nodes()
for node in call_group_nodes:
node.add_input('LnxAnySocket','')
# Function to remove a socket and handle the same in the related call group nodes
def remove_socket(self):
self.outputs.remove(self.outputs[-1])
call_group_nodes = self.get_call_group_nodes()
for node in call_group_nodes:
node.inputs.remove(node.inputs[-1])
if self.active_output > len(self.outputs) - 1:
self.active_output = self.active_output - 1
# Function to add a socket at certain index and
# handle the same in the related call group nodes
def add_socket_ext(self):
index = self.active_output + 1
self.insert_output('LnxAnySocket', index, '')
call_group_nodes = self.get_call_group_nodes()
for node in call_group_nodes:
node.insert_input('LnxAnySocket', index, '')
# Function to remove a socket at certain index and
# handle the same in the related call group nodes
def remove_socket_ext(self):
self.outputs.remove(self.outputs[self.active_output])
call_group_nodes = self.get_call_group_nodes()
for node in call_group_nodes:
node.inputs.remove(node.inputs[self.active_output])
if self.active_output > len(self.outputs) - 1:
self.active_output = len(self.outputs) - 1
# Handle deletion of group input node
def free(self):
call_group_nodes = self.get_call_group_nodes()
for node in call_group_nodes:
node.inputs.clear()
# Draw node UI
def draw_buttons(self, context, layout):
if self.mute:
layout.enabled = False
row = layout.row(align=True)
op = row.operator('lnx.node_call_func', text='New', icon='PLUS', emboss=True)
op.node_index = self.get_id_str()
op.callback_name = 'add_socket'
if len(self.outputs) > 1:
op2 = row.operator('lnx.node_call_func', text='', icon='X', emboss=True)
op2.node_index = self.get_id_str()
op2.callback_name = 'remove_socket'
# Draw side panel UI
def draw_buttons_ext(self, context, layout):
if self.mute:
layout.enabled = False
node = context.active_node
split = layout.row()
split.template_list('LNX_UL_InterfaceSockets', 'OUT', node, 'outputs', node, 'active_output')
ops_col = split.column()
add_remove_col = ops_col.column(align=True)
props = add_remove_col.operator('lnx.node_call_func', icon='ADD', text="")
props.node_index = self.get_id_str()
props.callback_name = 'add_socket_ext'
if len(self.outputs) > 1:
props = add_remove_col.operator('lnx.node_call_func', icon='REMOVE', text="")
props.node_index = self.get_id_str()
props.callback_name = 'remove_socket_ext'
ops_col.separator()
up_down_col = ops_col.column(align=True)
props = up_down_col.operator('lnx.node_call_func', icon='TRIA_UP', text="")
props.node_index = self.get_id_str()
props.callback_name = 'move_socket_up'
props = up_down_col.operator('lnx.node_call_func', icon='TRIA_DOWN', text="")
props.node_index = self.get_id_str()
props.callback_name = 'move_socket_down'
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
if self.lnx_version not in (0, 1, 2):
raise LookupError()
return node_tree.nodes.new('LNGroupInputsNode')

View File

@ -0,0 +1,217 @@
import bpy
import lnx.utils
import lnx.node_utils
from lnx.logicnode.lnx_nodes import *
import lnx.logicnode.miscellaneous.LN_call_group as LN_call_group
class GroupOutputsNode(LnxLogicTreeNode):
"""Output for a node group."""
bl_idname = 'LNGroupOutputsNode'
bl_label = 'Group Output Node'
lnx_section = 'group'
lnx_version = 3
def __init__(self):
self.register_id()
# Active socket selected
active_input: IntProperty(name='active_input', description='', default=0)
# Flag to store invalid links
invalid_link: BoolProperty(name='invalid_link', description='', default=False)
# Override copy prevention in certain situations such as copying entire group
copy_override: BoolProperty(name='copy override', description='', default=False)
def init(self, context):
tree = bpy.context.space_data.edit_tree
node_count = 0
for node in tree.nodes:
if node.bl_idname == 'LNGroupOutputsNode':
node_count += 1
if node_count > 1:
lnx.log.warn("Only one group output node per node tree is allowed")
self.mute = True
else:
super().init(context)
# Prevent copying of group node
def copy(self, node):
if not self.copy_override:
self.mute = True
self.inputs.clear()
self.copy_override = False
def lnx_init(self, context):
if not self.mute:
self.add_socket()
# Called when link is created
def insert_link(self, link):
to_socket = link.to_socket
from_node = link.from_node
from_socket = None
# Recursively search for other socket in case of reroutes
if from_node.type == 'REROUTE':
_, from_socket = lnx.node_utils.input_get_connected_node(to_socket)
else:
from_socket = link.from_socket
if from_socket is not None:
index = self.get_socket_index(to_socket)
# If socket connected to LnxAnySocket, link is invalid
if from_socket.bl_idname == 'LnxAnySocket':
self.invalid_link = True
else:
call_group_nodes = self.get_call_group_nodes()
for node in call_group_nodes:
# Change socket type according to the new link
node.change_output_socket(from_socket.bl_idname, index, link.to_socket.display_label)
# Use update method to remove invalid links
def update(self):
super().update()
if self.invalid_link:
self.remove_invalid_links()
# Called when name of the socket is changed
def socket_name_update(self, socket):
index = self.get_socket_index(socket)
# Update socket names of the related call group nodes
call_node_groups = self.get_call_group_nodes()
for node in call_node_groups:
out_socket = node.outputs[index]
if out_socket.bl_idname == 'LnxAnySocket':
out_socket.display_label = socket.display_label
else:
out_socket.name = socket.display_label
# Recursively search and remove invalid links
def remove_invalid_links(self):
for input in self.inputs:
for link in input.links:
if link.from_socket.bl_idname == 'LnxAnySocket':
tree = self.get_tree()
tree.links.remove(link)
break
self.invalid_link = False
# Function to move socket up and handle the same in related call group nodes
def move_socket_up(self):
if self.active_input > 0:
self.inputs.move(self.active_input, self.active_input - 1)
call_node_groups = self.get_call_group_nodes()
for nodes in call_node_groups:
nodes.outputs.move(self.active_input, self.active_input - 1)
self.active_input = self.active_input - 1
# Function to move socket down and handle the same in related call group nodes
def move_socket_down(self):
if self.active_input < len(self.inputs) - 1:
self.inputs.move(self.active_input, self.active_input + 1)
call_node_groups = self.get_call_group_nodes()
for nodes in call_node_groups:
nodes.outputs.move(self.active_input, self.active_input + 1)
self.active_input = self.active_input + 1
# Function to recursively get related call group nodes
def get_call_group_nodes(self):
call_group_nodes = []
# Return empty list if node is muted
if self.mute:
return call_group_nodes
for tree in bpy.data.node_groups:
if tree.bl_idname == "LnxLogicTreeType" or tree.bl_idname == "LnxGroupTree":
for node in tree.nodes:
if node.bl_idname == 'LNCallGroupNode':
if node.group_tree == self.get_tree():
call_group_nodes.append(node)
return call_group_nodes
# Function to add a socket and handle the same in the related call group nodes
def add_socket(self):
self.add_input('LnxAnySocket','',)
call_group_nodes = self.get_call_group_nodes()
for node in call_group_nodes:
node.add_output('LnxAnySocket','')
# Function to remove a socket and handle the same in the related call group nodes
def remove_socket(self):
self.inputs.remove(self.inputs[-1])
call_group_nodes = self.get_call_group_nodes()
for node in call_group_nodes:
node.outputs.remove(node.outputs[-1])
if self.active_input > len(self.inputs) - 1:
self.active_input = self.active_input - 1
# Function to add a socket at certain index and
# handle the same in the related call group nodes
def add_socket_ext(self):
index = self.active_input + 1
self.insert_input('LnxAnySocket', index, '')
call_group_nodes = self.get_call_group_nodes()
for node in call_group_nodes:
node.insert_output('LnxAnySocket', index, '')
# Function to remove a socket at certain index and
# handle the same in the related call group nodes
def remove_socket_ext(self):
self.inputs.remove(self.inputs[self.active_input])
call_group_nodes = self.get_call_group_nodes()
for node in call_group_nodes:
node.outputs.remove(node.outputs[self.active_input])
if self.active_input > len(self.inputs) - 1:
self.active_input = len(self.inputs) - 1
# Handle deletion of group input node
def free(self):
call_group_nodes = self.get_call_group_nodes()
for node in call_group_nodes:
node.outputs.clear()
# Draw node UI
def draw_buttons(self, context, layout):
if self.mute:
layout.enabled = False
row = layout.row(align=True)
op = row.operator('lnx.node_call_func', text='New', icon='PLUS', emboss=True)
op.node_index = self.get_id_str()
op.callback_name = 'add_socket'
if len(self.inputs) > 1:
op2 = row.operator('lnx.node_call_func', text='', icon='X', emboss=True)
op2.node_index = self.get_id_str()
op2.callback_name = 'remove_socket'
# Draw side panel UI
def draw_buttons_ext(self, context, layout):
if self.mute:
layout.enabled = False
node = context.active_node
split = layout.row()
split.template_list('LNX_UL_InterfaceSockets', 'IN', node, 'inputs', node, 'active_input')
ops_col = split.column()
add_remove_col = ops_col.column(align=True)
props = add_remove_col.operator('lnx.node_call_func', icon='ADD', text="")
props.node_index = self.get_id_str()
props.callback_name = 'add_socket_ext'
if len(self.inputs) > 1:
props = add_remove_col.operator('lnx.node_call_func', icon='REMOVE', text="")
props.node_index = self.get_id_str()
props.callback_name = 'remove_socket_ext'
ops_col.separator()
up_down_col = ops_col.column(align=True)
props = up_down_col.operator('lnx.node_call_func', icon='TRIA_UP', text="")
props.node_index = self.get_id_str()
props.callback_name = 'move_socket_up'
props = up_down_col.operator('lnx.node_call_func', icon='TRIA_DOWN', text="")
props.node_index = self.get_id_str()
props.callback_name = 'move_socket_down'
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
if self.lnx_version not in (0, 1, 2):
raise LookupError()
return node_tree.nodes.new('LNGroupOutputsNode')

View File

@ -0,0 +1,71 @@
from lnx.logicnode.lnx_nodes import *
class RegularExpressionNode(LnxLogicTreeNode):
"""
The first argument is a string with a regular expression pattern, the second one is a string with flags.
@input RegExp Pattern: regular expression patterns such as
- `.`: any character
- `*`: repeat zero-or-more
- `+`: repeat one-or-more
- `?`: optional zero-or-one
- `[A-Z0-9]`: character ranges
- `[^\\r\\n\\t]`: character not-in-range
- `(...)`: parenthesis to match groups of characters
- `^`: beginning of the string (beginning of a line in multiline matching mode)
- `$`: end of the string (end of a line in multiline matching mode)
- `|`: "OR" statement.
@input RegExp Flags: possible flags are the following
- `i`: case insensitive matching
- `g`: global replace or split, see below
- `m`: multiline matching, ^ and $ represent the beginning and end of a line
- `s`: the dot . will also match newlines (not supported by C# and JavaScript versions before ES2018)
- `u`: use UTF-8 matching (Neko and C++ targets only)
@input String: String to match, split or replace
@input Replace: String to use when replace
@output Match: boolean result comparing the regular expression pattern with the string
@output Matched: array containing list of matched patterns
@output Split: array string of string splits using the pattern
@output Replace: new string with the pattern replaced
"""
bl_idname = 'LNRegularExpressionNode'
bl_label = 'Regular Expression'
lnx_version = 1
def remove_extra_inputs(self, context):
while len(self.outputs) > 0:
self.outputs.remove(self.outputs[-1])
if len(self.inputs) != 3:
self.inputs.remove(self.inputs[-1])
if self.property0 == 'Match':
self.add_output('LnxBoolSocket', 'Match')
self.add_output('LnxNodeSocketArray', 'Matched', is_var=False)
if self.property0 == 'Split':
self.add_output('LnxNodeSocketArray', 'Split', is_var=False)
if self.property0 == 'Replace':
self.add_input('LnxStringSocket', 'Replace')
self.add_output('LnxStringSocket', 'String')
property0: HaxeEnumProperty(
'property0',
items = [('Match', 'Match', 'A regular expression is used to compare a string. Use () in the pattern to retrieve Matched groups'),
('Split', 'Split', 'A regular expression can also be used to split a string into several substrings'),
('Replace', 'Replace', 'A regular expression can also be used to replace a part of the string')],
name='', default='Match', update=remove_extra_inputs)
def lnx_init(self, context):
self.add_input('LnxStringSocket', 'RegExp Pattern')
self.add_input('LnxStringSocket', 'RegExp Flags')
self.add_input('LnxStringSocket', 'String')
self.add_output('LnxBoolSocket', 'Match')
self.add_output('LnxNodeSocketArray', 'Matched', is_var=False)
def draw_buttons(self, context, layout):
layout.prop(self, 'property0')

View File

@ -0,0 +1,24 @@
from lnx.logicnode.lnx_nodes import *
class SetDebugConsoleSettings(LnxLogicTreeNode):
"""Sets the debug console settings."""
bl_idname = 'LNSetDebugConsoleSettings'
bl_label = 'Set Debug Console Settings'
lnx_version = 1
property0: HaxeEnumProperty(
'property0',
items = [('left', 'Anchor Left', 'Anchor debug console in the top left'),
('center', 'Anchor Center', 'Anchor debug console in the top center'),
('right', 'Anchor Right', 'Anchor the debug console in the top right')],
name='', default='right')
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxBoolSocket', 'Visible')
self.add_input('LnxFloatSocket', 'Scale', default_value=1.0)
self.add_output('LnxNodeSocketAction', 'Out')
def draw_buttons(self, context, layout):
layout.prop(self, 'property0')

View File

@ -0,0 +1,13 @@
from lnx.logicnode.lnx_nodes import *
class SetTimeScaleNode(LnxLogicTreeNode):
"""Sets the global time scale."""
bl_idname = 'LNSetTimeScaleNode'
bl_label = 'Set Time Scale'
lnx_version = 1
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxFloatSocket', 'Scale', default_value=1.0)
self.add_output('LnxNodeSocketAction', 'Out')

View File

@ -0,0 +1,14 @@
from lnx.logicnode.lnx_nodes import *
class SleepNode(LnxLogicTreeNode):
"""Waits a specified amount of seconds until passing
through the incoming signal."""
bl_idname = 'LNSleepNode'
bl_label = 'Sleep'
lnx_version = 1
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxFloatSocket', 'Time')
self.add_output('LnxNodeSocketAction', 'Out')

View File

@ -0,0 +1,50 @@
from lnx.logicnode.lnx_nodes import *
class TimerNode(LnxLogicTreeNode):
"""Runs a timer with a specified amount of repetitions.
@input Start: Start the timer or continue if paused. In both cases,
the values of `Duration` and `Repeat` are (re-)evaluated.
@input Pause: Pause the timer.
@input Stop: Stop and reset the timer. This does not activate any outputs.
@input Duration: The time in seconds that the timer runs.
@input Repeat: The number of times the timer will repeat, or 0 for infinite repetition.
@output Out: Activated after each repetition.
@output Done: Activated after the last repetition (never activated if `Repeat` is 0).
@output Running: Whether the timer is currently running.
@output Time Passed: The time in seconds that has passed since the
current repetition started, excluding pauses.
@output Time Left: The time left in seconds until the timer is done
or the next repetition starts.
@output Progress: Percentage of the timer's progress of the current
repetition (`Time Passed/Duration`).
@output Repetitions: The index of the current repetition, starting at 0.
"""
bl_idname = 'LNTimerNode'
bl_label = 'Timer'
lnx_version = 1
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'Start')
self.add_input('LnxNodeSocketAction', 'Pause')
self.add_input('LnxNodeSocketAction', 'Stop')
self.add_input('LnxFloatSocket', 'Duration', default_value=1.0)
self.add_input('LnxIntSocket', 'Repeat')
self.add_output('LnxNodeSocketAction', 'Out')
self.add_output('LnxNodeSocketAction', 'Done')
self.add_output('LnxBoolSocket', 'Running')
self.add_output('LnxIntSocket', 'Time Passed')
self.add_output('LnxIntSocket', 'Time Left')
self.add_output('LnxFloatSocket', 'Progress')
self.add_output('LnxFloatSocket', 'Repetitions')
def draw_label(self) -> str:
inp_duration = self.inputs['Duration']
inp_repeat = self.inputs['Repeat']
if inp_duration.is_linked or inp_repeat.is_linked:
return self.bl_label
return f'{self.bl_label}: {round(inp_duration.default_value_raw, 3)}s ({inp_repeat.default_value_raw} R.)'

View File

@ -0,0 +1,5 @@
from lnx.logicnode.lnx_nodes import add_node_section
add_node_section(name='group', category='Miscellaneous')
add_node_section(name='screen', category='Miscellaneous')
add_node_section(name='default', category='Miscellaneous')