package battlecode.client.viewer.render {
    import battlecode.common.MapLocation;
    import battlecode.common.RobotType;
    import battlecode.common.Team;
    import battlecode.serial.RoundDelta;
    import battlecode.serial.RoundStats;
    import battlecode.world.GameMap;
    import battlecode.world.signals.*;

    public class DrawState extends DefaultSignalHandler {
        // state
        private var groundRobots:Object;
        private var zombieRobots:Object;
        private var archonsA:Object; // id -> DrawRobot
        private var archonsB:Object; // id -> DrawRobot

        // stats
        private var aPoints:Number;
        private var bPoints:Number;
        private var roundNum:uint;
        private var unitCounts:Object;

        // rubble
        private var rubble:Array; // Number[][]
        private var parts:Array; // Number[][]

        // immutables
        private var map:GameMap;
        private var origin:MapLocation;

        public function DrawState(map:GameMap) {
            groundRobots = {};
            zombieRobots = {};
            archonsA = {};
            archonsB = {};

            aPoints = 0;
            bPoints = 0;
            roundNum = 1;

            unitCounts = {};
            unitCounts[Team.A] = {};
            unitCounts[Team.B] = {};
            for each (var robotType:String in RobotType.units()) {
                unitCounts[Team.A][robotType] = 0;
                unitCounts[Team.B][robotType] = 0;
            }

            this.map = map;
            this.origin = map.getOrigin();

            var i:int = 0, j:int = 0;

            var initialRubble:Array = map.getInitialRubble();
            rubble = [];
            for (i = 0; i < map.getHeight(); i++) {
                rubble.push(new Array(map.getWidth()));
                for (j = 0; j < map.getWidth(); j++) {
                    rubble[i][j] = initialRubble[i][j];
                }
            }

            var initialParts:Array = map.getInitialParts();
            parts = [];
            for (i = 0; i < map.getHeight(); i++) {
                parts.push(new Array(map.getWidth()));
                for (j = 0; j < map.getWidth(); j++) {
                    parts[i][j] = initialParts[i][j];
                }
            }
        }

        ///////////////////////////////////////////////////////
        ///////////////// PROPERTY GETTERS ////////////////////
        ///////////////////////////////////////////////////////

        public function getGroundRobots():Object {
            return groundRobots;
        }

        public function getZombieRobots():Object {
            return zombieRobots;
        }

        public function getArchons(team:String):Object {
            return team == Team.A ? archonsA : archonsB;
        }

        public function getPoints(team:String):uint {
            return (team == Team.A) ? aPoints : bPoints;
        }

        public function getUnitCount(type:String, team:String):int {
            return unitCounts[team][type];
        }

        public function getRubble():Array {
            return rubble;
        }

        public function getParts():Array {
            return parts;
        }

        ///////////////////////////////////////////////////////
        /////////////////// CORE FUNCTIONS ////////////////////
        ///////////////////////////////////////////////////////

        private function copyStateFrom(state:DrawState):void {
            var a:*, i:int;

            groundRobots = {};
            for (a in state.groundRobots) {
                groundRobots[a] = state.groundRobots[a].clone();
            }

            zombieRobots = {};
            for (a in state.zombieRobots) {
                zombieRobots[a] = state.zombieRobots[a].clone();
            }

            archonsA = {};
            for (a in state.archonsA) {
                archonsA[a] = state.archonsA[a].clone();
            }

            archonsB = {};
            for (a in state.archonsB) {
                archonsB[a] = state.archonsB[a].clone();
            }

            unitCounts = {};
            unitCounts[Team.A] = {};
            unitCounts[Team.B] = {};
            for (var robotType:String in RobotType.values()) {
                unitCounts[Team.A][robotType] = state.unitCounts[Team.A][robotType];
                unitCounts[Team.B][robotType] = state.unitCounts[Team.B][robotType];
            }

            rubble = [];
            for (i = 0; i < state.rubble.length; i++) {
                rubble.push(state.rubble[i].concat());
            }

            parts = [];
            for (i = 0; i < state.parts.length; i++) {
                parts.push(state.parts[i].concat());
            }

            roundNum = state.roundNum;
        }

        public function clone():DrawState {
            var state:DrawState = new DrawState(map);
            state.copyStateFrom(this);
            return state;
        }

        public function applyDelta(delta:RoundDelta):void {
            updateRound();
            for each (var signal:Signal in delta.getSignals()) {
                applySignal(signal);
            }
            processEndOfRound();
        }

        public function applySignal(signal:Signal):void {
            if (signal != null) signal.accept(this);
        }

        public function applyStats(stats:RoundStats):void {
        }

        public function updateRound():void {
            var a:*, i:uint, j:uint;
            var o:DrawRobot;

            for (a in groundRobots) {
                o = groundRobots[a] as DrawRobot;
                o.updateRound();
                if (!o.isAlive()) {
                    if (o.parent) {
                        o.parent.removeChild(o);
                    }
                    delete groundRobots[a];
                }
            }

            for (a in zombieRobots) {
                o = zombieRobots[a] as DrawRobot;
                o.updateRound();
                if (!o.isAlive()) {
                    if (o.parent) {
                        o.parent.removeChild(o);
                    }
                    delete zombieRobots[a];
                }
            }

            for (a in archonsA) {
                o = archonsA[a] as DrawRobot;
                o.updateRound();
            }

            for (a in archonsB) {
                o = archonsB[a] as DrawRobot;
                o.updateRound();
            }
        }

        private function processEndOfRound():void {
            roundNum++;
        }

        ///////////////////////////////////////////////////////
        ////////////// PRIVATE HELPER FUNCTIONS ///////////////
        ///////////////////////////////////////////////////////

        private function getRobot(id:uint):DrawRobot {
            if (groundRobots[id]) return groundRobots[id] as DrawRobot;
            if (zombieRobots[id]) return zombieRobots[id] as DrawRobot;
            return null;
        }

        private function removeRobot(id:uint):void {
            if (groundRobots[id]) delete groundRobots[id];
            if (zombieRobots[id]) delete zombieRobots[id];
        }

        private function translateCoordinates(loc:MapLocation):MapLocation {
            return new MapLocation(loc.getX() - origin.getX(), loc.getY() - origin.getY());
        }

        ///////////////////////////////////////////////////////
        /////////////////// SIGNAL HANDLERS ///////////////////
        ///////////////////////////////////////////////////////

        override public function visitAttackSignal(s:AttackSignal):* {
            getRobot(s.getRobotID()).attack(s.getTargetLoc());
        }

        override public function visitBroadcastSignal(s:BroadcastSignal):* {
            getRobot(s.getRobotID()).broadcast();
        }

        override public function visitDeathSignal(s:DeathSignal):* {
            var robot:DrawRobot = getRobot(s.getRobotID());
            robot.destroyUnit(!s.getDeathByActivation());

            if (robot.getType() == RobotType.ARCHON) {
                var archon:DrawRobot = robot.getTeam() == Team.A
                        ? archonsA[robot.getRobotID()]
                        : archonsB[robot.getRobotID()];
                archon.destroyUnit(!s.getDeathByActivation());
            }

            if (Team.isPlayer(robot.getTeam())) {
                unitCounts[robot.getTeam()][robot.getType()]--;
            }
        }

        override public function visitHealthChangeSignal(s:HealthChangeSignal):* {
            var robotIDs:Array = s.getRobotIDs();
            var healths:Array = s.getHealths();

            for (var i:uint; i < robotIDs.length; i++) {
                var robot:DrawRobot = getRobot(robotIDs[i]);
                robot.setEnergon(healths[i]);

                if (robot.getType() == RobotType.ARCHON) {
                    var archon:DrawRobot = robot.getTeam() == Team.A
                            ? archonsA[robot.getRobotID()]
                            : archonsB[robot.getRobotID()];
                    archon.setEnergon(healths[i]);
                }
            }
        }

        override public function visitInfectionSignal(s:InfectionSignal):* {
            var robotIDs:Array = s.getRobotIDs();
            var zombieTurns:Array = s.getZombieTurns();
            var viperTurns:Array = s.getViperTurns();

            for (var i:uint; i < robotIDs.length; i++) {
                var robot:DrawRobot = getRobot(robotIDs[i]);
                robot.setZombieInfectedTurns(zombieTurns[i]);
                robot.setViperInfectedTurns(viperTurns[i]);

                if (robot.getType() == RobotType.ARCHON) {
                    var archon:DrawRobot = robot.getTeam() == Team.A
                            ? archonsA[robot.getRobotID()]
                            : archonsB[robot.getRobotID()];
                    archon.setZombieInfectedTurns(zombieTurns[i]);
                    archon.setViperInfectedTurns(viperTurns[i]);
                }
            }
        }

        override public function visitIndicatorStringSignal(s:IndicatorStringSignal):* {
            getRobot(s.getRobotID()).setIndicatorString(s.getIndicatorString(), s.getIndex());
        }

        override public function visitRubbleChangeSignal(s:RubbleChangeSignal):* {
            // robots can clear rubble for OOB locations
            if (!map.isOnMap(s.getLocation())) {
                return;
            }
            var loc:MapLocation = translateCoordinates(s.getLocation());
            rubble[loc.getY()][loc.getX()] = s.getRubble();
        }

        override public function visitPartsChangeSignal(s:PartsChangeSignal):* {
            var loc:MapLocation = translateCoordinates(s.getLocation());
            parts[loc.getY()][loc.getX()] = s.getParts();
        }

        override public function visitMovementSignal(s:MovementSignal):* {
            getRobot(s.getRobotID()).moveToLocation(s.getTargetLoc(), s.getDelay());
        }

        override public function visitSpawnSignal(s:SpawnSignal):* {
            var robot:DrawRobot = new DrawRobot(s.getRobotID(), s.getRobotType(), s.getTeam());
            robot.setLocation(s.getLocation());
            robot.spawn(s.getDelay());

            if (s.getRobotType() == RobotType.ARCHON) {
                if (s.getTeam() == Team.A) archonsA[s.getRobotID()] = robot.clone();
                if (s.getTeam() == Team.B) archonsB[s.getRobotID()] = robot.clone();
            }

            if (RobotType.isZombie(s.getRobotType())) {
                zombieRobots[s.getRobotID()] = robot;
            } else {
                groundRobots[s.getRobotID()] = robot;
            }

            if (Team.isPlayer(s.getTeam())) {
                unitCounts[s.getTeam()][s.getRobotType()]++;
            }
        }

        override public function visitTeamResourceSignal(s:TeamResourceSignal):* {
            if (s.getTeam() == Team.A) {
                aPoints = s.getResource();
            } else if (s.getTeam() == Team.B) {
                bPoints = s.getResource();
            }
        }

        override public function visitTypeChangeSignal(s:TypeChangeSignal):* {
            var r:DrawRobot = getRobot(s.getRobotID());

            if (Team.isPlayer(r.getTeam())) {
                unitCounts[r.getTeam()][r.getType()]--;
                unitCounts[r.getTeam()][s.getType()]++;
            }

            r.setType(s.getType());
        }
    }

}

package battlecode.client.viewer.render {
    import battlecode.common.MapLocation;
    import battlecode.common.RobotType;
    import battlecode.common.Team;
    import battlecode.serial.RoundDelta;
    import battlecode.serial.RoundStats;
    import battlecode.world.GameMap;
    import battlecode.world.signals.*;

    public class DrawState extends DefaultSignalHandler {
        // state
        private var groundRobots:Object;
        private var zombieRobots:Object;
        private var archonsA:Object; // id -> DrawRobot
        private var archonsB:Object; // id -> DrawRobot

        // stats
        private var aPoints:Number;
        private var bPoints:Number;
        private var roundNum:uint;
        private var unitCounts:Object;

        // rubble
        private var rubble:Array; // Number[][]
        private var parts:Array; // Number[][]

        // immutables
        private var map:GameMap;
        private var origin:MapLocation;

        public function DrawState(map:GameMap) {
            groundRobots = {};
            zombieRobots = {};
            archonsA = {};
            archonsB = {};

            aPoints = 0;
            bPoints = 0;
            roundNum = 1;

            unitCounts = {};
            unitCounts[Team.A] = {};
            unitCounts[Team.B] = {};
            for each (var robotType:String in RobotType.units()) {
                unitCounts[Team.A][robotType] = 0;
                unitCounts[Team.B][robotType] = 0;
            }

            this.map = map;
            this.origin = map.getOrigin();

            var i:int = 0, j:int = 0;

            var initialRubble:Array = map.getInitialRubble();
            rubble = [];
            for (i = 0; i < map.getHeight(); i++) {
                rubble.push(new Array(map.getWidth()));
                for (j = 0; j < map.getWidth(); j++) {
                    rubble[i][j] = initialRubble[i][j];
                }
            }

            var initialParts:Array = map.getInitialParts();
            parts = [];
            for (i = 0; i < map.getHeight(); i++) {
                parts.push(new Array(map.getWidth()));
                for (j = 0; j < map.getWidth(); j++) {
                    parts[i][j] = initialParts[i][j];
                }
            }
        }

        ///////////////////////////////////////////////////////
        ///////////////// PROPERTY GETTERS ////////////////////
        ///////////////////////////////////////////////////////

        public function getGroundRobots():Object {
            return groundRobots;
        }

        public function getZombieRobots():Object {
            return zombieRobots;
        }

        public function getArchons(team:String):Object {
            return team == Team.A ? archonsA : archonsB;
        }

        public function getPoints(team:String):uint {
            return (team == Team.A) ? aPoints : bPoints;
        }

        public function getUnitCount(type:String, team:String):int {
            return unitCounts[team][type];
        }

        public function getRubble():Array {
            return rubble;
        }

        public function getParts():Array {
            return parts;
        }

        ///////////////////////////////////////////////////////
        /////////////////// CORE FUNCTIONS ////////////////////
        ///////////////////////////////////////////////////////

        private function copyStateFrom(state:DrawState):void {
            var a:*, i:int;

            groundRobots = {};
            for (a in state.groundRobots) {
                groundRobots[a] = state.groundRobots[a].clone();
            }

            zombieRobots = {};
            for (a in state.zombieRobots) {
                zombieRobots[a] = state.zombieRobots[a].clone();
            }

            archonsA = {};
            for (a in state.archonsA) {
                archonsA[a] = state.archonsA[a].clone();
            }

            archonsB = {};
            for (a in state.archonsB) {
                archonsB[a] = state.archonsB[a].clone();
            }

            unitCounts = {};
            unitCounts[Team.A] = {};
            unitCounts[Team.B] = {};
            for each (var robotType:String in RobotType.values()) {
                unitCounts[Team.A][robotType] = state.unitCounts[Team.A][robotType];
                unitCounts[Team.B][robotType] = state.unitCounts[Team.B][robotType];
            }

            rubble = [];
            for (i = 0; i < state.rubble.length; i++) {
                rubble.push(state.rubble[i].concat());
            }

            parts = [];
            for (i = 0; i < state.parts.length; i++) {
                parts.push(state.parts[i].concat());
            }

            roundNum = state.roundNum;
        }

        public function clone():DrawState {
            var state:DrawState = new DrawState(map);
            state.copyStateFrom(this);
            return state;
        }

        public function applyDelta(delta:RoundDelta):void {
            updateRound();
            for each (var signal:Signal in delta.getSignals()) {
                applySignal(signal);
            }
            processEndOfRound();
        }

        public function applySignal(signal:Signal):void {
            if (signal != null) signal.accept(this);
        }

        public function applyStats(stats:RoundStats):void {
        }

        public function updateRound():void {
            var a:*, i:uint, j:uint;
            var o:DrawRobot;

            for (a in groundRobots) {
                o = groundRobots[a] as DrawRobot;
                o.updateRound();
                if (!o.isAlive()) {
                    if (o.parent) {
                        o.parent.removeChild(o);
                    }
                    delete groundRobots[a];
                }
            }

            for (a in zombieRobots) {
                o = zombieRobots[a] as DrawRobot;
                o.updateRound();
                if (!o.isAlive()) {
                    if (o.parent) {
                        o.parent.removeChild(o);
                    }
                    delete zombieRobots[a];
                }
            }

            for (a in archonsA) {
                o = archonsA[a] as DrawRobot;
                o.updateRound();
            }

            for (a in archonsB) {
                o = archonsB[a] as DrawRobot;
                o.updateRound();
            }
        }

        private function processEndOfRound():void {
            roundNum++;
        }

        ///////////////////////////////////////////////////////
        ////////////// PRIVATE HELPER FUNCTIONS ///////////////
        ///////////////////////////////////////////////////////

        private function getRobot(id:uint):DrawRobot {
            if (groundRobots[id]) return groundRobots[id] as DrawRobot;
            if (zombieRobots[id]) return zombieRobots[id] as DrawRobot;
            return null;
        }

        private function removeRobot(id:uint):void {
            if (groundRobots[id]) delete groundRobots[id];
            if (zombieRobots[id]) delete zombieRobots[id];
        }

        private function translateCoordinates(loc:MapLocation):MapLocation {
            return new MapLocation(loc.getX() - origin.getX(), loc.getY() - origin.getY());
        }

        ///////////////////////////////////////////////////////
        /////////////////// SIGNAL HANDLERS ///////////////////
        ///////////////////////////////////////////////////////

        override public function visitAttackSignal(s:AttackSignal):* {
            getRobot(s.getRobotID()).attack(s.getTargetLoc());
        }

        override public function visitBroadcastSignal(s:BroadcastSignal):* {
            getRobot(s.getRobotID()).broadcast();
        }

        override public function visitDeathSignal(s:DeathSignal):* {
            var robot:DrawRobot = getRobot(s.getRobotID());
            robot.destroyUnit(!s.getDeathByActivation());

            if (robot.getType() == RobotType.ARCHON) {
                var archon:DrawRobot = robot.getTeam() == Team.A
                        ? archonsA[robot.getRobotID()]
                        : archonsB[robot.getRobotID()];
                archon.destroyUnit(!s.getDeathByActivation());
            }

            if (Team.isPlayer(robot.getTeam())) {
                unitCounts[robot.getTeam()][robot.getType()]--;
            }
        }

        override public function visitHealthChangeSignal(s:HealthChangeSignal):* {
            var robotIDs:Array = s.getRobotIDs();
            var healths:Array = s.getHealths();

            for (var i:uint; i < robotIDs.length; i++) {
                var robot:DrawRobot = getRobot(robotIDs[i]);
                robot.setEnergon(healths[i]);

                if (robot.getType() == RobotType.ARCHON) {
                    var archon:DrawRobot = robot.getTeam() == Team.A
                            ? archonsA[robot.getRobotID()]
                            : archonsB[robot.getRobotID()];
                    archon.setEnergon(healths[i]);
                }
            }
        }

        override public function visitInfectionSignal(s:InfectionSignal):* {
            var robotIDs:Array = s.getRobotIDs();
            var zombieTurns:Array = s.getZombieTurns();
            var viperTurns:Array = s.getViperTurns();

            for (var i:uint; i < robotIDs.length; i++) {
                var robot:DrawRobot = getRobot(robotIDs[i]);
                robot.setZombieInfectedTurns(zombieTurns[i]);
                robot.setViperInfectedTurns(viperTurns[i]);

                if (robot.getType() == RobotType.ARCHON) {
                    var archon:DrawRobot = robot.getTeam() == Team.A
                            ? archonsA[robot.getRobotID()]
                            : archonsB[robot.getRobotID()];
                    archon.setZombieInfectedTurns(zombieTurns[i]);
                    archon.setViperInfectedTurns(viperTurns[i]);
                }
            }
        }

        override public function visitIndicatorStringSignal(s:IndicatorStringSignal):* {
            getRobot(s.getRobotID()).setIndicatorString(s.getIndicatorString(), s.getIndex());
        }

        override public function visitRubbleChangeSignal(s:RubbleChangeSignal):* {
            // robots can clear rubble for OOB locations
            if (!map.isOnMap(s.getLocation())) {
                return;
            }
            var loc:MapLocation = translateCoordinates(s.getLocation());
            rubble[loc.getY()][loc.getX()] = s.getRubble();
        }

        override public function visitPartsChangeSignal(s:PartsChangeSignal):* {
            var loc:MapLocation = translateCoordinates(s.getLocation());
            parts[loc.getY()][loc.getX()] = s.getParts();
        }

        override public function visitMovementSignal(s:MovementSignal):* {
            getRobot(s.getRobotID()).moveToLocation(s.getTargetLoc(), s.getDelay());
        }

        override public function visitSpawnSignal(s:SpawnSignal):* {
            var robot:DrawRobot = new DrawRobot(s.getRobotID(), s.getRobotType(), s.getTeam());
            robot.setLocation(s.getLocation());
            robot.spawn(s.getDelay());

            if (s.getRobotType() == RobotType.ARCHON) {
                if (s.getTeam() == Team.A) archonsA[s.getRobotID()] = robot.clone();
                if (s.getTeam() == Team.B) archonsB[s.getRobotID()] = robot.clone();
            }

            if (RobotType.isZombie(s.getRobotType())) {
                zombieRobots[s.getRobotID()] = robot;
            } else {
                groundRobots[s.getRobotID()] = robot;
            }

            if (Team.isPlayer(s.getTeam())) {
                unitCounts[s.getTeam()][s.getRobotType()]++;
            }
        }

        override public function visitTeamResourceSignal(s:TeamResourceSignal):* {
            if (s.getTeam() == Team.A) {
                aPoints = s.getResource();
            } else if (s.getTeam() == Team.B) {
                bPoints = s.getResource();
            }
        }

        override public function visitTypeChangeSignal(s:TypeChangeSignal):* {
            var r:DrawRobot = getRobot(s.getRobotID());

            if (Team.isPlayer(r.getTeam())) {
                unitCounts[r.getTeam()][r.getType()]--;
                unitCounts[r.getTeam()][s.getType()]++;
            }

            r.setType(s.getType());
        }
    }

}

fix iteration bug that causes unit counts to stop working


/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 package org.mangui.hls.demux {

    import org.mangui.hls.HLSSettings;
    import flash.utils.ByteArray;
    CONFIG::LOGGING {
    import org.mangui.hls.utils.Log;
    }

    /** Constants and utilities for the H264 video format. **/
    public class Nalu {
        /** H264 NAL unit names. **/
        private static const NAMES : Array = ['Unspecified',                  // 0
        'NDR',                          // 1
        'Partition A',                  // 2
        'Partition B',                  // 3
        'Partition C',                  // 4
        'IDR',                          // 5
        'SEI',                          // 6
        'SPS',                          // 7
        'PPS',                          // 8
        'AUD',                          // 9
        'End of Sequence',              // 10
        'End of Stream',                // 11
        'Filler Data'// 12
        ];

        /** Return an array with NAL delimiter indexes. **/
        public static function getNALU(nalu : ByteArray, position : uint) : Vector.<VideoFrame> {
            var units : Vector.<VideoFrame> = new Vector.<VideoFrame>();
            var unit_start : int;
            var unit_type : int;
            var unit_header : int;
            // Loop through data to find NAL startcodes.
            var window : uint = 0;
            nalu.position = position;
            while (nalu.bytesAvailable > 4) {
                window = nalu.readUnsignedInt();
                // Match four-byte startcodes
                if ((window & 0xFFFFFFFF) == 0x01) {
                    // push previous NAL unit if new start delimiter found, dont push unit with type = 0
                    if (unit_start && unit_type) {
                        units.push(new VideoFrame(unit_header, nalu.position - 4 - unit_start, unit_start, unit_type));
                    }
                    unit_header = 4;
                    unit_start = nalu.position;
                    unit_type = nalu.readByte() & 0x1F;
                    // NDR or IDR NAL unit
                    if (unit_type == 1 || unit_type == 5) {
                        break;
                    }
                    // Match three-byte startcodes
                } else if ((window & 0xFFFFFF00) == 0x100) {
                    // push previous NAL unit if new start delimiter found, dont push unit with type = 0
                    if (unit_start && unit_type) {
                        units.push(new VideoFrame(unit_header, nalu.position - 4 - unit_start, unit_start, unit_type));
                    }
                    nalu.position--;
                    unit_header = 3;
                    unit_start = nalu.position;
                    unit_type = nalu.readByte() & 0x1F;
                    // NDR or IDR NAL unit
                    if (unit_type == 1 || unit_type == 5) {
                        break;
                    }
                } else {
                    nalu.position -= 3;
                }
            }
            // Append the last NAL to the array.
            if (unit_start) {
                units.push(new VideoFrame(unit_header, nalu.length - unit_start, unit_start, unit_type));
            }
            // Reset position and return results.
            CONFIG::LOGGING {
            if (HLSSettings.logDebug2) {
                if (units.length) {
                    var txt : String = "AVC: ";
                    for (var i : int = 0; i < units.length; i++) {
                        txt += NAMES[units[i].type] + ", ";
                    }
                    Log.debug2(txt.substr(0, txt.length - 2) + " slices");
                } else {
                    Log.debug2('AVC: no NALU slices found');
                }
            }
            }
            nalu.position = position;
            return units;
        };
    }
}

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 package org.mangui.hls.demux {

    import flash.utils.ByteArray;
    CONFIG::LOGGING {
    import org.mangui.hls.HLSSettings;
    import org.mangui.hls.utils.Log;
    }

    /** Constants and utilities for the H264 video format. **/
    public class Nalu {
        /** H264 NAL unit names. **/
        private static const NAMES : Array = ['Unspecified',                  // 0
        'NDR',                          // 1
        'Partition A',                  // 2
        'Partition B',                  // 3
        'Partition C',                  // 4
        'IDR',                          // 5
        'SEI',                          // 6
        'SPS',                          // 7
        'PPS',                          // 8
        'AUD',                          // 9
        'End of Sequence',              // 10
        'End of Stream',                // 11
        'Filler Data'// 12
        ];

        /** Return an array with NAL delimiter indexes. **/
        public static function getNALU(nalu : ByteArray, position : uint) : Vector.<VideoFrame> {
            var units : Vector.<VideoFrame> = new Vector.<VideoFrame>();
            var unit_start : int;
            var unit_type : int;
            var unit_header : int;
            // Loop through data to find NAL startcodes.
            var window : uint = 0;
            nalu.position = position;
            while (nalu.bytesAvailable > 4) {
                window = nalu.readUnsignedInt();
                // Match four-byte startcodes
                if ((window & 0xFFFFFFFF) == 0x01) {
                    // push previous NAL unit if new start delimiter found, dont push unit with type = 0
                    if (unit_start && unit_type) {
                        units.push(new VideoFrame(unit_header, nalu.position - 4 - unit_start, unit_start, unit_type));
                    }
                    unit_header = 4;
                    unit_start = nalu.position;
                    unit_type = nalu.readByte() & 0x1F;
                    // NDR or IDR NAL unit
                    if (unit_type == 1 || unit_type == 5) {
                        break;
                    }
                    // Match three-byte startcodes
                } else if ((window & 0xFFFFFF00) == 0x100) {
                    // push previous NAL unit if new start delimiter found, dont push unit with type = 0
                    if (unit_start && unit_type) {
                        units.push(new VideoFrame(unit_header, nalu.position - 4 - unit_start, unit_start, unit_type));
                    }
                    nalu.position--;
                    unit_header = 3;
                    unit_start = nalu.position;
                    unit_type = nalu.readByte() & 0x1F;
                    // NDR or IDR NAL unit
                    if (unit_type == 1 || unit_type == 5) {
                        break;
                    }
                } else {
                    nalu.position -= 3;
                }
            }
            // Append the last NAL to the array.
            if (unit_start) {
                units.push(new VideoFrame(unit_header, nalu.length - unit_start, unit_start, unit_type));
            }
            // Reset position and return results.
            CONFIG::LOGGING {
            if (HLSSettings.logDebug2) {
                if (units.length) {
                    var txt : String = "AVC: ";
                    for (var i : int = 0; i < units.length; i++) {
                        txt += NAMES[units[i].type] + ", ";
                    }
                    Log.debug2(txt.substr(0, txt.length - 2) + " slices");
                } else {
                    Log.debug2('AVC: no NALU slices found');
                }
            }
            }
            nalu.position = position;
            return units;
        };
    }
}

Move HLSSettings importing into conditional compilation block

HLSSettings is only used when LOGGING is true.


package classes
{
	/**
	 AGORA - an interactive and web-based argument mapping tool that stimulates reasoning,
	 reflection, critique, deliberation, and creativity in individual argument construction
	 and in collaborative or adversarial settings.
	 Copyright (C) 2011 Georgia Institute of Technology

	 This program is free software: you can redistribute it and/or modify
	 it under the terms of the GNU Affero General Public License as
	 published by the Free Software Foundation, either version 3 of the
	 License, or (at your option) any later version.

	 This program 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 Affero General Public License for more details.

	 You should have received a copy of the GNU Affero General Public License
	 along with this program.  If not, see <http://www.gnu.org/licenses/>.

	 */
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;

	import mx.controls.Alert;

	import org.osmf.layout.AbsoluteLayoutFacet;

	public class Language
	{
		//I will set the language to either GERMAN, RUSSIAN or ENGLISH
		//based on this, you could read the values into the variables
		//by default, the language is EN-US

		public static const GERMAN:String = "GER";
		public static const ENGLISH:String = "EN-US";
		public static const RUSSIAN:String = "RUS";
		public static var language:String = RUSSIAN;

		public static var xml:XML;
		private static var ready:Boolean=false;

		public static function init():void
		{
			[Embed(source="../../../translation.xml", mimeType="application/octet-stream")]
			const MyData:Class;
			var byteArray:ByteArray = new MyData() as ByteArray;
			var x:XML = new XML(byteArray.readUTFBytes(byteArray.length));
			xml = x;
			ready=true;
		}

		/**The key function. Use this to look up a label from the translation document according to the set language.*/

		public static function lookup(label:String):String{
			if(!ready){
				init();
			}
			trace("Now looking up:" + label);
			var lbl:XMLList = xml.descendants(label);
			var lang:XMLList = lbl.descendants(language);
			var output:String = lang.attribute("text");
			if(!output){
				output = "error | ошибка | Fehler --- There was a problem getting the text for this item. The label was: " + label;
			}
			trace("Output is: " + output);
			return output;
		}
	}
}

package classes
{
	/**
	 AGORA - an interactive and web-based argument mapping tool that stimulates reasoning,
	 reflection, critique, deliberation, and creativity in individual argument construction
	 and in collaborative or adversarial settings.
	 Copyright (C) 2011 Georgia Institute of Technology

	 This program is free software: you can redistribute it and/or modify
	 it under the terms of the GNU Affero General Public License as
	 published by the Free Software Foundation, either version 3 of the
	 License, or (at your option) any later version.

	 This program 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 Affero General Public License for more details.

	 You should have received a copy of the GNU Affero General Public License
	 along with this program.  If not, see <http://www.gnu.org/licenses/>.

	 */
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;

	import mx.controls.Alert;

	import org.osmf.layout.AbsoluteLayoutFacet;

	public class Language
	{
		//I will set the language to either GERMAN, RUSSIAN or ENGLISH
		//based on this, you could read the values into the variables
		//by default, the language is EN-US

		public static const GERMAN:String = "GER";
		public static const ENGLISH:String = "EN-US";
		public static const RUSSIAN:String = "RUS";
		public static var language:String = ENGLISH;

		public static var xml:XML;
		private static var ready:Boolean=false;

		public static function init():void
		{
			[Embed(source="../../../translation.xml", mimeType="application/octet-stream")]
			const MyData:Class;
			var byteArray:ByteArray = new MyData() as ByteArray;
			var x:XML = new XML(byteArray.readUTFBytes(byteArray.length));
			xml = x;
			ready=true;
		}

		/**The key function. Use this to look up a label from the translation document according to the set language.*/

		public static function lookup(label:String):String{
			if(!ready){
				init();
			}
			trace("Now looking up:" + label);
			var lbl:XMLList = xml.descendants(label);
			var lang:XMLList = lbl.descendants(language);
			var output:String = lang.attribute("text");
			if(!output){
				output = "error | ошибка | Fehler --- There was a problem getting the text for this item. The label was: " + label;
			}
			trace("Output is: " + output);
			return output;
		}
	}
}

Switch langauge back to English

Switch langauge back to English


package aerys.minko.render
{
	import aerys.minko.ns.minko_render;
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.resource.Context3DResource;
	import aerys.minko.scene.node.Scene;
	import aerys.minko.type.Factory;
	import aerys.minko.type.KeyboardManager;
	import aerys.minko.type.MouseManager;
	import aerys.minko.type.Signal;

	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.Stage3D;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.display3D.Context3D;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TouchEvent;
	import flash.geom.Point;
	import flash.utils.getTimer;

	/**
	 * The Viewport is the display area where a 3D scene can be rendered.
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Viewport extends Sprite
	{
		private static const ZERO2		: Point				= new Point();

		private var _stage3d			: Stage3D			= null;
		private var _context3d			: Context3DResource	= null;

		private var _width				: uint				= 0;
		private var _height				: uint				= 0;
		private var _autoResize			: Boolean			= false;
		private var _antiAliasing		: uint				= 0;
		private var _backgroundColor	: uint				= 0;
		private var _backBuffer			: RenderTarget		= null;
		private var _invalidBackBuffer	: Boolean			= false;

		private var _alwaysOnTop		: Boolean			= false;
		private var _mask				: Shape				= new Shape();

		private var _mouseManager		: MouseManager		= new MouseManager();
		private var _keyboardManager	: KeyboardManager	= new KeyboardManager();

		private var _resized			: Signal			= new Signal('Viewport.resized');

		minko_render function get context3D() : Context3DResource
		{
			return _context3d;
		}

		minko_render function get backBuffer() : RenderTarget
		{
			var positionOnStage	: Point	= localToGlobal(ZERO2);

			if (_stage3d.x != positionOnStage.x || _stage3d.y != positionOnStage.y)
			{
				updateStage3D()
//				updateBackBuffer();
			}

			return _backBuffer;
		}

		public function get ready() : Boolean
		{
			return _stage3d != null && _stage3d.context3D != null && _backBuffer != null;
		}

		/**
		 * Whether the viewport is visible or not.
		 * @return
		 *
		 */
		override public function get visible() : Boolean
		{
			return _stage3d.visible;
		}
		override public function set visible(value : Boolean) : void
		{
			_stage3d.visible = value;
			super.visible = value;
		}

		override public function set x(value : Number) : void
		{
			super.x = value;
			updateStage3D();
		}

		override public function set y(value : Number) : void
		{
			super.y = value;
			updateStage3D();
		}

		/**
		 * The width of the display area.
		 * @return
		 *
		 */
		override public function get width() : Number
		{
			return _width;
		}
		override public function set width(value : Number) : void
		{
			resize(value, _height);
		}

		/**
		 * The height of the display area.
		 * @return
		 *
		 */
		override public function get height() : Number
		{
			return _height;
		}
		override public function set height(value : Number) : void
		{
			resize(_width, value);
		}

		public function get alwaysOnTop() : Boolean
		{
			return _alwaysOnTop;
		}
		public function set alwaysOnTop(value : Boolean) : void
		{
			_alwaysOnTop = value;
		}

		public function get keyboardManager() : KeyboardManager
		{
			return _keyboardManager;
		}

		public function get mouseManager() : MouseManager
		{
			return _mouseManager;
		}

		/**
		 * The signal executed when the viewport is resized.
		 * Callback functions for this signal should accept the following
		 * arguments:
		 *

		 *
viewport : Viewport, the viewport executing the signal

		 *
width : Number, the new width of the viewport

		 *
height : Number, the new height of the viewport

		 *

		 * @return
		 *
		 */
		public function get resized() : Signal
		{
			return _resized;
		}

		/**
		 * The background color of the display area. This value must use the
		 * RGB format.
		 * @return
		 *
		 */
		public function get backgroundColor() : uint
		{
			return _backgroundColor;
		}
		public function set backgroundColor(value : uint) : void
		{
			_backgroundColor = value;
			updateStage3D();
		}

		/**
		 * The anti-aliasing to use (0, 2, 4, 8 or 16). The actual anti-aliasing
		 * used for rendering depends on the hardware capabilities. If the specified
		 * anti-aliasing value is not supported, the value 0 will be used.
		 * @return
		 *
		 */
		public function get antiAliasing() : uint
		{
			return _antiAliasing;
		}
		public function set antiAliasing(value : uint) : void
		{
			_antiAliasing = value;
			updateStage3D();
		}

		/**
		 * The driver informations provided by the Stage3D API.
		 */
		public function get driverInfo() : String
		{
			return _stage3d && _stage3d.context3D
				? _stage3d.context3D.driverInfo
				: null;
		}

		public function Viewport(antiAliasing	: uint	= 0,
								 width			: uint 	= 0,
								 height			: uint	= 0)
		{
			_antiAliasing = antiAliasing;

			if (width == 0 && height == 0)
				_autoResize = true;

			_width = width;
			_height = height;

			initialize();
		}

		private function initialize() : void
		{
			_mouseManager.bind(this);

			addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
			addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
		}

		private function addedToStageHandler(event : Event) : void
		{
			_keyboardManager.bind(stage);

			parent.addEventListener(Event.RESIZE, parentResizedHandler);

			stage.addEventListener(Event.ADDED_TO_STAGE, displayObjectAddedToStageHandler);
			stage.addEventListener(Event.REMOVED_FROM_STAGE, displayObjectRemovedFromStageHandler);
			stage.addEventListener(MouseEvent.CLICK, stageEventHandler);
			stage.addEventListener(MouseEvent.DOUBLE_CLICK, stageEventHandler);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, stageEventHandler);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, stageEventHandler);
			stage.addEventListener(MouseEvent.MOUSE_OUT, stageEventHandler);
			stage.addEventListener(MouseEvent.MOUSE_OVER, stageEventHandler);
			stage.addEventListener(MouseEvent.MOUSE_WHEEL, stageEventHandler);
			stage.addEventListener(MouseEvent.ROLL_OUT, stageEventHandler);
			stage.addEventListener(MouseEvent.ROLL_OVER, stageEventHandler);
			stage.addEventListener(TouchEvent.TOUCH_BEGIN, stageEventHandler);
			stage.addEventListener(TouchEvent.TOUCH_END, stageEventHandler);
			stage.addEventListener(TouchEvent.TOUCH_MOVE, stageEventHandler);

			setupOnStage(stage);
		}

		private function removedFromStageHandler(event : Event) : void
		{
			_keyboardManager.unbind(stage);

			parent.removeEventListener(Event.RESIZE, parentResizedHandler);

			stage.removeEventListener(Event.ADDED_TO_STAGE, displayObjectAddedToStageHandler);
			stage.removeEventListener(Event.REMOVED_FROM_STAGE, displayObjectRemovedFromStageHandler);
			stage.removeEventListener(MouseEvent.CLICK, stageEventHandler);
			stage.removeEventListener(MouseEvent.DOUBLE_CLICK, stageEventHandler);
			stage.removeEventListener(MouseEvent.MOUSE_DOWN, stageEventHandler);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, stageEventHandler);
			stage.removeEventListener(MouseEvent.MOUSE_OUT, stageEventHandler);
			stage.removeEventListener(MouseEvent.MOUSE_OVER, stageEventHandler);
			stage.removeEventListener(MouseEvent.MOUSE_WHEEL, stageEventHandler);
			stage.removeEventListener(MouseEvent.ROLL_OUT, stageEventHandler);
			stage.removeEventListener(MouseEvent.ROLL_OVER, stageEventHandler);
			stage.removeEventListener(TouchEvent.TOUCH_BEGIN, stageEventHandler);
			stage.removeEventListener(TouchEvent.TOUCH_END, stageEventHandler);
			stage.removeEventListener(TouchEvent.TOUCH_MOVE, stageEventHandler);

			if (_stage3d != null)
				_stage3d.visible = false;
		}

		private function setupOnStage(stage : Stage, stage3dId : uint = 0) : void
		{
			if (_autoResize)
			{
				_width = stage.stageWidth;
				_height = stage.stageHeight;
			}

			if (!_stage3d)
			{
				_stage3d = stage.stage3Ds[stage3dId];
				_stage3d.addEventListener(Event.CONTEXT3D_CREATE, context3dCreatedHandler);
				_stage3d.requestContext3D();
			}
			else
			{
				_stage3d.visible = true;
			}

			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
		}

		/**
		 * Dispose the Viewport and all the Stage3D related objects. After this operation,
		 * the Viewport cannot be used anymore and is ready for garbage collection.
		 */
		public function dispose():void
		{
			if (_stage3d != null)
			{
				_stage3d.removeEventListener(Event.CONTEXT3D_CREATE, context3dCreatedHandler);
				_stage3d = null;
			}

			if (_context3d != null)
			{
				_context3d.dispose();
				_context3d = null;
			}

			return ;
		}

		/**
		 * Resize the display area. The "resized" signal is executed when the new width and
		 * height have be set.
		 * @param width
		 * @param height
		 *
		 */
		public function resize(width : Number, height : Number) : void
		{
			_autoResize = false;

			setSize(width, height);
		}

		private function setSize(width : Number, height : Number) : void
		{
			if (width == _width && _height == height)
				return ;

			_width = width;
			_height = height;

			updateStage3D();
			updateBackBuffer();
			_resized.execute(this, width, height);
		}

		private function stageResizedHandler(event : Event) : void
		{
			updateMask();
		}

		private function parentResizedHandler(event : Event) : void
		{
			if (_autoResize)
			{
				if (parent == stage)
					setSize(stage.stageWidth, stage.stageHeight);
				else
					setSize(parent.width, parent.height);
			}
		}

		private function context3dCreatedHandler(event : Event) : void
		{
			_context3d = new Context3DResource(_stage3d.context3D);

			updateStage3D();
			updateBackBuffer();

			dispatchEvent(new Event(Event.INIT));
		}

		private function updateBackBuffer() : void
		{
			if (_width == 0 || _height == 0 || _stage3d == null || _stage3d.context3D == null)
				return ;

			_invalidBackBuffer = false;
			_stage3d.context3D.configureBackBuffer(_width, _height, _antiAliasing, true);
			_backBuffer = new RenderTarget(_width, _height, null, 0, _backgroundColor);

			graphics.clear();
			graphics.beginFill(0, 0);
			graphics.drawRect(0, 0, _width, _height);
		}

		private function updateStage3D() : void
		{
			if (_stage3d == null)
				return ;

			var upperLeft	: Point	= localToGlobal(ZERO2);

			_stage3d.x = upperLeft.x;
			_stage3d.y = upperLeft.y;

			if (_width > 2048)
			{
				_stage3d.x = (_width - 2048) * 0.5;
				_width = 2048;
			}
			else
				_stage3d.x = upperLeft.x;

			if (_height > 2048)
			{
				_stage3d.y = (_height - 2048) * 0.5;
				_height = 2048;
			}
			else
				_stage3d.y = upperLeft.y;

			updateMask();
		}

		private function stageEventHandler(event : Object) : void
		{
			if (!_alwaysOnTop || event.target == this)
				return ;

			var stageX	: Number	= event.stageX;
			var stageY	: Number	= event.stageY;

			if (stageX > _stage3d.x && stageX < _stage3d.x + _width
				&& stageY > _stage3d.y && stageY < _stage3d.y + _height)
			{
				dispatchEvent(event.clone());
			}
		}

		private function updateMask() : void
		{
			if (!stage)
				return ;

			var numChildren : uint = stage.numChildren;
			var i 			: uint = 0;

			if (_alwaysOnTop)
			{
				var gfx			: Graphics	= _mask.graphics;
				var stageWidth	: int		= stage.stageWidth;
				var stageHeight	: int		= stage.stageHeight;

				gfx.clear();
				gfx.beginFill(0);
				gfx.moveTo(0, 0);
				gfx.lineTo(stageWidth, 0);
				gfx.lineTo(stageWidth, stageHeight);
				gfx.lineTo(0., stageHeight);
				gfx.lineTo(0, 0);
				gfx.moveTo(_stage3d.x, _stage3d.y);
				gfx.lineTo(_stage3d.x, _stage3d.y + height);
				gfx.lineTo(_stage3d.x + width, _stage3d.y + height);
				gfx.lineTo(_stage3d.x + width, _stage3d.y);
				gfx.lineTo(_stage3d.x, _stage3d.y);
				gfx.endFill();

				for (i = 0; i < numChildren; ++i)
					stage.getChildAt(i).mask = _mask;
			}
			else
			{
				for (i = 0; i < numChildren; ++i)
				{
					var child : DisplayObject = stage.getChildAt(i);

					if (child.mask == _mask)
						child.mask = null;
				}
			}
		}

		private function displayObjectAddedToStageHandler(event : Event) : void
		{
			var displayObject : DisplayObject	= event.target as DisplayObject;

			if (displayObject.parent == stage)
				updateMask();
		}

		private function displayObjectRemovedFromStageHandler(event : Event) : void
		{
			var displayObject : DisplayObject	= event.target as DisplayObject;

			if (_autoResize && displayObject.parent == stage)
				displayObject.mask = null;
		}
	}
}

package aerys.minko.render
{
	import aerys.minko.ns.minko_render;
	import aerys.minko.render.resource.Context3DResource;
	import aerys.minko.type.KeyboardManager;
	import aerys.minko.type.MouseManager;
	import aerys.minko.type.Signal;

	import flash.display.DisplayObject;
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.Stage3D;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TouchEvent;
	import flash.geom.Point;

	/**
	 * The Viewport is the display area where a 3D scene can be rendered.
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Viewport extends Sprite
	{
		private static const ZERO2		: Point				= new Point();

		private var _stage3d			: Stage3D			= null;
		private var _context3d			: Context3DResource	= null;

		private var _width				: uint				= 0;
		private var _height				: uint				= 0;
		private var _autoResize			: Boolean			= false;
		private var _antiAliasing		: uint				= 0;
		private var _backgroundColor	: uint				= 0;
		private var _backBuffer			: RenderTarget		= null;
		private var _invalidBackBuffer	: Boolean			= false;

		private var _alwaysOnTop		: Boolean			= false;
		private var _mask				: Shape				= new Shape();

		private var _mouseManager		: MouseManager		= new MouseManager();
		private var _keyboardManager	: KeyboardManager	= new KeyboardManager();

		private var _resized			: Signal			= new Signal('Viewport.resized');

		minko_render function get context3D() : Context3DResource
		{
			return _context3d;
		}

		minko_render function get backBuffer() : RenderTarget
		{
			var positionOnStage	: Point	= localToGlobal(ZERO2);

			if (_stage3d.x != positionOnStage.x || _stage3d.y != positionOnStage.y)
				updateStage3D()

			return _backBuffer;
		}

		public function get ready() : Boolean
		{
			return _stage3d != null && _stage3d.context3D != null && _backBuffer != null;
		}

		/**
		 * Whether the viewport is visible or not.
		 * @return
		 *
		 */
		override public function get visible() : Boolean
		{
			return _stage3d.visible;
		}
		override public function set visible(value : Boolean) : void
		{
			_stage3d.visible = value;
			super.visible = value;
		}

		override public function set x(value : Number) : void
		{
			super.x = value;
			updateStage3D();
		}

		override public function set y(value : Number) : void
		{
			super.y = value;
			updateStage3D();
		}

		/**
		 * The width of the display area.
		 * @return
		 *
		 */
		override public function get width() : Number
		{
			return _width;
		}
		override public function set width(value : Number) : void
		{
			resize(value, _height);
		}

		/**
		 * The height of the display area.
		 * @return
		 *
		 */
		override public function get height() : Number
		{
			return _height;
		}
		override public function set height(value : Number) : void
		{
			resize(_width, value);
		}

		public function get alwaysOnTop() : Boolean
		{
			return _alwaysOnTop;
		}
		public function set alwaysOnTop(value : Boolean) : void
		{
			_alwaysOnTop = value;
		}

		public function get keyboardManager() : KeyboardManager
		{
			return _keyboardManager;
		}

		public function get mouseManager() : MouseManager
		{
			return _mouseManager;
		}

		/**
		 * The signal executed when the viewport is resized.
		 * Callback functions for this signal should accept the following
		 * arguments:
		 *

		 *
viewport : Viewport, the viewport executing the signal

		 *
width : Number, the new width of the viewport

		 *
height : Number, the new height of the viewport

		 *

		 * @return
		 *
		 */
		public function get resized() : Signal
		{
			return _resized;
		}

		/**
		 * The background color of the display area. This value must use the
		 * RGB format.
		 * @return
		 *
		 */
		public function get backgroundColor() : uint
		{
			return _backgroundColor;
		}
		public function set backgroundColor(value : uint) : void
		{
			_backgroundColor = value;
			updateStage3D();
		}

		/**
		 * The anti-aliasing to use (0, 2, 4, 8 or 16). The actual anti-aliasing
		 * used for rendering depends on the hardware capabilities. If the specified
		 * anti-aliasing value is not supported, the value 0 will be used.
		 * @return
		 *
		 */
		public function get antiAliasing() : uint
		{
			return _antiAliasing;
		}
		public function set antiAliasing(value : uint) : void
		{
			_antiAliasing = value;
			updateStage3D();
		}

		/**
		 * The driver informations provided by the Stage3D API.
		 */
		public function get driverInfo() : String
		{
			return _stage3d && _stage3d.context3D
				? _stage3d.context3D.driverInfo
				: null;
		}

		public function Viewport(antiAliasing	: uint	= 0,
								 width			: uint 	= 0,
								 height			: uint	= 0)
		{
			_antiAliasing = antiAliasing;

			if (width == 0 && height == 0)
				_autoResize = true;

			_width = width;
			_height = height;

			initialize();
		}

		private function initialize() : void
		{
			_mouseManager.bind(this);

			addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
			addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
		}

		private function addedToStageHandler(event : Event) : void
		{
			_keyboardManager.bind(stage);

			parent.addEventListener(Event.RESIZE, parentResizedHandler);

			stage.addEventListener(Event.ADDED_TO_STAGE, displayObjectAddedToStageHandler);
			stage.addEventListener(Event.REMOVED_FROM_STAGE, displayObjectRemovedFromStageHandler);

			setupOnStage(stage);
		}

		private function removedFromStageHandler(event : Event) : void
		{
			_keyboardManager.unbind(stage);

			parent.removeEventListener(Event.RESIZE, parentResizedHandler);

			stage.removeEventListener(Event.ADDED_TO_STAGE, displayObjectAddedToStageHandler);
			stage.removeEventListener(Event.REMOVED_FROM_STAGE, displayObjectRemovedFromStageHandler);

			if (_stage3d != null)
				_stage3d.visible = false;
		}

		private function setupOnStage(stage : Stage, stage3dId : uint = 0) : void
		{
			if (_autoResize)
			{
				_width = stage.stageWidth;
				_height = stage.stageHeight;
			}

			if (!_stage3d)
			{
				_stage3d = stage.stage3Ds[stage3dId];
				_stage3d.addEventListener(Event.CONTEXT3D_CREATE, context3dCreatedHandler);
				_stage3d.requestContext3D();
			}
			else
			{
				_stage3d.visible = true;
			}

			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
		}

		/**
		 * Dispose the Viewport and all the Stage3D related objects. After this operation,
		 * the Viewport cannot be used anymore and is ready for garbage collection.
		 */
		public function dispose():void
		{
			if (_stage3d != null)
			{
				_stage3d.removeEventListener(Event.CONTEXT3D_CREATE, context3dCreatedHandler);
				_stage3d = null;
			}

			if (_context3d != null)
			{
				_context3d.dispose();
				_context3d = null;
			}

			return ;
		}

		/**
		 * Resize the display area. The "resized" signal is executed when the new width and
		 * height have be set.
		 * @param width
		 * @param height
		 *
		 */
		public function resize(width : Number, height : Number) : void
		{
			_autoResize = false;

			setSize(width, height);
		}

		private function setSize(width : Number, height : Number) : void
		{
			if (width == _width && _height == height)
				return ;

			_width = width;
			_height = height;

			updateStage3D();
			updateBackBuffer();
			_resized.execute(this, width, height);
		}

		private function stageResizedHandler(event : Event) : void
		{
			updateMask();
		}

		private function parentResizedHandler(event : Event) : void
		{
			if (_autoResize)
			{
				if (parent == stage)
					setSize(stage.stageWidth, stage.stageHeight);
				else
					setSize(parent.width, parent.height);
			}
		}

		private function context3dCreatedHandler(event : Event) : void
		{
			_context3d = new Context3DResource(_stage3d.context3D);

			updateStage3D();
			updateBackBuffer();

			dispatchEvent(new Event(Event.INIT));
		}

		private function updateBackBuffer() : void
		{
			if (_width == 0 || _height == 0 || _stage3d == null || _stage3d.context3D == null)
				return ;

			_invalidBackBuffer = false;
			_stage3d.context3D.configureBackBuffer(_width, _height, _antiAliasing, true);
			_backBuffer = new RenderTarget(_width, _height, null, 0, _backgroundColor);

			graphics.clear();
			graphics.beginFill(0, 0);
			graphics.drawRect(0, 0, _width, _height);
		}

		private function updateStage3D() : void
		{
			if (_stage3d == null)
				return ;

			var upperLeft	: Point	= localToGlobal(ZERO2);

			_stage3d.x = upperLeft.x;
			_stage3d.y = upperLeft.y;

			if (_width > 2048)
			{
				_stage3d.x = (_width - 2048) * 0.5;
				_width = 2048;
			}
			else
				_stage3d.x = upperLeft.x;

			if (_height > 2048)
			{
				_stage3d.y = (_height - 2048) * 0.5;
				_height = 2048;
			}
			else
				_stage3d.y = upperLeft.y;

			updateMask();
		}

		private function updateMask() : void
		{
			if (!stage)
				return ;

			var numChildren : uint = stage.numChildren;
			var i 			: uint = 0;

			if (_alwaysOnTop)
			{
				var gfx			: Graphics	= _mask.graphics;
				var stageWidth	: int		= stage.stageWidth;
				var stageHeight	: int		= stage.stageHeight;

				gfx.clear();
				gfx.beginFill(0);
				gfx.moveTo(0, 0);
				gfx.lineTo(stageWidth, 0);
				gfx.lineTo(stageWidth, stageHeight);
				gfx.lineTo(0., stageHeight);
				gfx.lineTo(0, 0);
				gfx.moveTo(_stage3d.x, _stage3d.y);
				gfx.lineTo(_stage3d.x, _stage3d.y + height);
				gfx.lineTo(_stage3d.x + width, _stage3d.y + height);
				gfx.lineTo(_stage3d.x + width, _stage3d.y);
				gfx.lineTo(_stage3d.x, _stage3d.y);
				gfx.endFill();

				for (i = 0; i < numChildren; ++i)
					stage.getChildAt(i).mask = _mask;
			}
			else
			{
				for (i = 0; i < numChildren; ++i)
				{
					var child : DisplayObject = stage.getChildAt(i);

					if (child.mask == _mask)
						child.mask = null;
				}
			}
		}

		private function displayObjectAddedToStageHandler(event : Event) : void
		{
			var displayObject : DisplayObject	= event.target as DisplayObject;

			if (displayObject.parent == stage)
				updateMask();
		}

		private function displayObjectRemovedFromStageHandler(event : Event) : void
		{
			var displayObject : DisplayObject	= event.target as DisplayObject;

			if (_autoResize && displayObject.parent == stage)
				displayObject.mask = null;
		}
	}
}

remove stage events handling in Viewport made useless by drawing a transparent rectangle on top of the viewport


package br.com.yuiti.lab.infiniship
{
    import flash.display.MovieClip;
    import flash.display.Shape;
    import flash.display.Sprite;

    /**
     * InfiniShip | AS3 :: A procedural spaceship generator
     * ======================================================================
     *
     * This is a remake of Dave Bollinger's "Pixel Spaceships", remade and
     * fully commented.
     *
     * I tried to organize things inside and comment/explain everything, but I'm
     * a little bit bad with programming so, sorry if I messed up something.
     *
     * The original script was made for Processing, in 2006, by Dave. But this
     * version has also used "mtheall" HTML5 Canvas (from 2013) version as reference
     * for some structure and methods.
     *
     * This version is intended to work the same way as Bollinger's original script,
     * and it tries to follow the same rules for the ship's cell grid.
     *
     * NOTE: Some of the creative output (images) generated by this script remains
     * property of Dave Bollinger, as this script follows his basic concept. Even
     * though the possible combination of ships is huge, Dave still has copyright
     * over his artistic output, so use this carefully.
     *
     * You are welcome (and highly encouraged) to fork, remix, create your
     * own way to generate sprites and use this as reference to build your own
     * generator. :)
     *
     * @author Fabio Y. Goto <lab@yuiti.com.br>
     */
    public class InfiniShip extends Sprite
    {
        /* PRIVATE VARIABLES
         * ====================================================================== */

        /**
         * Empty cell flag.
         */
        private var S_EMPTY:Number = 0;

        /**
         * Solid cell flag.
         */
        private var S_SOLID:Number = 1;

        /**
         * Main body cell flag.
         */
        private var S_SHAPE:Number = 2;

        /**
         * Cockpit cell flag.
         */
        private var S_CABIN:Number = 3;

        /**
         * Ship width, in pixels.
         */
        private var SHIP_W:Number = 12;

        /**
         * Ship height, in pixels.
         */
        private var SHIP_H:Number = 12;

        /**
         * Array containing saturation values, to be used when defining colors.
         */
        private var sats:Array = [
            40, 60, 80, 100, 80, 60, 80, 100, 120, 100, 80, 60
        ];

        /**
         * Array containing brightness values, to be used when defining colors.
         */
        private var bris:Array = [
            40, 70, 100, 130, 160, 190, 220, 220, 190, 160, 130, 100, 70, 40
        ];

        /**
         * Array containing the cell data for body cells in the ship's sprite.
         *
         * Content defined inside the constructor.
         */
        private var solidCell:Array;

        /**
         * Array containing the cell data for cockpit cells in the ship's sprite.
         *
         * Content defined inside the constructor.
         */
        private var shapeCell:Array;

        /**
         * Array containing the cell data for cockpit cells in the ship's sprite.
         *
         * Content defined inside the constructor.
         */
        private var cabinCell:Array;

        /**
         * Main ship array, used when generating the ship, to define the ship's cells.
         */
        private var shipCell:Array;

        /**
         * Pseudo-random integer, to be used a seed when defining the ship's shape.
         *
         * Content defined inside the constructor.
         */
        private var mainseed:Number;

        /**
         * Pseudo-random integer, to be used a seed when defining the ship's color.
         *
         * Content defined inside the constructor.
         */
        private var clrsseed:Number;

        /**
         * Main ship containter.
         */
        private var ship:Shape;

        /**
         * Main ship wrapper. This is the object that will be added to the stage.
         */
        private var wrap:MovieClip;

        /* CONSTRUCTOR
         * ====================================================================== */
        public function InfiniShip()
        {
            // Defining seeds
            mainseed = generateSeed();
            clrsseed = generateSeed();

            // Defining cell data
            solidCell = [
                cell(5, 2),  cell(5, 3),  cell(5, 4),
                cell(5, 5),  cell(5, 9)
            ];
            shapeCell = [
                cell(4, 1),  cell(5, 1),  cell(4, 2),  cell(3, 3),   cell(4, 3),
                cell(3, 4),  cell(4, 4),  cell(2, 5),  cell(3, 5),   cell(4, 5),
                cell(1, 6),  cell(2, 6),  cell(3, 6),  cell(1, 7),   cell(2, 7),
                cell(3, 7),  cell(1, 8),  cell(2, 8),  cell(3, 8),   cell(1, 9),
                cell(2, 9),  cell(3, 9),  cell(4, 9),  cell(3, 10),  cell(4, 10),
                cell(5, 10)
            ];
            cabinCell = [
                cell(4,6),  cell(5,6),  cell(4,7),  cell(5,7),
                cell(4,8),  cell(5,8)
            ];

            // Generating ship
            generateShip();
        }

        /* SEED GENERATION AND NUMBER OPERATIONS
         * ====================================================================== */

        /**
         * Calculates the pixel index value.
         * @param x
         * @param y
         * @return
         */
        private function cell(x:Number, y:Number):Number
        {
            return (y * SHIP_W) + x;
        }

        /**
         * Generates the seeds for defining the ship's shape and color.
         *
         * It tries to use something similar to the original script's seed generator.
         *
         * @return
         */
        private function generateSeed():Number
        {
            return Math.floor(Math.random() * 4 * 1024 * 1024 * 1024);
        }

        /**
         * Converts a decimal number to its HEX counterpart.
         *
         * Restricted from 0 to 255, if input is lower than 0 it will be changed
         * to 0, and if bigger than 255 will be changed to 255.
         *
         * @param nums
         * @return
         */
        private function dechex(nums:Number):String
        {
            // Checking if lower than 0 or bigger than 255
            if (nums < 0) nums = 0;
            if (nums > 255) nums = 255;
            // Converting to string and returning
            return nums.toString(16).toUpperCase();
        }

        /**
         * Returns the array length (number of items inside).
         *
         * @param array
         * @return
         */
        private function countArray(array:Array):Number
        {
            var length:int = 0;
            for (var i:* in array) length++;
            return length;
        }

        /* COLORS
         * ====================================================================== */

        /**
         * Converts the HSV (Hue, Saturation and Brightness) values from a color
         * into its RGB counterpart, returning them in a formatted object, with its
         * RGB values.
         *
         * @param h
         * @param s
         * @param v
         * @return
         */
        private function HSVRGB(h:Number, s:Number, v:Number):Number
        {
            // Declaring internal variables
            var r:Number, g:Number, b:Number, i:Number, f:Number, p:Number,
                q:Number, t:Number;
            // If saturation equals 0, returns a shade of gray
            if (s == 0) {
                // Generating shade of gray for all RGB channels
                var gray:String = dechex(Math.floor(v * 255));
                // Returning values
                return parseInt("0x" + gray + gray + gray);
            }
            // Defining color values
            i = Math.floor(h * 6);
            f = h * 6 - i;
            p = v * (1 - s);
            q = v * (1 - f * s);
            t = v * (1 * (1 - f) * s);
            // Defining RGB values5
            switch (i % 6) {
                case 1:
                    r = q;
                    g = v;
                    b = p;
                    break;
                case 2:
                    r = p;
                    g = v;
                    b = t;
                    break;
                case 3:
                    r = p;
                    g = q;
                    b = v;
                    break;
                case 4:
                    r = t;
                    g = p;
                    b = v;
                    break;
                case 5:
                    r = v;
                    g = p;
                    b = q;
                    break;
                default:
                    r = v;
                    g = t;
                    b = p;
                    break;
            }
            // Returning color
            return parseInt(
                "0x"
                + dechex(Math.floor(r * 255))
                + dechex(Math.floor(g * 255))
                + dechex(Math.floor(b * 255))
            );
        }

        /**
         * Defines the colors for a determined pixel, on the ship's body. Returns
         * it as an integer corresponding to the RGB values of the defined color.
         *
         * @param x
         * @param y
         * @return
         */
        private function shapeColor(x:Number, y:Number):Number
        {
            // Defining saturation
            var s:Number = sats[y] / 255.0;
            // Defining brightness
            var b:Number = bris[x] / 255.0;
            // Defining hue
            var h:Number;
            if (y < 6) {
                h = (clrsseed >> 8) & 0xFF;
            } else if (y < 9) {
                h = (clrsseed >> 16) & 0xFF;
            } else {
                h = (clrsseed >> 24) & 0xFF;
            }
            // Returning
            return HSVRGB(360 * h / 256, s, b);
        }

        /**
         * Defines the colors for a determined pixel, on the ship's cockpit. Returns
         * it as an integer corresponding to the RGB values of the defined color.
         *
         * @param x
         * @param y
         * @return
         */
        private function cabinColor(x:Number, y:Number):Number
        {
            // Defining saturation
            var s:Number = sats[y] / 255.0;
            // Defining brightness
            var b:Number = (bris[x] + 40) / 255.0;
            // Defining hue
            var h:Number = clrsseed & 0xFF;
            // Returning
            return HSVRGB(360 * h / 256, s, b);
        }

        /* SHIP GENERATION
         * ====================================================================== */

        /**
         * Generates a single ship and adds it to the stage.
         */
        private function generateShip():void
        {
            // Initializing ship sprite
            ship = new Shape();

            // Initializing sprite wrapper
            wrap = new MovieClip();

            // Initializing ship cell array
            shipCell = new Array();

            // Marking all cells as empty, to start
            var area:Number = SHIP_W * SHIP_H;
            for (var i:Number = 0; i < area; i++) {
                shipCell[i] = S_EMPTY;
            }
            // Initializing always solid cells
            for (var i = 0; i < countArray(solidCell); ++i ) {
                shipCell[solidCell[i]] = S_SOLID;
            }

            // Marking body cells
            for (var i:Number = 0; i < countArray(shapeCell); ++i ) {
                if ((mainseed & (1 << i)) > 0) {
                    shipCell[shapeCell[i]] = S_SHAPE;
                } else {
                    shipCell[shapeCell[i]] = S_EMPTY;
                }
            }

            // Marking the cockpit cells
            for (var i:Number = 0; i < countArray(cabinCell); ++i ) {
                if ((mainseed & (1 << (countArray(shapeCell) + 1))) > 0) {
                    shipCell[cabinCell[i]] = S_SOLID;
                } else {
                    shipCell[cabinCell[i]] = S_CABIN;
                }
            }

            // Defining border cells
            for (var y:Number = 0; y < SHIP_H; ++y) {
                for (var x:Number = 0; x < (SHIP_W / 2); ++x) {
                    // If the cell is a body cell
                    if (shipCell[cell(x, y)] == S_SHAPE) {
                        // Top
                        if (y > 0 && shipCell[cell(x, y - 1)] == S_EMPTY) {
                            shipCell[cell(x, y - 1)] = S_SOLID;
                        }
                        // Left
                        if (x > 0 && shipCell[cell(x - 1, y)] == S_EMPTY) {
                            shipCell[cell(x - 1, y)] = S_SOLID;
                        }
                        // Right
                        if (
                            x < Math.floor(SHIP_W / 2) - 1
                            && shipCell[cell(x + 1, y)] == S_EMPTY
                        ) {
                            shipCell[cell(x + 1, y)] = S_SOLID;
                        }
                        // Bottom
                        if (y < SHIP_H && shipCell[cell(x, y + 1)] == S_EMPTY) {
                            shipCell[cell(x, y + 1)] = S_SOLID;
                        }
                    }
                }
            }

            // Drawing the pixels inside the shape object
            for (var y:Number = 0; y < SHIP_H; ++y) {
                for (var x:Number = 0; x < (SHIP_W / 2); ++x) {
                    // If the current cell isn't an empty cell
                    if (shipCell[cell(x, y)] != S_EMPTY) {
                        // Defining colors to paint the ship
                        if (shipCell[cell(x, y)] == S_SOLID) {
                            // Border/solid cell color
                            ship.graphics.beginFill(0x000000, 1);
                        } else if (shipCell[cell(x, y)] == S_SHAPE) {
                            // Defining body color
                            var tint:Number = shapeColor(x, y);
                            // Begin filling with the current color
                            ship.graphics.beginFill(tint, 1);
                        } else if (shipCell[cell(x, y)] == S_CABIN) {
                            // Defining cockpit color
                            var tint:Number = cabinColor(x, y);
                            // Begin filling with the current color
                            ship.graphics.beginFill(tint, 1);
                        }
                        // Drawing the pixel
                        ship.graphics.drawRect(x, y, 1, 1);
                        // Drawing the mirrored pixel
                        ship.graphics.drawRect(SHIP_W - x - 1, y, 1, 1);
                    }
                }
            }

            // Wrapping the ship and adjusting position (centering in x0, y0)
            wrap.addChild(ship);
            ship.x = -6;
            ship.y = -6;

            // Adding it to the stage
            addChild(wrap);
        }
    }
}

package br.com.yuiti.lab.infiniship
{
    import flash.display.MovieClip;
    import flash.display.Shape;
    import flash.display.Sprite;

    /**
     * InfiniShip | AS3 :: A procedural spaceship generator
     * ======================================================================
     *
     * This is a remake of Dave Bollinger's "Pixel Spaceships", remade and
     * fully commented.
     *
     * I tried to organize things inside and comment/explain everything, but I'm
     * a little bit bad with programming so, sorry if I messed up something.
     *
     * The original script was made for Processing, in 2006, by Dave. But this
     * version has also used "mtheall" HTML5 Canvas (from 2013) version as reference
     * for some structure and methods.
     *
     * This version is intended to work the same way as Bollinger's original script,
     * and it tries to follow the same rules for the ship's cell grid.
     *
     * NOTE: Some of the creative output (images) generated by this script remains
     * property of Dave Bollinger, as this script follows his basic concept. Even
     * though the possible combination of ships is huge, Dave still has copyright
     * over his artistic output, so use this carefully.
     *
     * You are welcome (and highly encouraged) to fork, remix, create your
     * own way to generate sprites and use this as reference to build your own
     * generator. :)
     *
     * @author Fabio Y. Goto <lab@yuiti.com.br>
     */
    public class InfiniShip extends Sprite
    {
        /* PRIVATE VARIABLES
         * ====================================================================== */

        /**
         * Empty cell flag.
         */
        private var S_EMPTY:Number = 0;

        /**
         * Solid cell flag.
         */
        private var S_SOLID:Number = 1;

        /**
         * Main body cell flag.
         */
        private var S_SHAPE:Number = 2;

        /**
         * Cockpit cell flag.
         */
        private var S_CABIN:Number = 3;

        /**
         * Ship width, in pixels.
         */
        private var SHIP_W:Number = 12;

        /**
         * Ship height, in pixels.
         */
        private var SHIP_H:Number = 12;

        /**
         * Array containing saturation values, to be used when defining colors.
         */
        private var sats:Array = [
            40, 60, 80, 100, 80, 60, 80, 100, 120, 100, 80, 60
        ];

        /**
         * Array containing brightness values, to be used when defining colors.
         */
        private var bris:Array = [
            40, 70, 100, 130, 160, 190, 220, 220, 190, 160, 130, 100, 70, 40
        ];

        /**
         * Array containing the cell data for body cells in the ship's sprite.
         *
         * Content defined inside the constructor.
         */
        private var solidCell:Array;

        /**
         * Array containing the cell data for cockpit cells in the ship's sprite.
         *
         * Content defined inside the constructor.
         */
        private var shapeCell:Array;

        /**
         * Array containing the cell data for cockpit cells in the ship's sprite.
         *
         * Content defined inside the constructor.
         */
        private var cabinCell:Array;

        /**
         * Main ship array, used when generating the ship, to define the ship's cells.
         */
        private var shipCell:Array;

        /**
         * Pseudo-random integer, to be used a seed when defining the ship's shape.
         *
         * Content defined inside the constructor.
         */
        private var mainseed:Number;

        /**
         * Pseudo-random integer, to be used a seed when defining the ship's color.
         *
         * Content defined inside the constructor.
         */
        private var clrsseed:Number;

        /**
         * Main ship containter.
         */
        private var ship:Shape;

        /**
         * Main ship wrapper. This is the object that will be added to the stage.
         */
        private var wrap:MovieClip;

        /* CONSTRUCTOR
         * ====================================================================== */
        public function InfiniShip()
        {
            // Defining seeds
            mainseed = generateSeed();
            clrsseed = generateSeed();

            // Defining cell data
            solidCell = [
                cell(5, 2),  cell(5, 3),  cell(5, 4),
                cell(5, 5),  cell(5, 9)
            ];
            shapeCell = [
                cell(4, 1),  cell(5, 1),  cell(4, 2),  cell(3, 3),   cell(4, 3),
                cell(3, 4),  cell(4, 4),  cell(2, 5),  cell(3, 5),   cell(4, 5),
                cell(1, 6),  cell(2, 6),  cell(3, 6),  cell(1, 7),   cell(2, 7),
                cell(3, 7),  cell(1, 8),  cell(2, 8),  cell(3, 8),   cell(1, 9),
                cell(2, 9),  cell(3, 9),  cell(4, 9),  cell(3, 10),  cell(4, 10),
                cell(5, 10)
            ];
            cabinCell = [
                cell(4,6),  cell(5,6),  cell(4,7),  cell(5,7),
                cell(4,8),  cell(5,8)
            ];

            // Generating ship
            generateShip();
        }

        /* SEED GENERATION AND NUMBER OPERATIONS
         * ====================================================================== */

        /**
         * Calculates the pixel index value.
         * @param x
         * @param y
         * @return
         */
        private function cell(x:Number, y:Number):Number
        {
            return (y * SHIP_W) + x;
        }

        /**
         * Generates the seeds for defining the ship's shape and color.
         *
         * It tries to use something similar to the original script's seed generator.
         *
         * @return
         */
        private function generateSeed():Number
        {
            return Math.floor(Math.random() * 4 * 1024 * 1024 * 1024);
        }

        /**
         * Converts a decimal number to its HEX counterpart.
         *
         * Restricted from 0 to 255, if input is lower than 0 it will be changed
         * to 0, and if bigger than 255 will be changed to 255.
         *
         * @param nums
         * @return
         */
        private function dechex(nums:Number):String
        {
            // Checking if lower than 0 or bigger than 255
            if (nums < 0) nums = 0;
            if (nums > 255) nums = 255;
            // Converting to string and returning
            return nums.toString(16).toUpperCase();
        }

        /**
         * Returns the array length (number of items inside).
         *
         * @param array
         * @return
         */
        private function countArray(array:Array):Number
        {
            var length:int = 0;
            for (var i:* in array) length++;
            return length;
        }

        /* COLORS
         * ====================================================================== */

        /**
         * Converts the HSV (Hue, Saturation and Brightness) values from a color
         * into its RGB counterpart, returning them in a formatted object, with its
         * RGB values.
         *
         * @param h
         * @param s
         * @param v
         * @return
         */
        private function HSVRGB(h:Number, s:Number, v:Number):Number
        {
            // Declaring internal variables
            var r:Number, g:Number, b:Number, i:Number, f:Number, p:Number,
                q:Number, t:Number;
            // If saturation equals 0, returns a shade of gray
            if (s == 0) {
                // Generating shade of gray for all RGB channels
                var gray:String = dechex(Math.floor(v * 255));
                // Returning values
                return parseInt("0x" + gray + gray + gray);
            }
            // Defining color values
            i = Math.floor(h * 6);
            f = h * 6 - i;
            p = v * (1 - s);
            q = v * (1 - f * s);
            t = v * (1 * (1 - f) * s);
            // Defining RGB values5
            switch (i % 6) {
                case 1:
                    r = q;
                    g = v;
                    b = p;
                    break;
                case 2:
                    r = p;
                    g = v;
                    b = t;
                    break;
                case 3:
                    r = p;
                    g = q;
                    b = v;
                    break;
                case 4:
                    r = t;
                    g = p;
                    b = v;
                    break;
                case 5:
                    r = v;
                    g = p;
                    b = q;
                    break;
                default:
                    r = v;
                    g = t;
                    b = p;
                    break;
            }
            // Returning color
            return parseInt(
                "0x"
                + dechex(Math.floor(r * 255))
                + dechex(Math.floor(g * 255))
                + dechex(Math.floor(b * 255))
            );
        }

        /**
         * Defines the colors for a determined pixel, on the ship's body. Returns
         * it as an integer corresponding to the RGB values of the defined color.
         *
         * @param x
         * @param y
         * @return
         */
        private function shapeColor(x:Number, y:Number):Number
        {
            // Defining saturation
            var s:Number = sats[y] / 255.0;
            // Defining brightness
            var b:Number = bris[x] / 255.0;
            // Defining hue
            var h:Number;
            if (y < 6) {
                h = (clrsseed >> 8) & 0xFF;
            } else if (y < 9) {
                h = (clrsseed >> 16) & 0xFF;
            } else {
                h = (clrsseed >> 24) & 0xFF;
            }
            // Returning
            return HSVRGB(360 * h / 256, s, b);
        }

        /**
         * Defines the colors for a determined pixel, on the ship's cockpit. Returns
         * it as an integer corresponding to the RGB values of the defined color.
         *
         * @param x
         * @param y
         * @return
         */
        private function cabinColor(x:Number, y:Number):Number
        {
            // Defining saturation
            var s:Number = sats[y] / 255.0;
            // Defining brightness
            var b:Number = (bris[x] + 40) / 255.0;
            // Defining hue
            var h:Number = clrsseed & 0xFF;
            // Returning
            return HSVRGB(360 * h / 256, s, b);
        }

        /* SHIP GENERATION
         * ====================================================================== */

        /**
         * Generates a single ship and adds it to the stage.
         */
        private function generateShip():void
        {
            // Initializing ship sprite
            ship = new Shape();

            // Initializing sprite wrapper
            wrap = new MovieClip();

            // Initializing ship cell array
            shipCell = new Array();

            // Marking all cells as empty, to start
            var area:Number = SHIP_W * SHIP_H;
            for (var i:Number = 0; i < area; i++) {
                shipCell[i] = S_EMPTY;
            }
            // Initializing always solid cells
            for (var i = 0; i < countArray(solidCell); ++i ) {
                shipCell[solidCell[i]] = S_SOLID;
            }

            // Marking body cells
            for (var i:Number = 0; i < countArray(shapeCell); ++i ) {
                if ((mainseed & (1 << i)) > 0) {
                    shipCell[shapeCell[i]] = S_SHAPE;
                } else {
                    shipCell[shapeCell[i]] = S_EMPTY;
                }
            }

            // Marking the cockpit cells
            for (var i:Number = 0; i < countArray(cabinCell); ++i ) {
                if ((mainseed & (1 << (countArray(shapeCell) + i))) > 0) {
                    shipCell[cabinCell[i]] = S_SOLID;
                } else {
                    shipCell[cabinCell[i]] = S_CABIN;
                }
            }

            // Defining border cells
            for (var y:Number = 0; y < SHIP_H; ++y) {
                for (var x:Number = 0; x < (SHIP_W / 2); ++x) {
                    // If the cell is a body cell
                    if (shipCell[cell(x, y)] == S_SHAPE) {
                        // Top
                        if (y > 0 && shipCell[cell(x, y - 1)] == S_EMPTY) {
                            shipCell[cell(x, y - 1)] = S_SOLID;
                        }
                        // Left
                        if (x > 0 && shipCell[cell(x - 1, y)] == S_EMPTY) {
                            shipCell[cell(x - 1, y)] = S_SOLID;
                        }
                        // Right
                        if (
                            x < Math.floor(SHIP_W / 2) - 1
                            && shipCell[cell(x + 1, y)] == S_EMPTY
                        ) {
                            shipCell[cell(x + 1, y)] = S_SOLID;
                        }
                        // Bottom
                        if (y < SHIP_H && shipCell[cell(x, y + 1)] == S_EMPTY) {
                            shipCell[cell(x, y + 1)] = S_SOLID;
                        }
                    }
                }
            }

            // Drawing the pixels inside the shape object
            for (var y:Number = 0; y < SHIP_H; ++y) {
                for (var x:Number = 0; x < (SHIP_W / 2); ++x) {
                    // If the current cell isn't an empty cell
                    if (shipCell[cell(x, y)] != S_EMPTY) {
                        // Defining colors to paint the ship
                        if (shipCell[cell(x, y)] == S_SOLID) {
                            // Border/solid cell color
                            ship.graphics.beginFill(0x000000, 1);
                        } else if (shipCell[cell(x, y)] == S_SHAPE) {
                            // Defining body color
                            var tint:Number = shapeColor(x, y);
                            // Begin filling with the current color
                            ship.graphics.beginFill(tint, 1);
                        } else if (shipCell[cell(x, y)] == S_CABIN) {
                            // Defining cockpit color
                            var tint:Number = cabinColor(x, y);
                            // Begin filling with the current color
                            ship.graphics.beginFill(tint, 1);
                        }
                        // Drawing the pixel
                        ship.graphics.drawRect(x, y, 1, 1);
                        // Drawing the mirrored pixel
                        ship.graphics.drawRect(SHIP_W - x - 1, y, 1, 1);
                    }
                }
            }

            // Wrapping the ship and adjusting position (centering in x0, y0)
            wrap.addChild(ship);
            ship.x = -6;
            ship.y = -6;

            // Adding it to the stage
            addChild(wrap);
        }
    }
}

Update InfiniShip.as

Update InfiniShip.as