Overhaul hollywoo & hollywoo-flixel. Close #178
This commit is contained in:
@@ -2,6 +2,7 @@ package hollywoo;
|
||||
|
||||
import hollywoo.Scene;
|
||||
import hollywoo.Movie;
|
||||
import haxe.ds.Option;
|
||||
|
||||
enum Appearance {
|
||||
FirstAppearance;
|
||||
@@ -10,13 +11,31 @@ enum Appearance {
|
||||
|
||||
typedef Continuation = Void -> Void;
|
||||
|
||||
interface Director<Set, StagePosition, StageFacing, ScreenPosition, Actor, Sound, Song, Prop, VoiceTrack> {
|
||||
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 showCharacter(character:Character<StagePosition, StageFacing, Actor>, appearance:Appearance, cc:Continuation):Void;
|
||||
function hideCharacter(character:Character<StagePosition, StageFacing, Actor>, cc:Continuation):Void;
|
||||
function moveCharacter(character:Character<StagePosition, StageFacing, Actor>, toPos:StagePosition, toFacing:StageFacing, cc:Continuation):Void;
|
||||
function swapCharacters(a:Character<StagePosition, StageFacing, Actor>, b:Character<StagePosition, StageFacing, Actor>, cc:Continuation):Void;
|
||||
typedef StagePosition = {
|
||||
x:Float,
|
||||
y:Float,
|
||||
z:Float,
|
||||
};
|
||||
|
||||
enum StageFacing {
|
||||
TowardsCharacter(name:String);
|
||||
AwayFromCharacter(name:String);
|
||||
TowardsPosition(name:String);
|
||||
AwayFromPosition(name:String);
|
||||
}
|
||||
|
||||
typedef AutoZConfig = {
|
||||
zPerLayer:Float,
|
||||
frontLayer:Int
|
||||
};
|
||||
|
||||
interface Director<Set:Cloneable<Set>, ScreenPosition, Actor, Sound, Song, Prop, VoiceTrack> {
|
||||
var movie(default, default):Movie<Set, ScreenPosition, Actor, Sound, Song, Prop, VoiceTrack>;
|
||||
var autoZConfig(default,null):Option<AutoZConfig>;
|
||||
function showSet(set:Set, time:SceneTime, perspective:ScenePerspective, appearance:Appearance, cc:Continuation):Void;
|
||||
function hideSet(set:Set, cc:Continuation):Void;
|
||||
function showCharacter(character:Character<Actor>, appearance:Appearance, cc:Continuation):Void;
|
||||
function hideCharacter(character:Character<Actor>, cc:Continuation):Void;
|
||||
function playSound(sound:Sound, volumeMod:Float, waitForEnd:Bool, cc:Continuation):Void;
|
||||
function stopSound(sound:Sound):Void;
|
||||
function playSong(song:Song, volumeMod:Float, loop:Bool, waitForEnd:Bool, cc:Continuation):Void;
|
||||
@@ -25,7 +44,7 @@ interface Director<Set, StagePosition, StageFacing, ScreenPosition, Actor, Sound
|
||||
function stopVoiceTrack(track:VoiceTrack):Void;
|
||||
function startWaitForInput(cc:Continuation):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<Actor>, wryly:String, dialog:String, cc:Continuation):Void;
|
||||
function hideDialog():Void;
|
||||
function showTitleCard(text:Array<String>, cc:Continuation):Void;
|
||||
function hideTitleCard():Void;
|
||||
|
@@ -1,3 +1,34 @@
|
||||
(defMacro withProp [propKey name &body body]
|
||||
`(let [,name (dictGet props ,propKey)]
|
||||
,@body
|
||||
(cc)))
|
||||
|
||||
// like withProp, but you promise to call CC yourself in the body:
|
||||
(defMacro withPropCC [propKey name &body body]
|
||||
`(let [,name (dictGet props ,propKey)]
|
||||
,@body))
|
||||
|
||||
(defMacro withActor [actorKey name &body body]
|
||||
`(let [,name (dictGet actors ,actorKey)]
|
||||
,@body
|
||||
(cc)))
|
||||
|
||||
// like withActor, but you promise to call CC yourself in the body:
|
||||
(defMacro withActorCC [actorKey name &body body]
|
||||
`(let [,name (dictGet actors ,actorKey)]
|
||||
,@body))
|
||||
|
||||
// Do something with the given scene's instance of its set
|
||||
(defMacro withSceneSet [sceneKey name &body body]
|
||||
`(let [,name .set (dictGet scenes ,sceneKey)]
|
||||
,@body
|
||||
(cc)))
|
||||
|
||||
// like withSceneSet, but you promise to call CC yourself in the body:
|
||||
(defMacro withSceneSetCC [sceneKey name &body body]
|
||||
`(let [,name .set (dictGet scenes ,sceneKey)]
|
||||
,@body))
|
||||
|
||||
// When this file is loaded, all expressions in (preload <...>) will be collected. When (end) is called, they will
|
||||
// be injected into a method called (doPreload).
|
||||
// This allows assets to be declared in Hollywoo files where they first appear, but still loaded before execution starts.
|
||||
|
@@ -13,6 +13,10 @@ import uuid.Uuid;
|
||||
|
||||
using kiss.FuzzyMapTools;
|
||||
|
||||
typedef Cloneable<T> = {
|
||||
function clone():T;
|
||||
}
|
||||
|
||||
enum DelayHandling {
|
||||
Auto;
|
||||
AutoWithSkip;
|
||||
@@ -37,8 +41,4 @@ enum CreditsLine {
|
||||
* Model/controller of a Hollywoo film, and main execution script
|
||||
*/
|
||||
@:build(kiss.Kiss.build())
|
||||
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:
|
||||
// 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>>();
|
||||
}
|
||||
class Movie<Set:Cloneable<Set>, ScreenPosition, Actor, Sound, Song, Prop, VoiceTrack> extends AsyncEmbeddedScript {}
|
||||
|
@@ -1,3 +1,6 @@
|
||||
(defMacro makeCC [&body b]
|
||||
`->:Void {,@b})
|
||||
|
||||
// This file is designed to be loaded again by subclasses, with macroVar "subclass" set
|
||||
(#unless subclass
|
||||
|
||||
@@ -14,9 +17,8 @@
|
||||
|
||||
(prop &mut :DelayHandling delayHandling AutoWithSkip)
|
||||
|
||||
// TODO for some reason this won't work when declared in Kiss syntax:
|
||||
// Mutable representation of frames in time:
|
||||
// var scenes:Map<String, Scene<Set, StagePosition, StageFacing, ScreenPosition, Actor>> = [];
|
||||
(prop :FuzzyMap<Scene<Set,ScreenPosition,Actor,Prop>> scenes (new FuzzyMap<Scene<Set,ScreenPosition,Actor,Prop>>))
|
||||
|
||||
(prop :FuzzyMap<Bool> shownScenes (new FuzzyMap<Bool>))
|
||||
(prop :FuzzyMap<Bool> shownCharacters (new FuzzyMap<Bool>))
|
||||
@@ -40,7 +42,8 @@
|
||||
(method :Void showDialog [actorName dialogType wryly text cc]
|
||||
(when intercutMap
|
||||
(whenLet [sceneForActor (try (dictGet intercutMap actorName) (catch [e] null))]
|
||||
(setScene sceneForActor ->{})))
|
||||
(unless (= sceneForActor sceneKey)
|
||||
(setScene sceneForActor ->{}))))
|
||||
|
||||
(let [cc ->:Void {(director.hideDialog) (cc)}
|
||||
&mut skipCC cc]
|
||||
@@ -83,11 +86,66 @@
|
||||
[])]
|
||||
(dictSet voiceLines "$actorName $key" (objectWith [start line.start end line.end] trackKey alts))))))
|
||||
|
||||
(method _ccForEach <>[T] [:Iterable<T> collection :(T,Continuation)->Void do_ :Continuation finalCC]
|
||||
(let [:Iterator<T> iter (collection.iterator)]
|
||||
(withFunctions
|
||||
[
|
||||
(:Void doNext []
|
||||
(if (iter.hasNext)
|
||||
(do_ (iter.next) doNext)
|
||||
(finalCC)))
|
||||
]
|
||||
(doNext))))
|
||||
|
||||
(method _hideCurrentScene [:Continuation cc]
|
||||
(if sceneKey
|
||||
// hide current scene background
|
||||
(let [currentScene (dictGet scenes sceneKey)]
|
||||
(director.hideSet currentScene.set
|
||||
(makeCC
|
||||
// hide current scene characters
|
||||
(_ccForEach
|
||||
currentScene.characters
|
||||
->[:Character<Actor> c :Continuation cc]
|
||||
(director.hideCharacter c cc)
|
||||
(makeCC
|
||||
// hide current scene props, etc.
|
||||
(_ccForEach
|
||||
currentScene.propsOnScreen
|
||||
->[:ScreenProp<ScreenPosition,Prop> p :Continuation cc]
|
||||
(director.hideProp p.prop cc)
|
||||
cc))))))
|
||||
(cc)))
|
||||
|
||||
(method _showScene [:Scene<Set,ScreenPosition,Actor,Prop> scene :Appearance appearance :Continuation cc]
|
||||
// Show current scene background
|
||||
(director.showSet scene.set scene.time scene.perspective appearance
|
||||
(makeCC
|
||||
// Show current scene characters
|
||||
(_ccForEach
|
||||
(object iterator ->(scene.characters.keys))
|
||||
->[:String key :Continuation cc]
|
||||
(director.showCharacter (dictGet scene.characters key) (appearanceFlag shownCharacters key) cc)
|
||||
(makeCC
|
||||
// hide current scene props, etc.
|
||||
(_ccForEach
|
||||
scene.propsOnScreen
|
||||
->[:ScreenProp<ScreenPosition,Prop> p :Continuation cc]
|
||||
(director.showPropOnScreen p.prop p.screenPosition cc)
|
||||
cc))))))
|
||||
|
||||
(defNew
|
||||
[
|
||||
// "View" in the Model-View-Controller architecture:
|
||||
&prop :Director<Set,StagePosition,StageFacing,ScreenPosition,Actor,Sound,Song,Prop,VoiceTrack> director
|
||||
&prop :Director<Set,ScreenPosition,Actor,Sound,Song,Prop,VoiceTrack> director
|
||||
&opt :String voiceLinesJson
|
||||
&opt :String positionsJson
|
||||
]
|
||||
[
|
||||
:Map<String,StagePosition> stagePositions
|
||||
(if positionsJson
|
||||
(haxe.Json.parse (sys.io.File.getContent positionsJson))
|
||||
(new Map))
|
||||
]
|
||||
|
||||
(set director.movie this)
|
||||
@@ -99,7 +157,7 @@
|
||||
|
||||
// Some real magic happens here. This macro defines a method, AND a reader macro
|
||||
// for calling it with cc passed automatically if cc is an argument.
|
||||
|
||||
// GOTCHA: DO NOT use (method) directly in this file!!
|
||||
(defMacro hollywooMethod [nameAndType canSkip argList &builder b &body body]
|
||||
(let [args (expList argList)
|
||||
numArgs args.length
|
||||
@@ -162,25 +220,24 @@
|
||||
(dictSet scenes name (objectWith
|
||||
[
|
||||
set
|
||||
(dictGet sets setKey)
|
||||
(.clone (dictGet sets setKey))
|
||||
characters
|
||||
(new FuzzyMap<Character<StagePosition,StageFacing,Actor>>)
|
||||
(new FuzzyMap<Character<Actor>>)
|
||||
propsOnScreen
|
||||
(new FuzzyMap<Prop>)
|
||||
(new FuzzyMap<ScreenProp<ScreenPosition,Prop>>)
|
||||
]
|
||||
time
|
||||
perspective)))
|
||||
|
||||
(hollywooMethod newScene true [name :Scene<Set,StagePosition,StageFacing,ScreenPosition,Actor,Prop> scene]
|
||||
(assert isLoading)
|
||||
(dictSet scenes name scene))
|
||||
|
||||
(hollywooMethod setScene false [name :Continuation cc]
|
||||
(set sceneKey name)
|
||||
(director.showScene
|
||||
(dictGet scenes name)
|
||||
(appearanceFlag shownScenes name)
|
||||
cc))
|
||||
(_hideCurrentScene
|
||||
(makeCC
|
||||
(set sceneKey name)
|
||||
(_showScene
|
||||
(dictGet scenes name)
|
||||
(appearanceFlag shownScenes name)
|
||||
cc))))
|
||||
|
||||
|
||||
(hollywooMethod newSound true [name :Sound s]
|
||||
(assert isLoading)
|
||||
@@ -221,38 +278,62 @@
|
||||
(assert isLoading)
|
||||
(dictSet actors name actor))
|
||||
|
||||
(hollywooMethod addCharacter false [actorName :StagePosition position :StageFacing facing :Continuation cc]
|
||||
(let [character (object stagePosition position stageFacing facing actor (dictGet actors actorName))]
|
||||
(dictSet .characters (_currentScene) actorName character)
|
||||
(director.showCharacter
|
||||
character
|
||||
(appearanceFlag shownCharacters actorName)
|
||||
cc)))
|
||||
(hollywooMethod autoZProcess false [:StagePosition position :Continuation cc]
|
||||
// handle auto z recursively
|
||||
(ifLet [(Some (objectWith zPerLayer frontLayer)) director.autoZConfig]
|
||||
{
|
||||
(doFor =>name otherCharacter .characters (_currentScene)
|
||||
(when (and (= position.x otherCharacter.stagePosition.x) (= position.y otherCharacter.stagePosition.y) (= position.z otherCharacter.stagePosition.z))
|
||||
(moveCharacter name (object x position.x y position.y z (+ otherCharacter.stagePosition.z zPerLayer)) otherCharacter.stageFacing cc)
|
||||
(return)))
|
||||
(cc)
|
||||
}
|
||||
(cc)))
|
||||
|
||||
(hollywooMethod addCharacter false [actorName :Dynamic position :StageFacing facing :Continuation cc]
|
||||
(let [position (typeCase [position]
|
||||
([:String pKey] (dictGet stagePositions pKey))
|
||||
(otherwise position))
|
||||
character (object stagePosition position stageFacing facing actor (dictGet actors actorName))]
|
||||
(autoZProcess position
|
||||
(makeCC
|
||||
(dictSet .characters (_currentScene) actorName character)
|
||||
(director.showCharacter
|
||||
character
|
||||
(appearanceFlag shownCharacters actorName)
|
||||
cc)))))
|
||||
|
||||
(hollywooMethod removeCharacter false [actorName :Continuation cc]
|
||||
(let [c (dictGet .characters (_currentScene) actorName)]
|
||||
(.remove .characters (_currentScene) actorName)
|
||||
(director.hideCharacter c cc)))
|
||||
|
||||
(hollywooMethod moveCharacter false [actorName :StagePosition newPosition :StageFacing newFacing :Continuation cc]
|
||||
(let [c (dictGet .characters (_currentScene) actorName)]
|
||||
(director.moveCharacter c newPosition newFacing ->:Void {
|
||||
(set c.stagePosition newPosition)
|
||||
(set c.stageFacing newFacing)
|
||||
(cc)
|
||||
})))
|
||||
// INSTANTLY move a character:
|
||||
(hollywooMethod moveCharacter false [actorName :Dynamic newPosition :StageFacing newFacing :Continuation cc]
|
||||
(let [newPosition (typeCase [newPosition]
|
||||
([:String pKey] (dictGet stagePositions pKey))
|
||||
(otherwise newPosition))]
|
||||
(removeCharacter actorName
|
||||
(makeCC
|
||||
(addCharacter actorName newPosition newFacing cc)))))
|
||||
|
||||
// INSTANTLY swap characters
|
||||
(hollywooMethod swapCharacters false [actorNameA actorNameB :Continuation cc]
|
||||
// remove both, then re-add both, so they don't trigger
|
||||
// cascading auto z adjustments on top of each other:
|
||||
(let [a (dictGet .characters (_currentScene) actorNameA)
|
||||
b (dictGet .characters (_currentScene) actorNameB)]
|
||||
(director.swapCharacters a b ->:Void
|
||||
(let [tempStagePos a.stagePosition
|
||||
tempStageFacing a.stageFacing]
|
||||
(set a.stagePosition b.stagePosition)
|
||||
(set a.stageFacing b.stageFacing)
|
||||
(set b.stagePosition tempStagePos)
|
||||
(set b.stageFacing tempStageFacing)
|
||||
(cc)))))
|
||||
asp a.stagePosition
|
||||
asf a.stageFacing
|
||||
b (dictGet .characters (_currentScene) actorNameB)
|
||||
bsp b.stagePosition
|
||||
bsf b.stageFacing]
|
||||
(removeCharacter actorNameA
|
||||
(makeCC
|
||||
(removeCharacter actorNameB
|
||||
(makeCC
|
||||
(addCharacter actorNameA bsp bsf
|
||||
(makeCC
|
||||
(addCharacter actorNameB asp asf cc)))))))))
|
||||
|
||||
// TODO moveCharacter remove them, add them to another scene
|
||||
// TODO moveCharacterAndFollow remove them, add them to another scene, set that the scene
|
||||
@@ -262,10 +343,13 @@
|
||||
(dictSet props name prop))
|
||||
|
||||
(hollywooMethod addPropToScreen false [name :ScreenPosition position :Continuation cc]
|
||||
(dictSet .propsOnScreen (_currentScene) name (dictGet props name))
|
||||
(director.showPropOnScreen (dictGet props name) position cc))
|
||||
(let [prop (dictGet props name)]
|
||||
(dictSet .propsOnScreen (_currentScene) name (object screenPosition position prop prop))
|
||||
(director.showPropOnScreen prop position cc)))
|
||||
|
||||
(hollywooMethod removeProp false [name :Continuation cc]
|
||||
(.remove .propsOnScreen (_currentScene) name)
|
||||
// TODO (propsOnStage.remove name)
|
||||
(director.hideProp (dictGet props name) cc))
|
||||
|
||||
// Dialogue:
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package hollywoo;
|
||||
|
||||
import kiss.FuzzyMap;
|
||||
import hollywoo.Director;
|
||||
import hollywoo.Movie;
|
||||
|
||||
enum SceneTime {
|
||||
Morning;
|
||||
@@ -15,26 +17,31 @@ enum ScenePerspective {
|
||||
Mixed;
|
||||
}
|
||||
|
||||
typedef Character<StagePosition, StageFacing, Actor> = {
|
||||
typedef Character<Actor> = {
|
||||
stagePosition:StagePosition,
|
||||
stageFacing:StageFacing,
|
||||
actor:Actor
|
||||
};
|
||||
|
||||
enum SpeechType<StagePosition, StageFacing, Actor> {
|
||||
enum SpeechType<Actor> {
|
||||
Super;
|
||||
OffScreen(actor:Actor);
|
||||
VoiceOver(actor:Actor);
|
||||
TextMessage(actor:Actor);
|
||||
FromPhone(actor:Actor);
|
||||
OnScreen(character:Character<StagePosition, StageFacing, Actor>);
|
||||
OnScreen(character:Character<Actor>);
|
||||
Custom(type:String, actor:Actor, args:Dynamic);
|
||||
}
|
||||
|
||||
typedef Scene<Set, StagePosition, StageFacing, ScreenPosition, Actor, Prop> = {
|
||||
typedef ScreenProp<ScreenPosition,Prop> = {
|
||||
screenPosition:ScreenPosition,
|
||||
prop:Prop
|
||||
};
|
||||
|
||||
typedef Scene<Set:Cloneable<Set>, ScreenPosition, Actor, Prop> = {
|
||||
set:Set,
|
||||
characters:FuzzyMap<Character<StagePosition, StageFacing, Actor>>,
|
||||
propsOnScreen:FuzzyMap<Prop>,
|
||||
characters:FuzzyMap<Character<Actor>>,
|
||||
propsOnScreen:FuzzyMap<ScreenProp<ScreenPosition,Prop>>,
|
||||
// TODO props on stage
|
||||
time:SceneTime,
|
||||
perspective:ScenePerspective
|
||||
|
Reference in New Issue
Block a user