Browse Source

Implement Sound logic nodes

pull/35/head
Adam Johnson 9 years ago
parent
commit
fd3026021a
  1. 125
      korman/nodes/node_messages.py
  2. 15
      korman/properties/modifiers/sound.py

125
korman/nodes/node_messages.py

@ -482,6 +482,131 @@ class PlasmaSceneObjectMsgRcvrNode(PlasmaNodeBase, bpy.types.Node):
return ref_so_key return ref_so_key
class PlasmaSoundMsgNode(PlasmaMessageNode, bpy.types.Node):
bl_category = "MSG"
bl_idname = "PlasmaSoundMsgNode"
bl_label = "Sound"
bl_width_default = 190
object_name = StringProperty(name="Object",
description="Sound emitter object")
sound_name = StringProperty(name="Sound",
description="Sound datablock")
go_to = EnumProperty(name="Go To",
description="Where should the sound start?",
items=[("BEGIN", "Beginning", "The beginning"),
("CURRENT", "(Don't Change)", "The current position"),
("TIME", "Time", "The time specified in seconds")],
default="CURRENT")
looping = EnumProperty(name="Looping",
description="Is the sound looping?",
items=[("kSetLooping", "Yes", "The sound is looping",),
("CURRENT", "(Don't Change)", "Don't change the loop status"),
("kSetUnLooping", "No", "The sound is NOT looping")],
default="CURRENT")
action = EnumProperty(name="Action",
description="What do you want the sound to do?",
items=[("kPlay", "Play", "Plays the sound"),
("kStop", "Stop", "Stops the sound",),
("kToggleState", "Toggle", "Toggles between Play and Stop"),
("CURRENT", "(Don't Change)", "Don't change the sound's playing state")],
default="CURRENT")
volume = EnumProperty(name="Volume",
description="What should happen to the volume?",
items=[("MUTE", "Mute", "Mutes the volume"),
("CURRENT", "(Don't Change)", "Don't change the volume"),
("CUSTOM", "Custom", "Manually specify the volume")],
default="CURRENT")
time = FloatProperty(name="Time",
description="Time in seconds to begin playing from",
min=0.0, default=0.0,
options=set(), subtype="TIME", unit="TIME")
volume_pct = IntProperty(name="Volume Level",
description="Volume to play the sound",
min=0, max=100, default=100,
options=set(),
subtype="PERCENTAGE")
def convert_callback_message(self, exporter, so, msg, target, wait):
cb = plEventCallbackMsg()
cb.addReceiver(target)
cb.event = kEnd
cb.user = wait
msg.addCallback(cb)
msg.setCmd(plSoundMsg.kAddCallbacks)
def convert_message(self, exporter, so):
sound_bo = bpy.data.objects.get(self.object_name, None)
if sound_bo is None:
self.raise_error("'{}' is not a valid object".format(self.object_name))
soundemit = sound_bo.plasma_modifiers.soundemit
if not soundemit.enabled:
self.raise_error("'{}' is not a valid Sound Emitter".format(self.object_name))
# Always test the specified audible for validity
if self.sound_name and soundemit.sounds.get(self.sound_name, None) is None:
self.raise_error("Invalid Sound '{}' requested from Sound Emitter '{}'".format(self.sound_name, self.object_name))
# Remember that 3D stereo sounds are exported as two emitters...
# But, if we only have one sound attached, who cares, we can just address the message to all
audible_key = exporter.mgr.find_create_key(plAudioInterface, bl=sound_bo)
indices = (-1,) if not self.sound_name or len(soundemit.sounds) == 1 else soundemit.get_sound_indices(self.sound_name)
for idx in indices:
msg = plSoundMsg()
msg.addReceiver(audible_key)
msg.index = idx
# NOTE: There are a number of commands in Plasma's enumeration that do nothing.
# This is what I determine to be the most useful and functional subset...
# Please see plAudioInterface::MsgReceive for more details.
if self.go_to == "BEGIN":
msg.setCmd(plSoundMsg.kGoToTime)
msg.time = 0.0
elif self.go_to == "TIME":
msg.setCmd(plSoundMsg.kGoToTime)
msg.time = self.time
if self.volume == "MUTE":
msg.setCmd(plSoundMsg.kSetVolume)
msg.volume = 0.0
elif self.volume == "CUSTOM":
msg.setCmd(plSoundMsg.kSetVolume)
msg.volume = self.volume_pct
if self.looping != "CURRENT":
msg.setCmd(getattr(plSoundMsg, self.looping))
if self.action != "CURRENT":
msg.setCmd(getattr(plSoundMsg, self.action))
# Because we might be giving two messages here...
yield msg
def draw_buttons(self, context, layout):
layout.prop_search(self, "object_name", bpy.data, "objects")
bo = bpy.data.objects.get(self.object_name, None)
if bo is not None:
soundemit = bo.plasma_modifiers.soundemit
if soundemit.enabled:
layout.prop_search(self, "sound_name", soundemit, "sounds", icon="SOUND")
else:
layout.label("Not a Sound Emitter", icon="ERROR")
layout.prop(self, "go_to")
if self.go_to == "TIME":
layout.prop(self, "time")
layout.prop(self, "action")
if self.volume == "CUSTOM":
layout.prop(self, "volume_pct")
layout.prop(self, "looping")
layout.prop(self, "volume")
@property
def has_callbacks(self):
return True
class PlasmaTimerCallbackMsgNode(PlasmaMessageNode, bpy.types.Node): class PlasmaTimerCallbackMsgNode(PlasmaMessageNode, bpy.types.Node):
bl_category = "MSG" bl_category = "MSG"
bl_idname = "PlasmaTimerCallbackMsgNode" bl_idname = "PlasmaTimerCallbackMsgNode"

15
korman/properties/modifiers/sound.py

@ -344,6 +344,21 @@ class PlasmaSoundEmitter(PlasmaModifierProperties):
if i.sound_data and i.enabled: if i.sound_data and i.enabled:
i.convert_sound(exporter, so, winaud) i.convert_sound(exporter, so, winaud)
def get_sound_indices(self, name):
"""Returns the index of the given sound in the plWin32Sound. This is needed because stereo
3D sounds export as two mono sound objects -- wheeeeee"""
idx = 0
for i in self.sounds:
if i.name == name:
yield idx
if i.is_3d_stereo:
yield idx + 1
break
else:
idx += 2 if i.is_3d_stereo else 1
else:
raise ValueError(name)
@classmethod @classmethod
def register(cls): def register(cls):
bpy.types.Sound.plasma_owned = BoolProperty(default=False, options={"HIDDEN"}) bpy.types.Sound.plasma_owned = BoolProperty(default=False, options={"HIDDEN"})

Loading…
Cancel
Save