diff --git a/src/as/com/threerings/crowd/client/PlaceViewUtil.as b/src/as/com/threerings/crowd/client/PlaceViewUtil.as index bbed30845..3274e745e 100644 --- a/src/as/com/threerings/crowd/client/PlaceViewUtil.as +++ b/src/as/com/threerings/crowd/client/PlaceViewUtil.as @@ -22,8 +22,9 @@ package com.threerings.crowd.client { import flash.display.DisplayObject; +import flash.display.DisplayObjectContainer; -import com.threerings.util.DisplayUtil; +import mx.core.IRawChildrenContainer; // a simple interface from flex import com.threerings.crowd.data.PlaceObject; @@ -72,19 +73,36 @@ public class PlaceViewUtil return; } - DisplayUtil.applyToHierarchy(root as DisplayObject, - function (disp :DisplayObject) :void { - if (disp is PlaceView) { - try { - (root as PlaceView)[funct](plobj); - } catch (e :Error) { - var log :Log = Log.getLog(PlaceViewUtil); - log.warning("Component choked on " + funct + "() " + - "[component=" + root + ", plobj=" + plobj + "]."); - log.logStackTrace(e); - } + // much of the code in here is adapted from + // com.threerings.flash.DisplayUtil, which we cannot access because + // it's in the nenya package. So sad, too bad. + + if (root is PlaceView) { + try { + (root as PlaceView)[funct](plobj); + } catch (e :Error) { + var log :Log = Log.getLog(PlaceViewUtil); + log.warning("Component choked on " + funct + "() " + + "[component=" + root + ", plobj=" + plobj + "]."); + log.logStackTrace(e); + } + } + + if (root is DisplayObjectContainer) { + // a little type-unsafety so that we don't have to write two blocks + var o :Object= (root is IRawChildrenContainer) ? + IRawChildrenContainer(root).rawChildren : root; + var nn :int = int(o.numChildren); + for (var ii :int = 0; ii < nn; ii++) { + try { + root = o.getChildAt(ii); + } catch (err :SecurityError) { + // don't try dispatching to children we cannot access! + continue; } - }); + dispatch(root, plobj, funct); + } + } } } } diff --git a/src/as/com/threerings/media/image/ImageUtil.as b/src/as/com/threerings/media/image/ImageUtil.as deleted file mode 100644 index 7893a7d2b..000000000 --- a/src/as/com/threerings/media/image/ImageUtil.as +++ /dev/null @@ -1,88 +0,0 @@ -// -// $Id$ -// -// Narya library - tools for developing networked games -// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved -// http://www.threerings.net/code/narya/ -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -package com.threerings.media.image { - -import flash.display.Bitmap; -import flash.display.BitmapData; -import flash.display.DisplayObject; -import flash.display.Shape; - -import flash.geom.Point; -import flash.geom.Rectangle; - -import flash.text.TextField; -import flash.text.TextLineMetrics; - -/** - * Image and Bitmap related utility functions. - */ -public class ImageUtil -{ - /** - * Create a DisplayObject that will display an error message - * of the specified dimensions. - */ - public static function createErrorImage (width :int, height :int) - :DisplayObject - { - var shape :Shape = new Shape(); - shape.graphics.beginBitmapFill(createErrorBitmap()); - shape.graphics.drawRect(0, 0, width, height); - shape.graphics.endFill(); - return shape; - - /* - // Alternate implementation that creates an actual Bitmap object - var src :BitmapData = createErrorBitmap(); - var data :BitmapData = new BitmapData(width, height, false); - data.draw(src); - var rect :Rectangle = new Rectangle(0, 0, src.width, src.height); - for (var xx :int = 0; xx < width; xx += src.width) { - for (var yy :int = 0; yy < height; yy += src.height) { - if (xx != 0 || yy != 0) { - data.copyPixels(data, rect, new Point(xx, yy)); - } - } - } - return new Bitmap(data); - */ - } - - /** - * Create a minimally-sized "error" BitmapData. - */ - public static function createErrorBitmap () :BitmapData - { - var txt :TextField = new TextField(); - txt.text = "Error"; - var metrics :TextLineMetrics = txt.getLineMetrics(0); - var data :BitmapData = new BitmapData( - metrics.width + ERROR_PADDING, metrics.height + ERROR_PADDING, - false, 0xFF4040); - data.draw(txt); - return data; - } - - /** The amount to pad error messages by. */ - private static const ERROR_PADDING :int = 5; -} -} diff --git a/src/as/com/threerings/util/ColorUtil.as b/src/as/com/threerings/util/ColorUtil.as deleted file mode 100644 index 309fa33d3..000000000 --- a/src/as/com/threerings/util/ColorUtil.as +++ /dev/null @@ -1,49 +0,0 @@ -// -// $Id$ -// -// Narya library - tools for developing networked games -// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved -// http://www.threerings.net/code/narya/ -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -package com.threerings.util { - -/** - * Color utility methods. - * - * See also mx.utils.ColorUtil. - */ -public class ColorUtil -{ - /** - * Blend the two colors, either 50-50 or according to the ratio specified. - */ - public static function blend ( - first :uint, second :uint, firstPerc :Number = 0.5) :uint - { - var secondPerc :Number = 1 - firstPerc; - - var result :uint = 0; - for (var shift :int = 0; shift <= 16; shift += 8) { - var c1 :uint = (first >> shift) & 0xFF; - var c2 :uint = (second >> shift) & 0xFF; - result |= uint(Math.max(0, Math.min(255, - (c1 * firstPerc) + (c2 * secondPerc)))) << shift; - } - return result; - } -} -} diff --git a/src/as/com/threerings/util/DisplayUtil.as b/src/as/com/threerings/util/DisplayUtil.as deleted file mode 100644 index 9499dfdcb..000000000 --- a/src/as/com/threerings/util/DisplayUtil.as +++ /dev/null @@ -1,184 +0,0 @@ -// -// $Id$ -// -// Narya library - tools for developing networked games -// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved -// http://www.threerings.net/code/narya/ -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -package com.threerings.util { - -import flash.display.DisplayObject; -import flash.display.DisplayObjectContainer; - -import flash.geom.Point; -import flash.geom.Rectangle; - -import mx.core.IChildList; -import mx.core.IRawChildrenContainer; - -public class DisplayUtil -{ - /** - * Call the specified function for the display object and all descendants. - * - * This is nearly exactly like mx.utils.DisplayUtil.walkDisplayObjects, - * except this method copes with security errors when examining a child. - */ - public static function applyToHierarchy ( - disp :DisplayObject, callbackFunction :Function) :void - { - callbackFunction(disp); - - if (disp is DisplayObjectContainer) { - // a little type-unsafety so that we don't have to write two blocks - var o :Object = (disp is IRawChildrenContainer) ? - IRawChildrenContainer(disp).rawChildren : disp; - var nn :int = int(o.numChildren); - for (var ii :int = 0; ii < nn; ii++) { - try { - disp = DisplayObject(o.getChildAt(ii)); - } catch (err :SecurityError) { - continue; - } - // and then we apply outside of the try/catch block so that - // we don't hide errors thrown by the callbackFunction. - applyToHierarchy(disp, callbackFunction); - } - } - } - - /** - * Returns the most reasonable position for the specified rectangle to - * be placed at so as to maximize its containment by the specified - * bounding rectangle while still placing it as near its original - * coordinates as possible. - * - * @param rect the rectangle to be positioned. - * @param bounds the containing rectangle. - */ - public static function fitRectInRect ( - rect :Rectangle , bounds :Rectangle) :Point - { - // Guarantee that the right and bottom edges will be contained - // and do our best for the top and left edges. - var br :Point = bounds.bottomRight; - return new Point( - Math.min(br.x - rect.width, Math.max(rect.x, bounds.x)), - Math.min(br.y - rect.height, Math.max(rect.y, bounds.y))); - } - - /** - * Position the specified rectangle within the bounds, avoiding - * any of the Rectangles in the avoid array, which may be destructively - * modified. - * - * @return true if the rectangle was successfully placed, given the - * constraints, or false if the positioning failed (the rectangle will - * be left at its original location. - */ - public static function positionRect ( - r :Rectangle, bounds :Rectangle, avoid :Array) :Boolean - { - var origPos :Point = r.topLeft; - var pointSorter :Function = createPointSorter(origPos); - var possibles :Array = new Array(); - // start things off with the passed-in point (adjusted to - // be inside the bounds, if needed) - possibles.push(fitRectInRect(r, bounds)); - - // keep track of area that doesn't generate new possibles - var dead :Array = new Array(); - - // Note: labeled breaks and continues are supposed to be legal, - // but they throw wacky runtime exceptions for me. So instead - // I'm throwing a boolean and using that to continue the while - /* CHECKPOSSIBLES: */ while (possibles.length > 0) { - try { - var p :Point = (possibles.shift() as Point); - r.x = p.x; - r.y = p.y; - - // make sure the rectangle is in the view - if (!bounds.containsRect(r)) { - continue; - } - - // and not over a dead area - for each (var deadRect :Rectangle in dead) { - if (deadRect.intersects(r)) { - //continue CHECKPOSSIBLES; - throw true; // continue outer loop - } - } - - // see if it hits any rects we're trying to avoid - for (var ii :int = 0; ii < avoid.length; ii++) { - var avoidRect :Rectangle = (avoid[ii] as Rectangle); - if (avoidRect.intersects(r)) { - // remove it from the avoid list - avoid.splice(ii, 1); - // but add it to the dead list - dead.push(avoidRect); - - // add 4 new possible points, each pushed in - // one direction - possibles.push( - new Point(avoidRect.x - r.width, r.y), - new Point(r.x, avoidRect.y - r.height), - new Point(avoidRect.x + avoidRect.width, r.y), - new Point(r.x, avoidRect.y + avoidRect.height)); - - // re-sort the list - possibles.sort(pointSorter); - //continue CHECKPOSSIBLES; - throw true; // continue outer loop - } - } - - // hey! if we got here, then it worked! - return true; - - } catch (continueWhile :Boolean) { - // simply catch the boolean and use it to continue inner loops - } - } - - // we never found a match, move the rectangle back - r.x = origPos.x; - r.y = origPos.y; - return false; - } - - /** - * Create a sort Function that can be used to compare Points in an - * Array according to their distance from the specified Point. - * - * Note: The function will always sort according to distance from the - * passed-in point, even if that point's coordinates change after - * the function is created. - */ - public static function createPointSorter (origin :Point) :Function - { - return function (p1 :Point, p2 :Point) :Number { - var dist1 :Number = Point.distance(origin, p1); - var dist2 :Number = Point.distance(origin, p2); - - return (dist1 > dist2) ? 1 : ((dist1 < dist2) ? -1 : 0); // signum - }; - } -} -} diff --git a/src/as/com/threerings/util/FPSDisplay.as b/src/as/com/threerings/util/FPSDisplay.as deleted file mode 100644 index a35f91404..000000000 --- a/src/as/com/threerings/util/FPSDisplay.as +++ /dev/null @@ -1,67 +0,0 @@ -// -// $Id$ -// -// Narya library - tools for developing networked games -// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved -// http://www.threerings.net/code/narya/ -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -package com.threerings.util { - -import flash.events.Event; - -import flash.text.TextField; - -import flash.utils.getTimer; // function import - -public class FPSDisplay extends TextField -{ - public function FPSDisplay (framesToTrack :int = 150) - { - background = true; - text = String(Number.MIN_VALUE); - height = textHeight + 4; - - _framesToTrack = framesToTrack; - - addEventListener(Event.ENTER_FRAME, handleEnterFrame); - } - - protected function handleEnterFrame (event :Event) :void - { - var curStamp :Number = getTimer(); - _frameStamps.push(curStamp); - if (_frameStamps.length > _framesToTrack) { - _frameStamps.shift(); // forget the oldest timestamps - } - - var firstStamp :Number = Number(_frameStamps[0]); - var seconds :Number = (curStamp - firstStamp) / 1000; - // subtract one from the frames, since we're measuring the time - // elapsed over the frames (when there are two timestamps, that's - // the difference between 1 frame) - var frames :Number = _frameStamps.length - 1; - - this.text = String(frames / seconds); - } - - /** Timestamps of past ENTER_FRAME events. */ - protected var _frameStamps :Array = []; - - /** The number of running frames we track. */ - protected var _framesToTrack :int; -} -} diff --git a/src/as/com/threerings/util/MediaContainer.as b/src/as/com/threerings/util/MediaContainer.as deleted file mode 100644 index 1bcb8445a..000000000 --- a/src/as/com/threerings/util/MediaContainer.as +++ /dev/null @@ -1,517 +0,0 @@ -// -// $Id$ -// -// Narya library - tools for developing networked games -// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved -// http://www.threerings.net/code/narya/ -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -package com.threerings.util { - -//import flash.display.Bitmap; -import flash.display.DisplayObject; -import flash.display.DisplayObjectContainer; -import flash.display.Loader; -import flash.display.LoaderInfo; -import flash.display.Shape; -import flash.display.Sprite; - -import flash.errors.IOError; - -import flash.events.Event; -import flash.events.EventDispatcher; -import flash.events.IEventDispatcher; -import flash.events.IOErrorEvent; -import flash.events.MouseEvent; -import flash.events.NetStatusEvent; -import flash.events.ProgressEvent; -import flash.events.SecurityErrorEvent; -import flash.events.StatusEvent; -import flash.events.TextEvent; - -import flash.geom.Point; - -import flash.text.TextField; -import flash.text.TextFieldAutoSize; - -import flash.system.ApplicationDomain; -import flash.system.LoaderContext; -import flash.system.SecurityDomain; - -import flash.net.URLRequest; - -import com.threerings.util.StringUtil; - -import com.threerings.media.image.ImageUtil; - -/** - * A wrapper class for all media that will be placed on the screen. - * Subject to change. - */ -public class MediaContainer extends Sprite -{ - /** A ValueEvent we dispatch when our size is known. - * Value: [ width, height ]. */ - public static const SIZE_KNOWN :String = "mediaSizeKnown"; - - /** A log instance that can be shared by sprites. */ - protected static const log :Log = Log.getLog(MediaContainer); - - /** - * Constructor. - */ - public function MediaContainer (url :String = null) - { - if (url != null) { - setMedia(url); - } - - mouseEnabled = false; - mouseChildren = true; - } - - /** - * Get the media. If the media was loaded using a URL, this will - * likely be the Loader object holding the real media. - */ - public function getMedia () :DisplayObject - { - return _media; - } - - /** - * Configure the media to display. - */ - public function setMedia (url :String) :void - { - if (Util.equals(_url, url)) { - return; // no change - } - _url = url; - - // shutdown any previous media - if (_media != null) { - shutdown(false); - } - - // set up the new media - if (StringUtil.endsWith(url.toLowerCase(), ".flv")) { - setupVideo(url); - - } else { - setupSwfOrImage(url); - } - } - - /** - * Configure our media as an instance of the specified class. - */ - public function setMediaClass (clazz :Class) :void - { - setMediaObject(new clazz() as DisplayObject); - } - - /** - * Configure an already-instantiated DisplayObject as our media. - */ - public function setMediaObject (disp :DisplayObject) :void - { - _url = null; - if (_media != null) { - shutdown(false); - } - - addChild(disp); - _media = disp; - updateContentDimensions(disp.width, disp.height); - } - - /** - * Configure this sprite to show a video. - */ - protected function setupVideo (url :String) :void - { - var vid :VideoDisplayer = new VideoDisplayer(); - vid.addEventListener(VideoDisplayer.SIZE_KNOWN, handleVideoSizeKnown); - vid.addEventListener(VideoDisplayer.VIDEO_ERROR, handleVideoError); - _media = vid; - addChild(vid); - vid.setup(url); - } - - /** - * Configure this sprite to show an image or flash movie. - */ - protected function setupSwfOrImage (url :String) :void - { - startedLoading(); - - // create our loader and set up some event listeners - var loader :Loader = new Loader(); - _media = loader; - var info :LoaderInfo = loader.contentLoaderInfo; - info.addEventListener(Event.COMPLETE, loadingComplete); - info.addEventListener(IOErrorEvent.IO_ERROR, loadError); - info.addEventListener(ProgressEvent.PROGRESS, loadProgress); - - // create a mask to prevent the media from drawing out of bounds - if (getMaxContentWidth() < int.MAX_VALUE && - getMaxContentHeight() < int.MAX_VALUE) { - configureMask(getMaxContentWidth(), getMaxContentHeight()); - } - - // start it loading, add it as a child - loader.load(new URLRequest(url), getContext(url)); - addChild(loader); - - try { - updateContentDimensions(info.width, info.height); - } catch (err :Error) { - // an error is thrown trying to access these props before they're - // ready - } - } - - /** - * Display a 'broken image' to indicate there were troubles with - * loading the media. - */ - protected function setupBrokenImage (w :int = -1, h :int = -1) :void - { - if (w == -1) { - w = 100; - } - if (h == -1) { - h = 100; - } - setMediaObject(ImageUtil.createErrorImage(w, h)); - } - - /** - * Get the application domain being used by this media, or null if - * none or not applicable. - */ - public function getApplicationDomain () :ApplicationDomain - { - return (_media is Loader) - ? (_media as Loader).contentLoaderInfo.applicationDomain - : null; - } - - /** - * Unload the media we're displaying, clean up any resources. - * - * @param completely if true, we're going away and should stop - * everything. Otherwise, we're just loading up new media. - */ - public function shutdown (completely :Boolean = true) :void - { - try { - // remove the mask - if (_media != null && _media.mask != null) { - removeChild(_media.mask); - _media.mask = null; - } - - if (_media is Loader) { - var loader :Loader = (_media as Loader); - // remove any listeners - removeListeners(loader.contentLoaderInfo); - - // dispose of media - try { - loader.close(); - } catch (ioe :IOError) { - // ignore - } - loader.unload(); - - removeChild(loader); - - } else if (_media is VideoDisplayer) { - var vid :VideoDisplayer = (_media as VideoDisplayer); - vid.removeEventListener(VideoDisplayer.SIZE_KNOWN, handleVideoSizeKnown); - vid.removeEventListener(VideoDisplayer.VIDEO_ERROR, handleVideoError); - vid.shutdown(); - removeChild(vid); - - } else if (_media != null) { - removeChild(_media); - } - } catch (ioe :IOError) { - log.warning("Error shutting down media: " + ioe); - log.logStackTrace(ioe); - } - - // clean everything up - _w = 0; - _h = 0; - _media = null; - } - - /** - * Get the width of the content, bounded by the maximum. - */ - public function getContentWidth () :int - { - return Math.min(Math.abs(_w * getMediaScaleX()), getMaxContentWidth()); - } - - /** - * Get the height of the content, bounded by the maximum. - */ - public function getContentHeight () :int - { - return Math.min(Math.abs(_h * getMediaScaleY()), getMaxContentHeight()); - } - - /** - * Get the maximum allowable width for our content. - */ - public function getMaxContentWidth () :int - { - return int.MAX_VALUE; - } - - /** - * Get the maximum allowable height for our content. - */ - public function getMaxContentHeight () :int - { - return int.MAX_VALUE; - } - - /** - * Get the X scaling factor to use on the actual media. - */ - public function getMediaScaleX () :Number - { - return 1; - } - - /** - * Get the Y scaling factor to use on the actual media. - */ - public function getMediaScaleY () :Number - { - return 1; - } - - /** - * Called by MediaWrapper as notification that its size has changed. - */ - public function containerDimensionsUpdated (newWidth :Number, newHeight :Number) :void - { - // do nothing in base MediaContainer - } - - override public function toString () :String - { - return "MediaContainer[url=" + _url + "]"; - } - - /** - * Return the LoaderContext that should be used to load the media - * at the specified url. - */ - protected function getContext (url :String) :LoaderContext - { - if (isImage(url)) { - // load images into our domain so that we can view their pixels - return new LoaderContext(true, - new ApplicationDomain(ApplicationDomain.currentDomain), - SecurityDomain.currentDomain); - - } else { - // share nothing, trust nothing - return new LoaderContext(false, new ApplicationDomain(null), null); - } - } - - /** - * Does the specified url represent an image? - */ - protected function isImage (url :String) :Boolean - { - // look at the last 4 characters in the lowercased url - switch (url.toLowerCase().slice(-4)) { - case ".png": - case ".jpg": - case ".gif": - return true; - - default: - return false; - } - } - - /** - * Remove our listeners from the LoaderInfo object. - */ - protected function removeListeners (info :LoaderInfo) :void - { - info.removeEventListener(Event.COMPLETE, loadingComplete); - info.removeEventListener(IOErrorEvent.IO_ERROR, loadError); - info.removeEventListener(ProgressEvent.PROGRESS, loadProgress); - } - - /** - * A callback to receive IO_ERROR events. - */ - protected function loadError (event :IOErrorEvent) :void - { - stoppedLoading(); - setupBrokenImage(-1, -1); - } - - /** - * A callback to receive PROGRESS events. - */ - protected function loadProgress (event :ProgressEvent) :void - { - updateLoadingProgress(event.bytesLoaded, event.bytesTotal); - var info :LoaderInfo = (event.target as LoaderInfo); - try { - updateContentDimensions(info.width, info.height); - } catch (err :Error) { - // an error is thrown trying to access these props before they're - // ready - } - } - - /** - * Handles video size known. - */ - protected function handleVideoSizeKnown (event :ValueEvent) :void - { - var args :Array = (event.value as Array); - updateContentDimensions(int(args[0]), int(args[1])); - } - - /** - * Handles an error loading a video. - */ - protected function handleVideoError (event :ValueEvent) :void - { - log.warning("Error loading video [cause=" + event.value + "]."); - stoppedLoading(); - setupBrokenImage(-1, -1); - } - - /** - * Callback function to receive COMPLETE events for swfs or images. - */ - protected function loadingComplete (event :Event) :void - { - var info :LoaderInfo = (event.target as LoaderInfo); - removeListeners(info); - -// trace("Loading complete: " + info.url + -// ", childAllowsParent=" + info.childAllowsParent + -// ", parentAllowsChild=" + info.parentAllowsChild + -// ", sameDomain=" + info.sameDomain); - - updateContentDimensions(info.width, info.height); - updateLoadingProgress(1, 1); - stoppedLoading(); - } - - /** - * Configure the mask for this object. - */ - protected function configureMask (ww :int, hh :int) :void - { - var mask :Shape; - if (_media.mask != null) { - mask = (_media.mask as Shape); - - } else { - mask = new Shape(); - // the mask must be added to the display list (which is wacky) - addChild(mask); - _media.mask = mask; - } - - mask.graphics.clear(); - mask.graphics.beginFill(0xFFFFFF); - mask.graphics.drawRect(0, 0, ww, hh); - mask.graphics.endFill(); - } - - /** - * Called during loading as we figure out how big the content we're - * loading is. - */ - protected function updateContentDimensions (ww :int, hh :int) :void - { - // update our saved size, and possibly notify our container - if (_w != ww || _h != hh) { - _w = ww; - _h = hh; - contentDimensionsUpdated(); - // dispatch an event to any listeners - dispatchEvent(new ValueEvent(SIZE_KNOWN, [ ww, hh ])); - } - } - - /** - * Called when we know the true size of the content. - */ - protected function contentDimensionsUpdated () :void - { - // nada, by default - } - - /** - * Update the graphics to indicate how much is loaded. - */ - protected function updateLoadingProgress ( - soFar :Number, total :Number) :void - { - // nada, by default - } - - /** - * Called when we've started loading new media. Will not be called - * for new media that does not require loading. - */ - protected function startedLoading () :void - { - // nada - } - - /** - * Called when we've stopped loading, which may be as a result of - * completion, an error while loading, or early termination. - */ - protected function stoppedLoading () :void - { - // nada - } - - /** The unaltered URL of the content we're displaying. */ - protected var _url :String; - - /** The unscaled width of our content. */ - protected var _w :int; - - /** The unscaled height of our content. */ - protected var _h :int; - - /** Either a Loader or a VideoDisplay. */ - protected var _media :DisplayObject; -} -} diff --git a/src/as/com/threerings/util/MenuUtil.as b/src/as/com/threerings/util/MenuUtil.as deleted file mode 100644 index bb6b62d1c..000000000 --- a/src/as/com/threerings/util/MenuUtil.as +++ /dev/null @@ -1,48 +0,0 @@ -// -// $Id$ -// -// Narya library - tools for developing networked games -// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved -// http://www.threerings.net/code/narya/ -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -package com.threerings.util { - -import flash.ui.ContextMenuItem; -import flash.events.ContextMenuEvent; - -/** - */ -public class MenuUtil -{ - /** - * Create a menu item that will submit a controller command when selected. - */ - public static function createControllerMenuItem ( - caption :String, cmd :String, arg :Object = null, - separatorBefore :Boolean = false, enabled :Boolean = true, - visible :Boolean = true) :ContextMenuItem - { - var item :ContextMenuItem = - new ContextMenuItem(caption, separatorBefore, enabled, visible); - item.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, - function (event :ContextMenuEvent) :void { - CommandEvent.dispatch(event.mouseTarget, cmd, arg); - }); - return item; - } -} -} diff --git a/src/as/com/threerings/util/VideoDisplayer.as b/src/as/com/threerings/util/VideoDisplayer.as deleted file mode 100644 index 155b91bd9..000000000 --- a/src/as/com/threerings/util/VideoDisplayer.as +++ /dev/null @@ -1,269 +0,0 @@ -package com.threerings.util { // TODO: Move. - -import flash.display.Sprite; - -import flash.events.AsyncErrorEvent; -import flash.events.IOErrorEvent; -import flash.events.Event; -import flash.events.MouseEvent; -import flash.events.NetStatusEvent; -import flash.events.SecurityErrorEvent; -import flash.events.TimerEvent; - -import flash.media.Video; - -import flash.net.NetConnection; -import flash.net.NetStream; - -import flash.utils.Timer; - -public class VideoDisplayer extends Sprite -{ - /** A value event dispatched when the size of the video is known. - * Value: [ width, height ]. */ - public static const SIZE_KNOWN :String = "videoDisplayerSizeKnown"; - - /** A value event sent when there's an error loading the video. - * Value: original error event. */ - public static const VIDEO_ERROR :String = "videoDisplayerError"; - - /** - * Create a video displayer. - */ - public function VideoDisplayer () - { - _vid = new Video(); - addChild(_vid); - - addEventListener(MouseEvent.ROLL_OVER, handleRollOver); - addEventListener(MouseEvent.ROLL_OUT, handleRollOut); - - _videoChecker.addEventListener(TimerEvent.TIMER, handleVideoCheck); - - _pauser = new Sprite(); - _pauser.addEventListener(MouseEvent.CLICK, handleClick); - redrawPauser(); - } - - /** - * Start playing a video! - */ - public function setup (url :String) :void - { - _netCon = new NetConnection(); - _netCon.addEventListener(NetStatusEvent.NET_STATUS, handleNetStatus); - - // error handlers - _netCon.addEventListener(AsyncErrorEvent.ASYNC_ERROR, handleAsyncError); - _netCon.addEventListener(IOErrorEvent.IO_ERROR, handleIOError); - _netCon.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleSecurityError); - - _netCon.connect(null); - _netStream = new NetStream(_netCon); - // pass in refs to some of our protected methods - _netStream.client = { - onMetaData: metaDataReceived - }; - _netStream.addEventListener(NetStatusEvent.NET_STATUS, handleStreamNetStatus); - - _vid.attachNetStream(_netStream); - _videoChecker.start(); - _netStream.play(url); - _paused = false; - } - - /** - * Stop playing our video. - */ - public function shutdown () :void - { - _videoChecker.reset(); - _vid.attachNetStream(null); - - if (_netStream != null) { - _netStream.close(); - _netStream.removeEventListener(NetStatusEvent.NET_STATUS, handleStreamNetStatus); - _netStream = null; - } - if (_netCon != null) { - _netCon.close(); - _netCon.removeEventListener(NetStatusEvent.NET_STATUS, handleNetStatus); - _netCon.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, handleAsyncError); - _netCon.removeEventListener(IOErrorEvent.IO_ERROR, handleIOError); - _netCon.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, handleSecurityError); - _netCon = null; - } - } - - /** - * Check to see if we now know the dimensions of the video. - */ - protected function handleVideoCheck (event :TimerEvent) :void - { - if (_vid.videoWidth == 0 || _vid.videoHeight == 0) { - return; // not known yet! - } - - // stop the checker timer - _videoChecker.stop(); - - // set up the width/height - _vid.width = _vid.videoWidth; - _vid.height = _vid.videoHeight; - redrawPauser(); - - // tell any interested parties - dispatchEvent(new ValueEvent(SIZE_KNOWN, [ _vid.videoWidth, _vid.videoHeight ])); - } - - protected function handleRollOver (event :MouseEvent) :void - { - addChild(_pauser); - } - - protected function handleRollOut (event :MouseEvent) :void - { - if (_pauser.parent) { - removeChild(_pauser); - } - } - - protected function handleClick (event :MouseEvent) :void - { - // the buck stops here! - event.stopImmediatePropagation(); - - if (_paused) { - _netStream.resume(); - _paused = false; - - } else { - _netStream.pause(); - _paused = true; - } - redrawPauser(); - } - - /** - * Draw the pauser sprite, update it's location. - * This will become something artistic, etc. - */ - protected function redrawPauser () :void - { - with (_pauser.graphics) { - clear(); - // draw a nice circle - beginFill(0x333333); - drawCircle(0, 0, 20); - endFill(); - lineStyle(2, 0); - drawCircle(0, 0, 20); - - if (_paused) { - lineStyle(0, 0, 0); - beginFill(0x00FF00); - moveTo(-4, -10); - lineTo(4, 0); - lineTo(-4, 10); - lineTo(-4, -10); - endFill(); - - } else { - lineStyle(2, 0x00FF00); - moveTo(-4, -10); - lineTo(-4, 10); - moveTo(4, -10); - lineTo(4, 10); - } - } - - // and update the location - _pauser.x = _vid.width/2; - _pauser.y = _vid.height/2; - } - - protected function handleNetStatus (event :NetStatusEvent) :void - { - var info :Object = event.info; - if ("error" == info.level) { - trace("NetStatus error: " + info.code); - redispatchError(event); - return; - } - // else info.level == "status" - switch (info.code) { - case "NetConnection.Connect.Success": - case "NetConnection.Connect.Closed": - // these status events we ignore - break; - - default: - trace("NetStatus status: " + info.code); - break; - } - } - - protected function handleStreamNetStatus (event :NetStatusEvent) :void - { - if (event.info.code == "NetStream.Play.Stop") { - _netStream.seek(0); - _netStream.pause(); - _paused = true; - redrawPauser(); - } - } - - protected function handleAsyncError (event :AsyncErrorEvent) :void - { - trace("AsyncError: " + event); - redispatchError(event); - } - - protected function handleIOError (event :IOErrorEvent) :void - { - trace("IOError: " + event); - redispatchError(event); - } - - protected function handleSecurityError (event :SecurityErrorEvent) :void - { - trace("SecurityError: " + event); - redispatchError(event); - } - - /** - * Redispatch some error we received to our listeners. - */ - protected function redispatchError (event :Event) :void - { - dispatchEvent(new ValueEvent(VIDEO_ERROR, event)); - } - - /** - * Called when metadata (if any) is found in the video stream. - */ - protected function metaDataReceived (obj :Object) :void - { - trace("Got video metadata:"); - for (var n :String in obj) { - trace(" " + n + ": " + obj[n]); - } - } - - protected var _vid :Video; - - protected var _paused :Boolean = false; - - protected var _netCon :NetConnection; - - protected var _netStream :NetStream; - - protected var _pauser :Sprite; - - /** Checks the video every 100ms to see if the dimensions are now know. - * Yes, this is how to do it. We could trigger on ENTER_FRAME, but then - * we may not know the dimensions unless we're added on the display list, - * and we want this to work in the general case. */ - protected var _videoChecker :Timer = new Timer(100); -} -}