Files
LNXSDK/leenkx/blender/lnx/logicnode/input/LN_mouse_look.py

159 lines
8.2 KiB
Python

from lnx.logicnode.lnx_nodes import *
class MouseLookNode(LnxLogicTreeNode):
"""MouseLookNode - Blender UI interface for FPS-style mouse look camera controller
This class defines the Blender node interface for the MouseLookNode logic node.
It creates the visual node that appears in Blender's logic tree editor and
defines all the properties that configure the mouse look behavior.
The node provides controls for:
- Axis orientation configuration
- Mouse cursor behavior
- Movement inversion options
- Rotation limiting/capping
- Head rotation space behavior
Features:
- Built-in resolution-adaptive scaling for consistent feel across different screen resolutions
- Automatic physics synchronization for rigid bodies
- Support for both single-object and dual-object (body/head) setups
"""
# Blender node identification
bl_idname = 'LNMouseLookNode' # Unique identifier for Blender's node system
bl_label = 'Mouse Look' # Display name in node menu and header
lnx_section = 'mouse' # Category section in node add menu
lnx_version = 1 # Node version for compatibility tracking
# Property 0: Front Axis Configuration
# Determines which 3D axis represents the "forward" direction of the character/camera
# This affects how horizontal and vertical rotations are applied to the objects
property0: HaxeEnumProperty(
'property0',
items=[('X', 'X Axis', 'X Axis as front'), # X-forward (side-scrolling, specific orientations)
('Y', 'Y Axis', 'Y Axis as front'), # Y-forward (most common for 3D games)
('Z', 'Z Axis', 'Z Axis as front')], # Z-forward (top-down, specific orientations)
name='Front',
default='Y') # Y-axis is default as it's most common in 3D game development
# Property 1: Automatic Mouse Cursor Management
# When enabled, automatically centers and locks the mouse cursor when mouse input starts
# This is essential for FPS games to prevent cursor from leaving game window
property1: HaxeBoolProperty(
'property1',
name='Hide Locked',
description='Automatically center and lock the mouse cursor when mouse input begins',
default=True) # Enabled by default for typical FPS behavior
# Property 2: Horizontal Movement Inversion
# Allows users to invert horizontal mouse movement (left becomes right, right becomes left)
# Some players prefer inverted controls for consistency with flight simulators
property2: HaxeBoolProperty(
'property2',
name='Invert X',
description='Invert horizontal mouse movement - moving mouse right turns character left',
default=False) # Most players expect non-inverted horizontal movement
# Property 3: Vertical Movement Inversion
# Allows users to invert vertical mouse movement (up becomes down, down becomes up)
# More commonly used than horizontal inversion, especially by flight sim players
property3: HaxeBoolProperty(
'property3',
name='Invert Y',
description='Invert vertical mouse movement - moving mouse up looks down',
default=False) # Most players expect non-inverted vertical movement
# Property 4: Horizontal Rotation Limiting
# Prevents the character from rotating beyond specified horizontal limits
# Useful for fixed-perspective games or when character shouldn't turn completely around
property4: HaxeBoolProperty(
'property4',
name='Cap Left / Right',
description='Limit horizontal rotation to prevent full 360-degree turns',
default=False) # Disabled by default - most FPS games allow full horizontal rotation
# Property 5: Vertical Rotation Limiting
# Prevents looking too far up or down, simulating human neck movement limitations
# Essential for realistic FPS games to prevent disorienting over-rotation
property5: HaxeBoolProperty(
'property5',
name='Cap Up / Down',
description='Limit vertical rotation to simulate natural neck movement (±90 degrees)',
default=True) # Enabled by default for realistic FPS behavior
# Property 6: Head Rotation Space Mode
# Controls whether head rotation uses local or world space coordinates
# Critical for preventing rotation issues when head object is child of body object
property6: HaxeBoolProperty(
'property6',
name='Head Local Space',
description='Use local space for head rotation - enable when Head is child of Body to avoid gimbal lock',
default=False) # Disabled by default, enable when using parent-child object relationships
def lnx_init(self, context):
"""Initialize the node's input and output sockets
This method is called when the node is first created in Blender.
It defines all the connection points (sockets) that other nodes can connect to.
Input Sockets:
- Action In: Execution flow input (when this node should run)
- Body: The main character/player object that rotates horizontally
- Head: Optional camera/head object that rotates vertically (can be child of Body)
- Sensitivity: Mouse sensitivity multiplier (0.5 = half sensitivity, 2.0 = double sensitivity)
- Smoothing: Movement smoothing factor (0.0 = no smoothing, higher = more smoothing)
Output Sockets:
- Action Out: Execution flow output (continues to next node after processing)
"""
# Execution flow input - connects from previous logic node
self.add_input('LnxNodeSocketAction', 'In')
# Object inputs - require 3D objects from the scene
self.add_input('LnxNodeSocketObject', 'Body') # Main character object (required)
self.add_input('LnxNodeSocketObject', 'Head') # Camera/head object (optional)
# Numeric inputs with sensible defaults
self.add_input('LnxFloatSocket', 'Sensitivity', default_value=0.5) # Medium sensitivity
self.add_input('LnxFloatSocket', 'Smoothing', default_value=0.0) # No smoothing by default
# Execution flow output - connects to next logic node
self.add_output('LnxNodeSocketAction', 'Out')
def draw_buttons(self, context, layout):
"""Draw the node's user interface in Blender's logic tree editor
This method creates the visual controls that appear on the node in Blender.
It organizes properties into logical groups for better usability.
Args:
context: Blender context (current scene, selected objects, etc.)
layout: UI layout object for arranging interface elements
"""
# Basic configuration section
layout.prop(self, 'property0', text='Front') # Front axis dropdown
layout.prop(self, 'property1', text='Hide Locked') # Mouse locking checkbox
# Movement inversion controls section
# Group X and Y inversion together for logical organization
col = layout.column(align=True) # Create aligned column
col.label(text="Invert XY:") # Section header
row = col.row(align=True) # Create horizontal row within column
row.prop(self, 'property2', text='X', toggle=True) # X inversion toggle button
row.prop(self, 'property3', text='Y', toggle=True) # Y inversion toggle button
# Rotation limiting controls section
# Group rotation caps together since they're related functionality
col = layout.column(align=True) # Create new aligned column
col.prop(self, 'property4', text='Cap Left / Right') # Horizontal capping checkbox
col.prop(self, 'property5', text='Cap Up / Down') # Vertical capping checkbox
# Advanced head behavior section
# Separate advanced option that affects technical behavior
col = layout.column(align=True) # Create new aligned column
col.prop(self, 'property6', text='Head Local Space') # Head rotation space checkbox