diff --git a/leenkx/Sources/leenkx/logicnode/GetAudioPositionNode.hx b/leenkx/Sources/leenkx/logicnode/GetAudioPositionNode.hx new file mode 100644 index 0000000..63521dd --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/GetAudioPositionNode.hx @@ -0,0 +1,17 @@ +package leenkx.logicnode; + +import aura.Aura; +import aura.Types; + +class GetAudioPositionNode extends LogicNode { + + public function new(tree: LogicTree) { + super(tree); + } + + override function get(from: Int): Dynamic { + var audio = inputs[0].get(); + if (audio == null || audio.channel == null) return 0.0; + return audio.channel.floatPosition / audio.channel.sampleRate; + } +} diff --git a/leenkx/Sources/leenkx/logicnode/GetPositionSpeakerNode.hx b/leenkx/Sources/leenkx/logicnode/GetPositionSpeakerNode.hx new file mode 100644 index 0000000..66ced5f --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/GetPositionSpeakerNode.hx @@ -0,0 +1,33 @@ +package leenkx.logicnode; + +#if lnx_audio +import iron.object.SpeakerObject; +import kha.audio1.AudioChannel; +#end + +class GetPositionSpeakerNode extends LogicNode { + + public function new(tree: LogicTree) { + super(tree); + } + + override function get(from: Int): Dynamic { + #if lnx_audio + var object: SpeakerObject = cast(inputs[0].get(), SpeakerObject); + if (object == null || object.sound == null) return 0.0; + + if (object.channels.length == 0) return 0.0; + + var channel = object.channels[0]; + + var position = 0.0; + if (channel != null) { + position = @:privateAccess channel.get_position(); + } + + return position; + #else + return 0.0; + #end + } +} diff --git a/leenkx/Sources/leenkx/logicnode/SetAudioPositionNode.hx b/leenkx/Sources/leenkx/logicnode/SetAudioPositionNode.hx new file mode 100644 index 0000000..4aadece --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/SetAudioPositionNode.hx @@ -0,0 +1,23 @@ +package leenkx.logicnode; + +import aura.Aura; +import aura.Types; + +class SetAudioPositionNode extends LogicNode { + + public function new(tree: LogicTree) { + super(tree); + } + + override function run(from: Int) { + var audio = inputs[1].get(); + if (audio == null) return; + + var positionInSeconds:Float = inputs[2].get(); + if (positionInSeconds < 0.0) positionInSeconds = 0.0; + + audio.channel.floatPosition = positionInSeconds * audio.channel.sampleRate; + + runOutput(0); + } +} diff --git a/leenkx/Sources/leenkx/logicnode/SetPositionSpeakerNode.hx b/leenkx/Sources/leenkx/logicnode/SetPositionSpeakerNode.hx new file mode 100644 index 0000000..3114e6e --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/SetPositionSpeakerNode.hx @@ -0,0 +1,39 @@ +package leenkx.logicnode; + +#if lnx_audio +import iron.object.SpeakerObject; +import kha.audio1.AudioChannel; +import iron.system.Audio; +#end + +class SetPositionSpeakerNode extends LogicNode { + + public function new(tree: LogicTree) { + super(tree); + } + + override function run(from: Int) { + #if lnx_audio + var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject); + if (object == null || object.sound == null) return; + + var positionInSeconds:Float = inputs[2].get(); + if (positionInSeconds < 0) positionInSeconds = 0; + + var volume = object.data.volume; + var loop = object.data.loop; + var stream = object.data.stream; + + object.stop(); + + var channel = Audio.play(object.sound, loop, stream); + if (channel != null) { + object.channels.push(channel); + channel.volume = volume; + @:privateAccess channel.set_position(positionInSeconds); + } + + #end + runOutput(0); + } +} diff --git a/leenkx/blender/lnx/logicnode/custom/LN_get_audio_position.py b/leenkx/blender/lnx/logicnode/custom/LN_get_audio_position.py new file mode 100644 index 0000000..6924107 --- /dev/null +++ b/leenkx/blender/lnx/logicnode/custom/LN_get_audio_position.py @@ -0,0 +1,17 @@ +from lnx.logicnode.lnx_nodes import * + +class GetAudioPositionNode(LnxLogicTreeNode): + """Gets the current playback position of 3D audio in seconds.""" + bl_idname = 'LNGetAudioPositionNode' + bl_label = 'Get Audio Position' + bl_description = 'Gets the current playback position of 3D audio in seconds.' + lnx_category = '3D_Audio' + lnx_version = 1 + + def lnx_init(self, context): + self.add_input('LnxDynamicSocket', 'Audio') + self.add_output('LnxFloatSocket', 'Position (seconds)') + +def register(): + add_category('3D_Audio', icon='SOUND') + GetAudioPositionNode.on_register() \ No newline at end of file diff --git a/leenkx/blender/lnx/logicnode/custom/LN_set_audio_position.py b/leenkx/blender/lnx/logicnode/custom/LN_set_audio_position.py new file mode 100644 index 0000000..c38d120 --- /dev/null +++ b/leenkx/blender/lnx/logicnode/custom/LN_set_audio_position.py @@ -0,0 +1,20 @@ +from lnx.logicnode.lnx_nodes import * + +class SetAudioPositionNode(LnxLogicTreeNode): + """Sets the playback position of 3D audio. This node allows you to "scrub" through 3D audio by setting the current playback position to a specific time in seconds.""" + bl_idname = 'LNSetAudioPositionNode' + bl_label = 'Set Audio Position' + bl_description = 'Sets the playback position of 3D audio' + lnx_category = '3D_Audio' + lnx_version = 1 + + def lnx_init(self, context): + self.add_input('LnxNodeSocketAction', 'In') + self.add_input('LnxDynamicSocket', 'Audio') + self.add_input('LnxFloatSocket', 'Position (seconds)') + + self.add_output('LnxNodeSocketAction', 'Out') + +def register(): + add_category('3D_Audio', icon='SOUND') + SetAudioPositionNode.on_register() \ No newline at end of file diff --git a/leenkx/blender/lnx/logicnode/sound/LN_get_position_speaker.py b/leenkx/blender/lnx/logicnode/sound/LN_get_position_speaker.py new file mode 100644 index 0000000..571bc99 --- /dev/null +++ b/leenkx/blender/lnx/logicnode/sound/LN_get_position_speaker.py @@ -0,0 +1,11 @@ +from lnx.logicnode.lnx_nodes import * + +class GetPositionSpeakerNode(LnxLogicTreeNode): + """Gets the current playback position of the given speaker object in seconds.""" + bl_idname = 'LNGetPositionSpeakerNode' + bl_label = 'Get Position Speaker' + lnx_version = 1 + + def lnx_init(self, context): + self.add_input('LnxNodeSocketObject', 'Speaker') + self.add_output('LnxFloatSocket', 'Position (seconds)') diff --git a/leenkx/blender/lnx/logicnode/sound/LN_set_position_speaker.py b/leenkx/blender/lnx/logicnode/sound/LN_set_position_speaker.py new file mode 100644 index 0000000..cd38b3f --- /dev/null +++ b/leenkx/blender/lnx/logicnode/sound/LN_set_position_speaker.py @@ -0,0 +1,17 @@ +from lnx.logicnode.lnx_nodes import * + +class SetPositionSpeakerNode(LnxLogicTreeNode): + """Sets the playback position of the given speaker object. + This node allows you to "scrub" through audio by setting the current playback position + to a specific time in seconds. The speaker must be playing for this to take effect. + """ + bl_idname = 'LNSetPositionSpeakerNode' + bl_label = 'Set Position Speaker' + lnx_version = 1 + + def lnx_init(self, context): + self.add_input('LnxNodeSocketAction', 'In') + self.add_input('LnxNodeSocketObject', 'Speaker') + self.add_input('LnxFloatSocket', 'Position (seconds)') + + self.add_output('LnxNodeSocketAction', 'Out') diff --git a/leenkx/blender/lnx/material/cycles.py b/leenkx/blender/lnx/material/cycles.py index 949f124..eb61a1a 100644 --- a/leenkx/blender/lnx/material/cycles.py +++ b/leenkx/blender/lnx/material/cycles.py @@ -228,6 +228,8 @@ def parse_shader(node: bpy.types.Node, socket: bpy.types.NodeSocket) -> Tuple[st 'EMISSION', 'BSDF_GLASS', 'GLASS_BSDF', + 'BSDF_REFRACTION', + 'REFRACTION_BSDF', 'HOLDOUT', 'SUBSURFACE_SCATTERING', 'BSDF_TRANSLUCENT',