mirror of
https://github.com/litruv/PNGTuber-Plus.git
synced 2026-07-24 02:26:02 +10:00
145 lines
4.8 KiB
GDScript
145 lines
4.8 KiB
GDScript
extends SubViewport
|
|
|
|
## NDI Avatar Viewport Controller
|
|
## Handles avatar-only NDI streaming with synchronized states
|
|
|
|
#Node Reference
|
|
@onready var origin = $OriginMotion/Origin
|
|
@onready var ndi_output = $NDIOutput
|
|
|
|
## Initialize viewport settings for transparent background and avatar mirroring
|
|
func _ready():
|
|
# Set transparent background
|
|
transparent_bg = true
|
|
|
|
# Connect to the main scene for state sync
|
|
if Global.main:
|
|
Global.main.connect("spriteVisToggles", Callable(self, "_on_sprite_visibility_toggle"))
|
|
Global.main.connect("bounceChange", Callable(self, "_sync_bounce"))
|
|
|
|
## Sync avatar sprites from main scene to this viewport
|
|
func sync_avatar():
|
|
# Clear existing sprites
|
|
for child in origin.get_children():
|
|
child.queue_free()
|
|
|
|
# Wait for cleanup
|
|
await get_tree().process_frame
|
|
|
|
# Get sprites from main scene
|
|
var main_sprites = get_tree().get_nodes_in_group("saved")
|
|
for sprite in main_sprites:
|
|
clone_sprite(sprite)
|
|
|
|
## Clone a sprite from main scene to this viewport
|
|
func clone_sprite(original_sprite):
|
|
# Create new instance
|
|
var sprite_scene = preload("res://ui_scenes/selectedSprite/spriteObject.tscn")
|
|
var cloned_sprite = sprite_scene.instantiate()
|
|
|
|
# Copy all properties
|
|
cloned_sprite.path = original_sprite.path
|
|
cloned_sprite.id = original_sprite.id
|
|
cloned_sprite.parentId = original_sprite.parentId
|
|
cloned_sprite.displayName = original_sprite.displayName
|
|
|
|
# Visual properties
|
|
cloned_sprite.offset = original_sprite.offset
|
|
cloned_sprite.z = original_sprite.z
|
|
cloned_sprite.position = original_sprite.position
|
|
|
|
# Physics properties
|
|
cloned_sprite.dragSpeed = original_sprite.dragSpeed
|
|
cloned_sprite.xFrq = original_sprite.xFrq
|
|
cloned_sprite.xAmp = original_sprite.xAmp
|
|
cloned_sprite.yFrq = original_sprite.yFrq
|
|
cloned_sprite.yAmp = original_sprite.yAmp
|
|
cloned_sprite.rFrq = original_sprite.rFrq
|
|
cloned_sprite.rAmp = original_sprite.rAmp
|
|
cloned_sprite.rdragStr = original_sprite.rdragStr
|
|
cloned_sprite.rLimitMin = original_sprite.rLimitMin
|
|
cloned_sprite.rLimitMax = original_sprite.rLimitMax
|
|
cloned_sprite.stretchAmount = original_sprite.stretchAmount
|
|
cloned_sprite.ignoreBounce = original_sprite.ignoreBounce
|
|
|
|
# Animation properties
|
|
cloned_sprite.frames = original_sprite.frames
|
|
cloned_sprite.animSpeed = original_sprite.animSpeed
|
|
|
|
# Visibility properties
|
|
cloned_sprite.showOnTalk = original_sprite.showOnTalk
|
|
cloned_sprite.showOnBlink = original_sprite.showOnBlink
|
|
cloned_sprite.costumeLayers = original_sprite.costumeLayers.duplicate()
|
|
cloned_sprite.spriteOpacity = original_sprite.spriteOpacity
|
|
cloned_sprite.affectChildrenOpacity = original_sprite.affectChildrenOpacity
|
|
cloned_sprite.blendMode = original_sprite.blendMode
|
|
cloned_sprite.toggle = original_sprite.toggle
|
|
cloned_sprite.clipped = original_sprite.clipped
|
|
|
|
# Transform properties
|
|
cloned_sprite.staticRotation = original_sprite.staticRotation
|
|
cloned_sprite.mirrorHorizontal = original_sprite.mirrorHorizontal
|
|
cloned_sprite.mirrorVertical = original_sprite.mirrorVertical
|
|
|
|
# Wobble sync
|
|
cloned_sprite.wobbleSyncGroup = original_sprite.wobbleSyncGroup
|
|
|
|
# Add to origin
|
|
origin.add_child(cloned_sprite)
|
|
|
|
# Apply current costume visibility
|
|
if Global.main:
|
|
var current_costume = Global.main.costume
|
|
if cloned_sprite.costumeLayers[current_costume - 1] == 1:
|
|
cloned_sprite.visible = true
|
|
else:
|
|
cloned_sprite.visible = false
|
|
|
|
## Process function to keep sprites in sync with main scene
|
|
func _process(delta):
|
|
if !Global.main:
|
|
return
|
|
|
|
# Sync origin position with bounce from main scene
|
|
$OriginMotion.position.y = 360 + Global.main.bounceChange
|
|
|
|
# Sync sprites with main scene
|
|
var main_sprites = get_tree().get_nodes_in_group("saved")
|
|
var avatar_sprites = origin.get_children()
|
|
|
|
for i in range(min(main_sprites.size(), avatar_sprites.size())):
|
|
sync_sprite_state(main_sprites[i], avatar_sprites[i])
|
|
|
|
## Sync individual sprite state
|
|
func sync_sprite_state(main_sprite, avatar_sprite):
|
|
if !is_instance_valid(main_sprite) or !is_instance_valid(avatar_sprite):
|
|
return
|
|
|
|
# Sync position and transform
|
|
avatar_sprite.position = main_sprite.position
|
|
avatar_sprite.rotation = main_sprite.rotation
|
|
avatar_sprite.scale = main_sprite.scale
|
|
|
|
# Sync visibility based on costume
|
|
if Global.main:
|
|
var current_costume = Global.main.costume
|
|
if avatar_sprite.costumeLayers[current_costume - 1] == 1:
|
|
avatar_sprite.visible = main_sprite.visible
|
|
else:
|
|
avatar_sprite.visible = false
|
|
|
|
# Sync animation frame
|
|
if avatar_sprite.has_method("get_sprite") and main_sprite.has_method("get_sprite"):
|
|
var avatar_spr = avatar_sprite.get_sprite()
|
|
var main_spr = main_sprite.get_sprite()
|
|
if avatar_spr and main_spr:
|
|
avatar_spr.frame = main_spr.frame
|
|
|
|
## Handle sprite visibility toggles
|
|
func _on_sprite_visibility_toggle():
|
|
sync_avatar()
|
|
|
|
## Sync bounce changes
|
|
func _sync_bounce(bounce_change):
|
|
$OriginMotion.position.y = 360 + bounce_change
|