revert add new node called Set Look at Rotation
This commit is contained in:
2025-06-24 17:38:18 +00:00
parent 6a1df9ec46
commit 06b003ecdb
736 changed files with 0 additions and 557 deletions

View File

@ -1,367 +0,0 @@
from lnx.logicnode.lnx_nodes import *
import bpy
class SetLookAtRotationNode(LnxLogicTreeNode):
"""Returns a rotation that makes an object look at a target object or location"""
bl_idname = 'LNSetLookAtRotationNode'
bl_label = 'Set Look At Rotation'
lnx_section = 'rotation'
lnx_version = 1
use_vector: bpy.props.BoolProperty(
name='Use Vector for Target Location',
description='Use a vector location instead of a target object',
default=False,
update=lambda self, context: self.update_sockets(context)
)
use_source_vector: bpy.props.BoolProperty(
name='Use Vector for Source',
description='Use a vector location instead of a source object',
default=False,
update=lambda self, context: self.update_sockets(context)
)
disable_rotation_on_align_axis: bpy.props.BoolProperty(
name='Disable Rotation on Aligning Axis',
description='Zero out the rotation on the aligning axis after look at is applied',
default=False,
update=lambda self, context: self.update_sockets(context)
)
damping: bpy.props.FloatProperty(
name='Damping',
description='Amount of damping for rotation (0.0 = instant, 1.0 = no movement)',
default=0.0,
min=0.0,
max=1.0,
step=10,
precision=2,
update=lambda self, context: self.update_damping_socket(context)
)
# Store object references as custom properties
source_object_name: bpy.props.StringProperty(default="")
target_object_name: bpy.props.StringProperty(default="")
property0: HaxeEnumProperty(
'property0',
items = [('X', ' X', 'X'),
('-X', '-X', '-X'),
('Y', ' Y', 'Y'),
('-Y', '-Y', '-Y'),
('Z', ' Z', 'Z'),
('-Z', '-Z', '-Z')],
name='With', default='Z')
property1: HaxeEnumProperty(
'property1',
items = [('true', 'True', 'True'),
('false', 'False', 'False')],
name='Use Vector for Target Location', default='false')
property2: HaxeEnumProperty(
'property2',
items = [('true', 'True', 'True'),
('false', 'False', 'False')],
name='Use Vector for Source', default='false')
property3: bpy.props.StringProperty(name='Damping', default='0.0')
property4: HaxeEnumProperty(
'property4',
items = [('true', 'True', 'True'),
('false', 'False', 'False')],
name='Disable Rotation on Aligning Axis', default='false')
def lnx_init(self, context):
# Add inputs in standard order
self.inputs.new('LnxNodeSocketAction', 'In')
# Add the initial source input
self.inputs.new('LnxNodeSocketObject', 'Source Object')
# Add the initial target input
self.inputs.new('LnxNodeSocketObject', 'Target Object')
# Add damping input socket with default value
damping_socket = self.inputs.new('LnxFloatSocket', 'Damping')
damping_socket.default_value_raw = 0.0
# Add outputs
self.add_output('LnxNodeSocketAction', 'Out')
# Add rotation output socket
self.add_output('LnxRotationSocket', 'Rotation')
def draw_buttons(self, context, layout):
# 1. Axis Selector
layout.prop(self, 'property0')
# 2. 'Use Vector for Source' checkbox
layout.prop(self, 'use_source_vector')
# 3. 'Use Vector for Target Location' checkbox
layout.prop(self, 'use_vector')
# 4. 'Disable Rotation on Aligning Axis' checkbox
layout.prop(self, 'disable_rotation_on_align_axis')
# Note: Damping is now handled by the input socket
def update_sockets(self, context):
# Update the Haxe properties to match the Python properties
self.property1 = 'true' if self.use_vector else 'false'
self.property2 = 'true' if self.use_source_vector else 'false'
self.property3 = str(self.damping) # Keep for backward compatibility
self.property4 = 'true' if self.disable_rotation_on_align_axis else 'false'
# Store current object references before changing sockets
self.save_object_references()
# Helper to find a socket by name
def find_input_socket(name):
for i, s in enumerate(self.inputs):
if s.name == name:
return i, s
return -1, None
# Ensure we have the 'In' socket at index 0
in_idx, in_socket = find_input_socket('In')
if in_idx == -1:
# If 'In' socket is missing, add it at index 0
self.inputs.new('LnxNodeSocketAction', 'In')
# Fixed indices for our sockets
SOURCE_INDEX = 1
TARGET_INDEX = 2
DAMPING_INDEX = 3
# Get current socket information
source_names = ['Source Object', 'Source Location']
target_names = ['Target Object', 'Target Location']
# Find current source and target sockets
source_idx = -1
source_socket = None
for name in source_names:
idx, socket = find_input_socket(name)
if idx != -1:
source_idx = idx
source_socket = socket
break
target_idx = -1
target_socket = None
for name in target_names:
idx, socket = find_input_socket(name)
if idx != -1:
target_idx = idx
target_socket = socket
break
# Expected types based on current settings
expected_source_name = 'Source Location' if self.use_source_vector else 'Source Object'
expected_source_type = 'LnxVectorSocket' if self.use_source_vector else 'LnxNodeSocketObject'
expected_target_name = 'Target Location' if self.use_vector else 'Target Object'
expected_target_type = 'LnxVectorSocket' if self.use_vector else 'LnxNodeSocketObject'
# Ensure we have exactly 4 sockets (In, Source, Target, Damping) in the correct order
while len(self.inputs) > 4:
# Remove any extra sockets
self.inputs.remove(self.inputs[-1])
# Make sure we have exactly 4 sockets
while len(self.inputs) < 4:
if len(self.inputs) == 0:
self.inputs.new('LnxNodeSocketAction', 'In')
elif len(self.inputs) == 1:
self.inputs.new(expected_source_type, expected_source_name)
elif len(self.inputs) == 2:
self.inputs.new(expected_target_type, expected_target_name)
elif len(self.inputs) == 3:
damping_socket = self.inputs.new('LnxFloatSocket', 'Damping')
damping_socket.default_value_raw = self.damping
# Now update the source socket if needed
if source_socket and source_socket.name != expected_source_name:
# Store links before removing
links = []
for link in source_socket.links:
links.append(link.from_socket)
# Get the index where this socket should be
correct_idx = SOURCE_INDEX
# Create the new socket at the correct position
self.inputs.remove(source_socket)
new_socket = self.inputs.new(expected_source_type, expected_source_name)
# Move the new socket to the correct position
if not new_socket.is_linked: # Only move if not linked
# Move the socket to the correct index
if correct_idx < len(self.inputs) - 1:
self.inputs.move(len(self.inputs) - 1, correct_idx)
# Restore links
if links and hasattr(context, 'space_data') and context.space_data and hasattr(context.space_data, 'edit_tree'):
for link_socket in links:
context.space_data.edit_tree.links.new(link_socket, new_socket)
# Update the target socket if needed
if target_socket and target_socket.name != expected_target_name:
# Store links before removing
links = []
for link in target_socket.links:
links.append(link.from_socket)
# Get the index where this socket should be
correct_idx = TARGET_INDEX
# Create the new socket at the correct position
self.inputs.remove(target_socket)
new_socket = self.inputs.new(expected_target_type, expected_target_name)
# Move the new socket to the correct position
if not new_socket.is_linked: # Only move if not linked
# Move the socket to the correct index
if correct_idx < len(self.inputs) - 1:
self.inputs.move(len(self.inputs) - 1, correct_idx)
# Restore links
if links and hasattr(context, 'space_data') and context.space_data and hasattr(context.space_data, 'edit_tree'):
for link_socket in links:
context.space_data.edit_tree.links.new(link_socket, new_socket)
# Make a final check to ensure the sockets are in the correct order
# This is a safety measure to ensure consistent UI
in_idx, in_socket = find_input_socket('In')
source_idx = -1
for name in source_names:
idx, _ = find_input_socket(name)
if idx != -1:
source_idx = idx
break
target_idx = -1
for name in target_names:
idx, _ = find_input_socket(name)
if idx != -1:
target_idx = idx
break
damping_idx, damping_socket = find_input_socket('Damping')
# If the order is wrong, fix it by recreating the sockets in the correct order
if not (in_idx == 0 and source_idx == 1 and target_idx == 2 and damping_idx == 3):
# Store all links
all_links = {}
for i, socket in enumerate(self.inputs):
# Store links
links = []
for link in socket.links:
links.append(link.from_socket)
all_links[socket.name] = links
# Clear all inputs
while len(self.inputs) > 0:
self.inputs.remove(self.inputs[0])
# Recreate in the correct order
in_socket = self.inputs.new('LnxNodeSocketAction', 'In')
source_socket = self.inputs.new(expected_source_type, expected_source_name)
target_socket = self.inputs.new(expected_target_type, expected_target_name)
damping_socket = self.inputs.new('LnxFloatSocket', 'Damping')
damping_socket.default_value_raw = self.damping
# Restore links
if hasattr(context, 'space_data') and context.space_data and hasattr(context.space_data, 'edit_tree'):
# Restore In links
if 'In' in all_links:
for link_socket in all_links['In']:
context.space_data.edit_tree.links.new(link_socket, in_socket)
# Restore Source links
source_links = []
for name in source_names:
if name in all_links:
source_links.extend(all_links[name])
for link_socket in source_links:
context.space_data.edit_tree.links.new(link_socket, source_socket)
# Restore Target links
target_links = []
for name in target_names:
if name in all_links:
target_links.extend(all_links[name])
for link_socket in target_links:
context.space_data.edit_tree.links.new(link_socket, target_socket)
# Restore Damping links
if 'Damping' in all_links:
for link_socket in all_links['Damping']:
context.space_data.edit_tree.links.new(link_socket, damping_socket)
# Restore object references after socket changes
self.restore_object_references()
def update_damping_socket(self, context):
"""Update the damping socket default value when the slider changes"""
for socket in self.inputs:
if socket.name == 'Damping' and hasattr(socket, 'default_value_raw'):
socket.default_value_raw = self.damping
break
def save_object_references(self):
"""Save object references to custom properties"""
# Find source and target object sockets
for socket in self.inputs:
if socket.name == 'Source Object' and socket.is_linked:
for link in socket.links:
if hasattr(link.from_node, 'item') and link.from_node.item:
self.source_object_name = link.from_node.item.name
if socket.name == 'Target Object' and socket.is_linked:
for link in socket.links:
if hasattr(link.from_node, 'item') and link.from_node.item:
self.target_object_name = link.from_node.item.name
def restore_object_references(self):
"""Restore object references from custom properties"""
# Only restore if we're not using vector inputs
if not self.use_source_vector:
# Find source object socket
for socket in self.inputs:
if socket.name == 'Source Object' and not socket.is_linked:
# Try to find the object in the scene
if self.source_object_name and self.source_object_name in bpy.context.scene.objects:
# Find the appropriate object node in the node tree
if hasattr(self, 'id_data') and hasattr(self.id_data, 'nodes'):
for node in self.id_data.nodes:
if (node.bl_idname == 'LNObjectNode' and
hasattr(node, 'item') and
node.item and
node.item.name == self.source_object_name):
# Create a link between the nodes
if hasattr(self.id_data, 'links'):
self.id_data.links.new(node.outputs[0], socket)
break
if not self.use_vector:
# Find target object socket
for socket in self.inputs:
if socket.name == 'Target Object' and not socket.is_linked:
# Try to find the object in the scene
if self.target_object_name and self.target_object_name in bpy.context.scene.objects:
# Find the appropriate object node in the node tree
if hasattr(self, 'id_data') and hasattr(self.id_data, 'nodes'):
for node in self.id_data.nodes:
if (node.bl_idname == 'LNObjectNode' and
hasattr(node, 'item') and
node.item and
node.item.name == self.target_object_name):
# Create a link between the nodes
if hasattr(self.id_data, 'links'):
self.id_data.links.new(node.outputs[0], socket)
break