diff --git a/kiss/src/kiss/FuzzyMap.hx b/kiss/src/kiss/FuzzyMap.hx index e4216e7c..b22c2259 100644 --- a/kiss/src/kiss/FuzzyMap.hx +++ b/kiss/src/kiss/FuzzyMap.hx @@ -20,7 +20,7 @@ abstract FuzzyMap(StringMap) from StringMap to StringMap { return this; } - static var threshold = 0.8; + static var threshold = 0.4; function bestMatch(fuzzySearchKey:String, ?throwIfNone=true):String { if (this.exists(fuzzySearchKey)) return fuzzySearchKey; diff --git a/projects/hollywoo-flixel/src/hollywoo_flixel/FlxDirector.hx b/projects/hollywoo-flixel/src/hollywoo_flixel/FlxDirector.hx index e6e71394..d9701034 100644 --- a/projects/hollywoo-flixel/src/hollywoo_flixel/FlxDirector.hx +++ b/projects/hollywoo-flixel/src/hollywoo_flixel/FlxDirector.hx @@ -17,4 +17,4 @@ import flixel.system.FlxSound; import flixel.util.FlxTimer; @:build(kiss.Kiss.build()) -class FlxDirector implements Director {} +class FlxDirector implements Director {} diff --git a/projects/hollywoo-flixel/src/hollywoo_flixel/FlxDirector.kiss b/projects/hollywoo-flixel/src/hollywoo_flixel/FlxDirector.kiss index 19273055..ee4c200c 100644 --- a/projects/hollywoo-flixel/src/hollywoo_flixel/FlxDirector.kiss +++ b/projects/hollywoo-flixel/src/hollywoo_flixel/FlxDirector.kiss @@ -1,6 +1,6 @@ (prop :FlxActionDigital continueAction) (prop actionManager (new FlxActionManager)) -(prop &mut :Movie movie) +(prop &mut :Movie movie) (defNew [] (set continueAction (new FlxActionDigital "Continue" onContinue)) @@ -105,17 +105,12 @@ } (set dialogText.y DIALOG_Y)) (dialogText.revive) + (startWaitForInput cc)) - // wait for input or delay - // TODO customize the delay in a more sophisticated way to the dialog length or voice-over length, - // or rely on FlxTypeText to add breathing room - (movie.delay (+ 5 (* 0.5 .length (text.split " "))) - ->{ - (dialogText.kill) - (speakerNameText.kill) - (dialogBox.kill) - (cc) - })) +(method :Void hideDialog [] + (dialogText.kill) + (speakerNameText.kill) + (dialogBox.kill)) (method :Void playSound [:FlxSound sound :Float volumeMod :Bool waitForEnd :Continuation cc] (let [originalVolume sound.volume @@ -128,6 +123,13 @@ (sound.play) (unless waitForEnd (cc))) +(method :Void playVoiceTrack [:FlxSound track :Float volumeMod :Float start :Float end :Continuation cc] + (let [originalVolume track.volume + restoreOriginalVolume ->(set track.volume originalVolume)] + (*= track.volume volumeMod) + (set track.onComplete ->{(restoreOriginalVolume) (cc)})) + (track.play false (* 1000 start) (* 1000 end))) + (prop &mut :FlxSound music) (prop MUSIC_FADE_SEC 1) (prop MUSIC_FADE_STEPS 10) diff --git a/projects/hollywoo-flixel/src/hollywoo_flixel/FlxMovie.hx b/projects/hollywoo-flixel/src/hollywoo_flixel/FlxMovie.hx index 341cbfcd..fe44d711 100644 --- a/projects/hollywoo-flixel/src/hollywoo_flixel/FlxMovie.hx +++ b/projects/hollywoo-flixel/src/hollywoo_flixel/FlxMovie.hx @@ -31,4 +31,4 @@ enum FlxScreenPosition { /** * Model/controller of a Hollywoo-Flixel film, and main execution script */ -class FlxMovie extends Movie {} +class FlxMovie extends Movie {} diff --git a/projects/hollywoo/src/hollywoo/Director.hx b/projects/hollywoo/src/hollywoo/Director.hx index 972068a6..a756c5a7 100644 --- a/projects/hollywoo/src/hollywoo/Director.hx +++ b/projects/hollywoo/src/hollywoo/Director.hx @@ -9,17 +9,19 @@ enum Appearance { typedef Continuation = Void -> Void; -interface Director { - var movie(default, default):Movie; +interface Director { + var movie(default, default):Movie; function showScene(scene:Scene, appearance:Appearance, cc:Continuation):Void; function showCharacter(character:Character, appearance:Appearance, cc:Continuation):Void; function hideCharacter(character:Character, cc:Continuation):Void; function playSound(sound:Sound, volumeMod:Float, waitForEnd:Bool, cc:Continuation):Void; function playSong(song:Song, volumeMod:Float, loop:Bool, waitForEnd:Bool, cc:Continuation):Void; + function playVoiceTrack(track:VoiceTrack, volumeMod:Float, start:Float, end:Float, cc:Continuation):Void; function stopSong():Void; function startWaitForInput(cc:Continuation):Void; function stopWaitForInput():Void; function showDialog(speakerName:String, type:SpeechType, wryly:String, dialog:String, cc:Continuation):Void; + function hideDialog():Void; function showPropOnScreen(prop:Prop, position:ScreenPosition, cc:Continuation):Void; // TODO showPropOnStage function hideProp(prop:Prop, cc:Continuation):Void; diff --git a/projects/hollywoo/src/hollywoo/Movie.hx b/projects/hollywoo/src/hollywoo/Movie.hx index 32a1e553..67173fbb 100644 --- a/projects/hollywoo/src/hollywoo/Movie.hx +++ b/projects/hollywoo/src/hollywoo/Movie.hx @@ -7,6 +7,8 @@ import kiss.Prelude; import kiss.FuzzyMap; import hollywoo.Scene; import hollywoo.Director; +import haxe.Json; +import uuid.Uuid; enum DelayHandling { Auto; @@ -14,11 +16,17 @@ enum DelayHandling { Manual; } +typedef VoiceLine = { + trackKey:String, + start:Float, + end:Float +}; + /** * Model/controller of a Hollywoo film, and main execution script */ @:build(kiss.Kiss.build()) -class Movie extends AsyncEmbeddedScript { +class Movie extends AsyncEmbeddedScript { // TODO for some reason this wasn't working when declared in Movie.kiss: // Mutable representation of frames in time: var scenes:FuzzyMap> = new FuzzyMap>(); diff --git a/projects/hollywoo/src/hollywoo/Movie.kiss b/projects/hollywoo/src/hollywoo/Movie.kiss index 8eebbd51..b4c2d5df 100644 --- a/projects/hollywoo/src/hollywoo/Movie.kiss +++ b/projects/hollywoo/src/hollywoo/Movie.kiss @@ -7,6 +7,8 @@ (prop :FuzzyMap sounds (new FuzzyMap)) (prop :FuzzyMap songs (new FuzzyMap)) (prop :FuzzyMap props (new FuzzyMap)) + (prop :Map voiceTracks (new Map)) + (prop :FuzzyMap voiceLines (new FuzzyMap)) (prop &mut :DelayHandling delayHandling AutoWithSkip) @@ -32,16 +34,30 @@ (method _currentScene [] (dictGet scenes sceneKey)) (prop &mut :Map intercutMap) - (method showDialog [actorName dialogType wryly text cc] + (method :Void showDialog [actorName dialogType wryly text cc] (when intercutMap (whenLet [sceneForActor (dictGet intercutMap actorName)] (setScene sceneForActor ->{}))) - (director.showDialog actorName dialogType wryly text cc)) + + (let [cc ->:Void {(director.hideDialog) (cc)}] + (director.showDialog actorName dialogType wryly text cc) + (when (< 0 (count voiceTracks)) + (case (try (dictGet voiceLines "$actorName $text") (catch [e] (print e) null)) + ((objectWith trackKey start end) + (director.playVoiceTrack (dictGet voiceTracks trackKey) 1 start end cc)) + (otherwise))))) + + (method newVoiceTrack [actorName :VoiceTrack track :String lineJson] + (let [trackKey (Uuid.v4) + :haxe.DynamicAccess lines (Json.parse lineJson)] + (dictSet voiceTracks trackKey track) + (doFor =>key line (lines.keyValueIterator) + (dictSet voiceLines "$actorName $key" (objectWith [start line.start end line.end] trackKey))))) (defNew [ // "View" in the Model-View-Controller architecture: - &prop :Director director + &prop :Director director ] (set director.movie this)