diff --git a/src/as/com/threerings/media/tile/DataPackTileSetRepository.as b/src/as/com/threerings/media/tile/DataPackTileSetRepository.as index 2da41070..64503ec0 100644 --- a/src/as/com/threerings/media/tile/DataPackTileSetRepository.as +++ b/src/as/com/threerings/media/tile/DataPackTileSetRepository.as @@ -38,6 +38,7 @@ import com.threerings.util.Integer; import com.threerings.util.Log; import com.threerings.util.Maps; import com.threerings.util.Map; +import com.threerings.util.Set; import com.threerings.util.StringUtil; public class DataPackTileSetRepository @@ -191,6 +192,38 @@ public class DataPackTileSetRepository } } + public function ensureLoaded (tileSets :Set, completeCallback :Function, + progressCallback :Function) :void + { + var completeCt :int = 0; + + var size :int = tileSets.size(); + + // Handles the completion of a single tileset, which if it's our last may call the callback. + function completeOneSet () :void { + completeCt++; + + progressCallback(completeCt / Number(size)); + + if (completeCt >= tileSets.size()) { + completeCallback(); + + // Ensure we stop making callbacks. + completeCallback = null; + progressCallback = null; + } + }; + + tileSets.forEach(function (setId :int) :void { + var thisSet :TileSet = getTileSet(setId); + if (thisSet.isLoaded()) { + completeOneSet(); + } else { + thisSet.notifyOnLoad(completeOneSet); + } + }); + } + /** Contains the tileset meta-data for all tilesets. */ protected var _metaPack : DataPack; diff --git a/src/as/com/threerings/media/tile/TileManager.as b/src/as/com/threerings/media/tile/TileManager.as index 783c5716..006e4743 100644 --- a/src/as/com/threerings/media/tile/TileManager.as +++ b/src/as/com/threerings/media/tile/TileManager.as @@ -20,6 +20,7 @@ package com.threerings.media.tile { import com.threerings.util.Log; +import com.threerings.util.Set; /** * The tile manager provides a simplified interface for retrieving and caching tiles. Tiles can be @@ -132,6 +133,12 @@ public class TileManager return set.getTile(tileIndex, rizer); } + public function ensureLoaded (tileSets :Set, completeCallback :Function, + progressCallback :Function) :void + { + _setrep.ensureLoaded(tileSets, completeCallback, progressCallback); + } + /** The tile set repository. */ protected var _setrep :TileSetRepository; } diff --git a/src/as/com/threerings/media/tile/TileSetRepository.as b/src/as/com/threerings/media/tile/TileSetRepository.as index 83a2f1bf..b5768b5c 100644 --- a/src/as/com/threerings/media/tile/TileSetRepository.as +++ b/src/as/com/threerings/media/tile/TileSetRepository.as @@ -19,6 +19,8 @@ package com.threerings.media.tile { +import com.threerings.util.Set; + public interface TileSetRepository { /** @@ -66,5 +68,11 @@ public interface TileSetRepository { * communicating with the underlying persistence mechanism. */ function getTileSetByName (setName :String) :TileSet; + + /** + * Ensures we are ready with quick-access to all the specified tilesets. + */ + function ensureLoaded (tileSets :Set, completeCallback :Function, + progressCallback :Function) :void; } } \ No newline at end of file diff --git a/src/as/com/threerings/miso/client/MisoScenePanel.as b/src/as/com/threerings/miso/client/MisoScenePanel.as index 635230a1..a000fbe3 100644 --- a/src/as/com/threerings/miso/client/MisoScenePanel.as +++ b/src/as/com/threerings/miso/client/MisoScenePanel.as @@ -21,6 +21,7 @@ package com.threerings.miso.client { import flash.utils.getTimer; +import flash.display.DisplayObject; import flash.display.Sprite; import flash.events.Event; @@ -28,11 +29,16 @@ import flash.events.Event; import flash.geom.Point; import flash.geom.Rectangle; +import flash.text.TextField; +import flash.text.TextFieldAutoSize; +import flash.text.TextFormat; + import flash.events.MouseEvent; import mx.core.ClassFactory; import as3isolib.display.primitive.IsoBox; +import as3isolib.display.renderers.SimpleSceneLayoutRenderer; import as3isolib.geom.Pt; import as3isolib.geom.IsoMath; import as3isolib.display.scene.IsoGrid; @@ -41,6 +47,7 @@ import as3isolib.display.IsoView; import com.threerings.crowd.client.PlaceView; import com.threerings.crowd.data.PlaceObject; +import com.threerings.util.DelayUtil; import com.threerings.util.Log; import com.threerings.media.tile.Colorizer; import com.threerings.media.tile.NoSuchTileSetError; @@ -73,7 +80,34 @@ public class MisoScenePanel extends Sprite _isoView.addEventListener(MouseEvent.CLICK, onClick); - addChild(_isoView); + addChild(_loading = createLoadingPanel()); + } + + /** + * Creates whatever we want to show while we're waiting to load our exciting scene tile data. + */ + protected function createLoadingPanel () :DisplayObject + { + // By default we just stick up a basic label for this... + var loadingText :TextField = new TextField(); + loadingText.textColor = 0xFFFFFF; + var loadingFmt :TextFormat = new TextFormat(); + loadingFmt.size = 24; + loadingText.defaultTextFormat = loadingFmt; + loadingText.autoSize = TextFieldAutoSize.LEFT; + + _loadingProgressFunc = function (progress :Number) :void { + loadingText.text = "Loading... " + int(progress*100) + "%"; + }; + _loadingProgressFunc(0.0); + return loadingText; + } + + protected function loadingProgress (progress :Number) :void + { + if (_loadingProgressFunc != null) { + _loadingProgressFunc(progress); + } } public function onClick (event :MouseEvent) :void @@ -86,7 +120,13 @@ public class MisoScenePanel extends Sprite public function setSceneModel (model :MisoSceneModel) :void { _model = model; - refreshScene(); + _ctx.getTileManager().ensureLoaded(_model.getAllTilesets(), function() :void { + DelayUtil.delayFrame(function() :void { + refreshScene(); + removeChild(_loading); + addChild(_isoView); + }); + }, loadingProgress); } public function willEnterPlace (plobj :PlaceObject) :void @@ -110,6 +150,7 @@ public class MisoScenePanel extends Sprite for (var si :int = -2; si < 4; si++) { for (var sj :int = -1; sj < 3; sj++) { var baseScene :IsoScene = new IsoScene(); + baseScene.layoutRenderer = new ClassFactory(SimpleSceneLayoutRenderer); for (var ii :int = 10*si; ii < 10*si + 10; ii++) { for (var jj :int = 10*sj; jj < 10*sj + 10; jj++) { var tileId :int = _model.getBaseTileId(ii, jj); @@ -201,6 +242,12 @@ public class MisoScenePanel extends Sprite protected var _metrics :MisoSceneMetrics; + /** What we display while we're loading up our tilesets. */ + protected var _loading :DisplayObject; + + /** If we should do something when we hear about progress updates, this is it. */ + protected var _loadingProgressFunc :Function; + protected const DEF_WIDTH :int = 985; protected const DEF_HEIGHT :int = 560; } diff --git a/src/as/com/threerings/miso/client/TileIsoSprite.as b/src/as/com/threerings/miso/client/TileIsoSprite.as index 4c19fb7b..a8d17ef2 100644 --- a/src/as/com/threerings/miso/client/TileIsoSprite.as +++ b/src/as/com/threerings/miso/client/TileIsoSprite.as @@ -32,7 +32,7 @@ import com.threerings.media.tile.TileUtil; import com.threerings.util.Log; import com.threerings.miso.util.MisoSceneMetrics; -public class TileIsoSprite extends IsoDisplayObject +public class TileIsoSprite extends IsoSprite implements PriorityIsoDisplayObject { private static var log :Log = Log.getLog(TileIsoSprite); @@ -41,26 +41,20 @@ public class TileIsoSprite extends IsoDisplayObject metrics :MisoSceneMetrics) { _tileId = tileId; - _metrics = metrics; - _priority = priority; - moveTo(x, y, 0); - layout(x, y, tile); + setSize(tile.getBaseWidth(), tile.getBaseHeight(), 1); + if (tile.getImage() == null) { - var box :IsoBox = new IsoBox(); - box.width = width; - box.height = height; - box.length = length; - box.fill = new SolidColorFill(0x808080, 0.5); - addChild(box); + tile.notifyOnLoad(function() :void { + gotTileImage(tile); + }); } else { - addSprite(tile); + gotTileImage(tile); } - tile.notifyOnLoad(loaded); } public function layout (x :int, y :int, tile :Tile) :void @@ -68,31 +62,15 @@ public class TileIsoSprite extends IsoDisplayObject moveTo(x, y, 0); } - /** - * Our tile was loaded, set ourselves up appropriately to use it. - */ - public function loaded (tile :Tile) :void + protected function gotTileImage (tile :Tile) :void { - removeAllChildren(); - addSprite(tile); - } - - protected function addSprite (tile :Tile) :void - { - var sprite :IsoSprite = new IsoSprite(); var image :DisplayObject = tile.getImage(); - if (image == null) { - log.warning("TileIsoSprite tile image is null", "tileId", _tileId); - return; - } // as3isolib uses top instead of bottom. image.x = -tile.getOriginX() + _metrics.tilewid * ((tile.getBaseWidth() - tile.getBaseHeight())/2);; image.y = -tile.getOriginY() + _metrics.tilehei * ((tile.getBaseWidth() + tile.getBaseHeight())/2); - sprite.sprites = [image]; - sprite.setSize(tile.getBaseWidth(), tile.getBaseHeight(), 1); - addChild(sprite); + sprites = [image]; render(); } diff --git a/src/as/com/threerings/miso/data/MisoSceneModel.as b/src/as/com/threerings/miso/data/MisoSceneModel.as index aa4e0998..828ae090 100644 --- a/src/as/com/threerings/miso/data/MisoSceneModel.as +++ b/src/as/com/threerings/miso/data/MisoSceneModel.as @@ -30,6 +30,7 @@ import com.threerings.io.ObjectInputStream; import com.threerings.miso.data.ObjectInfo; import com.threerings.util.ClassUtil; import com.threerings.util.Cloneable; +import com.threerings.util.Set; import com.threerings.io.ObjectOutputStream; /** @@ -97,5 +98,9 @@ public /*abstract*/ class MisoSceneModel extends SimpleStreamableObject throw new Error("abstract"); } + public function getAllTilesets () :Set + { + throw new Error("abstract"); + } } } diff --git a/src/as/com/threerings/miso/data/SparseMisoSceneModel.as b/src/as/com/threerings/miso/data/SparseMisoSceneModel.as index 1c9feade..b8aee8ad 100644 --- a/src/as/com/threerings/miso/data/SparseMisoSceneModel.as +++ b/src/as/com/threerings/miso/data/SparseMisoSceneModel.as @@ -33,6 +33,8 @@ import com.threerings.util.Integer; import com.threerings.util.Iterator; import com.threerings.util.Joiner; import com.threerings.util.MathUtil; +import com.threerings.util.Set; +import com.threerings.util.Sets; import com.threerings.util.StreamableHashMap; import com.threerings.util.StringUtil; @@ -193,6 +195,18 @@ public class SparseMisoSceneModel extends MisoSceneModel _sections.put(key(section.x, section.y), section); } + override public function getAllTilesets () :Set + { + var tilesets :Set = Sets.newSetOf(int); + for each (var section :SparseMisoSceneModel_Section in _sections.values()) { + section.getAllTilesets(tilesets); + } + + tilesets.add(getDefaultBaseTileSet()); + + return tilesets; + } + // from interface Streamable override public function readObject (ins :ObjectInputStream) :void { diff --git a/src/as/com/threerings/miso/data/SparseMisoSceneModel_Section.as b/src/as/com/threerings/miso/data/SparseMisoSceneModel_Section.as index 9c7146f0..61a5c08a 100644 --- a/src/as/com/threerings/miso/data/SparseMisoSceneModel_Section.as +++ b/src/as/com/threerings/miso/data/SparseMisoSceneModel_Section.as @@ -27,11 +27,13 @@ import com.threerings.io.ObjectOutputStream; import com.threerings.io.ObjectInputStream; import com.threerings.io.SimpleStreamableObject; import com.threerings.io.TypedArray; +import com.threerings.media.tile.TileUtil; import com.threerings.miso.util.ObjectSet; import com.threerings.util.ArrayUtil; import com.threerings.util.ClassUtil; import com.threerings.util.Cloneable; import com.threerings.util.Log; +import com.threerings.util.Set; import com.threerings.util.StringUtil; public class SparseMisoSceneModel_Section extends SimpleStreamableObject @@ -232,6 +234,26 @@ public class SparseMisoSceneModel_Section extends SimpleStreamableObject } } + /** + * Adds all tilesets we reference to the set. + */ + public function getAllTilesets (tilesets :Set) :void + { + for each (var base :int in baseTileIds) { + var baseSetId :int = TileUtil.getTileSetId(base); + if (baseSetId != 0) { + tilesets.add(baseSetId); + } + } + for each (var obj :int in objectTileIds) { + tilesets.add(TileUtil.getTileSetId(obj)); + } + + for each (var objInfo :ObjectInfo in objectInfo) { + tilesets.add(TileUtil.getTileSetId(objInfo.tileId)); + } + } + // from interface Streamable override public function readObject (ins :ObjectInputStream) :void {