From e2d18c898abb89cd139ce1f5ed6f23738fa30349 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 26 Jun 2016 20:51:37 -0400 Subject: [PATCH] Implement sound volume animations --- korman/exporter/animation.py | 27 ++++++++++++++++++++ korman/properties/modifiers/sound.py | 37 +++++++++++++++++++--------- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/korman/exporter/animation.py b/korman/exporter/animation.py index d902a4b..f87f214 100644 --- a/korman/exporter/animation.py +++ b/korman/exporter/animation.py @@ -47,6 +47,8 @@ class AnimationConverter: # things that aren't the typical position, rotation, scale animations. applicators = [] applicators.append(self._convert_transform_animation(bo.name, fcurves, bo.matrix_basis)) + if bo.plasma_modifiers.soundemit.enabled: + applicators.extend(self._convert_sound_volume_animation(bo.name, fcurves, bo.plasma_modifiers.soundemit)) # Check to make sure we have some valid animation applicators before proceeding. if not any(applicators): @@ -83,6 +85,31 @@ class AnimationConverter: atcanim.easeOutMax = 1.0 atcanim.easeOutLength = 1.0 + def _convert_sound_volume_animation(self, name, fcurves, soundemit): + def convert_volume(value): + if value == 0.0: + return 0.0 + else: + return math.log10(value) * 20.0 + + for sound in soundemit.sounds: + path = "{}.volume".format(sound.path_from_id()) + fcurve = next((i for i in fcurves if i.data_path == path and i.keyframe_points), None) + if fcurve is None: + continue + + for i in soundemit.get_sound_indices(sound=sound): + applicator = plSoundVolumeApplicator() + applicator.channelName = name + applicator.index = i + + # libHSPlasma assumes a channel is not shared among applicators... + # so yes, we must convert the same animation data again and again. + channel = plScalarControllerChannel() + channel.controller = self.make_scalar_leaf_controller(fcurve, convert=convert_volume) + applicator.channel = channel + yield applicator + def _convert_transform_animation(self, name, fcurves, xform): pos = self.make_pos_controller(fcurves, xform) rot = self.make_rot_controller(fcurves, xform) diff --git a/korman/properties/modifiers/sound.py b/korman/properties/modifiers/sound.py index a641141..4ed90cf 100644 --- a/korman/properties/modifiers/sound.py +++ b/korman/properties/modifiers/sound.py @@ -131,7 +131,7 @@ class PlasmaSound(bpy.types.PropertyGroup): volume = IntProperty(name="Volume", description="Volume to play the sound", min=0, max=100, default=100, - options=set(), + options={"ANIMATABLE"}, subtype="PERCENTAGE") fade_in = PointerProperty(type=PlasmaSfxFade, options=set()) @@ -344,20 +344,35 @@ class PlasmaSoundEmitter(PlasmaModifierProperties): if i.sound_data and i.enabled: i.convert_sound(exporter, so, winaud) - def get_sound_indices(self, name): + def get_sound_indices(self, name=None, sound=None): """Returns the index of the given sound in the plWin32Sound. This is needed because stereo 3D sounds export as two mono sound objects -- wheeeeee""" + assert name or sound idx = 0 - for i in self.sounds: - if i.name == name: - yield idx - if i.is_3d_stereo: - yield idx + 1 - break + + if name is None: + for i in self.sounds: + if i == sound: + yield idx + if i.is_3d_stereo: + yield idx + 1 + break + else: + idx += 2 if i.is_3d_stereo else 1 else: - idx += 2 if i.is_3d_stereo else 1 - else: - raise ValueError(name) + raise LookupError(sound) + + if sound is None: + 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 def register(cls):