Add voice track support to Hollywoo
This commit is contained in:
@@ -20,7 +20,7 @@ abstract FuzzyMap<T>(StringMap<T>) from StringMap<T> to StringMap<T> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
static var threshold = 0.8;
|
static var threshold = 0.4;
|
||||||
function bestMatch(fuzzySearchKey:String, ?throwIfNone=true):String {
|
function bestMatch(fuzzySearchKey:String, ?throwIfNone=true):String {
|
||||||
if (this.exists(fuzzySearchKey)) return fuzzySearchKey;
|
if (this.exists(fuzzySearchKey)) return fuzzySearchKey;
|
||||||
|
|
||||||
|
@@ -17,4 +17,4 @@ import flixel.system.FlxSound;
|
|||||||
import flixel.util.FlxTimer;
|
import flixel.util.FlxTimer;
|
||||||
|
|
||||||
@:build(kiss.Kiss.build())
|
@:build(kiss.Kiss.build())
|
||||||
class FlxDirector implements Director<String, FlxStagePosition, FlxStageFacing, FlxScreenPosition, ActorFlxSprite, FlxSound, String, FlxSprite> {}
|
class FlxDirector implements Director<String, FlxStagePosition, FlxStageFacing, FlxScreenPosition, ActorFlxSprite, FlxSound, String, FlxSprite, FlxSound> {}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
(prop :FlxActionDigital continueAction)
|
(prop :FlxActionDigital continueAction)
|
||||||
(prop actionManager (new FlxActionManager))
|
(prop actionManager (new FlxActionManager))
|
||||||
(prop &mut :Movie<String,FlxStagePosition,FlxStageFacing,FlxScreenPosition,ActorFlxSprite,FlxSound,String,FlxSprite> movie)
|
(prop &mut :Movie<String,FlxStagePosition,FlxStageFacing,FlxScreenPosition,ActorFlxSprite,FlxSound,String,FlxSprite,FlxSound> movie)
|
||||||
|
|
||||||
(defNew []
|
(defNew []
|
||||||
(set continueAction (new FlxActionDigital "Continue" onContinue))
|
(set continueAction (new FlxActionDigital "Continue" onContinue))
|
||||||
@@ -105,17 +105,12 @@
|
|||||||
}
|
}
|
||||||
(set dialogText.y DIALOG_Y))
|
(set dialogText.y DIALOG_Y))
|
||||||
(dialogText.revive)
|
(dialogText.revive)
|
||||||
|
(startWaitForInput cc))
|
||||||
|
|
||||||
// wait for input or delay
|
(method :Void hideDialog []
|
||||||
// TODO customize the delay in a more sophisticated way to the dialog length or voice-over length,
|
(dialogText.kill)
|
||||||
// or rely on FlxTypeText to add breathing room
|
(speakerNameText.kill)
|
||||||
(movie.delay (+ 5 (* 0.5 .length (text.split " ")))
|
(dialogBox.kill))
|
||||||
->{
|
|
||||||
(dialogText.kill)
|
|
||||||
(speakerNameText.kill)
|
|
||||||
(dialogBox.kill)
|
|
||||||
(cc)
|
|
||||||
}))
|
|
||||||
|
|
||||||
(method :Void playSound [:FlxSound sound :Float volumeMod :Bool waitForEnd :Continuation cc]
|
(method :Void playSound [:FlxSound sound :Float volumeMod :Bool waitForEnd :Continuation cc]
|
||||||
(let [originalVolume sound.volume
|
(let [originalVolume sound.volume
|
||||||
@@ -128,6 +123,13 @@
|
|||||||
(sound.play)
|
(sound.play)
|
||||||
(unless waitForEnd (cc)))
|
(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 &mut :FlxSound music)
|
||||||
(prop MUSIC_FADE_SEC 1)
|
(prop MUSIC_FADE_SEC 1)
|
||||||
(prop MUSIC_FADE_STEPS 10)
|
(prop MUSIC_FADE_STEPS 10)
|
||||||
|
@@ -31,4 +31,4 @@ enum FlxScreenPosition {
|
|||||||
/**
|
/**
|
||||||
* Model/controller of a Hollywoo-Flixel film, and main execution script
|
* Model/controller of a Hollywoo-Flixel film, and main execution script
|
||||||
*/
|
*/
|
||||||
class FlxMovie extends Movie<String, FlxStagePosition, FlxStageFacing, FlxScreenPosition, ActorFlxSprite, FlxSound, String, FlxSprite> {}
|
class FlxMovie extends Movie<String, FlxStagePosition, FlxStageFacing, FlxScreenPosition, ActorFlxSprite, FlxSound, String, FlxSprite, FlxSound> {}
|
||||||
|
@@ -9,17 +9,19 @@ enum Appearance {
|
|||||||
|
|
||||||
typedef Continuation = Void -> Void;
|
typedef Continuation = Void -> Void;
|
||||||
|
|
||||||
interface Director<Set, StagePosition, StageFacing, ScreenPosition, Actor, Sound, Song, Prop> {
|
interface Director<Set, StagePosition, StageFacing, ScreenPosition, Actor, Sound, Song, Prop, VoiceTrack> {
|
||||||
var movie(default, default):Movie<Set, StagePosition, StageFacing, ScreenPosition, Actor, Sound, Song, Prop>;
|
var movie(default, default):Movie<Set, StagePosition, StageFacing, ScreenPosition, Actor, Sound, Song, Prop, VoiceTrack>;
|
||||||
function showScene(scene:Scene<Set, StagePosition, StageFacing, ScreenPosition, Actor, Prop>, appearance:Appearance, cc:Continuation):Void;
|
function showScene(scene:Scene<Set, StagePosition, StageFacing, ScreenPosition, Actor, Prop>, appearance:Appearance, cc:Continuation):Void;
|
||||||
function showCharacter(character:Character<StagePosition, StageFacing, Actor>, appearance:Appearance, cc:Continuation):Void;
|
function showCharacter(character:Character<StagePosition, StageFacing, Actor>, appearance:Appearance, cc:Continuation):Void;
|
||||||
function hideCharacter(character:Character<StagePosition, StageFacing, Actor>, cc:Continuation):Void;
|
function hideCharacter(character:Character<StagePosition, StageFacing, Actor>, cc:Continuation):Void;
|
||||||
function playSound(sound:Sound, volumeMod:Float, waitForEnd:Bool, 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 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 stopSong():Void;
|
||||||
function startWaitForInput(cc:Continuation):Void;
|
function startWaitForInput(cc:Continuation):Void;
|
||||||
function stopWaitForInput():Void;
|
function stopWaitForInput():Void;
|
||||||
function showDialog(speakerName:String, type:SpeechType<StagePosition, StageFacing, Actor>, wryly:String, dialog:String, cc:Continuation):Void;
|
function showDialog(speakerName:String, type:SpeechType<StagePosition, StageFacing, Actor>, wryly:String, dialog:String, cc:Continuation):Void;
|
||||||
|
function hideDialog():Void;
|
||||||
function showPropOnScreen(prop:Prop, position:ScreenPosition, cc:Continuation):Void;
|
function showPropOnScreen(prop:Prop, position:ScreenPosition, cc:Continuation):Void;
|
||||||
// TODO showPropOnStage
|
// TODO showPropOnStage
|
||||||
function hideProp(prop:Prop, cc:Continuation):Void;
|
function hideProp(prop:Prop, cc:Continuation):Void;
|
||||||
|
@@ -7,6 +7,8 @@ import kiss.Prelude;
|
|||||||
import kiss.FuzzyMap;
|
import kiss.FuzzyMap;
|
||||||
import hollywoo.Scene;
|
import hollywoo.Scene;
|
||||||
import hollywoo.Director;
|
import hollywoo.Director;
|
||||||
|
import haxe.Json;
|
||||||
|
import uuid.Uuid;
|
||||||
|
|
||||||
enum DelayHandling {
|
enum DelayHandling {
|
||||||
Auto;
|
Auto;
|
||||||
@@ -14,11 +16,17 @@ enum DelayHandling {
|
|||||||
Manual;
|
Manual;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef VoiceLine = {
|
||||||
|
trackKey:String,
|
||||||
|
start:Float,
|
||||||
|
end:Float
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model/controller of a Hollywoo film, and main execution script
|
* Model/controller of a Hollywoo film, and main execution script
|
||||||
*/
|
*/
|
||||||
@:build(kiss.Kiss.build())
|
@:build(kiss.Kiss.build())
|
||||||
class Movie<Set, StagePosition, StageFacing, ScreenPosition, Actor, Sound, Song, Prop> extends AsyncEmbeddedScript {
|
class Movie<Set, StagePosition, StageFacing, ScreenPosition, Actor, Sound, Song, Prop, VoiceTrack> extends AsyncEmbeddedScript {
|
||||||
// TODO for some reason this wasn't working when declared in Movie.kiss:
|
// TODO for some reason this wasn't working when declared in Movie.kiss:
|
||||||
// Mutable representation of frames in time:
|
// Mutable representation of frames in time:
|
||||||
var scenes:FuzzyMap<Scene<Set, StagePosition, StageFacing, ScreenPosition, Actor, Prop>> = new FuzzyMap<Scene<Set, StagePosition, StageFacing, ScreenPosition, Actor, Prop>>();
|
var scenes:FuzzyMap<Scene<Set, StagePosition, StageFacing, ScreenPosition, Actor, Prop>> = new FuzzyMap<Scene<Set, StagePosition, StageFacing, ScreenPosition, Actor, Prop>>();
|
||||||
|
@@ -7,6 +7,8 @@
|
|||||||
(prop :FuzzyMap<Sound> sounds (new FuzzyMap<Sound>))
|
(prop :FuzzyMap<Sound> sounds (new FuzzyMap<Sound>))
|
||||||
(prop :FuzzyMap<Song> songs (new FuzzyMap<Song>))
|
(prop :FuzzyMap<Song> songs (new FuzzyMap<Song>))
|
||||||
(prop :FuzzyMap<Prop> props (new FuzzyMap<Prop>))
|
(prop :FuzzyMap<Prop> props (new FuzzyMap<Prop>))
|
||||||
|
(prop :Map<String,VoiceTrack> voiceTracks (new Map))
|
||||||
|
(prop :FuzzyMap<VoiceLine> voiceLines (new FuzzyMap<VoiceLine>))
|
||||||
|
|
||||||
(prop &mut :DelayHandling delayHandling AutoWithSkip)
|
(prop &mut :DelayHandling delayHandling AutoWithSkip)
|
||||||
|
|
||||||
@@ -32,16 +34,30 @@
|
|||||||
(method _currentScene [] (dictGet scenes sceneKey))
|
(method _currentScene [] (dictGet scenes sceneKey))
|
||||||
|
|
||||||
(prop &mut :Map<String,String> intercutMap)
|
(prop &mut :Map<String,String> intercutMap)
|
||||||
(method showDialog [actorName dialogType wryly text cc]
|
(method :Void showDialog [actorName dialogType wryly text cc]
|
||||||
(when intercutMap
|
(when intercutMap
|
||||||
(whenLet [sceneForActor (dictGet intercutMap actorName)]
|
(whenLet [sceneForActor (dictGet intercutMap actorName)]
|
||||||
(setScene sceneForActor ->{})))
|
(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<Dynamic> 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
|
(defNew
|
||||||
[
|
[
|
||||||
// "View" in the Model-View-Controller architecture:
|
// "View" in the Model-View-Controller architecture:
|
||||||
&prop :Director<Set,StagePosition,StageFacing,ScreenPosition,Actor,Sound,Song,Prop> director
|
&prop :Director<Set,StagePosition,StageFacing,ScreenPosition,Actor,Sound,Song,Prop,VoiceTrack> director
|
||||||
]
|
]
|
||||||
|
|
||||||
(set director.movie this)
|
(set director.movie this)
|
||||||
|
Reference in New Issue
Block a user