////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2008-2016 Esri. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
package com.esri.builder.controllers.supportClasses
{

import com.esri.builder.model.CustomWidgetType;
import com.esri.builder.model.WidgetType;
import com.esri.builder.supportClasses.FileUtil;
import com.esri.builder.supportClasses.LogUtil;

import flash.events.EventDispatcher;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.utils.ByteArray;

import modules.IBuilderModule;
import modules.supportClasses.CustomXMLModule;

import mx.core.FlexGlobals;
import mx.events.ModuleEvent;
import mx.logging.ILogger;
import mx.logging.Log;
import mx.modules.IModuleInfo;
import mx.modules.ModuleManager;

public class WidgetTypeLoader extends EventDispatcher
{
    private static const LOG:ILogger = LogUtil.createLogger(WidgetTypeLoader);

    internal static var loadedModuleInfos:Array = [];

    private var swf:File;
    private var config:File;

    //need reference when loading to avoid being garbage collected before load completes
    private var moduleInfo:IModuleInfo;

    //requires either swf or config
    public function WidgetTypeLoader(swf:File = null, config:File = null)
    {
        this.swf = swf;
        this.config = config;
    }

    public function get name():String
    {
        var fileName:String;

        if (swf && swf.exists)
        {
            fileName = FileUtil.getFileName(swf);
        }
        else if (config && config.exists)
        {
            fileName = FileUtil.getFileName(config);
        }

        return fileName;
    }

    public function load():void
    {
        if (swf && swf.exists)
        {
            loadModule();
        }
        else if (!swf.exists && config.exists)
        {
            loadConfigModule();
        }
        else
        {
            dispatchError();
        }
    }

    private function loadConfigModule():void
    {
        if (Log.isInfo())
        {
            LOG.info('Loading XML module: {0}', config.url);
        }

        var moduleConfig:XML = readModuleConfig(config);
        if (moduleConfig)
        {
            var customWidgetType:CustomWidgetType = parseCustomWidgetType(moduleConfig);
            if (customWidgetType)
            {
                dispatchComplete(customWidgetType);
                return;
            }
        }

        dispatchError();
    }

    private function loadModule():void
    {
        if (Log.isInfo())
        {
            LOG.info('Loading SWF module: {0}', swf.url);
        }

        moduleInfo = ModuleManager.getModule(swf.url);

        if (moduleInfo.ready)
        {
            if (Log.isInfo())
            {
                LOG.info('Unloading module: {0}', swf.url);
            }

            moduleInfo.addEventListener(ModuleEvent.UNLOAD, moduleInfo_unloadHandler);
            moduleInfo.release();
            moduleInfo.unload();
        }
        else
        {
            if (Log.isInfo())
            {
                LOG.info('Loading module: {0}', swf.url);
            }

            var fileBytes:ByteArray = new ByteArray();
            var fileStream:FileStream = new FileStream();
            fileStream.open(swf, FileMode.READ);
            fileStream.readBytes(fileBytes);
            fileStream.close();

            moduleInfo.addEventListener(ModuleEvent.READY, moduleInfo_readyHandler);
            moduleInfo.addEventListener(ModuleEvent.ERROR, moduleInfo_errorHandler);
            moduleInfo.load(null, null, fileBytes, FlexGlobals.topLevelApplication.moduleFactory);
        }
    }

    private function moduleInfo_unloadHandler(event:ModuleEvent):void
    {
        if (Log.isInfo())
        {
            LOG.info('Module unloaded: {0}', swf.url);
        }

        var moduleInfo:IModuleInfo = event.module;
        moduleInfo.removeEventListener(ModuleEvent.UNLOAD, moduleInfo_unloadHandler);
        var moduleInfoIndex:int = loadedModuleInfos.indexOf(moduleInfo);
        if (moduleInfoIndex > -1)
        {
            loadedModuleInfos.splice(moduleInfoIndex, 1);
        }
        this.moduleInfo = null;
        FlexGlobals.topLevelApplication.callLater(loadModule);
    }

    private function moduleInfo_readyHandler(event:ModuleEvent):void
    {
        if (Log.isInfo())
        {
            LOG.info('Module loaded: {0}', swf.url);
        }

        var moduleInfo:IModuleInfo = event.currentTarget as IModuleInfo;
        moduleInfo.removeEventListener(ModuleEvent.READY, moduleInfo_readyHandler);
        moduleInfo.removeEventListener(ModuleEvent.ERROR, moduleInfo_errorHandler);

        if (config && config.exists)
        {
            if (Log.isInfo())
            {
                LOG.info('Reading module config: {0}', config.url);
            }
            var moduleConfig:XML = readModuleConfig(config);
        }

        const builderModule:IBuilderModule = event.module.factory.create() as IBuilderModule;
        if (builderModule)
        {
            if (Log.isInfo())
            {
                LOG.info('Widget type created for module: {0}', swf.url);
            }
            var widgetType:WidgetType = getWidgetType(moduleInfo, builderModule, moduleConfig);
        }

        loadedModuleInfos.push(moduleInfo);
        this.moduleInfo = null;
        dispatchComplete(widgetType);
    }

    private function dispatchComplete(widgetType:WidgetType):void
    {
        if (Log.isInfo())
        {
            LOG.info('Module load complete: {0}', name);
        }

        dispatchEvent(new WidgetTypeLoaderEvent(WidgetTypeLoaderEvent.LOAD_COMPLETE, widgetType));
    }

    private function getWidgetType(moduleInfo:IModuleInfo, builderModule:IBuilderModule, moduleConfig:XML):WidgetType
    {
        var customModulesDirectoryURL:String = WellKnownDirectories.getInstance().customModules.url;
        var isCustomModule:Boolean = (moduleInfo.url.indexOf(customModulesDirectoryURL) > -1);
        if (moduleConfig)
        {
            var configXML:XML = moduleConfig.configuration[0];
            var version:String = moduleConfig.widgetversion[0];
        }

        return isCustomModule ?
            new CustomWidgetType(builderModule, version, configXML) :
            new WidgetType(builderModule);
    }

    private function readModuleConfig(configFile:File):XML
    {
        var configXML:XML;

        var fileStream:FileStream = new FileStream();
        try
        {
            fileStream.open(configFile, FileMode.READ);
            configXML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
        }
        catch (e:Error)
        {
            //ignore
            if (Log.isInfo())
            {
                LOG.info('Could not read module config: {0}', e.toString());
            }
        }
        finally
        {
            fileStream.close();
        }

        return configXML;
    }

    private function moduleInfo_errorHandler(event:ModuleEvent):void
    {
        var moduleInfo:IModuleInfo = event.module;
        moduleInfo.removeEventListener(ModuleEvent.ERROR, moduleInfo_errorHandler);
        moduleInfo.removeEventListener(ModuleEvent.READY, moduleInfo_readyHandler);
        this.moduleInfo = null;
        dispatchError();
    }

    private function dispatchError():void
    {
        if (Log.isInfo())
        {
            LOG.info('Module load failed: {0}', name);
        }

        dispatchEvent(new WidgetTypeLoaderEvent(WidgetTypeLoaderEvent.LOAD_ERROR));
    }

    private function parseCustomWidgetType(configXML:XML):CustomWidgetType
    {
        if (Log.isInfo())
        {
            LOG.info('Creating widget type from XML: {0}', configXML);
        }

        var customModule:CustomXMLModule = new CustomXMLModule();
        customModule.widgetName = configXML.name;
        customModule.isOpenByDefault = (configXML.openbydefault == 'true');

        var widgetLabel:String = configXML.label[0];
        var widgetDescription:String = configXML.description[0];
        var widgetHelpURL:String = configXML.helpurl[0];
        var widgetConfiguration:XML = configXML.configuration[0] ? configXML.configuration[0] : <configuration/>;
        var widgetVersion:String = configXML.widgetversion[0];

        customModule.widgetIconLocation = createWidgetIconPath(configXML.icon[0], customModule.widgetName);
        customModule.widgetLabel = widgetLabel ? widgetLabel : customModule.widgetName;
        customModule.widgetDescription = widgetDescription ? widgetDescription : "";
        customModule.widgetHelpURL = widgetHelpURL ? widgetHelpURL : "";

        return new CustomWidgetType(customModule, widgetVersion, widgetConfiguration);
    }

    private function createWidgetIconPath(iconPath:String, widgetName:String):String
    {
        var widgetIconPath:String;

        if (iconPath)
        {
            widgetIconPath = "widgets/" + widgetName + "/" + iconPath;
        }
        else
        {
            widgetIconPath = "assets/images/i_widget.png";
        }

        return widgetIconPath;
    }
}
}

////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2008-2016 Esri. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
package com.esri.builder.controllers.supportClasses
{

import com.esri.builder.model.CustomWidgetType;
import com.esri.builder.model.WidgetType;
import com.esri.builder.supportClasses.FileUtil;
import com.esri.builder.supportClasses.LogUtil;

import flash.events.EventDispatcher;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.utils.ByteArray;

import modules.IBuilderModule;
import modules.supportClasses.CustomXMLModule;

import mx.core.FlexGlobals;
import mx.events.ModuleEvent;
import mx.logging.ILogger;
import mx.logging.Log;
import mx.modules.IModuleInfo;
import mx.modules.ModuleManager;

public class WidgetTypeLoader extends EventDispatcher
{
    private static const LOG:ILogger = LogUtil.createLogger(WidgetTypeLoader);

    internal static var loadedModuleInfos:Array = [];

    private var swf:File;
    private var config:File;

    //need reference when loading to avoid being garbage collected before load completes
    private var moduleInfo:IModuleInfo;

    //requires either swf or config
    public function WidgetTypeLoader(swf:File = null, config:File = null)
    {
        this.swf = swf;
        this.config = config;
    }

    public function get name():String
    {
        var fileName:String;

        if (swf && swf.exists)
        {
            fileName = FileUtil.getFileName(swf);
        }
        else if (config && config.exists)
        {
            fileName = FileUtil.getFileName(config);
        }

        return fileName;
    }

    public function load():void
    {
        if (swf && swf.exists)
        {
            loadModule();
        }
        else if (config && config.exists)
        {
            loadConfigModule();
        }
        else
        {
            dispatchError();
        }
    }

    private function loadConfigModule():void
    {
        if (Log.isInfo())
        {
            LOG.info('Loading XML module: {0}', config.url);
        }

        var moduleConfig:XML = readModuleConfig(config);
        if (moduleConfig)
        {
            var customWidgetType:CustomWidgetType = parseCustomWidgetType(moduleConfig);
            if (customWidgetType)
            {
                dispatchComplete(customWidgetType);
                return;
            }
        }

        dispatchError();
    }

    private function loadModule():void
    {
        if (Log.isInfo())
        {
            LOG.info('Loading SWF module: {0}', swf.url);
        }

        moduleInfo = ModuleManager.getModule(swf.url);

        if (moduleInfo.ready)
        {
            if (Log.isInfo())
            {
                LOG.info('Unloading module: {0}', swf.url);
            }

            moduleInfo.addEventListener(ModuleEvent.UNLOAD, moduleInfo_unloadHandler);
            moduleInfo.release();
            moduleInfo.unload();
        }
        else
        {
            if (Log.isInfo())
            {
                LOG.info('Loading module: {0}', swf.url);
            }

            var fileBytes:ByteArray = new ByteArray();
            var fileStream:FileStream = new FileStream();
            fileStream.open(swf, FileMode.READ);
            fileStream.readBytes(fileBytes);
            fileStream.close();

            moduleInfo.addEventListener(ModuleEvent.READY, moduleInfo_readyHandler);
            moduleInfo.addEventListener(ModuleEvent.ERROR, moduleInfo_errorHandler);
            moduleInfo.load(null, null, fileBytes, FlexGlobals.topLevelApplication.moduleFactory);
        }
    }

    private function moduleInfo_unloadHandler(event:ModuleEvent):void
    {
        if (Log.isInfo())
        {
            LOG.info('Module unloaded: {0}', swf.url);
        }

        var moduleInfo:IModuleInfo = event.module;
        moduleInfo.removeEventListener(ModuleEvent.UNLOAD, moduleInfo_unloadHandler);
        var moduleInfoIndex:int = loadedModuleInfos.indexOf(moduleInfo);
        if (moduleInfoIndex > -1)
        {
            loadedModuleInfos.splice(moduleInfoIndex, 1);
        }
        this.moduleInfo = null;
        FlexGlobals.topLevelApplication.callLater(loadModule);
    }

    private function moduleInfo_readyHandler(event:ModuleEvent):void
    {
        if (Log.isInfo())
        {
            LOG.info('Module loaded: {0}', swf.url);
        }

        var moduleInfo:IModuleInfo = event.currentTarget as IModuleInfo;
        moduleInfo.removeEventListener(ModuleEvent.READY, moduleInfo_readyHandler);
        moduleInfo.removeEventListener(ModuleEvent.ERROR, moduleInfo_errorHandler);

        if (config && config.exists)
        {
            if (Log.isInfo())
            {
                LOG.info('Reading module config: {0}', config.url);
            }
            var moduleConfig:XML = readModuleConfig(config);
        }

        const builderModule:IBuilderModule = event.module.factory.create() as IBuilderModule;
        if (builderModule)
        {
            if (Log.isInfo())
            {
                LOG.info('Widget type created for module: {0}', swf.url);
            }
            var widgetType:WidgetType = getWidgetType(moduleInfo, builderModule, moduleConfig);
        }

        loadedModuleInfos.push(moduleInfo);
        this.moduleInfo = null;
        dispatchComplete(widgetType);
    }

    private function dispatchComplete(widgetType:WidgetType):void
    {
        if (Log.isInfo())
        {
            LOG.info('Module load complete: {0}', name);
        }

        dispatchEvent(new WidgetTypeLoaderEvent(WidgetTypeLoaderEvent.LOAD_COMPLETE, widgetType));
    }

    private function getWidgetType(moduleInfo:IModuleInfo, builderModule:IBuilderModule, moduleConfig:XML):WidgetType
    {
        var customModulesDirectoryURL:String = WellKnownDirectories.getInstance().customModules.url;
        var isCustomModule:Boolean = (moduleInfo.url.indexOf(customModulesDirectoryURL) > -1);
        if (moduleConfig)
        {
            var configXML:XML = moduleConfig.configuration[0];
            var version:String = moduleConfig.widgetversion[0];
        }

        return isCustomModule ?
            new CustomWidgetType(builderModule, version, configXML) :
            new WidgetType(builderModule);
    }

    private function readModuleConfig(configFile:File):XML
    {
        var configXML:XML;

        var fileStream:FileStream = new FileStream();
        try
        {
            fileStream.open(configFile, FileMode.READ);
            configXML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
        }
        catch (e:Error)
        {
            //ignore
            if (Log.isInfo())
            {
                LOG.info('Could not read module config: {0}', e.toString());
            }
        }
        finally
        {
            fileStream.close();
        }

        return configXML;
    }

    private function moduleInfo_errorHandler(event:ModuleEvent):void
    {
        var moduleInfo:IModuleInfo = event.module;
        moduleInfo.removeEventListener(ModuleEvent.ERROR, moduleInfo_errorHandler);
        moduleInfo.removeEventListener(ModuleEvent.READY, moduleInfo_readyHandler);
        this.moduleInfo = null;
        dispatchError();
    }

    private function dispatchError():void
    {
        if (Log.isInfo())
        {
            LOG.info('Module load failed: {0}', name);
        }

        dispatchEvent(new WidgetTypeLoaderEvent(WidgetTypeLoaderEvent.LOAD_ERROR));
    }

    private function parseCustomWidgetType(configXML:XML):CustomWidgetType
    {
        if (Log.isInfo())
        {
            LOG.info('Creating widget type from XML: {0}', configXML);
        }

        var customModule:CustomXMLModule = new CustomXMLModule();
        customModule.widgetName = configXML.name;
        customModule.isOpenByDefault = (configXML.openbydefault == 'true');

        var widgetLabel:String = configXML.label[0];
        var widgetDescription:String = configXML.description[0];
        var widgetHelpURL:String = configXML.helpurl[0];
        var widgetConfiguration:XML = configXML.configuration[0] ? configXML.configuration[0] : <configuration/>;
        var widgetVersion:String = configXML.widgetversion[0];

        customModule.widgetIconLocation = createWidgetIconPath(configXML.icon[0], customModule.widgetName);
        customModule.widgetLabel = widgetLabel ? widgetLabel : customModule.widgetName;
        customModule.widgetDescription = widgetDescription ? widgetDescription : "";
        customModule.widgetHelpURL = widgetHelpURL ? widgetHelpURL : "";

        return new CustomWidgetType(customModule, widgetVersion, widgetConfiguration);
    }

    private function createWidgetIconPath(iconPath:String, widgetName:String):String
    {
        var widgetIconPath:String;

        if (iconPath)
        {
            widgetIconPath = "widgets/" + widgetName + "/" + iconPath;
        }
        else
        {
            widgetIconPath = "assets/images/i_widget.png";
        }

        return widgetIconPath;
    }
}
}

Fix typo when checking for custom widget config existence.


//
// $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.Loader;
import flash.display.LoaderInfo;

import flash.errors.IllegalOperationError;

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;

import flash.utils.ByteArray;

import flash.system.ApplicationDomain;
import flash.system.LoaderContext;

/**
 * Allows you to load an embeded SWF stored as a Byte Array then access any stored classes
 * within the SWF.
 * Embed your swf like:
 * [Embed(source="foo.swf", mimeType="application/octet-stream"]
 * Then, instantiate that class and pass it to load() as a ByteArray.
 *
 * An Event.COMPLETE will be dispatched upon the successful completion of a call to
 * {@link load}.  IOErrorEvent.IO_ERROR will be dispatched if there's a problem reading the
 * ByteArray.
 *
 * @deprecated Content packs are coming, and symbols can be embedded directly
 * by using [Embed(source="foo.swf#somesymbol")]
 */
public class EmbeddedSwfLoader extends EventDispatcher
{
    public function EmbeddedSwfLoader ()
    {
        _loader = new Loader();
        _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, dispatchEvent);
        _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, dispatchEvent);
    }

// This doesn't work. We cannot write parameters to the contentLoaderInfo.
// So: there is no way to pass parameters to content loaded using loadBytes,
// and there's no way to pass parameters to any other content without
// destroying caching (because you must append them to the url). Stupid flash.
//    /**
//     * Set a parameter accessible to the loaded content.
//     */
//    public function setParameter (name :String, val :String) :void
//    {
//        _loader.contentLoaderInfo.parameters[name] = val;
//    }

    /**
     * Load the SWF from a Byte Array.  A CLASS_LOADED event will be dispatched on successful
     * completion of the load.  If any errors occur, a LOAD_ERROR event will be dispatched.
     */
    public function load (byteArray :ByteArray) :void
    {
        var context :LoaderContext = new LoaderContext();
        context.applicationDomain = ApplicationDomain.currentDomain;
        _loader.loadBytes(byteArray, context);
    }

    /**
     * Get the top-level display object defined in the loaded SWF.
     */
    public function getContent () :DisplayObject
    {
        checkLoaded();
        return _loader.content;
    }

    /**
     * Retrieves a class definition from the loaded swf.
     *
     * @throws IllegalOperationError when the swf has not completed loading or the class does
     * not exist
     */
    public function getClass (className :String) :Class
    {
        return getSymbol(className) as Class;
    }

    /**
     * Retrieves a Function definition from the loaded swf.
     *
     * @throws IllegalOperationError when the swf has not completed loading or the class does
     * not exist
     */
    public function getFunction (functionName :String) :Function
    {
        return getSymbol(functionName) as Function;
    }

    /**
     * Retrieves a symbol definition from the loaded swf.
     *
     * @throws IllegalOperationError when the swf has not completed loading or the class does
     * not exist
     */
    public function getSymbol (symbolName :String) :Object
    {
        checkLoaded();
        try {
            return _loader.contentLoaderInfo.applicationDomain.getDefinition(symbolName);
        } catch (e: Error) {
            throw new IllegalOperationError(symbolName + " definition not found");
        }
        return null;
    }

    /**
     * Checks if a symbol exists in the library.
     *
     * @throws IllegalOperationError when the swf has not completed loading.
     */
    public function isSymbol (className :String) :Boolean
    {
        checkLoaded();
        return _loader.contentLoaderInfo.applicationDomain.hasDefinition(className);
    }

    /**
     * Validate that the load operation is complete.
     */
    protected function checkLoaded () :void
    {
        var loaderInfo :LoaderInfo = _loader.contentLoaderInfo;
        if (loaderInfo.bytesTotal == 0 || loaderInfo.bytesLoaded != loaderInfo.bytesTotal) {

            throw new IllegalOperationError("SWF has not completed loading");
        }
    }

    protected var _loader :Loader;
}
}

//
// $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.Loader;
import flash.display.LoaderInfo;

import flash.errors.IllegalOperationError;

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;

import flash.utils.ByteArray;

import flash.system.ApplicationDomain;
import flash.system.LoaderContext;

/**
 * Allows you to load an embeded SWF stored as a Byte Array then access any stored classes
 * within the SWF.
 * Embed your swf like:
 * [Embed(source="foo.swf", mimeType="application/octet-stream"]
 * Then, instantiate that class and pass it to load() as a ByteArray.
 *
 * An Event.COMPLETE will be dispatched upon the successful completion of a call to
 * {@link load}.  IOErrorEvent.IO_ERROR will be dispatched if there's a problem reading the
 * ByteArray.
 *
 * @deprecated Content packs are coming, and symbols can be embedded directly
 * by using [Embed(source="foo.swf#somesymbol")]
 */
public class EmbeddedSwfLoader extends EventDispatcher
{
    public function EmbeddedSwfLoader (useSubDomain :Boolean = false)
    {
        _useSubDomain = useSubDomain;
        _loader = new Loader();
        _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, dispatchEvent);
        _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, dispatchEvent);
    }

// This doesn't work. We cannot write parameters to the contentLoaderInfo.
// So: there is no way to pass parameters to content loaded using loadBytes,
// and there's no way to pass parameters to any other content without
// destroying caching (because you must append them to the url). Stupid flash.
//    /**
//     * Set a parameter accessible to the loaded content.
//     */
//    public function setParameter (name :String, val :String) :void
//    {
//        _loader.contentLoaderInfo.parameters[name] = val;
//    }

    /**
     * Load the SWF from a Byte Array.  A CLASS_LOADED event will be dispatched on successful
     * completion of the load.  If any errors occur, a LOAD_ERROR event will be dispatched.
     */
    public function load (byteArray :ByteArray) :void
    {
        var context :LoaderContext = new LoaderContext();
        context.applicationDomain = _useSubDomain ?
            new ApplicationDomain(ApplicationDomain.currentDomain) :
            ApplicationDomain.currentDomain;
        _loader.loadBytes(byteArray, context);
    }

    /**
     * Get the top-level display object defined in the loaded SWF.
     */
    public function getContent () :DisplayObject
    {
        checkLoaded();
        return _loader.content;
    }

    /**
     * Retrieves a class definition from the loaded swf.
     *
     * @throws IllegalOperationError when the swf has not completed loading or the class does
     * not exist
     */
    public function getClass (className :String) :Class
    {
        return getSymbol(className) as Class;
    }

    /**
     * Retrieves a Function definition from the loaded swf.
     *
     * @throws IllegalOperationError when the swf has not completed loading or the class does
     * not exist
     */
    public function getFunction (functionName :String) :Function
    {
        return getSymbol(functionName) as Function;
    }

    /**
     * Retrieves a symbol definition from the loaded swf.
     *
     * @throws IllegalOperationError when the swf has not completed loading or the class does
     * not exist
     */
    public function getSymbol (symbolName :String) :Object
    {
        checkLoaded();
        try {
            return _loader.contentLoaderInfo.applicationDomain.getDefinition(symbolName);
        } catch (e: Error) {
            throw new IllegalOperationError(symbolName + " definition not found");
        }
        return null;
    }

    /**
     * Checks if a symbol exists in the library.
     *
     * @throws IllegalOperationError when the swf has not completed loading.
     */
    public function isSymbol (className :String) :Boolean
    {
        checkLoaded();
        return _loader.contentLoaderInfo.applicationDomain.hasDefinition(className);
    }

    /**
     * Validate that the load operation is complete.
     */
    protected function checkLoaded () :void
    {
        var loaderInfo :LoaderInfo = _loader.contentLoaderInfo;
        if (loaderInfo.bytesTotal == 0 || loaderInfo.bytesLoaded != loaderInfo.bytesTotal) {

            throw new IllegalOperationError("SWF has not completed loading");
        }
    }

    protected var _loader :Loader;
    protected var _useSubDomain :Boolean;
}
}

allow the use of subdomains, if wished

allow the use of subdomains, if wished

git-svn-id: a1a4b28b82a3276cc491891159dd9963a0a72fae@4614 542714f4-19e9-0310-aa3c-eee0fc999fb1


//
// Flump - Copyright 2013 Flump Authors

package flump.export {

import aspire.util.Log;
import aspire.util.Set;
import aspire.util.Sets;
import aspire.util.StringUtil;

import flash.display.StageQuality;
import flash.filesystem.File;

import flump.mold.AtlasMold;
import flump.mold.optional;
import flump.mold.require;
import flump.xfl.XflLibrary;

public class ExportConf
{
    public static const OPTIMIZE_MEMORY :String = "Memory";
    public static const OPTIMIZE_SPEED :String = "Speed";

    public var name :String = "default";
    public var format :String = JSONZipFormat.NAME;
    public var scale :Number = 1;
    /** The size of the border around each texture in an atlas, in pixels */
    public var textureBorder :int = 1;
    /** The maximum size of the width and height of a generated texture atlas */
    public var maxAtlasSize :int = 2048;
    /** Additional scaleFactors to output */
    public var additionalScaleFactors :Array = [];
    /** The optimization strategy. */
    public var optimize :String = OPTIMIZE_SPEED;
    /** The stage quality setting (StageQuality). */
    public var quality :String = StageQuality.BEST;
    /** Whether or not to pretty print the library. */
    public var prettyPrint :Boolean = false;

    public function get scaleFactorsString () :String {
        return this.additionalScaleFactors.join(",");
    }

    public function set scaleFactorsString (str :String) :void {
        var strings :Array = str.split(",");
        var values :Set = Sets.newSetOf(int);
        for each (var num :String in str.split(",")) {
            try {
                // additional scale factors must be integers > 1
                var scale :int = StringUtil.parseUnsignedInteger(StringUtil.trim(num));
                if (scale > 1) {
                    values.add(scale);
                }
            } catch (e :Error) {}
        }

        this.additionalScaleFactors = values.toArray();
        this.additionalScaleFactors.sort();
    }

    public function get description () :String {
        const scaleString :String = (this.scale * 100).toFixed(0) + "%";
        var scaleFactors :String = "";
        for each (var scaleFactor :int in this.additionalScaleFactors) {
            scaleFactors += ", " + AtlasMold.scaleFactorSuffix(scaleFactor);
        }

        return "'" + this.name + "' (" + this.format + ", " + scaleString + scaleFactors + ")";
    }

    public static function fromJSON (o :Object) :ExportConf {
        const conf :ExportConf = new ExportConf();
        conf.name = require(o, "name");
        conf.scale = require(o, "scale");
        conf.format = require(o, "format");
        conf.textureBorder = optional(o, "textureBorder", 1);
        conf.maxAtlasSize = optional(o, "maxAtlasSize", 2048);
        conf.additionalScaleFactors = optional(o, "additionalScaleFactors", []);
        conf.optimize = optional(o, "optimize", OPTIMIZE_MEMORY);
        conf.quality = optional(o, "quality", StageQuality.BEST);
        conf.prettyPrint = optional(o, "prettyPrint", false);
        return conf;
    }

    public function createPublishFormat (exportDir :File, lib :XflLibrary) :PublishFormat {
        var formatClass :Class;
        switch (format.toLowerCase()) {
            case JSONFormat.NAME.toLowerCase(): formatClass = JSONFormat; break;
            case JSONZipFormat.NAME.toLowerCase(): formatClass = JSONZipFormat; break;
            case XMLFormat.NAME.toLowerCase(): formatClass = XMLFormat; break;
            default:
                log.error("Invalid publish format", "name", format);
                formatClass = JSONZipFormat;
                break;
        }
        return new formatClass(exportDir, lib, this);
    }

    protected static const log :Log = Log.getLog(ExportConf);
}
}

//
// Flump - Copyright 2013 Flump Authors

package flump.export {

import aspire.util.Log;
import aspire.util.Set;
import aspire.util.Sets;
import aspire.util.StringUtil;

import flash.display.StageQuality;
import flash.filesystem.File;

import flump.mold.AtlasMold;
import flump.mold.optional;
import flump.mold.require;
import flump.xfl.XflLibrary;

public class ExportConf
{
    public static const OPTIMIZE_MEMORY :String = "Memory";
    public static const OPTIMIZE_SPEED :String = "Speed";

    public var name :String = "default";
    public var format :String = JSONZipFormat.NAME;
    public var scale :Number = 1;
    /** The size of the border around each texture in an atlas, in pixels */
    public var textureBorder :int = 1;
    /** The maximum size of the width and height of a generated texture atlas */
    public var maxAtlasSize :int = 2048;
    /** Additional scaleFactors to output */
    public var additionalScaleFactors :Array = [];
    /** The optimization strategy. */
    public var optimize :String = OPTIMIZE_SPEED;
    /** The stage quality setting (StageQuality). */
    public var quality :String = StageQuality.BEST;
    /** Whether or not to pretty print the library. */
    public var prettyPrint :Boolean = false;

    public function get scaleFactorsString () :String {
        return this.additionalScaleFactors.join(",");
    }

    public function set scaleFactorsString (str :String) :void {
        var values :Set = Sets.newSetOf(int);
        for each (var num :String in str.split(",")) {
            try {
                // additional scale factors must be integers > 1
                var scale :int = StringUtil.parseUnsignedInteger(StringUtil.trim(num));
                if (scale > 1) {
                    values.add(scale);
                }
            } catch (e :Error) {}
        }

        this.additionalScaleFactors = values.toArray();
        this.additionalScaleFactors.sort();
    }

    public function get description () :String {
        const scaleString :String = (this.scale * 100).toFixed(0) + "%";
        var scaleFactors :String = "";
        for each (var scaleFactor :int in this.additionalScaleFactors) {
            scaleFactors += ", " + AtlasMold.scaleFactorSuffix(scaleFactor);
        }

        return "'" + this.name + "' (" + this.format + ", " + scaleString + scaleFactors + ")";
    }

    public static function fromJSON (o :Object) :ExportConf {
        const conf :ExportConf = new ExportConf();
        conf.name = require(o, "name");
        conf.scale = require(o, "scale");
        conf.format = require(o, "format");
        conf.textureBorder = optional(o, "textureBorder", 1);
        conf.maxAtlasSize = optional(o, "maxAtlasSize", 2048);
        conf.additionalScaleFactors = optional(o, "additionalScaleFactors", []);
        conf.optimize = optional(o, "optimize", OPTIMIZE_MEMORY);
        conf.quality = optional(o, "quality", StageQuality.BEST);
        conf.prettyPrint = optional(o, "prettyPrint", false);
        return conf;
    }

    public function createPublishFormat (exportDir :File, lib :XflLibrary) :PublishFormat {
        var formatClass :Class;
        switch (format.toLowerCase()) {
            case JSONFormat.NAME.toLowerCase(): formatClass = JSONFormat; break;
            case JSONZipFormat.NAME.toLowerCase(): formatClass = JSONZipFormat; break;
            case XMLFormat.NAME.toLowerCase(): formatClass = XMLFormat; break;
            default:
                log.error("Invalid publish format", "name", format);
                formatClass = JSONZipFormat;
                break;
        }
        return new formatClass(exportDir, lib, this);
    }

    protected static const log :Log = Log.getLog(ExportConf);
}
}

Remove unused code

Remove unused code


package {
  import asunit.framework.TestSuite;

  public class Suite extends TestSuite {
    public function Suite() {
      super();
      addTest(new PlayerTest("testPass"));
    }
  }
}

package {
  import asunit.framework.TestSuite;

  public class Suite extends TestSuite {
    public function Suite() {
      super();
      addTest(new PlayerTest("testPass"));
      addTest(new UriTest("test_isSafe"));
    }
  }
}

Add URI tests to the asunit test suite

Add URI tests to the asunit test suite


//
// $Id: CommandButton.as 408 2008-02-06 01:03:55Z ray $
//
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// 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.flex {

import flash.events.MouseEvent;

import mx.controls.CheckBox;

import com.threerings.util.CommandEvent;

/**
 * A checkbox that dispatches a command (or calls a function) when it is toggled.
 */
public class CommandCheckBox extends CheckBox
{
    /**
     * Create a command button.
     *
     * @param label the label text for the button.
     * @param cmdOrFn either a String, which will be the CommandEvent command to dispatch,
     *        or a function, which will be called when clicked.
     * @param arg the argument for the CommentEvent or the function. If the arg is an Array
     *        then those parameters are used for calling the function.
     * Note that if arg is null, the actual argument passed will be the 'selected' state of the
     * button. If you really want to call a method with no args, specify arg as an emtpy Array.
     */
    public function CommandCheckBox (label :String = null, cmdOrFn :* = null, arg :Object = null)
    {
        CommandButton.validateCmd(cmdOrFn);
        this.label = label;
        _cmdOrFn = cmdOrFn;
        _arg = arg;
    }

    /**
     * Set the command and argument to be issued when this button is pressed.
     */
    public function setCommand (cmd :String, arg :Object = null) :void
    {
        _cmdOrFn = cmd;
        _arg = arg;
    }

    /**
     * Set a callback function to call when the button is pressed.
     */
    public function setCallback (fn :Function, arg :Object = null) :void
    {
        _cmdOrFn = fn;
        _arg = arg;
    }

    override protected function clickHandler (event :MouseEvent) :void
    {
        super.clickHandler(event);
        CommandButton.processCommandClick(this, event, _cmdOrFn, _arg);
    }

    /** The command (String) to submit, or the function (Function) to call
     * when clicked,  */
    protected var _cmdOrFn :Object;

    /** The argument that accompanies our command. */
    protected var _arg :Object;
}
}

//
// $Id: CommandButton.as 408 2008-02-06 01:03:55Z ray $
//
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// 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.flex {

import flash.events.MouseEvent;

import mx.controls.CheckBox;

import com.threerings.util.CommandEvent;

/**
 * A checkbox that dispatches a command (or calls a function) when it is toggled.
 */
public class CommandCheckBox extends CheckBox
{
    /**
     * Create a command checkbox.
     *
     * @param label the label text for the checkbox.
     * @param cmdOrFn either a String, which will be the CommandEvent command to dispatch,
     *        or a function, which will be called when clicked.
     * @param arg the argument for the CommentEvent or the function. If the arg is an Array
     *        then those parameters are used for calling the function.
     * Note that if arg is null, the actual argument passed will be the 'selected' state of the
     * checkbox. If you really want to call a method with no args, specify arg as an emtpy Array.
     */
    public function CommandCheckBox (label :String = null, cmdOrFn :* = null, arg :Object = null)
    {
        CommandButton.validateCmd(cmdOrFn);
        this.label = label;
        _cmdOrFn = cmdOrFn;
        _arg = arg;
    }

    /**
     * Set the command and argument to be issued when this button is pressed.
     */
    public function setCommand (cmd :String, arg :Object = null) :void
    {
        _cmdOrFn = cmd;
        _arg = arg;
    }

    /**
     * Set a callback function to call when the button is pressed.
     */
    public function setCallback (fn :Function, arg :Object = null) :void
    {
        _cmdOrFn = fn;
        _arg = arg;
    }

    override protected function clickHandler (event :MouseEvent) :void
    {
        super.clickHandler(event);
        CommandButton.processCommandClick(this, event, _cmdOrFn, _arg);
    }

    /** The command (String) to submit, or the function (Function) to call
     * when clicked,  */
    protected var _cmdOrFn :Object;

    /** The argument that accompanies our command. */
    protected var _arg :Object;
}
}

Comment tweak.

Comment tweak.

git-svn-id: b675b909355d5cf946977f44a8ec5a6ceb3782e4@736 ed5b42cb-e716-0410-a449-f6a68f950b19


package aerys.minko.render.shader.part.environment
{
	import aerys.minko.render.material.environment.EnvironmentMappingProperties;
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.render.shader.part.BlendingShaderPart;
	import aerys.minko.render.shader.part.phong.LightAwareShaderPart;
	import aerys.minko.render.shader.part.projection.BlinnNewellProjectionShaderPart;
	import aerys.minko.render.shader.part.projection.ProbeProjectionShaderPart;
	import aerys.minko.type.enum.Blending;
	import aerys.minko.type.enum.EnvironmentMappingType;
	import aerys.minko.type.enum.SamplerDimension;
	import aerys.minko.type.enum.SamplerFiltering;
	import aerys.minko.type.enum.SamplerFormat;
	import aerys.minko.type.enum.SamplerMipMapping;
	import aerys.minko.type.enum.SamplerWrapping;

	import flash.geom.Rectangle;

	public class EnvironmentMappingShaderPart extends LightAwareShaderPart
	{
		private var _blinnNewellProjectionPart	: BlinnNewellProjectionShaderPart;
		private var _probeProjectionPart		: ProbeProjectionShaderPart;
		private var _blending					: BlendingShaderPart;

		public function EnvironmentMappingShaderPart(main : Shader)
		{
			super(main);

			_blinnNewellProjectionPart	= new BlinnNewellProjectionShaderPart(main);
			_probeProjectionPart		= new ProbeProjectionShaderPart(main);
			_blending					= new BlendingShaderPart(main);
		}

		public function getEnvironmentColor() : SFloat
		{
            if (!meshBindings.propertyExists(EnvironmentMappingProperties.ENVIRONMENT_MAPPING_TYPE)
                || !meshBindings.propertyExists(EnvironmentMappingProperties.ENVIRONMENT_MAP))
                return float4(0, 0, 0, 0);

			// compute reflected vector
			var cWorldCameraPosition	: SFloat = this.cameraPosition;
			var vsWorldVertexToCamera	: SFloat = normalize(subtract(cWorldCameraPosition, vsWorldPosition));
			var reflected				: SFloat = normalize(interpolate(reflect(vsWorldVertexToCamera.xyzz, vsWorldNormal.xyzz)));
			var reflectionType 			: int	 = meshBindings.getProperty(
				EnvironmentMappingProperties.ENVIRONMENT_MAPPING_TYPE
			);
            var reflectionMap           : SFloat    = getEnvironmentMap(reflectionType);

			// retrieve reflection color from reflection map
			var reflectionMapUV			: SFloat;
			var reflectionColor			: SFloat;

			switch (reflectionType)
			{
				case EnvironmentMappingType.NONE:
					reflectionColor = float4(0, 0, 0, 0);
					break;

				case EnvironmentMappingType.PROBE:
					reflectionMapUV = _probeProjectionPart.projectVector(reflected, new Rectangle(0, 0, 1, 1));
					reflectionColor = sampleTexture(reflectionMap, reflectionMapUV);
					break;

				case EnvironmentMappingType.BLINN_NEWELL:
					reflectionMapUV = _blinnNewellProjectionPart.projectVector(reflected, new Rectangle(0, 0, 1, 1));
					reflectionColor = sampleTexture(reflectionMap, reflectionMapUV);
					break;

				case EnvironmentMappingType.CUBE:
					reflectionColor = sampleTexture(reflectionMap, reflected);
					break;

				default:
					throw new Error('Unsupported reflection type');
			}

			// modifify alpha color
			if (meshBindings.propertyExists(EnvironmentMappingProperties.REFLECTIVITY))
			{
				var reflectivity : SFloat = meshBindings.getParameter(
					EnvironmentMappingProperties.REFLECTIVITY, 1
				);

				reflectionColor = float4(reflectionColor.xyz, multiply(reflectionColor.w, reflectivity));
			}

			return reflectionColor;
		}

        public function getEnvironmentMap(environmentMappingType : uint = 0) : SFloat
        {
            if (!environmentMappingType)
                meshBindings.getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAPPING_TYPE);

            return meshBindings.getTextureParameter(
                EnvironmentMappingProperties.ENVIRONMENT_MAP,
                meshBindings.getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_FILTERING, SamplerFiltering.NEAREST),
                meshBindings.getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_MIPMAPPING, SamplerMipMapping.DISABLE),
                meshBindings.getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_WRAPPING, SamplerWrapping.CLAMP),
                environmentMappingType == EnvironmentMappingType.CUBE ? SamplerDimension.CUBE : SamplerDimension.FLAT,
                meshBindings.getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_FORMAT, SamplerFormat.RGBA)
            );
        }

		public function applyEnvironmentMapping(diffuse : SFloat) : SFloat
		{
			if (!meshBindings.propertyExists(EnvironmentMappingProperties.ENVIRONMENT_MAPPING_TYPE))
				return diffuse;

			return _blending.blend(
				getEnvironmentColor(),
				diffuse,
				meshBindings.getProperty(EnvironmentMappingProperties.ENVIRONMENT_BLENDING, Blending.ALPHA)
			);
		}
	}
}

package aerys.minko.render.shader.part.environment
{
	import aerys.minko.render.material.environment.EnvironmentMappingProperties;
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.render.shader.part.BlendingShaderPart;
	import aerys.minko.render.shader.part.phong.LightAwareShaderPart;
	import aerys.minko.render.shader.part.projection.BlinnNewellProjectionShaderPart;
	import aerys.minko.render.shader.part.projection.ProbeProjectionShaderPart;
	import aerys.minko.type.enum.Blending;
	import aerys.minko.type.enum.EnvironmentMappingType;
	import aerys.minko.type.enum.SamplerDimension;
	import aerys.minko.type.enum.SamplerFiltering;
	import aerys.minko.type.enum.SamplerFormat;
	import aerys.minko.type.enum.SamplerMipMapping;
	import aerys.minko.type.enum.SamplerWrapping;

	import flash.geom.Rectangle;

	public class EnvironmentMappingShaderPart extends LightAwareShaderPart
	{
		private var _blinnNewellProjectionPart	: BlinnNewellProjectionShaderPart;
		private var _probeProjectionPart		: ProbeProjectionShaderPart;
		private var _blending					: BlendingShaderPart;

		public function EnvironmentMappingShaderPart(main : Shader)
		{
			super(main);

			_blinnNewellProjectionPart	= new BlinnNewellProjectionShaderPart(main);
			_probeProjectionPart		= new ProbeProjectionShaderPart(main);
			_blending					= new BlendingShaderPart(main);
		}

		public function getEnvironmentColor() : SFloat
		{
            if (!meshBindings.propertyExists(EnvironmentMappingProperties.ENVIRONMENT_MAPPING_TYPE)
                || !meshBindings.propertyExists(EnvironmentMappingProperties.ENVIRONMENT_MAP))
                return float4(0, 0, 0, 0);

			// compute reflected vector
			var cWorldCameraPosition	: SFloat = this.cameraPosition;
			var vsWorldVertexToCamera	: SFloat = normalize(subtract(cWorldCameraPosition, vsWorldPosition));
			var reflected				: SFloat = normalize(interpolate(reflect(vsWorldNormal.xyzz, vsWorldVertexToCamera.xyzz)));
			var reflectionType 			: int	 = meshBindings.getProperty(
				EnvironmentMappingProperties.ENVIRONMENT_MAPPING_TYPE
			);
            var reflectionMap           : SFloat    = getEnvironmentMap(reflectionType);

			// retrieve reflection color from reflection map
			var reflectionMapUV			: SFloat;
			var reflectionColor			: SFloat;

			switch (reflectionType)
			{
				case EnvironmentMappingType.NONE:
					reflectionColor = float4(0, 0, 0, 0);
					break;

				case EnvironmentMappingType.PROBE:
					reflectionMapUV = _probeProjectionPart.projectVector(reflected, new Rectangle(0, 0, 1, 1));
					reflectionColor = sampleTexture(reflectionMap, reflectionMapUV);
					break;

				case EnvironmentMappingType.BLINN_NEWELL:
					reflectionMapUV = _blinnNewellProjectionPart.projectVector(reflected, new Rectangle(0, 0, 1, 1));
					reflectionColor = sampleTexture(reflectionMap, reflectionMapUV);
					break;

				case EnvironmentMappingType.CUBE:
					reflectionColor = sampleTexture(reflectionMap, reflected);
					break;

				default:
					throw new Error('Unsupported reflection type');
			}

			// modifify alpha color
			if (meshBindings.propertyExists(EnvironmentMappingProperties.REFLECTIVITY))
			{
				var reflectivity : SFloat = meshBindings.getParameter(
					EnvironmentMappingProperties.REFLECTIVITY, 1
				);

				reflectionColor = float4(reflectionColor.xyz, multiply(reflectionColor.w, reflectivity));
			}

			return reflectionColor;
		}

        public function getEnvironmentMap(environmentMappingType : uint = 0) : SFloat
        {
            if (!environmentMappingType)
                meshBindings.getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAPPING_TYPE);

            return meshBindings.getTextureParameter(
                EnvironmentMappingProperties.ENVIRONMENT_MAP,
                meshBindings.getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_FILTERING, SamplerFiltering.NEAREST),
                meshBindings.getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_MIPMAPPING, SamplerMipMapping.DISABLE),
                meshBindings.getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_WRAPPING, SamplerWrapping.CLAMP),
                environmentMappingType == EnvironmentMappingType.CUBE ? SamplerDimension.CUBE : SamplerDimension.FLAT,
                meshBindings.getProperty(EnvironmentMappingProperties.ENVIRONMENT_MAP_FORMAT, SamplerFormat.RGBA)
            );
        }

		public function applyEnvironmentMapping(diffuse : SFloat) : SFloat
		{
			if (!meshBindings.propertyExists(EnvironmentMappingProperties.ENVIRONMENT_MAPPING_TYPE))
				return diffuse;

			return _blending.blend(
				getEnvironmentColor(),
				diffuse,
				meshBindings.getProperty(EnvironmentMappingProperties.ENVIRONMENT_BLENDING, Blending.ALPHA)
			);
		}
	}
}

Fix flipped env map

Fix flipped env map


////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package org.apache.flex.events
{
	COMPILE::JS
	{
		import goog.events.EventTarget;
	}

	COMPILE::AS3
	{
		import flash.events.EventDispatcher;
	}

	/**
	 * This class simply wraps flash.events.EventDispatcher so that
	 * no flash packages are needed on the JS side.
	 *
	 * @langversion 3.0
	 * @playerversion Flash 10.2
	 * @playerversion AIR 2.6
	 * @productversion FlexJS 0.0
	 */
	COMPILE::AS3
	public class EventDispatcher extends flash.events.EventDispatcher implements IEventDispatcher
	{
		/**
		 * Constructor.
		 *
		 * @langversion 3.0
		 * @playerversion Flash 10.2
		 * @playerversion AIR 2.6
		 * @productversion FlexJS 0.0
		 */
		public function EventDispatcher()
		{
			super();
		}
	}

	COMPILE::JS
	public class EventDispatcher extends goog.events.EventTarget implements IEventDispatcher
	{

		override public function addEventListener(type:String, handler:Object, opt_capture:Boolean = false, opt_handlerScope:Object = null):void
		{
			super.addEventListener(type, handler, opt_capture, opt_handlerScope);

			const that:* = this;
			var source:* = this;

			if (that.element && that.element.nodeName &&
				that.element.nodeName.toLowerCase() !== 'div' &&
				that.element.nodeName.toLowerCase() !== 'body')
			{
				source = that.element;
			}
			else if (ElementEvents.elementEvents[type])
			{
				// mouse and keyboard events also dispatch off the element.
				source = that.element;
			}

			goog.events.listen(source, type, handler);
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package org.apache.flex.events
{
	COMPILE::JS
	{
        import goog.events;
		import goog.events.EventTarget;
	}

	COMPILE::AS3
	{
		import flash.events.EventDispatcher;
	}

	/**
	 * This class simply wraps flash.events.EventDispatcher so that
	 * no flash packages are needed on the JS side.
	 *
	 * @langversion 3.0
	 * @playerversion Flash 10.2
	 * @playerversion AIR 2.6
	 * @productversion FlexJS 0.0
	 */
	COMPILE::AS3
	public class EventDispatcher extends flash.events.EventDispatcher implements IEventDispatcher
	{
		/**
		 * Constructor.
		 *
		 * @langversion 3.0
		 * @playerversion Flash 10.2
		 * @playerversion AIR 2.6
		 * @productversion FlexJS 0.0
		 */
		public function EventDispatcher()
		{
			super();
		}
	}

	COMPILE::JS
	public class EventDispatcher extends goog.events.EventTarget implements IEventDispatcher
	{

		override public function addEventListener(type:String, handler:Object, opt_capture:Boolean = false, opt_handlerScope:Object = null):void
		{
			super.addEventListener(type, handler, opt_capture, opt_handlerScope);

			const that:* = this;
			var source:* = this;

			if (that.element && that.element.nodeName &&
				that.element.nodeName.toLowerCase() !== 'div' &&
				that.element.nodeName.toLowerCase() !== 'body')
			{
				source = that.element;
			}
			else if (ElementEvents.elementEvents[type])
			{
				// mouse and keyboard events also dispatch off the element.
				source = that.element;
			}

			goog.events.listen(source, type, handler);
		}
	}
}

use goog.events class

use goog.events class


//
// $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.utils.ByteArray;

public class Util
{
    /**
     * Initialize the target object with values present in the initProps object and the defaults
     * object. Neither initProps nor defaults will be modified.
     * @throws ReferenceError if a property cannot be set on the target object.
     *
     * @param target any object or class instance.
     * @param initProps a plain Object hash containing names and properties to set on the target
     *                  object.
     * @param defaults a plain Object hash containing names and properties to set on the target
     *                 object, only if the same property name does not exist in initProps.
     * @param maskProps a plain Object hash containing names of properties to omit setting
     *                  from the initProps object. This allows you to add custom properties to
     *                  initProps without having to modify the value from your callers.
     */
    public static function init (
        target :Object, initProps :Object, defaults :Object = null, maskProps :Object = null) :void
    {
        var prop :String;
        for (prop in initProps) {
            if (maskProps == null || !(prop in maskProps)) {
                target[prop] = initProps[prop];
            }
        }

        if (defaults != null) {
            for (prop in defaults) {
                if (!(prop in initProps)) {
                    target[prop] = defaults[prop];
                }
            }
        }
    }

    /**
     * Is the specified object 'simple': one of the basic built-in flash types.
     */
    public static function isSimple (obj :Object) :Boolean
    {
        var type :String = typeof(obj);
        switch (type) {
        case "number":
        case "string":
        case "boolean":
            return true;

        case "object":
            return (obj is Date) || (obj is Array);

        default:
            return false;
        }
    }

    /**
     * Parse the 'value' object into XML safely. This is equivalent to new XML(value)
     * but offers protection from other code that may have changing the default settings
     * used for parsing XML. Also, if you would like to use non-standard parsing settings
     * this method will protect other code from being broken by you.
     *
     * @param value the value to parse into XML.
     * @param settings an Object containing your desired non-standard XML parsing settings.
     * @see XML#setSettings()
     */
    public static function newXML (value :Object, settings :Object = null) :XML
    {
        return safeXMLOp(function () :* {
            return new XML(value);
        }, settings) as XML;
    }

    /**
     * Call toString() on the specified XML object safely. This is equivalent to
     * xml.toString() but offers protection from other code that may have changed
     * the default settings used for stringing XML. Also, if you would like to use the
     * non-standard printing settings this method will protect other code from being
     * broken by you.
     *
     * @param xml the xml value to Stringify.
     * @param settings an Object containing
     * @see XML#toString()
     * @see XML#setSettings()
     */
    public static function XMLtoString (xml :XML, settings :Object = null) :String
    {
        return safeXMLOp(function () :* {
            return xml.toString();
        }, settings) as String;
    }

    /**
     * Call toXMLString() on the specified XML object safely. This is equivalent to
     * xml.toXMLString() but offers protection from other code that may have changed
     * the default settings used for stringing XML. Also, if you would like to use the
     * non-standard printing settings this method will protect other code from being
     * broken by you.
     *
     * @param xml the xml value to Stringify.
     * @param settings an Object containing
     * @see XML#toXMLString()
     * @see XML#setSettings()
     */
    public static function XMLtoXMLString (xml :XML, settings :Object = null) :String
    {
        return safeXMLOp(function () :* {
            return xml.toXMLString();
        }, settings) as String;
    }

    /**
     * Perform an operation on XML that takes place using the specified settings, and
     * restores the XML settings to their previous values.
     *
     * @param fn a function to be called with no arguments.
     * @param settings any custom XML settings, or null to use the defaults.
     *
     * @return the return value of your function, if any.
     * @see XML#setSettings()
     * @see XML#settings()
     */
    public static function safeXMLOp (fn :Function, settings :Object = null) :*
    {
        var oldSettings :Object = XML.settings();
        try {
            XML.setSettings(settings);
            return fn();
        } finally {
            XML.setSettings(oldSettings);
        }
    }

    /**
     * A nice utility method for testing equality in a better way.
     * If the objects are Equalable, then that will be tested. Arrays
     * and ByteArrays are also compared and are equal if they have
     * elements that are equals (deeply).
     */
    public static function equals (obj1 :Object, obj2 :Object) :Boolean
    {
        // catch various common cases (both primitive or null)
        if (obj1 === obj2) {
            return true;

        } else if (obj1 is Equalable) {
            // if obj1 is Equalable, then that decides it
            return (obj1 as Equalable).equals(obj2);

        } else if ((obj1 is Array) && (obj2 is Array)) {
            return ArrayUtil.equals(obj1 as Array, obj2 as Array);

        } else if ((obj1 is ByteArray) && (obj2 is ByteArray)) {
            var ba1 :ByteArray = (obj1 as ByteArray);
            var ba2 :ByteArray = (obj2 as ByteArray);
            if (ba1.length != ba2.length) {
                return false;
            }
            for (var ii :int = 0; ii < ba1.length; ii++) {
                if (ba1[ii] != ba2[ii]) {
                    return false;
                }
            }
            return true;
        }

        return false;
    }

    /**
     * If you call a varargs method by passing it an array, the array
     * will end up being arg 1.
     */
    public static function unfuckVarargs (args :Array) :Array
    {
        return (args.length == 1 && (args[0] is Array)) ? (args[0] as Array)
                                                        : args;
    }
}
}

//
// $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.utils.ByteArray;

public class Util
{
    /**
     * Initialize the target object with values present in the initProps object and the defaults
     * object. Neither initProps nor defaults will be modified.
     * @throws ReferenceError if a property cannot be set on the target object.
     *
     * @param target any object or class instance.
     * @param initProps a plain Object hash containing names and properties to set on the target
     *                  object.
     * @param defaults a plain Object hash containing names and properties to set on the target
     *                 object, only if the same property name does not exist in initProps.
     * @param maskProps a plain Object hash containing names of properties to omit setting
     *                  from the initProps object. This allows you to add custom properties to
     *                  initProps without having to modify the value from your callers.
     */
    public static function init (
        target :Object, initProps :Object, defaults :Object = null, maskProps :Object = null) :void
    {
        var prop :String;
        for (prop in initProps) {
            if (maskProps == null || !(prop in maskProps)) {
                target[prop] = initProps[prop];
            }
        }

        if (defaults != null) {
            for (prop in defaults) {
                if (!(prop in initProps)) {
                    target[prop] = defaults[prop];
                }
            }
        }
    }

    /**
     * Is the specified object 'simple': one of the basic built-in flash types.
     */
    public static function isSimple (obj :Object) :Boolean
    {
        var type :String = typeof(obj);
        switch (type) {
        case "number":
        case "string":
        case "boolean":
            return true;

        case "object":
            return (obj is Date) || (obj is Array);

        default:
            return false;
        }
    }

    /**
     * Parse the 'value' object into XML safely. This is equivalent to new XML(value)
     * but offers protection from other code that may have changing the default settings
     * used for parsing XML. Also, if you would like to use non-standard parsing settings
     * this method will protect other code from being broken by you.
     *
     * @param value the value to parse into XML.
     * @param settings an Object containing your desired XML settings, or null (or omitted) to
     * use the default settings.
     * @see XML#setSettings()
     */
    public static function newXML (value :Object, settings :Object = null) :XML
    {
        return safeXMLOp(function () :* {
            return new XML(value);
        }, settings) as XML;
    }

    /**
     * Call toString() on the specified XML object safely. This is equivalent to
     * xml.toString() but offers protection from other code that may have changed
     * the default settings used for stringing XML. Also, if you would like to use the
     * non-standard printing settings this method will protect other code from being
     * broken by you.
     *
     * @param xml the xml value to Stringify.
     * @param settings an Object containing your desired XML settings, or null (or omitted) to
     * use the default settings.
     * @see XML#toString()
     * @see XML#setSettings()
     */
    public static function XMLtoString (xml :XML, settings :Object = null) :String
    {
        return safeXMLOp(function () :* {
            return xml.toString();
        }, settings) as String;
    }

    /**
     * Call toXMLString() on the specified XML object safely. This is equivalent to
     * xml.toXMLString() but offers protection from other code that may have changed
     * the default settings used for stringing XML. Also, if you would like to use the
     * non-standard printing settings this method will protect other code from being
     * broken by you.
     *
     * @param xml the xml value to Stringify.
     * @param settings an Object containing your desired XML settings, or null (or omitted) to
     * use the default settings.
     * @see XML#toXMLString()
     * @see XML#setSettings()
     */
    public static function XMLtoXMLString (xml :XML, settings :Object = null) :String
    {
        return safeXMLOp(function () :* {
            return xml.toXMLString();
        }, settings) as String;
    }

    /**
     * Perform an operation on XML that takes place using the specified settings, and
     * restores the XML settings to their previous values.
     *
     * @param fn a function to be called with no arguments.
     * @param settings an Object containing your desired XML settings, or null (or omitted) to
     * use the default settings.
     *
     * @return the return value of your function, if any.
     * @see XML#setSettings()
     * @see XML#settings()
     */
    public static function safeXMLOp (fn :Function, settings :Object = null) :*
    {
        var oldSettings :Object = XML.settings();
        try {
            XML.setSettings(settings); // setting to null resets to all the defaults
            return fn();
        } finally {
            XML.setSettings(oldSettings);
        }
    }

    /**
     * A nice utility method for testing equality in a better way.
     * If the objects are Equalable, then that will be tested. Arrays
     * and ByteArrays are also compared and are equal if they have
     * elements that are equals (deeply).
     */
    public static function equals (obj1 :Object, obj2 :Object) :Boolean
    {
        // catch various common cases (both primitive or null)
        if (obj1 === obj2) {
            return true;

        } else if (obj1 is Equalable) {
            // if obj1 is Equalable, then that decides it
            return (obj1 as Equalable).equals(obj2);

        } else if ((obj1 is Array) && (obj2 is Array)) {
            return ArrayUtil.equals(obj1 as Array, obj2 as Array);

        } else if ((obj1 is ByteArray) && (obj2 is ByteArray)) {
            var ba1 :ByteArray = (obj1 as ByteArray);
            var ba2 :ByteArray = (obj2 as ByteArray);
            if (ba1.length != ba2.length) {
                return false;
            }
            for (var ii :int = 0; ii < ba1.length; ii++) {
                if (ba1[ii] != ba2[ii]) {
                    return false;
                }
            }
            return true;
        }

        return false;
    }

    /**
     * If you call a varargs method by passing it an array, the array
     * will end up being arg 1.
     */
    public static function unfuckVarargs (args :Array) :Array
    {
        return (args.length == 1 && (args[0] is Array)) ? (args[0] as Array)
                                                        : args;
    }
}
}

Fix docs, clarify.

Fix docs, clarify.

git-svn-id: a1a4b28b82a3276cc491891159dd9963a0a72fae@4934 542714f4-19e9-0310-aa3c-eee0fc999fb1


package aerys.minko.render.shader.part
{
	import aerys.minko.render.material.basic.BasicProperties;
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.type.enum.SamplerFiltering;
	import aerys.minko.type.enum.SamplerMipMapping;
	import aerys.minko.type.enum.SamplerWrapping;

	public class DiffuseShaderPart extends ShaderPart
	{
		/**
		 * The shader part to use a diffuse map or fallback and use a solid color.
		 *
		 * @param main
		 *
		 */
		public function DiffuseShaderPart(main : Shader)
		{
			super(main);
		}

		public function getDiffuseColor() : SFloat
		{
			var diffuseColor : SFloat	= null;

			if (meshBindings.propertyExists(BasicProperties.DIFFUSE_MAP))
			{
				var uv			: SFloat	= vertexUV.xy;
				var diffuseMap	: SFloat	= meshBindings.getTextureParameter(
					BasicProperties.DIFFUSE_MAP,
					meshBindings.getConstant(BasicProperties.DIFFUSE_FILTERING, SamplerFiltering.LINEAR),
					meshBindings.getConstant(BasicProperties.DIFFUSE_MIPMAPPING, SamplerMipMapping.LINEAR),
					meshBindings.getConstant(BasicProperties.DIFFUSE_WRAPPING, SamplerWrapping.REPEAT)
				);

				if (meshBindings.propertyExists(BasicProperties.DIFFUSE_UV_SCALE))
					uv.scaleBy(meshBindings.getParameter(BasicProperties.DIFFUSE_UV_SCALE, 2));

				if (meshBindings.propertyExists(BasicProperties.DIFFUSE_UV_OFFSET))
					uv.incrementBy(meshBindings.getParameter(BasicProperties.DIFFUSE_UV_OFFSET, 2));

				diffuseColor = sampleTexture(diffuseMap,interpolate(uv));
			}
			else if (meshBindings.propertyExists(BasicProperties.DIFFUSE_COLOR))
			{
				diffuseColor = meshBindings.getParameter(BasicProperties.DIFFUSE_COLOR, 4);
			}
			else
			{
				diffuseColor = float4(0., 0., 0., 1.);
			}

			// Apply HLSA modifiers
			if (meshBindings.propertyExists(BasicProperties.DIFFUSE_TRANSFORM))
			{
				diffuseColor = multiply4x4(
					diffuseColor,
					meshBindings.getParameter(BasicProperties.DIFFUSE_TRANSFORM, 16)
				);
			}

			if (meshBindings.propertyExists(BasicProperties.ALPHA_THRESHOLD))
			{
				var alphaThreshold : SFloat = meshBindings.getParameter(
					BasicProperties.ALPHA_THRESHOLD, 1
				);

				kill(subtract(0.5, lessThan(diffuseColor.w, alphaThreshold)));
			}

			return diffuseColor;
		}
	}
}

package aerys.minko.render.shader.part
{
	import aerys.minko.render.material.basic.BasicProperties;
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.type.enum.SamplerFiltering;
	import aerys.minko.type.enum.SamplerMipMapping;
	import aerys.minko.type.enum.SamplerWrapping;

	public class DiffuseShaderPart extends ShaderPart
	{
		/**
		 * The shader part to use a diffuse map or fallback and use a solid color.
		 *
		 * @param main
		 *
		 */
		public function DiffuseShaderPart(main : Shader)
		{
			super(main);
		}

		public function getDiffuseColor(killOnAlphaThreshold : Boolean = true) : SFloat
		{
			var diffuseColor : SFloat	= null;

			if (meshBindings.propertyExists(BasicProperties.DIFFUSE_MAP))
			{
				var uv			: SFloat	= vertexUV.xy;
				var diffuseMap	: SFloat	= meshBindings.getTextureParameter(
					BasicProperties.DIFFUSE_MAP,
					meshBindings.getConstant(BasicProperties.DIFFUSE_FILTERING, SamplerFiltering.LINEAR),
					meshBindings.getConstant(BasicProperties.DIFFUSE_MIPMAPPING, SamplerMipMapping.LINEAR),
					meshBindings.getConstant(BasicProperties.DIFFUSE_WRAPPING, SamplerWrapping.REPEAT)
				);

				if (meshBindings.propertyExists(BasicProperties.DIFFUSE_UV_SCALE))
					uv.scaleBy(meshBindings.getParameter(BasicProperties.DIFFUSE_UV_SCALE, 2));

				if (meshBindings.propertyExists(BasicProperties.DIFFUSE_UV_OFFSET))
					uv.incrementBy(meshBindings.getParameter(BasicProperties.DIFFUSE_UV_OFFSET, 2));

				diffuseColor = sampleTexture(diffuseMap,interpolate(uv));
			}
			else if (meshBindings.propertyExists(BasicProperties.DIFFUSE_COLOR))
			{
				diffuseColor = meshBindings.getParameter(BasicProperties.DIFFUSE_COLOR, 4);
			}
			else
			{
				diffuseColor = float4(0., 0., 0., 1.);
			}

			// Apply HLSA modifiers
			if (meshBindings.propertyExists(BasicProperties.DIFFUSE_TRANSFORM))
			{
				diffuseColor = multiply4x4(
					diffuseColor,
					meshBindings.getParameter(BasicProperties.DIFFUSE_TRANSFORM, 16)
				);
			}

			if (killOnAlphaThreshold && meshBindings.propertyExists(BasicProperties.ALPHA_THRESHOLD))
			{
				var alphaThreshold : SFloat = meshBindings.getParameter(
					BasicProperties.ALPHA_THRESHOLD, 1
				);

				kill(subtract(0.5, lessThan(diffuseColor.w, alphaThreshold)));
			}

			return diffuseColor;
		}
	}
}

add a killOnAlphaThreshold : Boolean argument to DiffuseShaderPart.getDiffuseColor() to enable/disable the kill that is sometime done at a later stage (cf. wireframe)


//
// $Id$
//
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// 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.flex {

import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;

import flash.geom.Rectangle;

import mx.controls.Menu;
import mx.core.mx_internal;
import mx.core.Application;
import mx.core.ScrollPolicy;
import mx.events.MenuEvent;

import mx.utils.ObjectUtil;

import flexlib.controls.ScrollableArrowMenu;

import com.threerings.util.CommandEvent;

use namespace mx_internal;

/**
 * A pretty standard menu that can submit CommandEvents if menu items
 * have "command" and possibly "arg" properties. Commands are submitted to
 * controllers for processing. Alternatively, you may specify
 * "callback" properties that specify a function closure to call, with the
 * "arg" property containing either a single arg or an array of args.
 *
 * Example dataProvider array:
 * [ { label: "Go home", icon: homeIconClass,
 *     command: Controller.GO_HOME, arg: homeId },
 *   { type: "separator"},
     { label: "Crazytown", callback: setCrazy, arg: [ true, false ] },
 *   { label: "Other places", children: subMenuArray }
 * ];
 *
 * See "Defining menu structure and data" in the Flex manual for the
 * full list.
 */
public class CommandMenu extends ScrollableArrowMenu
{
    public function CommandMenu ()
    {
        super();
        verticalScrollPolicy = ScrollPolicy.OFF;

        addEventListener(MenuEvent.ITEM_CLICK, itemClicked);
    }

    /**
     * Factory method to create a command menu.
     *
     * @param items an array of menu items.
     */
    public static function createMenu (items :Array) :CommandMenu
    {
        var menu :CommandMenu = new CommandMenu();
        menu.owner = DisplayObjectContainer(Application.application);
        menu.tabEnabled = false;
        menu.showRoot = true;
        Menu.popUpMenu(menu, null, items);
        return menu;
    }

    /**
     * Actually pop up the menu. This can be used instead of show().
     */
    public function popUp (
        trigger :DisplayObject, popUpwards :Boolean = false) :void
    {
        var r :Rectangle = trigger.getBounds(trigger.stage);

        if (popUpwards) {
            show(r.x, 0);
            // then, reposition the y once we know our size
            y = r.y - getExplicitOrMeasuredHeight();

        } else {
            // position it below the trigger
            show(r.x, r.y + r.height);
        }
    }

    /**
     * Just like our superclass's show(), except that when invoked
     * with no args, causes the menu to show at the current mouse location
     * instead of the top-left corner of the application.
     */
    override public function show (xShow :Object = null, yShow :Object = null) :void
    {
        if (xShow == null) {
            xShow = DisplayObject(Application.application).mouseX;
        }
        if (yShow == null) {
            yShow = DisplayObject(Application.application).mouseY;
        }
        super.show(xShow, yShow);
    }

    /**
     * Callback for MenuEvent.ITEM_CLICK.
     */
    protected function itemClicked (event :MenuEvent) :void
    {
        var arg :Object = getItemProp(event.item, "arg");
        var cmdOrFn :Object = getItemProp(event.item, "command");
        if (cmdOrFn == null) {
            cmdOrFn = getItemProp(event.item, "callback");
        }
        if (cmdOrFn != null) {
            event.stopImmediatePropagation();
            CommandEvent.dispatch(mx_internal::parentDisplayObject, cmdOrFn, arg)
        }
        // else: no warning. There may be non-command menu items mixed in.
    }

    /**
     * Get the specified property for the specified item, if any.
     * Somewhat similar to bits in the DefaultDataDescriptor.
     */
    protected function getItemProp (item :Object, prop :String) :Object
    {
        try {
            if (item is XML) {
                return String((item as XML).attribute(prop));

            } else if (prop in item) {
                return item[prop];
            }

        } catch (e :Error) {
            // alas; fall through
        }
        return null;
    }
}
}

//
// $Id$
//
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// 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.flex {

import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.events.IEventDispatcher;

import flash.geom.Rectangle;

import mx.controls.Menu;
import mx.core.mx_internal;
import mx.core.Application;
import mx.core.ScrollPolicy;
import mx.events.MenuEvent;

import mx.utils.ObjectUtil;

import flexlib.controls.ScrollableArrowMenu;

import com.threerings.util.CommandEvent;

use namespace mx_internal;

/**
 * A pretty standard menu that can submit CommandEvents if menu items have "command" and possibly
 * "arg" properties. Commands are submitted to controllers for processing. Alternatively, you may
 * specify "callback" properties that specify a function closure to call, with the "arg" property
 * containing either a single arg or an array of args.
 *
 * Example dataProvider array:
 * [ { label: "Go home", icon: homeIconClass,
 *     command: Controller.GO_HOME, arg: homeId },
 *   { type: "separator"},
     { label: "Crazytown", callback: setCrazy, arg: [ true, false ] },
 *   { label: "Other places", children: subMenuArray }
 * ];
 *
 * See "Defining menu structure and data" in the Flex manual for the full list.
 */
public class CommandMenu extends ScrollableArrowMenu
{
    /**
     * Factory method to create a command menu.
     *
     * @param items an array of menu items.
     */
    public static function createMenu (items :Array) :CommandMenu
    {
        var menu :CommandMenu = new CommandMenu();
        menu.owner = DisplayObjectContainer(Application.application);
        menu.tabEnabled = false;
        menu.showRoot = true;
        Menu.popUpMenu(menu, null, items);
        return menu;
    }

    public function CommandMenu ()
    {
        super();
        verticalScrollPolicy = ScrollPolicy.OFF;
        addEventListener(MenuEvent.ITEM_CLICK, itemClicked);
    }

    /**
     * Configures the event dispatcher to be used when dispatching this menu's events. By default
     * they will be dispatched on the stage.
     */
    public function setDispatcher (dispatcher :IEventDispatcher) :void
    {
        _dispatcher = dispatcher;
    }

    /**
     * Actually pop up the menu. This can be used instead of show().
     */
    public function popUp (
        trigger :DisplayObject, popUpwards :Boolean = false) :void
    {
        var r :Rectangle = trigger.getBounds(trigger.stage);

        if (popUpwards) {
            show(r.x, 0);
            // then, reposition the y once we know our size
            y = r.y - getExplicitOrMeasuredHeight();

        } else {
            // position it below the trigger
            show(r.x, r.y + r.height);
        }
    }

    /**
     * Just like our superclass's show(), except that when invoked with no args, causes the menu to
     * show at the current mouse location instead of the top-left corner of the application.
     */
    override public function show (xShow :Object = null, yShow :Object = null) :void
    {
        if (xShow == null) {
            xShow = DisplayObject(Application.application).mouseX;
        }
        if (yShow == null) {
            yShow = DisplayObject(Application.application).mouseY;
        }
        super.show(xShow, yShow);
    }

    /**
     * Callback for MenuEvent.ITEM_CLICK.
     */
    protected function itemClicked (event :MenuEvent) :void
    {
        var arg :Object = getItemProp(event.item, "arg");
        var cmdOrFn :Object = getItemProp(event.item, "command");
        if (cmdOrFn == null) {
            cmdOrFn = getItemProp(event.item, "callback");
        }
        if (cmdOrFn != null) {
            event.stopImmediatePropagation();
            CommandEvent.dispatch(_dispatcher == null ? mx_internal::parentDisplayObject :
                                  _dispatcher, cmdOrFn, arg);
        }
        // else: no warning. There may be non-command menu items mixed in.
    }

    /**
     * Get the specified property for the specified item, if any.  Somewhat similar to bits in the
     * DefaultDataDescriptor.
     */
    protected function getItemProp (item :Object, prop :String) :Object
    {
        try {
            if (item is XML) {
                return String((item as XML).attribute(prop));

            } else if (prop in item) {
                return item[prop];
            }

        } catch (e :Error) {
            // alas; fall through
        }
        return null;
    }

    protected var _dispatcher :IEventDispatcher;
}
}

Allow a custom dispatcher to be provided because the default (dispatching on
the stage) only routes commands to the global controller, bypassing the
controller for the current place view.

git-svn-id: b675b909355d5cf946977f44a8ec5a6ceb3782e4@190 ed5b42cb-e716-0410-a449-f6a68f950b19


/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 *   Marc Alcaraz <ekameleon@gmail.com>.
 */

package com.google.analytics.core
{
    import com.google.analytics.utils.Environment;
    import com.google.analytics.utils.Variables;
    import com.google.analytics.utils.Version;
    import com.google.analytics.v4.Configuration;

    /**
     * The BrowserInfo class.
     */
    public class BrowserInfo
    {
        private var _config:Configuration;
        private var _info:Environment;

        /**
         * Creates a new BrowserInfo instance.
         * @param info The Environment reference of the BrowserInfo instance.
         */
        public function BrowserInfo( config:Configuration, info:Environment )
        {
            _config = config;
            _info   = info;
        }

        /**
         * Language encoding for the browser.
         *
Some browsers don't set this, in which case it is set to "-".

         *
Example : utmcs=ISO-8859-1

         */
        public function get utmcs():String
        {
            return _info.languageEncoding;
        }

        /**
         * The Screen resolution
         *
Example : utmsr=2400x1920

         */
        public function get utmsr():String
        {
            return _info.screenWidth + "x" + _info.screenHeight;
        }

        /**
         * Screen color depth
         *
Example :utmsc=24-bit

         */
        public function get utmsc():String
        {
            return _info.screenColorDepth + "-bit";
        }

        /**
         * Browser language.
         *
Example :utmul=pt-br

         */
        public function get utmul():String
        {
            return _info.language.toLowerCase();
        }

        /**
         * Indicates if browser is Java-enabled.
         *
Example :utmje=1

         */
        public function get utmje():String
        {
            return "0"; //not supported
        }

        /**
         * Flash Version.
         *
Example :utmfl=9.0%20r48

         */
        public function get utmfl():String
        {
            if( _config.detectFlash )
            {
                var v:Version = _info.flashVersion;
                return v.major+"."+v.minor+" r"+v.build;
            }

            return "-";
        }

        /**
         * Returns a Variables object representation.
         * @return a Variables object representation.
         */
        public function toVariables():Variables
        {
            var variables:Variables = new Variables();
                variables.URIencode = true;
                variables.utmcs = utmcs;
                variables.utmsr = utmsr;
                variables.utmsc = utmsc;
                variables.utmul = utmul;
                variables.utmje = utmje;
                variables.utmfl = utmfl;
            return variables;
        }

        /**
         * Returns the url String representation of the object.
         * @return the url String representation of the object.
         */
        public function toURLString():String
        {
            var v:Variables = toVariables();
            return v.toString();
        }
    }
}

/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 *   Marc Alcaraz <ekameleon@gmail.com>.
 */

package com.google.analytics.core
{
    import com.google.analytics.utils.Environment;
    import com.google.analytics.utils.Variables;
    import com.google.analytics.v4.Configuration;

    import core.version;

    public class BrowserInfo
    {
        private var _config:Configuration;
        private var _info:Environment;

        /**
         * Creates a new BrowserInfo instance.
         * @param info The Environment reference of the BrowserInfo instance.
         */
        public function BrowserInfo( config:Configuration, info:Environment )
        {
            _config = config;
            _info   = info;
        }

        /**
         * Language encoding for the browser.
         *
Some browsers don't set this, in which case it is set to "-".

         *
Example : utmcs=ISO-8859-1

         */
        public function get utmcs():String
        {
            return _info.languageEncoding;
        }

        /**
         * The Screen resolution
         *
Example : utmsr=2400x1920

         */
        public function get utmsr():String
        {
            return _info.screenWidth + "x" + _info.screenHeight;
        }

        /**
         * Screen color depth
         *
Example :utmsc=24-bit

         */
        public function get utmsc():String
        {
            return _info.screenColorDepth + "-bit";
        }

        /**
         * Browser language.
         *
Example :utmul=pt-br

         */
        public function get utmul():String
        {
            return _info.language.toLowerCase();
        }

        /**
         * Indicates if browser is Java-enabled.
         *
Example :utmje=1

         */
        public function get utmje():String
        {
            return "0"; //not supported
        }

        /**
         * Flash Version.
         *
Example :utmfl=9.0%20r48

         */
        public function get utmfl():String
        {
            if( _config.detectFlash )
            {
                var v:version = _info.flashVersion;
                return v.major+"."+v.minor+" r"+v.build;
            }

            return "-";
        }

        /**
         * Returns a Variables object representation.
         * @return a Variables object representation.
         */
        public function toVariables():Variables
        {
            var variables:Variables = new Variables();
                variables.URIencode = true;
                variables.utmcs = utmcs;
                variables.utmsr = utmsr;
                variables.utmsc = utmsc;
                variables.utmul = utmul;
                variables.utmje = utmje;
                variables.utmfl = utmfl;
            return variables;
        }

        /**
         * Returns the url String representation of the object.
         * @return the url String representation of the object.
         */
        public function toURLString():String
        {
            var v:Variables = toVariables();
            return v.toString();
        }
    }
}

replace class Version by core.version

replace class Version by core.version