refactor asset loading
This commit is contained in:
10
memory-fix.org
Normal file
10
memory-fix.org
Normal file
@@ -0,0 +1,10 @@
|
||||
* DONE for all asset types, make the Director define load*()
|
||||
* DONE instead of requiring Cloneable<Set>, add Director.cloneSet()
|
||||
* DONE in all newMethods take a path, not the object.
|
||||
** DONE allow for alternative loading with the object directly, like how some props in HollywooFlixel are animated via ActorFlxSprite
|
||||
** DONE if the assetpath doesn't start with assets/, call (assetPath "<typeDir>" "<path>")
|
||||
** DONE make loading things at runtime a compiler error
|
||||
* TODO in all new* methods, save the path that was loaded
|
||||
* TODO in all with_ macros, mark those assets as dirty (needing to be reloaded)
|
||||
* TODO Movie.scavenge before cleanup
|
||||
* TODO in all new* methods, don't load the new thing if it exists already
|
@@ -26,7 +26,7 @@ typedef AutoZConfig = {
|
||||
};
|
||||
|
||||
@:keepSub
|
||||
interface Director<Set:Cloneable<Set>, Actor, Sound, Song, Prop, VoiceTrack, Camera, LightSource:Jsonable<LightSource>> {
|
||||
interface Director<Set, Actor, Sound, Song, Prop, VoiceTrack, Camera, LightSource:Jsonable<LightSource>> {
|
||||
var movie(default, default):Movie<Set, Actor, Sound, Song, Prop, VoiceTrack, Camera, LightSource>;
|
||||
function autoZConfig():Option<AutoZConfig>;
|
||||
|
||||
@@ -51,15 +51,19 @@ interface Director<Set:Cloneable<Set>, Actor, Sound, Song, Prop, VoiceTrack, Cam
|
||||
function defineStagePosition(camera:Camera, submit:StagePosition->Void, ?oldPosition:StagePosition):Void;
|
||||
function defineLightSource(submit:LightSource->Void):Void;
|
||||
|
||||
function loadSet(path:String):Set;
|
||||
function cloneSet(set:Set):Set;
|
||||
function showSet(set:Set, time:SceneTime, perspective:ScenePerspective, appearance:Appearance, camera:Camera, cc:Continuation):Void;
|
||||
function hideSet(set:Set, camera: Camera, cc:Continuation):Void;
|
||||
|
||||
function showLighting(sceneTime:SceneTime, lightSources:Array<LightSource>, camera:Camera):Void;
|
||||
function hideLighting():Void;
|
||||
|
||||
function loadActor(path:String):Actor;
|
||||
function showCharacter(character:Character<Actor>, appearance:Appearance, camera:Camera, cc:Continuation):Void;
|
||||
function hideCharacter(character:Character<Actor>, camera:Camera, cc:Continuation):Void;
|
||||
|
||||
function loadSound(path:String):Sound;
|
||||
function playSound(sound:Sound, volumeMod:Float, ?cc:Continuation):Void;
|
||||
function getSoundLength(sound:Sound):Float;
|
||||
function stopSound(sound:Sound):Void;
|
||||
@@ -67,11 +71,13 @@ interface Director<Set:Cloneable<Set>, Actor, Sound, Song, Prop, VoiceTrack, Cam
|
||||
function showCaption(description:String, id:Int):Void;
|
||||
function hideCaption(id:Int):Void;
|
||||
|
||||
function loadSong(path:String):Song;
|
||||
function playSong(song:Song, volumeMod:Float, loop:Bool, waitForEnd:Bool, cc:Continuation):Void;
|
||||
function getSongLength(song:Song):Float;
|
||||
function changeSongVolume(volumeMod:Float, cc:Continuation):Void;
|
||||
function stopSong():Void;
|
||||
|
||||
function loadVoiceTrack(path:String):VoiceTrack;
|
||||
function playVoiceTrack(track:VoiceTrack, volumeMod:Float, start:Float, end:Float, cc:Continuation):Void;
|
||||
function stopVoiceTrack(track:VoiceTrack):Void;
|
||||
|
||||
@@ -87,6 +93,7 @@ interface Director<Set:Cloneable<Set>, Actor, Sound, Song, Prop, VoiceTrack, Cam
|
||||
function showBlackScreen():Void;
|
||||
function hideBlackScreen():Void;
|
||||
|
||||
function loadProp(path:String):Prop;
|
||||
function showProp(prop:Prop, position:StagePosition, appearance:Appearance, camera:Camera, cc:Continuation):Void;
|
||||
function hideProp(prop:Prop, camera:Camera, cc:Continuation):Void;
|
||||
|
||||
|
@@ -73,15 +73,29 @@
|
||||
(director.showTitleCard ["LOADING"]
|
||||
(makeCC
|
||||
(set isLoading true)
|
||||
(director.doLoading ,preloadFuncs
|
||||
(makeCC
|
||||
(set isLoading false)
|
||||
(.start (director.shortcutHandler))
|
||||
(director.hideTitleCard)
|
||||
// When all loading is done, prompt to start obs recording automatically:
|
||||
(#if debug
|
||||
(promptToRecord cc)
|
||||
(cc)))))))
|
||||
(let [loadVoiceTrack _loadVoiceTrack
|
||||
addVoiceTrack _addVoiceTrack
|
||||
noVoiceTracks _noVoiceTracks
|
||||
loadProp _loadProp
|
||||
addProp _addProp
|
||||
loadSong _loadSong
|
||||
addSong _addSong
|
||||
loadActor _loadActor
|
||||
addActor _addActor
|
||||
loadSet _loadSet
|
||||
addSet _addSet
|
||||
newSceneFromSet _newSceneFromSet
|
||||
loadSound _loadSound
|
||||
addSound _addSound]
|
||||
(director.doLoading ,preloadFuncs
|
||||
(makeCC
|
||||
(set isLoading false)
|
||||
(.start (director.shortcutHandler))
|
||||
(director.hideTitleCard)
|
||||
// When all loading is done, prompt to start obs recording automatically:
|
||||
(#if debug
|
||||
(promptToRecord cc)
|
||||
(cc))))))))
|
||||
@:keep
|
||||
(method doCleanup []
|
||||
(director.cleanup)
|
||||
|
@@ -20,10 +20,6 @@ import kiss_tools.TimerWithPause;
|
||||
|
||||
using kiss.FuzzyMapTools;
|
||||
|
||||
typedef Cloneable<T> = {
|
||||
function clone():T;
|
||||
}
|
||||
|
||||
enum DelayHandling {
|
||||
Auto;
|
||||
AutoWithSkip;
|
||||
@@ -65,4 +61,4 @@ enum PlayMode {
|
||||
* Model/controller of a Hollywoo film, and main execution script
|
||||
*/
|
||||
@:build(kiss.Kiss.build())
|
||||
class Movie<Set:Cloneable<Set>, Actor, Sound, Song, Prop, VoiceTrack, Camera, LightSource:Jsonable<LightSource>> extends AsyncEmbeddedScript2 {}
|
||||
class Movie<Set, Actor, Sound, Song, Prop, VoiceTrack, Camera, LightSource:Jsonable<LightSource>> extends AsyncEmbeddedScript2 {}
|
||||
|
@@ -142,11 +142,36 @@
|
||||
(throw "No handler for custom dialog type $type")))
|
||||
(otherwise (director.showDialog actorName dialogType wryly text skipCC)))))))
|
||||
|
||||
(method noVoiceTracks [actorName]
|
||||
(dictSet voiceTracksPerActor actorName 0)
|
||||
(dictSet voiceLines actorName (new FuzzyMap<VoiceLine>)))
|
||||
(defMacro withIndexedPath [pathVar typeDefaultDir &body body]
|
||||
(#if (or sys hxnodejs)
|
||||
`(let [,pathVar
|
||||
(if (StringTools.startsWith ,pathVar assetDir)
|
||||
,pathVar
|
||||
(assetPath ,typeDefaultDir ,pathVar))]
|
||||
,@body)
|
||||
body))
|
||||
|
||||
(method newVoiceTrack [actorName :VoiceTrack track :String lineJson]
|
||||
// Methods for loading new assets in a hollywoo movie follow a special naming convention.
|
||||
// _add*() is a method which takes the asset DIRECTLY and adds it to the corresponding asset map.
|
||||
// This is to be used in cases where the asset needs to be loaded specially in a way
|
||||
// the Director's load*() function can't handle.
|
||||
// _load*() is a method which takes the asset's PATH and lets the Director load the asset object.
|
||||
//
|
||||
// Neither of these is not meant to be called directly, as a precaution against loading new assets
|
||||
// at Movie runtime. However, within the context of (preload...) blocks, they will be
|
||||
// bound to these names:
|
||||
// add*()
|
||||
// new*() At which point you can use them. Therefore, if you accidentally try to call new*()
|
||||
// outside of a preload block, your code won't compile.
|
||||
// Which is desired because (preload...) blocks are meant to be allowed at any point in a script,
|
||||
// even following the usage of the assets they load. Runtime loading allows for errors
|
||||
// caused by moving the load calls or asset usages around so the load doesn't precede the usage.
|
||||
(method _loadVoiceTrack [actorName :String path :String lineJson]
|
||||
(withIndexedPath path "vo"
|
||||
(_addVoiceTrack actorName (director.loadVoiceTrack path) lineJson)))
|
||||
|
||||
(method _addVoiceTrack [actorName :VoiceTrack track :String lineJson]
|
||||
(assert isLoading)
|
||||
(let [actorNumVoiceTracks (or (dictGet voiceTracksPerActor actorName) 0)
|
||||
trackKey "${actorName}${actorNumVoiceTracks}"
|
||||
:haxe.DynamicAccess<Dynamic> lines (Json.parse lineJson)]
|
||||
@@ -161,6 +186,68 @@
|
||||
(dictSet voiceLines actorName (new FuzzyMap<VoiceLine>)))
|
||||
(dictSet (dictGet voiceLines actorName) key (objectWith [start line.start end line.end] trackKey alts))))))
|
||||
|
||||
(method _noVoiceTracks [actorName]
|
||||
(assert isLoading)
|
||||
(dictSet voiceTracksPerActor actorName 0)
|
||||
(dictSet voiceLines actorName (new FuzzyMap<VoiceLine>)))
|
||||
|
||||
(method _loadProp [name :String path]
|
||||
(withIndexedPath path "images"
|
||||
(_addProp name (director.loadProp path))))
|
||||
|
||||
(method _addProp [name :Prop prop]
|
||||
(assert isLoading)
|
||||
(dictSet props name prop))
|
||||
|
||||
(method _loadSong [name :String path]
|
||||
(withIndexedPath path "music"
|
||||
(_addSong name (director.loadSong path))))
|
||||
|
||||
(method _addSong [name :Song song]
|
||||
(assert isLoading)
|
||||
(dictSet songs name song))
|
||||
|
||||
(method _loadActor [name :String path]
|
||||
(withIndexedPath path "images"
|
||||
(_addActor name (director.loadActor path))))
|
||||
|
||||
(method _addActor [name :Actor actor]
|
||||
(assert isLoading)
|
||||
(dictSet actors name actor))
|
||||
|
||||
(method _loadSet [name :String path]
|
||||
(withIndexedPath path "images"
|
||||
(_addSet name (director.loadSet path))))
|
||||
|
||||
(method _addSet [name :Set set]
|
||||
(assert isLoading)
|
||||
(dictSet sets name set))
|
||||
|
||||
(method _newSceneFromSet [name :String setKey :SceneTime time :ScenePerspective perspective :Camera camera]
|
||||
(assert isLoading)
|
||||
(dictSet scenes name (objectWith
|
||||
[
|
||||
set
|
||||
(director.cloneSet (dictGet sets setKey))
|
||||
characters
|
||||
(new FuzzyMap<Character<Actor>>)
|
||||
props
|
||||
(new FuzzyMap<StageProp<Prop>>)
|
||||
camera
|
||||
camera
|
||||
]
|
||||
time
|
||||
perspective)))
|
||||
|
||||
(method _loadSound [name :String path :String description]
|
||||
(withIndexedPath path "sounds"
|
||||
(_addSound name (director.loadSound path) description)))
|
||||
|
||||
(method _addSound [name :Sound s :String description]
|
||||
(assert isLoading)
|
||||
(dictSet sounds name s)
|
||||
(dictSet soundDescriptions name description))
|
||||
|
||||
(method _ccForEach <>[T] [:Iterable<T> collection :(T,Continuation)->Void do_ :Continuation finalCC]
|
||||
(let [:Iterator<T> iter (collection.iterator)]
|
||||
(withFunctions
|
||||
@@ -263,8 +350,10 @@
|
||||
|
||||
(#when (or sys hxnodejs)
|
||||
(prop :FuzzyMap<FuzzyMap<String>> assetPaths (new FuzzyMap))
|
||||
(prop &mut :String assetDir "")
|
||||
(prop :Array<Array<String>> loadedCredits [])
|
||||
(method _indexAssetPaths [:String assetDir]
|
||||
(set this.assetDir assetDir)
|
||||
(let [dirParts (assetDir.split "/")]
|
||||
(doFor part dirParts
|
||||
(dictSet assetPaths part (new FuzzyMap))))
|
||||
@@ -445,15 +534,8 @@
|
||||
((dictGet runners label))
|
||||
})))))
|
||||
|
||||
(super)))
|
||||
|
||||
// END Parent class definitions
|
||||
|
||||
(defMacro indexAssetPaths [dir]
|
||||
`(preload
|
||||
(_indexAssetPaths ,dir)))
|
||||
|
||||
(#unless subclass
|
||||
(super))
|
||||
|
||||
@:keep
|
||||
(method :Void _strobe [:Bool skipping :Bool prop :String actorOrPropKey :Float strobeSec :Int times &opt :Continuation cc]
|
||||
(when skipping
|
||||
@@ -497,6 +579,13 @@
|
||||
(when cc
|
||||
(TimerWithPause.delay cc (* strobeSec 2 (+ 1 times)))))))
|
||||
|
||||
// END Parent class definitions
|
||||
|
||||
(defMacro indexAssetPaths [dir]
|
||||
`(preload
|
||||
(_indexAssetPaths ,dir)))
|
||||
|
||||
|
||||
// Some real magic happens here. This macro defines a method, AND a reader macro
|
||||
// for calling it with skipping and cc passed automatically if cc is an argument.
|
||||
// GOTCHA: DO NOT use (method) directly in this file!!
|
||||
@@ -574,26 +663,6 @@
|
||||
}))
|
||||
(otherwise (throw "Unsupported delay type $delayHandling")))))
|
||||
|
||||
(hollywooMethod newSet [name :Set set]
|
||||
(assert isLoading)
|
||||
(dictSet sets name set))
|
||||
|
||||
(hollywooMethod newSceneFromSet [name :String setKey :SceneTime time :ScenePerspective perspective :Camera camera]
|
||||
(assert isLoading)
|
||||
(dictSet scenes name (objectWith
|
||||
[
|
||||
set
|
||||
(.clone (dictGet sets setKey))
|
||||
characters
|
||||
(new FuzzyMap<Character<Actor>>)
|
||||
props
|
||||
(new FuzzyMap<StageProp<Prop>>)
|
||||
camera
|
||||
camera
|
||||
]
|
||||
time
|
||||
perspective)))
|
||||
|
||||
(hollywooMethod setSceneSong [:String scene :String songKey &opt :Float volumeMod :Continuation cc]
|
||||
(dictSet sceneMusic scene songKey)
|
||||
(dictSet sceneMusicVolume scene volumeMod)
|
||||
@@ -633,12 +702,6 @@
|
||||
.camera (dictGet scenes name)
|
||||
cc)))))
|
||||
|
||||
|
||||
(hollywooMethod newSound [name :Sound s :String description]
|
||||
(assert isLoading)
|
||||
(dictSet sounds name s)
|
||||
(dictSet soundDescriptions name description))
|
||||
|
||||
(hollywooMethod playSound [:Bool skipping name :Continuation cc &opt :Float volumeMod :Bool waitForEnd]
|
||||
(when skipping
|
||||
(cc)
|
||||
@@ -692,10 +755,6 @@
|
||||
(playAgain))))
|
||||
(cc))
|
||||
|
||||
(hollywooMethod newSong [name :Song song]
|
||||
(assert isLoading)
|
||||
(dictSet songs name song))
|
||||
|
||||
// This is never skipped because the music might be expected to continue on to the place
|
||||
// we skip to:
|
||||
(hollywooMethod playSong [name :Continuation cc &opt :Float volumeMod :Bool loop :Bool waitForEnd]
|
||||
@@ -719,10 +778,6 @@
|
||||
(director.stopSong)
|
||||
(cc))
|
||||
|
||||
(hollywooMethod newActor [name :Actor actor]
|
||||
(assert isLoading)
|
||||
(dictSet actors name actor))
|
||||
|
||||
(hollywooMethod autoZProcess [:StagePosition position :Continuation cc]
|
||||
// handle auto z recursively
|
||||
(ifLet [(Some (objectWith zPerLayer frontLayer)) (director.autoZConfig)]
|
||||
@@ -802,10 +857,6 @@
|
||||
// TODO moveCharacter remove them, add them to another scene
|
||||
// TODO moveCharacterAndFollow remove them, add them to another scene, set that the scene
|
||||
|
||||
(hollywooMethod newProp [name :Prop prop]
|
||||
(assert isLoading)
|
||||
(dictSet props name prop))
|
||||
|
||||
(hollywooMethod addProp [name :Dynamic position :Continuation cc]
|
||||
(let [name (FuzzyMapTools.bestMatch props name)
|
||||
prop (dictGet props name)
|
||||
|
@@ -38,7 +38,7 @@ typedef StageProp<Prop> = {
|
||||
prop:Prop
|
||||
};
|
||||
|
||||
typedef Scene<Set:Cloneable<Set>, Actor, Prop, Camera> = {
|
||||
typedef Scene<Set, Actor, Prop, Camera> = {
|
||||
set:Set,
|
||||
characters:FuzzyMap<Character<Actor>>,
|
||||
props:FuzzyMap<StageProp<Prop>>,
|
||||
|
Reference in New Issue
Block a user