1. package Game{
  2.     import Actions.*;
  3.    
  4.     import Box2D.Collision.*;
  5.     import Box2D.Collision.Shapes.*;
  6.     import Box2D.Common.Math.*;
  7.     import Box2D.Dynamics.*;
  8.     import Box2D.Dynamics.Contacts.*;
  9.     import Box2D.Dynamics.Joints.*;
  10.    
  11.     import Game.Challenges.*;
  12.     import Game.Graphics.*;
  13.     import Game.Tutorials.*;
  14.    
  15.     import General.*;
  16.  
  17.     import Gui.*;
  18.     import Parts.*;
  19.     import flash.display.*;
  20.     import flash.errors.IllegalOperationError;
  21.     import flash.events.*;
  22.     import flash.geom.Matrix;
  23.     import flash.media.*;
  24.     import flash.text.*;
  25.     import flash.utils.getTimer;
  26.  
  27.    
  28.     public class ControllerGame extends Controller {
  29.  
  30.         //======================
  31.         // Member Data
  32.         //======================
  33.         static public const INIT_PHYS_SCALE:Number = 30;
  34.  
  35.         protected static const MIN_ZOOM_VAL:Number = 0.01;
  36.         protected static const MAX_ZOOM_VAL:Number = 20000;
  37.  
  38.         static public const ZOOM_FOCUS_X:Number = 400;
  39.         static public const ZOOM_FOCUS_Y:Number = 310;
  40.        
  41.         public static const REPLAY_SYNC_FRAMES:int = 3;
  42.        
  43.         public static const ADMIN_USERS:Array = ["Oliver", "Ryan Clark", "aaaaajon", "andreas002", "BillyJimBob", "EMDF", "fighterlegend", "Sruixan", "Illume", "Cheeseyx", "Leafsnail", "bigjohnpalmer", "jayther", "Spedione", "Thax", "b0tman", "zom", "KyuubisSlave", "Redstater", "rutgersemp", "Euphrates", "lakeeriesuperstar", "SilverGun", "mattbob", "bowman9898", "willempiee", "dark dan21", "pandm"];
  44.         static public var playingReplay:Boolean = false;
  45.         static public var viewingUnsavedReplay:Boolean = false;
  46.         static public var replay:Replay;
  47.         static public var replayDirectlyLinked:Boolean = false;
  48.  
  49.         private var replaySplineXs:Array;
  50.         private var replaySplineYs:Array;
  51.         private var replaySplineAngles:Array;
  52.  
  53.         static public var collisionGroup:int = 0x0001;
  54.        
  55.         public var degree:Number;
  56.         public var newAngle:Number;
  57.         public var radian:Number;
  58.         public var newdegree:Number;
  59.         public var initrotang:Number;
  60.        
  61.         public var rect:ShapePart;
  62.        
  63.         public var m_world:b2World = null;
  64.         public var m_mouseJoint:b2MouseJoint = null;
  65.         public var m_iterations:int = 10;
  66.         public var m_timeStep:Number = 1.0/30;
  67.         public var m_physScale:Number = INIT_PHYS_SCALE;
  68.         // world mouse position
  69.         static public var wasMouseDown:Boolean = false;
  70.         static public var mouseXWorldPhys:Number;
  71.         static public var mouseYWorldPhys:Number;
  72.         static public var mouseXWorld:Number;
  73.         static public var mouseYWorld:Number;
  74.         static public var prevMouseXWorld:Number;
  75.         static public var prevMouseYWorld:Number;
  76.         // Sprite to draw in to
  77.         public var m_canvas:Sprite;
  78.         public var m_buildAreas:Array = new Array();
  79.         public var m_badBuildAreas:Array = new Array();
  80.         public var m_selectedBuildAreas:Array = new Array();
  81.         public var m_guiMenu:DropDownMenu;
  82.         public var m_guiPanel:MainEditPanel;
  83.         public var m_sidePanel:PartEditWindow;
  84.         public var m_chooserWindow:SaveLoadWindow = null;
  85.         public var m_loginWindow:LoginWindow = null;
  86.         public var m_newUserWindow:NewUserWindow = null;
  87.         public var m_scoreWindow:ScoreWindow = null;
  88.         public var m_progressDialog:DialogWindow = null;
  89.         public var m_linkDialog:LinkWindow = null;
  90.         public var m_tutorialDialog:TutorialWindow = null;
  91.         public var m_postReplayWindow:PostReplayWindow = null;
  92.         public var m_rateDialog:RateWindow = null;
  93.         public var m_restrictionsDialog:RestrictionsWindow = null;
  94.         public var m_conditionsDialog:ConditionsWindow = null;
  95.         public var m_sandboxWindow:AdvancedSandboxWindow = null;
  96.         public var m_challengeWindow:ChooseChallengeWindow = null;
  97.         public var m_reportWindow:ReportWindow = null;
  98.         public var m_loadWindow:LoadWindow = null;
  99.         public var m_exportDialog:ExportWindow = null;
  100.         public var m_importDialog:ImportWindow = null;
  101.         public var m_fader:Sprite;
  102.  
  103.         public static var minDensity:Number = 0.01;
  104.         public static var maxDensity:Number = 100;
  105.         public static var maxRJStrength:Number = 100;
  106.         public static var maxRJSpeed:Number = 100;
  107.         public static var maxSJStrength:Number = 100;
  108.         public static var maxSJSpeed:Number = 100;
  109.         public static var maxThrusterStrength:Number = 100;
  110.        
  111.         protected var hasPanned:Boolean = true;
  112.         protected var hasZoomed:Boolean = true;
  113.         protected var redrawBuildArea:Boolean = true;
  114.         protected var redrawRobot:Boolean = true;
  115.        
  116.         public var paused:Boolean = true;
  117.         public var simStarted:Boolean = false;
  118.         public var wonChallenge:Boolean = false;
  119.         public var canSaveReplay:Boolean = true;
  120.         protected var autoPanning:Boolean = true;
  121.         protected var cameraPart:ShapePart = null;
  122.        
  123.         public static var initX:Number = Number.MAX_VALUE;
  124.         public static var initY:Number = Number.MAX_VALUE;
  125.         public static var initZoom:Number = Number.MAX_VALUE;
  126.        
  127.         public static var defaultR:Number = 150;
  128.         public static var defaultG:Number = 150;
  129.         public static var defaultB:Number = 150;
  130.         public static var defaultO:Number = 255;
  131.         public static var clickedBox:Boolean = false;
  132.         public static var adStarted:Boolean = false;
  133.         public static var snapToCenter:Boolean = true;
  134.         public static var showJoints:Boolean = true;
  135.         public static var showOutlines:Boolean = true;
  136.         public static var showGraphics:Boolean = true;
  137.         public static var showColours:Boolean = true;
  138.         public static var centerOnSelected:Boolean = false;
  139.         public static var failedChallenge:Boolean = false;
  140.         public static var justLoadedRobotWithChallenge:Boolean = false;
  141.         private var initRotatingAngle:Number;
  142.         private var initDragX:Number;
  143.         private var initDragY:Number;
  144.         protected var curAction:int = -1;
  145.         private var actionStep:int = 0;
  146.         private var firstClickX:Number;
  147.         private var firstClickY:Number;
  148.         private var secondClickX:Number;
  149.         private var secondClickY:Number;
  150.         private var savedDrawXOff:Number;
  151.         private var savedDrawYOff:Number;
  152.         private var mostRecentScaleFactor:Number
  153.        
  154.         public var draw:Draw;
  155.        
  156.         public var sSky:Sky;
  157.        
  158.         public var allParts:Array;
  159.         public static var cannonballs:Array = null;
  160.         public var actions:Array;
  161.         public var cameraMovements:Array;
  162.         public var keyPresses:Array;
  163.         public var syncPoints:Array;
  164.        
  165.         public var frameCounter:int;
  166.         public var lastAction:int = -1;
  167.         protected var partsFit:Boolean = true;
  168.         private var draggingTutorial:Boolean = false;
  169.         private var selectingCondition:Boolean = false;
  170.         private var delayedSelection:Boolean = false;
  171.         public var ignoreAClick:Boolean = false;
  172.         public var backToSaveWindow:Boolean = false;
  173.         public var clickedReport:Boolean = false;
  174.         public var clickedSave:Boolean = false;
  175.         public var clickedSaveReplay:Boolean = false;
  176.         public var clickedSaveChallenge:Boolean = false;
  177.         public var clickedSubmitScore:Boolean = false;
  178.         public static var showTutorial:Boolean = true;
  179.         private var redirectAfterRating:int = 0;
  180.         public static var ratedCurRobot:Boolean = false;
  181.         public static var ratedCurReplay:Boolean = false;
  182.         public static var ratedCurChallenge:Boolean = false;
  183.         public var saveAfterRestrictions:Boolean = false;
  184.  
  185.         public static var loadAndInsert:Boolean = false;
  186.         public static var potentialRobotID:String = "";
  187.         public static var potentialRobotEditable:Boolean = false;
  188.         public static var potentialRobotPublic:Boolean = false;
  189.         public static var potentialRobotFeatured:Boolean = false;
  190.         public static var potentialChallengeID:String = "";
  191.         public static var potentialChallengeEditable:Boolean = false;
  192.         public static var potentialChallengePublic:Boolean = false;
  193.         public static var potentialChallengeFeatured:Boolean = false;
  194.         public static var potentialReplayID:String = "";
  195.         public static var potentialReplayPublic:Boolean = false;
  196.         public static var potentialReplayFeatured:Boolean = false;
  197.         public static var curRobotID:String = "";
  198.         public static var curRobotEditable:Boolean = true;
  199.         public static var curRobotPublic:Boolean = false;
  200.         public static var curRobotFeatured:Boolean = false;
  201.         public static var curChallengeID:String = "";
  202.         public static var curChallengePublic:Boolean = false;
  203.         public static var curChallengeFeatured:Boolean = false;
  204.         public static var curReplayID:String = "";
  205.         public static var curReplayPublic:Boolean = false;
  206.         public static var curReplayFeatured:Boolean = false;
  207.         public static var userName:String = "_Public";
  208.         public static var password:String = "";
  209.         public static var sessionID:String = "";
  210.  
  211.         public var selectedParts:Array = new Array();
  212.         public var selectedBuildArea:b2AABB;
  213.         public var rotatingPart:Object = null;
  214.         public var rotatingParts:Array = null;
  215.         public var draggingPart:Part = null;
  216.         public var draggingParts:Array = null;
  217.         public static var clipboardParts:Array = new Array();
  218.         public var jointPart:ShapePart = null;
  219.         private var lastSelectedShape:ShapePart = null;
  220.         private var lastSelectedJoint:JointPart = null;
  221.         private var lastSelectedText:TextPart = null;
  222.         private var lastSelectedThrusters:Thrusters = null;
  223.         public var copiedJoint:JointPart = null;
  224.         public var copiedThrusters:Thrusters = null;
  225.         public static var replayParts:Array = new Array();
  226.         public static var loadedParts:Array = null;
  227.        
  228.         protected var removedGraphics:Array = new Array();
  229.        
  230.         protected var uneditableText:TextField;
  231.         protected var rotatingText:TextField;
  232.         protected var scalingText:TextField;
  233.         protected var boxText:TextField;
  234.         protected var horizLineText:TextField;
  235.         protected var vertLineText:TextField;
  236.         protected var shapeText:TextField;
  237.         private var newText:Object = null;
  238.         private var oldText:String = "";
  239.        
  240.         public var potentialJointPart1:ShapePart = null;
  241.         public var potentialJointPart2:ShapePart = null;
  242.         public var candidateJointX:Number;
  243.         public var candidateJointY:Number;
  244.         public var candidateJointType:int;
  245.         public var candidateJointParts:Array;
  246.        
  247.         public static var shapeSound1:Sound = new Resource.cShape1();
  248.         public static var shapeSound2:Sound = new Resource.cShape2();
  249.         public static var shapeSound3:Sound = new Resource.cShape3();
  250.         public static var shapeSound4:Sound = new Resource.cShape4();
  251.         public static var shapeSound5:Sound = new Resource.cShape5();
  252.         public static var jointSound1:Sound = new Resource.cJoint1();
  253.         public static var jointSound2:Sound = new Resource.cJoint2();
  254.         public static var jointSound3:Sound = new Resource.cJoint3();
  255.         public static var jointSound4:Sound = new Resource.cJoint4();
  256.         public static var jointSound5:Sound = new Resource.cJoint5();
  257.         public static var winSound:Sound = new Resource.cWin();
  258.         public static var loseSound:Sound = new Resource.cLose();
  259.         public static var channel:SoundChannel = null;
  260.         public static var musicChannel:SoundChannel = null;
  261.         public static var introVolume:Number = 0.5;
  262.        
  263.         public static const NEW_CIRCLE:int = 0;
  264.         public static const NEW_RECT:int = 1;
  265.         public static const NEW_TRIANGLE:int = 2;
  266.         public static const NEW_FIXED_JOINT:int = 3;
  267.         public static const NEW_REVOLUTE_JOINT:int = 4;
  268.         public static const NEW_PRISMATIC_JOINT:int = 5;
  269.         public static const ROTATE:int = 6;
  270.         public static const PASTE:int = 7;
  271.         public static const BOX_SELECTING:int = 8;
  272.         public static const FINALIZING_JOINT:int = 9;
  273.         public static const NEW_TEXT:int = 10;
  274.         public static const RESIZING_TEXT:int = 11;
  275.         public static const RESIZING_SHAPES:int = 12;
  276.         public static const NEW_THRUSTERS:int = 13;
  277.         public static const DRAWING_BOX:int = 14;
  278.         public static const DRAWING_HORIZONTAL_LINE:int = 15;
  279.         public static const DRAWING_VERTICAL_LINE:int = 16;
  280.         public static const SELECTING_SHAPE:int = 17;
  281.         public static const DRAWING_BUILD_BOX:int = 18;
  282.         public static const NEW_CANNON:int = 19;
  283.        
  284.         public function ControllerGame() {
  285.             allParts = new Array();
  286.             cannonballs = new Array();
  287.             actions = new Array();
  288.            
  289.             Input.m_currController = this;
  290.             Action.m_controller = this;
  291.            
  292.             m_canvas = new Sprite();
  293.             m_guiPanel = new MainEditPanel(this);
  294.             m_guiMenu = new DropDownMenu(this);
  295.             m_sidePanel = new PartEditWindow(this);
  296.  
  297.             m_fader = new Sprite();
  298.             m_fader.graphics.beginFill(0, 0.2);
  299.             m_fader.graphics.lineStyle(0, 0, 0.2);
  300.             m_fader.graphics.moveTo(0, 0);
  301.             m_fader.graphics.lineTo(800, 0);
  302.             m_fader.graphics.lineTo(800, 600);
  303.             m_fader.graphics.lineTo(0, 600);
  304.             m_fader.graphics.lineTo(0, 0);
  305.             m_fader.graphics.endFill();
  306.             m_fader.visible = false;
  307.  
  308.             uneditableText = new TextField();
  309.             uneditableText.x = 0;
  310.             uneditableText.y = 102;
  311.             uneditableText.width = 800;
  312.             uneditableText.text = "The current robot is uneditable.  Some features, including saving and submitting scores, will be disabled.";
  313.             uneditableText.selectable = false;
  314.             uneditableText.visible = false;
  315.             var format:TextFormat = new TextFormat();
  316.             format.align = TextFormatAlign.CENTER;
  317.             format.font = Main.GLOBAL_FONT;
  318.             format.size = 12;
  319.             uneditableText.setTextFormat(format);
  320.  
  321.             rotatingText = new TextField();
  322.             rotatingText.x = 0;
  323.             rotatingText.y = 102;
  324.             rotatingText.width = 800;
  325.             rotatingText.text = "Move the mouse around to rotate the shape - hold shift to increment by 45 degrees, and click when you're done.";
  326.             rotatingText.selectable = false;
  327.             rotatingText.visible = false;
  328.             rotatingText.setTextFormat(format);
  329.  
  330.             scalingText = new TextField();
  331.             scalingText.x = 0;
  332.             scalingText.y = 102;
  333.             scalingText.width = 800;
  334.             scalingText.text = "Move the mouse to the right to increase the shape's size, and left to decrease it.";
  335.             scalingText.selectable = false;
  336.             scalingText.visible = false;
  337.             scalingText.setTextFormat(format);
  338.  
  339.             boxText = new TextField();
  340.             boxText.x = 0;
  341.             boxText.y = 102;
  342.             boxText.width = 800;
  343.             boxText.text = "Use the mouse to click and drag a box for the given condition.  You can use the arrow keys to scroll.";
  344.             boxText.selectable = false;
  345.             boxText.visible = false;
  346.             boxText.setTextFormat(format);
  347.  
  348.             horizLineText = new TextField();
  349.             horizLineText.x = 0;
  350.             horizLineText.y = 102;
  351.             horizLineText.width = 800;
  352.             horizLineText.text = "Use the mouse to draw a horizontal line for the given condition.  You can use the arrow keys to scroll.";
  353.             horizLineText.selectable = false;
  354.             horizLineText.visible = false;
  355.             horizLineText.setTextFormat(format);
  356.  
  357.             vertLineText = new TextField();
  358.             vertLineText.x = 0;
  359.             vertLineText.y = 102;
  360.             vertLineText.width = 800;
  361.             vertLineText.text = "Use the mouse to draw a vertical line for the given condition.  You can use the arrow keys to scroll.";
  362.             vertLineText.selectable = false;
  363.             vertLineText.visible = false;
  364.             vertLineText.setTextFormat(format);
  365.  
  366.             shapeText = new TextField();
  367.             shapeText.x = 0;
  368.             shapeText.y = 102;
  369.             shapeText.width = 800;
  370.             shapeText.text = "Select a shape for the given condition.  You can use the arrow keys to scroll.";
  371.             shapeText.selectable = false;
  372.             shapeText.visible = false;
  373.             shapeText.setTextFormat(format);
  374.  
  375.             // set debug draw
  376.             draw = new Draw();
  377.             draw.m_sprite = m_canvas;
  378.             draw.m_drawScale = m_physScale;
  379.             draw.m_drawYOff = -100;
  380.             if (showColours) draw.m_fillAlpha = 1.0;
  381.             else draw.m_fillAlpha = 0.5;
  382.             draw.m_drawFlags = b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit;
  383.  
  384.             if (playingReplay) {
  385.                 replay.cont = this;
  386.             } else {
  387.                 viewingUnsavedReplay = false;
  388.             }
  389.            
  390.             addEventListener(Event.ADDED_TO_STAGE, Init);
  391.         }
  392.        
  393.         public virtual function Init(e:Event):void {
  394.             addChild(m_canvas);
  395.             addChild(uneditableText);
  396.             addChild(rotatingText);
  397.             addChild(scalingText);
  398.             addChild(boxText);
  399.             addChild(horizLineText);
  400.             addChild(vertLineText);
  401.             addChild(shapeText);
  402.             addChild(m_guiPanel);
  403.             addChild(m_sidePanel);
  404.             addChild(m_guiMenu);
  405.             addChild(m_fader);
  406.             if (playingReplay) {
  407.                 allParts = allParts.concat(replayParts);
  408.                 for (var i:int = 0; i < allParts.length; i++) {
  409.                     if (allParts[i] is TextPart) {
  410.                         var newTextPart:TextPart = new TextPart(this, allParts[i].x, allParts[i].y, allParts[i].w, allParts[i].h, allParts[i].text);
  411.                         newTextPart.alwaysVisible = allParts[i].alwaysVisible;
  412.                         newTextPart.displayKey = allParts[i].displayKey;
  413.                         newTextPart.red = allParts[i].red;
  414.                         newTextPart.green = allParts[i].green;
  415.                         newTextPart.blue = allParts[i].blue;
  416.                         newTextPart.size = allParts[i].size;
  417.                         allParts[i] = newTextPart;
  418.                     }
  419.                 }
  420.             }
  421.            
  422.             if (loadedParts) {
  423.                 if (this is ControllerChallenge && ControllerChallenge.playChallengeMode && !justLoadedRobotWithChallenge) {
  424.                     for (i = 0; i < loadedParts.length; i++) {
  425.                         loadedParts[i].isEditable = false;
  426.                     }
  427.                 }
  428.                 if (justLoadedRobotWithChallenge) {
  429.                     allParts = allParts.concat(ControllerChallenge.challenge.allParts);
  430.                     for (i = 0; i < allParts.length; i++) {
  431.                         allParts[i].isEditable = false;
  432.                     }
  433.                 }
  434.                 justLoadedRobotWithChallenge = false;
  435.                 allParts = allParts.concat(loadedParts);
  436.                 for (i = 0; i < allParts.length; i++) {
  437.                     if (allParts[i] is TextPart) {
  438.                         newTextPart = new TextPart(this, allParts[i].x, allParts[i].y, allParts[i].w, allParts[i].h, allParts[i].text);
  439.                         newTextPart.alwaysVisible = allParts[i].alwaysVisible;
  440.                         newTextPart.displayKey = allParts[i].displayKey;
  441.                         newTextPart.red = allParts[i].red;
  442.                         newTextPart.green = allParts[i].green;
  443.                         newTextPart.blue = allParts[i].blue;
  444.                         newTextPart.size = allParts[i].size;
  445.                         if (!allParts[i].isEditable) newTextPart.isEditable = false;
  446.                         allParts[i] = newTextPart;
  447.                     }
  448.                 }
  449.                 loadedParts = null;
  450.                 if (initX != Number.MAX_VALUE) {
  451.                     draw.m_drawXOff = initX;
  452.                     draw.m_drawYOff = initY;
  453.                     m_physScale = initZoom;
  454.                 } else if (!(this is ControllerChallenge)) {
  455.                     CenterOnLoadedRobot();
  456.                 }
  457.             } else if (!playingReplay) {
  458.                 curRobotID = "";
  459.                 curRobotEditable = true;
  460.                 curRobotPublic = false;
  461.             }
  462.            
  463.             initX = Number.MAX_VALUE;
  464.             initY = Number.MAX_VALUE;
  465.             initZoom = Number.MAX_VALUE;
  466.            
  467.             if (this is ControllerChallenge) {
  468.                 minDensity = (ControllerChallenge.challenge.minDensity == -Number.MAX_VALUE ? 1 : ControllerChallenge.challenge.minDensity);
  469.                 maxDensity = (ControllerChallenge.challenge.maxDensity == Number.MAX_VALUE ? 30 : ControllerChallenge.challenge.maxDensity);
  470.                 maxRJStrength = (ControllerChallenge.challenge.maxRJStrength == Number.MAX_VALUE ? 30 : ControllerChallenge.challenge.maxRJStrength);
  471.                 maxRJSpeed = (ControllerChallenge.challenge.maxRJSpeed == Number.MAX_VALUE ? 30 : ControllerChallenge.challenge.maxRJSpeed);
  472.                 maxSJStrength = (ControllerChallenge.challenge.maxSJStrength == Number.MAX_VALUE ? 30 : ControllerChallenge.challenge.maxSJStrength);
  473.                 maxSJSpeed = (ControllerChallenge.challenge.maxSJSpeed == Number.MAX_VALUE ? 30 : ControllerChallenge.challenge.maxSJSpeed);
  474.                 maxThrusterStrength = (ControllerChallenge.challenge.maxThrusterStrength == Number.MAX_VALUE ? 30 : ControllerChallenge.challenge.maxThrusterStrength);
  475.             } else {
  476.                 minDensity = 1;
  477.                 maxDensity = 30;
  478.                 maxRJStrength = 30;
  479.                 maxRJSpeed = 30;
  480.                 maxSJStrength = 30;
  481.                 maxSJSpeed = 30;
  482.                 maxThrusterStrength = 30;
  483.             }
  484.            
  485.             PrismaticJoint.jbTutorial = false;
  486.            
  487.             if (Main.inIFrame) {
  488.                 curRobotEditable = false;
  489.                 uneditableText.text = "";
  490.             }
  491.         }
  492.        
  493.         public function BuildBuildArea():void {
  494.             for (var i:int = 0; i < m_buildAreas.length; i++) {
  495.                 removeChild(m_buildAreas[i]);
  496.                 removeChild(m_badBuildAreas[i]);
  497.                 removeChild(m_selectedBuildAreas[i]);
  498.             }
  499.             m_buildAreas = new Array();
  500.             m_badBuildAreas = new Array();
  501.             m_selectedBuildAreas = new Array();
  502.            
  503.             var childIndex:int = sSky.lastCloudIndex + 1;
  504.             for (i = 0; i < NumBuildingAreas(); i++) {
  505.                 var m_buildArea:Sprite = new Sprite();
  506.                 m_buildArea.graphics.lineStyle(6, 0xDEB05D);
  507.                 var m:Matrix = new Matrix();
  508.                 m.createGradientBox(700, 550, Math.PI / 2);
  509.                 m_buildArea.graphics.beginGradientFill(GradientType.LINEAR, [0xFF8F17, 0xFFC150], [0.15, 0.15], [0, 255], m);
  510.                 m_buildArea.graphics.drawRect(0, 0, 700, 550);
  511.                 m_buildArea.graphics.endFill();
  512.                 addChildAt(m_buildArea, childIndex);
  513.                 m_buildAreas.push(m_buildArea);
  514.                 var m_badBuildArea:Sprite = new Sprite();
  515.                 m_badBuildArea.graphics.lineStyle(6, 0xDE6A5D);
  516.                 m = new Matrix();
  517.                 m.createGradientBox(700, 550, Math.PI / 2);
  518.                 m_badBuildArea.graphics.beginGradientFill(GradientType.LINEAR, [0xFF4D17, 0xFF8F50], [0.15, 0.15], [0, 255], m);
  519.                 m_badBuildArea.graphics.drawRect(0, 0, 700, 550);
  520.                 m_badBuildArea.graphics.endFill();
  521.                 addChildAt(m_badBuildArea, childIndex);
  522.                 m_badBuildAreas.push(m_badBuildArea);
  523.                 var m_selectedBuildArea:Sprite = new Sprite();
  524.                 m_selectedBuildArea.graphics.lineStyle(6, 0xFECA5D);
  525.                 m = new Matrix();
  526.                 m.createGradientBox(700, 550, Math.PI / 2);
  527.                 m_selectedBuildArea.graphics.beginGradientFill(GradientType.LINEAR, [0xFF4D17, 0xFF8F50], [0.15, 0.15], [0, 255], m);
  528.                 m_selectedBuildArea.graphics.drawRect(0, 0, 700, 550);
  529.                 m_selectedBuildArea.graphics.endFill();
  530.                 addChildAt(m_selectedBuildArea, childIndex);
  531.                 m_selectedBuildAreas.push(m_selectedBuildArea);
  532.             }
  533.         }
  534.        
  535.         public function PlayShapeSound():void {
  536.             if (Main.enableSound) {
  537.                 var soundNum:int = int(Util.RangedRandom(0, 5));
  538.                 var sound:Sound = (soundNum == 0 ? shapeSound1 : (soundNum == 1 ? shapeSound2 : (soundNum == 2 ? shapeSound3 : (soundNum == 3 ? shapeSound4 : shapeSound5))));
  539.                 channel = sound.play();
  540.                 var st:SoundTransform = new SoundTransform(0.7);
  541.                 channel.soundTransform = st;
  542.             }
  543.         }
  544.        
  545.         public function PlayJointSound():void {
  546.             if (Main.enableSound) {
  547.                 var soundNum:int = int(Util.RangedRandom(0, 5));
  548.                 var sound:Sound = (soundNum == 0 ? jointSound1 : (soundNum == 1 ? jointSound2 : (soundNum == 2 ? jointSound3 : (soundNum == 3 ? jointSound4 : jointSound5))));
  549.                 channel = sound.play();
  550.                 var st:SoundTransform = new SoundTransform(0.7);
  551.                 channel.soundTransform = st;
  552.             }
  553.         }
  554.        
  555.         public override function GetPhysScale():Number {
  556.             return m_physScale;
  557.         }
  558.        
  559.         public virtual override function GetMinX():Number {
  560.             return -Number.MAX_VALUE;
  561.         }
  562.        
  563.         public virtual override function GetMaxX():Number {
  564.             return Number.MAX_VALUE;
  565.         }
  566.        
  567.         public virtual override function GetMinY():Number {
  568.             return -Number.MAX_VALUE;
  569.         }
  570.        
  571.         public virtual override function GetMaxY():Number {
  572.             return Number.MAX_VALUE;
  573.         }
  574.        
  575.         public virtual override function Update():void {
  576.             if (ControllerMainMenu.channel) {
  577.                 introVolume -= 0.005;
  578.                 var st:SoundTransform = new SoundTransform(introVolume);
  579.                 ControllerMainMenu.channel.soundTransform = st;
  580.                 if (introVolume <= 0) {
  581.                     ControllerMainMenu.channel.stop();
  582.                     ControllerMainMenu.channel = null;
  583.                 }
  584.             }
  585.            
  586.             if (!m_fader.visible) {
  587.                 if (showColours) draw.m_fillAlpha = 1.0;
  588.                 else draw.m_fillAlpha = 0.5;
  589.                
  590.                 if (playingReplay && !simStarted) playButton(new MouseEvent(""));
  591.                
  592.                 // update mouse position
  593.                 mouseXWorldPhys = ((Input.mouseX) + draw.m_drawXOff)/m_physScale;
  594.                 mouseYWorldPhys = ((Input.mouseY) + draw.m_drawYOff)/m_physScale;
  595.                 prevMouseXWorld = mouseXWorld;
  596.                 prevMouseYWorld = mouseYWorld;
  597.                 mouseXWorld = (Input.mouseX);
  598.                 mouseYWorld = (Input.mouseY);
  599.  
  600.                 Main.ShowMouse();
  601.  
  602.                 if (!paused && autoPanning) {
  603.                     HandleCamera();
  604.                 }
  605.  
  606.                 MouseDrag();
  607.                 HandleKey();
  608.  
  609.                 for (var i:int = 0; i < allParts.length; i++) {
  610.                     if (allParts[i] is RevoluteJoint || allParts[i] is PrismaticJoint) allParts[i].CheckForBreakage(m_world);
  611.                 }
  612.  
  613.                 m_guiMenu.Update();
  614.                 m_guiPanel.Update(curAction);
  615.  
  616.                 uneditableText.visible = (!curRobotEditable && !playingReplay && !simStarted);
  617.                 rotatingText.visible = (curAction == ROTATE);
  618.                 scalingText.visible = (curAction == RESIZING_SHAPES);
  619.  
  620.                 if (newText && lastSelectedText is TextPart) {
  621.                     lastSelectedText.text = newText.text;
  622.                     lastSelectedText.m_textField.text = newText.text;
  623.                     newText = null;
  624.                 }
  625.  
  626.                 // Update physics
  627.                 var physStart:uint = getTimer();
  628.                 if (!paused) {
  629.                     if (!playingReplay) {
  630.                         if (frameCounter % REPLAY_SYNC_FRAMES == 0) AddSyncPoint();
  631.                         m_world.Step(1/60, 5);
  632.                         m_world.Step(1/60, m_iterations);
  633.                     }
  634.                     frameCounter++;
  635.                     m_guiPanel.SetTimer(frameCounter);
  636.                    
  637.                     if (frameCounter >= 9000 || cannonballs.length > 500) canSaveReplay = false;
  638.                 }
  639.             }
  640.  
  641.             draw.m_drawScale = m_physScale;
  642.             draw.drawColours = showColours;
  643.             if (!simStarted) {
  644.                 for (i = 0; i < m_buildAreas.length; i++) {
  645.                     var box:b2AABB = GetBuildingAreaNumber(i);
  646.                     if (hasPanned || hasZoomed || redrawBuildArea) {
  647.                         m_buildAreas[i].x = World2ScreenX(box.lowerBound.x);
  648.                         m_buildAreas[i].y = World2ScreenY(box.lowerBound.y);
  649.                         m_badBuildAreas[i].x = World2ScreenX(box.lowerBound.x);
  650.                         m_badBuildAreas[i].y = World2ScreenY(box.lowerBound.y);
  651.                         m_selectedBuildAreas[i].x = World2ScreenX(box.lowerBound.x);
  652.                         m_selectedBuildAreas[i].y = World2ScreenY(box.lowerBound.y);
  653.                     }
  654.                     if (hasZoomed || redrawBuildArea) {
  655.                         m_buildAreas[i].width = World2ScreenX(box.upperBound.x) - World2ScreenX(box.lowerBound.x);
  656.                         m_buildAreas[i].height = World2ScreenY(box.upperBound.y) - World2ScreenY(box.lowerBound.y);
  657.                         m_badBuildAreas[i].width = World2ScreenX(box.upperBound.x) - World2ScreenX(box.lowerBound.x);
  658.                         m_badBuildAreas[i].height = World2ScreenY(box.upperBound.y) - World2ScreenY(box.lowerBound.y);
  659.                         m_selectedBuildAreas[i].width = World2ScreenX(box.upperBound.x) - World2ScreenX(box.lowerBound.x);
  660.                         m_selectedBuildAreas[i].height = World2ScreenY(box.upperBound.y) - World2ScreenY(box.lowerBound.y);
  661.                     }
  662.                     m_selectedBuildAreas[i].visible = (m_sidePanel.BuildWindowShowing() && selectedBuildArea == ControllerChallenge.challenge.buildAreas[i]);
  663.                     m_buildAreas[i].visible = (!m_selectedBuildAreas[i].visible && partsFit);
  664.                     m_badBuildAreas[i].visible = (!m_selectedBuildAreas[i].visible && !partsFit);
  665.                 }
  666.                 redrawBuildArea = false;
  667.             } else {
  668.                 for (i = 0; i < m_buildAreas.length; i++) {
  669.                     m_buildAreas[i].visible = false;
  670.                     m_badBuildAreas[i].visible = false;
  671.                     m_selectedBuildAreas[i].visible = false;
  672.                 }
  673.             }
  674.             if (hasPanned || hasZoomed || !paused || draggingPart || curAction != -1 || redrawRobot) {
  675.                 m_canvas.graphics.clear();
  676.                 draw.DrawWorld(allParts, selectedParts, m_world, !simStarted, false, showJoints, showOutlines, ((this is ControllerChallenge) ? ControllerChallenge.challenge : null));
  677.                 redrawRobot = false;
  678.             }
  679.             var snapPart:ShapePart = FindPartToSnapTo();
  680.             if (!simStarted) {
  681.                 if (snapToCenter && snapPart && (curAction == NEW_FIXED_JOINT || curAction == NEW_REVOLUTE_JOINT || curAction == NEW_PRISMATIC_JOINT || curAction == NEW_THRUSTERS)) {
  682.                     draw.DrawTempShape(curAction, actionStep, firstClickX, firstClickY, secondClickX, secondClickY, snapPart.centerX, snapPart.centerY);
  683.                 } else if (curAction == FINALIZING_JOINT && candidateJointType == NEW_PRISMATIC_JOINT && actionStep == 1) {
  684.                     draw.DrawTempShape(NEW_PRISMATIC_JOINT, actionStep, firstClickX, firstClickY, secondClickX, secondClickY, candidateJointX, candidateJointY);
  685.                 } else if (curAction == FINALIZING_JOINT && candidateJointType == NEW_THRUSTERS) {
  686.                     draw.DrawTempShape(NEW_THRUSTERS, actionStep, firstClickX, firstClickY, secondClickX, secondClickY, candidateJointX, candidateJointY);
  687.                 } else if (curAction == FINALIZING_JOINT) {
  688.                     draw.DrawTempShape(curAction, actionStep, firstClickX, firstClickY, secondClickX, secondClickY, candidateJointX, candidateJointY);
  689.                 } else {
  690.                     draw.DrawTempShape(curAction, actionStep, firstClickX, firstClickY, secondClickX, secondClickY, mouseXWorldPhys, mouseYWorldPhys);
  691.                 }
  692.             }
  693.            
  694.             //Main.m_fpsCounter.updatePhys(physStart);
  695.            
  696.             if (Database.errorOccurred) {
  697.                 m_progressDialog.StopTimer();
  698.                 m_progressDialog.SetMessage(Database.lastErrorMsg, true);
  699.                 Database.errorOccurred = false;
  700.                 if (Database.versionErrorOccurred) {
  701.                     Database.versionErrorOccurred = false;
  702.                     m_progressDialog.ShowOKAndCancelButton(5);
  703.                 } else {
  704.                     m_progressDialog.ShowOKButton();
  705.                 }
  706.                 removeChild(m_progressDialog);
  707.                 addChild(m_progressDialog);
  708.                 Main.ShowMouse();
  709.             }
  710.            
  711.             if (!paused && ChallengeOver()) {
  712.                 wonChallenge = true;
  713.                 pauseButton(new MouseEvent(""));
  714.                 if (!playingReplay || viewingUnsavedReplay) {
  715.                     m_fader.visible = true;
  716.                     if (this is ControllerTutorial || WonChallenge()) {
  717.                         if (m_scoreWindow) {
  718.                             try {
  719.                                 removeChild(m_scoreWindow);
  720.                             } catch (type:Error) {
  721.                                
  722.                             }
  723.                         }
  724.                         m_scoreWindow = new ScoreWindow(this, GetScore());
  725.                         if (Main.enableSound) {
  726.                             musicChannel = winSound.play();
  727.                             st = new SoundTransform(0.5);
  728.                             musicChannel.soundTransform = st;
  729.                         }
  730.                         addChild(m_scoreWindow);
  731.                         if (this is ControllerTutorial) {
  732.                             LSOManager.SetLevelDone(Main.nextControllerType - 10);
  733.                         } else if (this is ControllerMonkeyBars || this is ControllerClimb || this is ControllerRace || this is ControllerSpaceship) {
  734.                             LSOManager.SetLevelDone(Main.nextControllerType + 8);
  735.                         }
  736.                     } else {
  737.                         failedChallenge = true;
  738.                         ShowDialog3("Sorry, you have failed this challenge!");
  739.                         m_progressDialog.ShowOKButton();
  740.                         m_progressDialog.StopTimer();
  741.                         if (Main.enableSound) {
  742.                             musicChannel = loseSound.play();
  743.                             st = new SoundTransform(0.5);
  744.                             musicChannel.soundTransform = st;
  745.                         }
  746.                     }
  747.                 }
  748.             }          
  749.         }
  750.        
  751.         public override function MoveCameraForReplay(cameraMovement:Object):void {
  752.             if (cameraMovement.x != Number.POSITIVE_INFINITY) {
  753.                 var oldX:Number = draw.m_drawXOff;
  754.                 var oldY:Number = draw.m_drawYOff;
  755.                 draw.m_drawXOff = cameraMovement.x;
  756.                 draw.m_drawYOff = cameraMovement.y;
  757.                 autoPanning = false;
  758.                 if (oldX != draw.m_drawXOff || oldY != draw.m_drawYOff) hasPanned = true;
  759.             }
  760.             var oldScale:Number = m_physScale;
  761.             m_physScale = cameraMovement.scale;
  762.             if (m_physScale != oldScale) hasZoomed = true;
  763.             if (autoPanning) HandleCamera();
  764.         }
  765.        
  766.         public function AddSyncPoint():void  {
  767.             if (syncPoints.length == 0 || frameCounter != syncPoints[syncPoints.length - 1].frame) {
  768.                 var bodiesUsed:Array = new Array();
  769.                 var syncPoint:ReplaySyncPoint = new ReplaySyncPoint();
  770.                 syncPoint.frame = frameCounter;
  771.                 for (var i:int = 0; i < allParts.length; i++) {
  772.                     if (allParts[i] is ShapePart && !allParts[i].isStatic && !Util.ObjectInArray(allParts[i].GetBody(), bodiesUsed)) {
  773.                         syncPoint.positions.push(Util.Vector(allParts[i].GetBody().GetPosition().x, allParts[i].GetBody().GetPosition().y));
  774.                         syncPoint.angles.push(allParts[i].GetBody().GetAngle());
  775.                         bodiesUsed.push(allParts[i].GetBody());
  776.                     }
  777.                 }
  778.                 for (i = 0; i < cannonballs.length; i++) {
  779.                     syncPoint.cannonballPositions.push(Util.Vector(cannonballs[i].GetPosition().x, cannonballs[i].GetPosition().y));
  780.                 }
  781.                 syncPoints.push(syncPoint);
  782.             }
  783.         }
  784.        
  785.         private function ComputeReplaySplines(type:int):Array {
  786.             // Compute the h and b
  787.             var h:Array = new Array();
  788.             var b:Array = new Array();
  789.             for (var i:int = 0; i < replay.syncPoints.length - 1; i++) {
  790.                 h.push(replay.syncPoints[i + 1].frame - replay.syncPoints[i].frame);
  791.                 var inner:Array = new Array();
  792.                 for (var j:int = 0; j < replay.syncPoints[0].positions.length; j++) {
  793.                     if (type == 0) inner.push((replay.syncPoints[i + 1].positions[j].x - replay.syncPoints[i].positions[j].x) / h[i]);
  794.                     else if (type == 1) inner.push((replay.syncPoints[i + 1].positions[j].y - replay.syncPoints[i].positions[j].y) / h[i]);
  795.                     else {
  796.                         var deltaAngle:Number = replay.syncPoints[i + 1].angles[j] - replay.syncPoints[i].angles[j];
  797.                         if (Math.abs(deltaAngle) > 20) {
  798.                             var a1:Number = Util.NormalizeAngle(replay.syncPoints[i].angles[j]);
  799.                             var a2:Number = Util.NormalizeAngle(replay.syncPoints[i + 1].angles[j]);
  800.                             if (Math.abs(a1 - a2) < Math.PI) {
  801.                                 deltaAngle = a2 - a1;
  802.                             } else if (a1 > a2) {
  803.                                 deltaAngle = a2 + 2 * Math.PI - a1;
  804.                             } else {
  805.                                 deltaAngle = a2 - (a1 + 2 * Math.PI);
  806.                             }
  807.                         }
  808.                         inner.push(deltaAngle / h[i]);
  809.                     }
  810.                 }
  811.                 b.push(inner);
  812.             }
  813.  
  814.             // Gaussian Elimination
  815.             var u:Array = new Array();
  816.             var v:Array = new Array();
  817.             u.push(0);
  818.             u.push(2 * (h[0] + h[1]));
  819.             inner = new Array();
  820.             for (j = 0; j < replay.syncPoints[0].positions.length; j++) {
  821.                 inner.push(0);
  822.             }
  823.             v.push(inner);
  824.             inner = new Array();
  825.             for (j = 0; j < replay.syncPoints[0].positions.length; j++) {
  826.                 if (b.length < 2) inner.push(0);
  827.                 else inner.push(6 * (b[1][j] - b[0][j]));
  828.             }
  829.             v.push(inner);
  830.             for (i = 2; i < replay.syncPoints.length - 1; i++) {
  831.                 u.push(2 * (h[i - 1] + h[i]) - h[i - 1] * h[i - 1] / u[i - 1]);
  832.                 inner = new Array();
  833.                 for (j = 0; j < replay.syncPoints[0].positions.length; j++) {
  834.                     inner.push(6 * (b[i][j] - b[i - 1][j]) - h[i - 1] * v[i - 1][j] / u[i - 1]);
  835.                 }
  836.                 v.push(inner);
  837.             }
  838.  
  839.             // Back-substitution
  840.             var z:Array = new Array();
  841.             inner = new Array();
  842.             for (j = 0; j < replay.syncPoints[0].positions.length; j++) {
  843.                 inner.push(0);
  844.             }
  845.             z[replay.syncPoints.length - 1] = inner;
  846.             for (i = replay.syncPoints.length - 2; i > 0; i--) {
  847.                 inner = new Array();
  848.                 for (j = 0; j < replay.syncPoints[0].positions.length; j++) {
  849.                     inner.push((v[i][j] - h[i] * z[i + 1][j]) / u[i]);
  850.                 }
  851.                 z[i] = inner;
  852.             }
  853.             inner = new Array();
  854.             for (j = 0; j < replay.syncPoints[0].positions.length; j++) {
  855.                 inner.push(0);
  856.             }
  857.             z[0] = inner;
  858.            
  859.             var S:Array = new Array();
  860.             var As:Array = new Array();
  861.             var Bs:Array = new Array();
  862.             var Cs:Array = new Array();
  863.             var Ds:Array = new Array();
  864.             for (i = 0; i < replay.syncPoints.length - 1; i++) {
  865.                 var innerA:Array = new Array();
  866.                 var innerB:Array = new Array();
  867.                 var innerC:Array = new Array();
  868.                 var innerD:Array = new Array();
  869.                 for (j = 0; j < replay.syncPoints[0].positions.length; j++) {
  870.                     innerA.push(type == 0 ? replay.syncPoints[i].positions[j].x : (type == 1 ? replay.syncPoints[i].positions[j].y : replay.syncPoints[i].angles[j]));
  871.                     deltaAngle = replay.syncPoints[i + 1].angles[j] - replay.syncPoints[i].angles[j];
  872.                     if (Math.abs(deltaAngle) > 20) {
  873.                         a1 = Util.NormalizeAngle(replay.syncPoints[i].angles[j]);
  874.                         a2 = Util.NormalizeAngle(replay.syncPoints[i + 1].angles[j]);
  875.                         if (Math.abs(a1 - a2) < Math.PI) {
  876.                             deltaAngle = a2 - a1;
  877.                         } else if (a1 > a2) {
  878.                             deltaAngle = a2 + 2 * Math.PI - a1;
  879.                         } else {
  880.                             deltaAngle = a2 - (a1 + 2 * Math.PI);
  881.                         }
  882.                     }
  883.                     innerB.push(-h[i] * z[i + 1][j] / 6 - h[i] * z[i][j] / 3 + (type == 0 ? replay.syncPoints[i + 1].positions[j].x - innerA[j] : (type == 1 ? replay.syncPoints[i + 1].positions[j].y - innerA[j] : deltaAngle)) / h[i]);
  884.                     innerC.push(z[i][j] / 2);
  885.                     innerD.push((z[i + 1][j] - z[i][j]) / (6 * h[i]));
  886.                 }
  887.                 As.push(innerA);
  888.                 Bs.push(innerB);
  889.                 Cs.push(innerC);
  890.                 Ds.push(innerD);
  891.             }
  892.             S.push(As);
  893.             S.push(Bs);
  894.             S.push(Cs);
  895.             S.push(Ds);
  896.             return S;
  897.         }
  898.        
  899.         public override function SyncReplay(syncPoint:Object):void {
  900.             var bodiesUsed:Array = new Array();
  901.             var curIndex:int = 0;
  902.             for (var i:int = 0; i < allParts.length; i++) {
  903.                 if (allParts[i] is ShapePart && !allParts[i].isStatic && !Util.ObjectInArray(allParts[i].GetBody(), bodiesUsed)) {
  904.                     allParts[i].GetBody().SetXForm(syncPoint.positions[curIndex], syncPoint.angles[curIndex]);
  905.                     curIndex++;
  906.                     bodiesUsed.push(allParts[i].GetBody());
  907.                 }
  908.             }
  909.             for (i = 0; i < cannonballs.length; i++) {
  910.                 cannonballs[i].SetXForm(syncPoint.cannonballPositions[i], 0);
  911.             }
  912.         }
  913.  
  914.         public override function SyncReplay2(syncPoint1:Object, syncPoint2:Object):void {
  915.             var syncPointIndex:int = replay.syncPoints.indexOf(syncPoint1);
  916.             var bodiesUsed:Array = new Array();
  917.             var curIndex:int = 0;
  918.             for (var i:int = 0; i < allParts.length; i++) {
  919.                 if (allParts[i] is ShapePart && !allParts[i].isStatic && !Util.ObjectInArray(allParts[i].GetBody(), bodiesUsed)) {
  920.                     var x:Number = replaySplineXs[0][syncPointIndex][curIndex] + (frameCounter - syncPoint1.frame) * (replaySplineXs[1][syncPointIndex][curIndex] + (frameCounter - syncPoint1.frame) * (replaySplineXs[2][syncPointIndex][curIndex] + (frameCounter - syncPoint1.frame) * replaySplineXs[3][syncPointIndex][curIndex]));
  921.                     var y:Number = replaySplineYs[0][syncPointIndex][curIndex] + (frameCounter - syncPoint1.frame) * (replaySplineYs[1][syncPointIndex][curIndex] + (frameCounter - syncPoint1.frame) * (replaySplineYs[2][syncPointIndex][curIndex] + (frameCounter - syncPoint1.frame) * replaySplineYs[3][syncPointIndex][curIndex]));
  922.                     var angle:Number = replaySplineAngles[0][syncPointIndex][curIndex] + (frameCounter - syncPoint1.frame) * (replaySplineAngles[1][syncPointIndex][curIndex] + (frameCounter - syncPoint1.frame) * (replaySplineAngles[2][syncPointIndex][curIndex] + (frameCounter - syncPoint1.frame) * replaySplineAngles[3][syncPointIndex][curIndex]));
  923.                     allParts[i].GetBody().SetXForm(Util.Vector(x, y), angle);
  924.                     curIndex++;
  925.                     bodiesUsed.push(allParts[i].GetBody());
  926.                 }
  927.             }
  928.             for (i = 0; i < cannonballs.length; i++) {
  929.                 if (syncPoint1.cannonballPositions.length > i) {
  930.                     var frameDiff:int = syncPoint2.frame - syncPoint1.frame;
  931.                     var newX:Number = (syncPoint1.cannonballPositions[i].x * (syncPoint2.frame - frameCounter) + syncPoint2.cannonballPositions[i].x * (frameCounter - syncPoint1.frame)) / frameDiff;
  932.                     var newY:Number = (syncPoint1.cannonballPositions[i].y * (syncPoint2.frame - frameCounter) + syncPoint2.cannonballPositions[i].y * (frameCounter - syncPoint1.frame)) / frameDiff;
  933.                     cannonballs[i].SetXForm(Util.Vector(newX, newY), 0);
  934.                 } else {
  935.                     cannonballs[i].SetXForm(syncPoint2.cannonballPositions[i], 0);
  936.                 }
  937.             }
  938.         }
  939.  
  940.         public override function IsPaused():Boolean {
  941.             return paused;
  942.         }
  943.        
  944.         public override function World2ScreenX(x:Number):Number {
  945.             return x * m_physScale - draw.m_drawXOff;
  946.         }
  947.        
  948.         public override function World2ScreenY(y:Number):Number {
  949.             return y * m_physScale - draw.m_drawYOff;
  950.         }
  951.        
  952.         public function Screen2WorldX(x:Number):Number {
  953.             return (x + draw.m_drawXOff) / m_physScale;
  954.         }
  955.        
  956.         public function Screen2WorldY(y:Number):Number {
  957.             return (y + draw.m_drawYOff) / m_physScale;
  958.         }
  959.        
  960.         protected virtual function ChallengeOver():Boolean {
  961.             throw new IllegalOperationError("abstract function ControllerGame.ChallengeOver() called");
  962.         }
  963.        
  964.         protected virtual function WonChallenge():Boolean {
  965.             return false;
  966.         }
  967.        
  968.         protected virtual function LostChallenge():Boolean {
  969.             return false;
  970.         }
  971.        
  972.         public virtual function GetScore():int {
  973.             throw new IllegalOperationError("abstract function ControllerGame.GetScore() called");
  974.         }
  975.        
  976.         public virtual function ContactAdded(point:b2ContactPoint):void {
  977.            
  978.         }
  979.        
  980.         protected virtual function GetBuildingArea():b2AABB {
  981.             throw new IllegalOperationError("abstract function ControllerGame.GetBuildingArea() called");
  982.         }
  983.        
  984.         protected virtual function GetBuildingAreaNumber(i:int):b2AABB {
  985.             return GetBuildingArea();
  986.         }
  987.        
  988.         protected virtual function NumBuildingAreas():int {
  989.             return 1;
  990.         }
  991.        
  992.         public function GetBoxForConditions():void {
  993.             boxText.visible = true;
  994.             curAction = DRAWING_BOX;
  995.             actionStep = 0;
  996.             selectingCondition = true;
  997.         }
  998.        
  999.         public function GetHorizontalLineForConditions():void {
  1000.             horizLineText.visible = true;
  1001.             curAction = DRAWING_HORIZONTAL_LINE;
  1002.             actionStep = 0;
  1003.             selectingCondition = true;
  1004.         }
  1005.        
  1006.         public function GetVerticalLineForConditions():void {
  1007.             vertLineText.visible = true;
  1008.             curAction = DRAWING_VERTICAL_LINE;
  1009.             actionStep = 0;
  1010.             selectingCondition = true;
  1011.         }
  1012.        
  1013.         public function GetShapeForConditions():void {
  1014.             if (!m_conditionsDialog.shape1) selectedParts = new Array();
  1015.             shapeText.visible = true;
  1016.             curAction = SELECTING_SHAPE;
  1017.             selectingCondition = true;
  1018.         }
  1019.        
  1020.         protected function CheckIfPartsFit():void {
  1021.             var partsToCheck:Array = allParts.filter(PartIsEditable);
  1022.             var numAreas:int = NumBuildingAreas();
  1023.            
  1024.             partsFit = true;
  1025.            
  1026.             if (this is ControllerSandbox && !(this is ControllerChallenge)) return;
  1027.             if (this is ControllerChallenge && !ControllerChallenge.playChallengeMode) return;
  1028.             if (numAreas == 0) return;
  1029.            
  1030.             // Make sure the parts fit in the allowed building area
  1031.             var minX:Number;
  1032.             var maxX:Number;
  1033.             var minY:Number;
  1034.             var maxY:Number;
  1035.             for (var i:int = 0; i < partsToCheck.length; i++) {
  1036.                 var partFits:Boolean = false;
  1037.                 for (var j:int = 0; j < numAreas; j++) {
  1038.                     var buildingArea:b2AABB = GetBuildingAreaNumber(j);
  1039.                     if (partsToCheck[i] is Circle) {
  1040.                         minX = partsToCheck[i].centerX - partsToCheck[i].radius;
  1041.                         maxX = partsToCheck[i].centerX + partsToCheck[i].radius;
  1042.                         minY = partsToCheck[i].centerY - partsToCheck[i].radius;
  1043.                         maxY = partsToCheck[i].centerY + partsToCheck[i].radius;
  1044.                     } else if (partsToCheck[i] is Rectangle || partsToCheck[i] is Triangle || partsToCheck[i] is Cannon) {
  1045.                         var verts:Array = partsToCheck[i].GetVertices();
  1046.                         minX = Number.MAX_VALUE;
  1047.                         minY = Number.MAX_VALUE;
  1048.                         maxX = -Number.MAX_VALUE;
  1049.                         maxY = -Number.MAX_VALUE;
  1050.                         for (var k:int = 0; k < verts.length; k++) {
  1051.                             minX = Math.min(minX, verts[k].x);
  1052.                             maxX = Math.max(maxX, verts[k].x);
  1053.                             minY = Math.min(minY, verts[k].y);
  1054.                             maxY = Math.max(maxY, verts[k].y);
  1055.                         }
  1056.                     } else {
  1057.                         minX = Number.MAX_VALUE;
  1058.                         minY = Number.MAX_VALUE;
  1059.                         maxX = -Number.MAX_VALUE;
  1060.                         maxY = -Number.MAX_VALUE;
  1061.                     }
  1062.                     if (minX >= buildingArea.lowerBound.x && minY >= buildingArea.lowerBound.y && maxX < buildingArea.upperBound.x && maxY < buildingArea.upperBound.y) {
  1063.                         partFits = true;
  1064.                         break;
  1065.                     }
  1066.                 }
  1067.                 if (!partFits) {
  1068.                     partsFit = false;
  1069.                     break;
  1070.                 }
  1071.             }
  1072.         }
  1073.        
  1074.         protected virtual function HandleKey():void {
  1075.             // keyboard input for motors/pistons
  1076.             if (!paused) {
  1077.                 if (playingReplay) {
  1078.                     if (replay.Update(frameCounter)) {
  1079.                         pauseButton(new MouseEvent(""));
  1080.                     }
  1081.                 }
  1082.                 for (var i:int = 0; i < allParts.length; i++) {
  1083.                     allParts[i].Update(m_world);
  1084.                 }
  1085.             } else if (!simStarted && !m_sidePanel.EnteringInput()) {
  1086.                 if (Input.isKeyDown(37)) {
  1087.                     draw.m_drawXOff -= 10;
  1088.                     hasPanned = true;
  1089.                 }
  1090.                 if (Input.isKeyDown(39)) {
  1091.                     draw.m_drawXOff += 10;
  1092.                     hasPanned = true;
  1093.                 }
  1094.                 if (Input.isKeyDown(38)) {
  1095.                     draw.m_drawYOff -= 10;
  1096.                     hasPanned = true;
  1097.                 }
  1098.                 if (Input.isKeyDown(40)) {
  1099.                     draw.m_drawYOff += 10;
  1100.                     hasPanned = true;
  1101.                 }
  1102.             }
  1103.         }
  1104.        
  1105.         protected function CenterOnLoadedRobot():void {
  1106.             var cameraPart:ShapePart = null;
  1107.             for (var i:int = 0; i < allParts.length; i++) {
  1108.                 if (allParts[i] is ShapePart && allParts[i].isCameraFocus) cameraPart = allParts[i];
  1109.             }
  1110.             if (!cameraPart) {
  1111.                 for (i = 0; i < allParts.length; i++) {
  1112.                     allParts[i].checkedCollisionGroup = false;
  1113.                 }
  1114.                 for (i = 0; i < allParts.length; i++) {
  1115.                     if (allParts[i] is ShapePart) allParts[i].SetCollisionGroup(-(i + 1));
  1116.                 }
  1117.                 cameraPart = FindCenterOfRobot();
  1118.             }
  1119.             if (cameraPart) {
  1120.                 var oldX:Number = draw.m_drawXOff;
  1121.                 var oldY:Number = draw.m_drawYOff;
  1122.                 draw.m_drawXOff = cameraPart.centerX * m_physScale - ZOOM_FOCUS_X;
  1123.                 draw.m_drawYOff = cameraPart.centerY * m_physScale - ZOOM_FOCUS_Y;
  1124.                 if (oldX != draw.m_drawXOff || oldY != draw.m_drawYOff) hasPanned = true;
  1125.             }
  1126.         }
  1127.        
  1128.         protected virtual function HandleCamera():void {
  1129.             if (cameraPart) {
  1130.                 var oldX:Number = draw.m_drawXOff;
  1131.                 var oldY:Number = draw.m_drawYOff;
  1132.                 draw.m_drawXOff = cameraPart.GetBody().GetWorldCenter().x * m_physScale - ZOOM_FOCUS_X;
  1133.                 draw.m_drawYOff = cameraPart.GetBody().GetWorldCenter().y * m_physScale - ZOOM_FOCUS_Y;
  1134.                 if (isNaN(draw.m_drawXOff) || isNaN(draw.m_drawYOff)) {
  1135.                     draw.m_drawXOff = oldX;
  1136.                     draw.m_drawYOff = oldY;
  1137.                 }
  1138.                 if (oldX != draw.m_drawXOff || oldY != draw.m_drawYOff) hasPanned = true;
  1139.             }
  1140.         }
  1141.        
  1142.         public function MouseDrag():void {
  1143.             if (!simStarted) {
  1144.                 // mouse press
  1145.                 if (Input.mouseDown && mouseYWorld >= 100 && !m_sidePanel.sliderDown && !m_guiMenu.MouseOverMenu(mouseXWorld, mouseYWorld) && (mouseXWorld >= 120 || !m_sidePanel.visible) && (mouseXWorld >= 230 || mouseYWorld >= 340 || !m_sidePanel.ColourWindowShowing()) && curAction != BOX_SELECTING && curAction != DRAWING_BUILD_BOX && curAction != DRAWING_BOX && curAction != DRAWING_HORIZONTAL_LINE && curAction != DRAWING_VERTICAL_LINE) {
  1146.                     if (!m_tutorialDialog || !m_tutorialDialog.MouseOver(mouseXWorld, mouseYWorld)) {
  1147.                         var shapeOrJoint:Part = GetPartAtMouse();
  1148.                        
  1149.                         if (!wasMouseDown && curRobotEditable && shapeOrJoint is ShapePart) {
  1150.                             var part:ShapePart = (shapeOrJoint as ShapePart);
  1151.                             // rotation
  1152.                             if (draggingPart == null && (curAction == -1 || curAction == SELECTING_SHAPE)) {
  1153.                                 if (MouseOverSelectedPart()) {
  1154.                                     delayedSelection = true;
  1155.                                 } else {
  1156.                                     if (!Util.ObjectInArray(part, selectedParts)) {
  1157.                                         if (!Input.isKeyDown(16)) {
  1158.                                             selectedParts = new Array();
  1159.                                         }
  1160.                                         selectedParts.push(part);
  1161.                                     } else if (Input.isKeyDown(16)) {
  1162.                                         selectedParts = Util.RemoveFromArray(part, selectedParts);
  1163.                                     }
  1164.                                     redrawRobot = true;
  1165.                                 }
  1166.                                 draggingPart = selectedParts[0];
  1167.                                 initDragX = mouseXWorldPhys;
  1168.                                 initDragY = mouseYWorldPhys;
  1169.                                 draggingParts = new Array();
  1170.                                 for (var i:int = 0; i < selectedParts.length; i++) {
  1171.                                     draggingParts = Util.RemoveDuplicates(draggingParts.concat(selectedParts[i].GetAttachedParts()));
  1172.                                 }
  1173.                                 for (i = 0; i < draggingParts.length; i++) {
  1174.                                     if (draggingParts[i] is ShapePart || draggingParts[i] is Thrusters) {
  1175.                                         draggingParts[i].dragXOff = mouseXWorldPhys - draggingParts[i].centerX;
  1176.                                         draggingParts[i].dragYOff = mouseYWorldPhys - draggingParts[i].centerY;
  1177.                                     } else if (draggingParts[i] is JointPart) {
  1178.                                         draggingParts[i].dragXOff = mouseXWorldPhys - draggingParts[i].anchorX;
  1179.                                         draggingParts[i].dragYOff = mouseYWorldPhys - draggingParts[i].anchorY;
  1180.                                     } else {
  1181.                                         draggingParts[i].dragXOff = mouseXWorldPhys - draggingParts[i].x;
  1182.                                         draggingParts[i].dragYOff = mouseYWorldPhys - draggingParts[i].y;
  1183.                                     }
  1184.                                 }
  1185.                             }
  1186.                         } else if (!wasMouseDown && curRobotEditable && shapeOrJoint is JointPart && draggingPart == null && (curAction == -1 || curAction == SELECTING_SHAPE)) {
  1187.                             if (MouseOverSelectedPart()) {
  1188.                                 delayedSelection = true;
  1189.                             } else {
  1190.                                 if (!Util.ObjectInArray(shapeOrJoint, selectedParts)) {
  1191.                                     if (!Input.isKeyDown(16)) {
  1192.                                         selectedParts = new Array();
  1193.                                     }
  1194.                                     selectedParts.push(shapeOrJoint);
  1195.                                 } else if (Input.isKeyDown(16)) {
  1196.                                     selectedParts = Util.RemoveFromArray(shapeOrJoint, selectedParts);
  1197.                                 }
  1198.                                 redrawRobot = true;
  1199.                             }
  1200.                             draggingPart = shapeOrJoint;
  1201.                             initDragX = mouseXWorldPhys;
  1202.                             initDragY = mouseYWorldPhys;
  1203.                             draggingParts = new Array();
  1204.                             for (i = 0; i < selectedParts.length; i++) {
  1205.                                 draggingParts = Util.RemoveDuplicates(draggingParts.concat(selectedParts[i].GetAttachedParts()));
  1206.                             }
  1207.                             for (i = 0; i < draggingParts.length; i++) {
  1208.                                 if (draggingParts[i] is ShapePart || draggingParts[i] is Thrusters) {
  1209.                                     draggingParts[i].dragXOff = mouseXWorldPhys - draggingParts[i].centerX;
  1210.                                     draggingParts[i].dragYOff = mouseYWorldPhys - draggingParts[i].centerY;
  1211.                                 } else if (draggingParts[i] is JointPart) {
  1212.                                     draggingParts[i].dragXOff = mouseXWorldPhys - draggingParts[i].anchorX;
  1213.                                     draggingParts[i].dragYOff = mouseYWorldPhys - draggingParts[i].anchorY;
  1214.                                 } else {
  1215.                                     draggingParts[i].dragXOff = mouseXWorldPhys - draggingParts[i].x;
  1216.                                     draggingParts[i].dragYOff = mouseYWorldPhys - draggingParts[i].y;
  1217.                                 }
  1218.                             }
  1219.                         } else if (!wasMouseDown && curRobotEditable && shapeOrJoint is TextPart && draggingPart == null && (curAction == -1 || curAction == SELECTING_SHAPE)) {
  1220.                             if (MouseOverSelectedPart()) {
  1221.                                 delayedSelection = true;
  1222.                             } else {
  1223.                                 if (!Util.ObjectInArray(shapeOrJoint, selectedParts)) {
  1224.                                     if (!Input.isKeyDown(16)) {
  1225.                                         selectedParts = new Array();
  1226.                                     }
  1227.                                     selectedParts.push(shapeOrJoint);
  1228.                                 } else if (Input.isKeyDown(16)) {
  1229.                                     selectedParts = Util.RemoveFromArray(shapeOrJoint, selectedParts);
  1230.                                 }
  1231.                                 redrawRobot = true;
  1232.                             }
  1233.                             draggingPart = shapeOrJoint;
  1234.                             initDragX = mouseXWorldPhys;
  1235.                             initDragY = mouseYWorldPhys;
  1236.                             if ((shapeOrJoint as TextPart).InsideMoveBox(mouseXWorldPhys, mouseYWorldPhys, m_physScale, true)) {
  1237.                                 curAction = RESIZING_TEXT;
  1238.                             } else {
  1239.                                 draggingParts = new Array();
  1240.                                 for (i = 0; i < selectedParts.length; i++) {
  1241.                                     draggingParts = Util.RemoveDuplicates(draggingParts.concat(selectedParts[i].GetAttachedParts()));
  1242.                                 }
  1243.                                 for (i = 0; i < draggingParts.length; i++) {
  1244.                                     if (draggingParts[i] is ShapePart || draggingParts[i] is Thrusters) {
  1245.                                         draggingParts[i].dragXOff = mouseXWorldPhys - draggingParts[i].centerX;
  1246.                                         draggingParts[i].dragYOff = mouseYWorldPhys - draggingParts[i].centerY;
  1247.                                     } else if (draggingParts[i] is JointPart) {
  1248.                                         draggingParts[i].dragXOff = mouseXWorldPhys - draggingParts[i].anchorX;
  1249.                                         draggingParts[i].dragYOff = mouseYWorldPhys - draggingParts[i].anchorY;
  1250.                                     } else {
  1251.                                         draggingParts[i].dragXOff = mouseXWorldPhys - draggingParts[i].x;
  1252.                                         draggingParts[i].dragYOff = mouseYWorldPhys - draggingParts[i].y;
  1253.                                     }
  1254.                                 }
  1255.                             }
  1256.                         } else if (!wasMouseDown && curRobotEditable && shapeOrJoint is Thrusters && draggingPart == null && (curAction == -1 || curAction == SELECTING_SHAPE)) {
  1257.                             if (MouseOverSelectedPart()) {
  1258.                                 delayedSelection = true;
  1259.                             } else {
  1260.                                 if (!Util.ObjectInArray(shapeOrJoint, selectedParts)) {
  1261.                                     if (!Input.isKeyDown(16)) {
  1262.                                         selectedParts = new Array();
  1263.                                     }
  1264.                                     selectedParts.push(shapeOrJoint);
  1265.                                 } else if (Input.isKeyDown(16)) {
  1266.                                     selectedParts = Util.RemoveFromArray(shapeOrJoint, selectedParts);
  1267.                                 }
  1268.                                 redrawRobot = true;
  1269.                             }
  1270.                             draggingPart = shapeOrJoint;
  1271.                             initDragX = mouseXWorldPhys;
  1272.                             initDragY = mouseYWorldPhys;
  1273.                             draggingParts = new Array();
  1274.                             for (i = 0; i < selectedParts.length; i++) {
  1275.                                 draggingParts = Util.RemoveDuplicates(draggingParts.concat(selectedParts[i].GetAttachedParts()));
  1276.                             }
  1277.                             for (i = 0; i < draggingParts.length; i++) {
  1278.                                 if (draggingParts[i] is ShapePart || draggingParts[i] is Thrusters) {
  1279.                                     draggingParts[i].dragXOff = mouseXWorldPhys - draggingParts[i].centerX;
  1280.                                     draggingParts[i].dragYOff = mouseYWorldPhys - draggingParts[i].centerY;
  1281.                                 } else if (draggingParts[i] is JointPart) {
  1282.                                     draggingParts[i].dragXOff = mouseXWorldPhys - draggingParts[i].anchorX;
  1283.                                     draggingParts[i].dragYOff = mouseYWorldPhys - draggingParts[i].anchorY;
  1284.                                 } else {
  1285.                                     draggingParts[i].dragXOff = mouseXWorldPhys - draggingParts[i].x;
  1286.                                     draggingParts[i].dragYOff = mouseYWorldPhys - draggingParts[i].y;
  1287.                                 }
  1288.                             }
  1289.                         } else if (draggingPart == null && rotatingPart == null && (curAction == -1 || curAction == SELECTING_SHAPE)) {
  1290.                             if (Input.isKeyDown(16) && curRobotEditable) {
  1291.                                 curAction = BOX_SELECTING;
  1292.                                 firstClickX = mouseXWorldPhys;
  1293.                                 firstClickY = mouseYWorldPhys;
  1294.                             } else {
  1295.                                 // dragging the world around
  1296.                                 var oldX:Number = draw.m_drawXOff;
  1297.                                 var oldY:Number = draw.m_drawYOff;
  1298.                                 draw.m_drawXOff -= (mouseXWorld - prevMouseXWorld);
  1299.                                 draw.m_drawYOff -= (mouseYWorld - prevMouseYWorld);
  1300.                                 if (oldX != draw.m_drawXOff || oldY != draw.m_drawYOff) hasPanned = true;
  1301.                             }
  1302.                            
  1303.                             selectedParts = new Array();
  1304.                             redrawRobot = true;
  1305.                         }
  1306.                     }
  1307.                 }
  1308.  
  1309.                 if (Input.mouseDown && !m_sidePanel.sliderDown && !m_guiMenu.MouseOverMenu(mouseXWorld, mouseYWorld) && mouseYWorld >= 100 && (mouseXWorld >= 120 || !m_sidePanel.visible) && (mouseXWorld >= 230 || mouseYWorld >= 340 || !m_sidePanel.ColourWindowShowing()) && curAction != BOX_SELECTING) {
  1310.                     if (!m_tutorialDialog || !m_tutorialDialog.MouseOver(mouseXWorld, mouseYWorld)) {
  1311.                         RefreshSidePanel();
  1312.                     }
  1313.                 }
  1314.  
  1315.                 if (!Input.mouseDown) draggingTutorial = false;
  1316.                 if (draggingTutorial) {
  1317.                     m_tutorialDialog.x = mouseXWorld - initDragX;
  1318.                     m_tutorialDialog.y = mouseYWorld - initDragY;
  1319.                 }
  1320.  
  1321.                 // drag a part
  1322.                 if (draggingPart != null && curAction != RESIZING_TEXT) {
  1323.                     for (i = 0; i < draggingParts.length; i++) {
  1324.                         draggingParts[i].Move(mouseXWorldPhys - draggingParts[i].dragXOff, mouseYWorldPhys - draggingParts[i].dragYOff);
  1325.                     }
  1326.                     curRobotID = "";
  1327.                 }
  1328.            
  1329.                 // rotate a part
  1330.                 if (curAction == ROTATE && rotatingPart != null) {
  1331.                     if (Input.isKeyDown(16) == false) {
  1332.                         newAngle = Math.atan2(mouseYWorldPhys - rotatingPart.centerY, mouseXWorldPhys - rotatingPart.centerX);
  1333.                         // Radians to Degrees
  1334.                         degree = (newAngle * 180 / Math.PI);
  1335.                         newdegree = Math.round(degree / 15) * 15;
  1336.                         // Degrees to Radians
  1337.                         initrotang = initRotatingAngle;
  1338.                         newAngle = initrotang + (newdegree * Math.PI / 180);
  1339.                             for (i = 0; i < rotatingParts.length; i++) {
  1340.                             rotatingParts[i].RotateAround(rotatingPart.centerX, rotatingPart.centerY, newAngle - initRotatingAngle);
  1341.                             }
  1342.                     } else {
  1343.                         newAngle = Math.atan2(mouseYWorldPhys - rotatingPart.centerY, mouseXWorldPhys - rotatingPart.centerX);
  1344.                         // Radians to Degrees
  1345.                         degree = (newAngle * 180 / Math.PI);
  1346.                         newdegree = Math.round(degree / 45) * 45;
  1347.                         // Degrees to Radians
  1348.                         initrotang = initRotatingAngle;
  1349.                         newAngle = initrotang + (newdegree * Math.PI / 180);
  1350.                             for (i = 0; i < rotatingParts.length; i++) {
  1351.                                 rotatingParts[i].RotateAround(rotatingPart.centerX, rotatingPart.centerY, newAngle - initRotatingAngle);
  1352.                             }
  1353.  
  1354.                     }
  1355.                 }
  1356.                
  1357.                 if (curAction == SELECTING_SHAPE && selectedParts.length == 1 && selectedParts[0] is ShapePart && selectedParts[0] != m_conditionsDialog.shape1) {
  1358.                     m_conditionsDialog.visible = true;
  1359.                     m_fader.visible = true;
  1360.                     curAction = -1;
  1361.                     m_sidePanel.visible = false;
  1362.                     shapeText.visible = false;
  1363.                     selectingCondition = false;
  1364.                     m_conditionsDialog.FinishSelectingForCondition(selectedParts[0]);
  1365.                 }
  1366.                
  1367.                 // scale parts?
  1368.                 if (curAction == RESIZING_SHAPES) {
  1369.                     // determine scale factor
  1370.                     var scaleFactor:Number = (mouseXWorld - firstClickX);
  1371.                     if (scaleFactor >= 0) {
  1372.                         scaleFactor /= 75;
  1373.                         scaleFactor += 1;
  1374.                     } else {
  1375.                         scaleFactor /= 25;
  1376.                         scaleFactor -= 1;
  1377.                         scaleFactor = -1 / scaleFactor;
  1378.                     }
  1379.                     for (i = 0; i < draggingParts.length; i++) {
  1380.                         if (draggingParts[i] is Circle) {
  1381.                             if (draggingParts[i].initRadius * scaleFactor > Circle.MAX_RADIUS) scaleFactor = Circle.MAX_RADIUS / draggingParts[i].initRadius;
  1382.                             if (draggingParts[i].initRadius * scaleFactor < Circle.MIN_RADIUS) scaleFactor = Circle.MIN_RADIUS / draggingParts[i].initRadius;
  1383.                         } else if (draggingParts[i] is Rectangle) {
  1384.                             if (draggingParts[i].initW * scaleFactor > Rectangle.MAX_WIDTH) scaleFactor = Rectangle.MAX_WIDTH / draggingParts[i].initW;
  1385.                             if (draggingParts[i].initW * scaleFactor < Rectangle.MIN_WIDTH) scaleFactor = Rectangle.MIN_WIDTH / draggingParts[i].initW;
  1386.                             if (draggingParts[i].initH * scaleFactor > Rectangle.MAX_WIDTH) scaleFactor = Rectangle.MAX_WIDTH / draggingParts[i].initH;
  1387.                             if (draggingParts[i].initH * scaleFactor < Rectangle.MIN_WIDTH) scaleFactor = Rectangle.MIN_WIDTH / draggingParts[i].initH;
  1388.                         } else if (draggingParts[i] is Triangle) {
  1389.                             var length1:Number = Util.GetDist(draggingParts[i].initX1, draggingParts[i].initY1, draggingParts[i].initX2, draggingParts[i].initY2);
  1390.                             if (length1 * scaleFactor > Triangle.MAX_SIDE_LENGTH) scaleFactor = Triangle.MAX_SIDE_LENGTH / length1;
  1391.                             if (length1 * scaleFactor < Triangle.MIN_SIDE_LENGTH) scaleFactor = Triangle.MIN_SIDE_LENGTH / length1;
  1392.                             var length2:Number = Util.GetDist(draggingParts[i].initX1, draggingParts[i].initY1, draggingParts[i].initX3, draggingParts[i].initY3);
  1393.                             if (length2 * scaleFactor > Triangle.MAX_SIDE_LENGTH) scaleFactor = Triangle.MAX_SIDE_LENGTH / length2;
  1394.                             if (length2 * scaleFactor < Triangle.MIN_SIDE_LENGTH) scaleFactor = Triangle.MIN_SIDE_LENGTH / length2;
  1395.                             var length3:Number = Util.GetDist(draggingParts[i].initX2, draggingParts[i].initY2, draggingParts[i].initX3, draggingParts[i].initY3);
  1396.                             if (length3 * scaleFactor > Triangle.MAX_SIDE_LENGTH) scaleFactor = Triangle.MAX_SIDE_LENGTH / length3;
  1397.                             if (length3 * scaleFactor < Triangle.MIN_SIDE_LENGTH) scaleFactor = Triangle.MIN_SIDE_LENGTH / length3;
  1398.                         } else if (draggingParts[i] is Cannon) {
  1399.                             if (draggingParts[i].initW * scaleFactor > Cannon.MAX_WIDTH) scaleFactor = Cannon.MAX_WIDTH / draggingParts[i].initW;
  1400.                             if (draggingParts[i].initW * scaleFactor < Cannon.MIN_WIDTH) scaleFactor = Cannon.MIN_WIDTH / draggingParts[i].initW;
  1401.                         }
  1402.                     }
  1403.                    
  1404.                     // scale the parts
  1405.                     for (i = 0; i < draggingParts.length; i++) {
  1406.                         if (draggingParts[i] is Circle) {
  1407.                             draggingParts[i].radius = draggingParts[i].initRadius * scaleFactor;
  1408.                             draggingParts[i].Move(initDragX + draggingParts[i].dragXOff * scaleFactor, initDragY + draggingParts[i].dragYOff * scaleFactor);
  1409.                         } else if (draggingParts[i] is Rectangle) {
  1410.                             draggingParts[i].w = draggingParts[i].initW * scaleFactor;
  1411.                             draggingParts[i].h = draggingParts[i].initH * scaleFactor;
  1412.                             draggingParts[i].Move(initDragX + draggingParts[i].dragXOff * scaleFactor, initDragY + draggingParts[i].dragYOff * scaleFactor);
  1413.                         } else if (draggingParts[i] is Triangle) {
  1414.                             draggingParts[i].centerX = initDragX + draggingParts[i].dragXOff * scaleFactor;
  1415.                             draggingParts[i].centerY = initDragY + draggingParts[i].dragYOff * scaleFactor;
  1416.                             draggingParts[i].x1 = draggingParts[i].centerX + draggingParts[i].initX1 * scaleFactor;
  1417.                             draggingParts[i].y1 = draggingParts[i].centerY + draggingParts[i].initY1 * scaleFactor;
  1418.                             draggingParts[i].x2 = draggingParts[i].centerX + draggingParts[i].initX2 * scaleFactor;
  1419.                             draggingParts[i].y2 = draggingParts[i].centerY + draggingParts[i].initY2 * scaleFactor;
  1420.                             draggingParts[i].x3 = draggingParts[i].centerX + draggingParts[i].initX3 * scaleFactor;
  1421.                             draggingParts[i].y3 = draggingParts[i].centerY + draggingParts[i].initY3 * scaleFactor;
  1422.                         } else if (draggingParts[i] is Cannon) {
  1423.                             draggingParts[i].w = draggingParts[i].initW * scaleFactor;
  1424.                             draggingParts[i].Move(initDragX + draggingParts[i].dragXOff * scaleFactor, initDragY + draggingParts[i].dragYOff * scaleFactor);
  1425.                         } else if (draggingParts[i] is JointPart) {
  1426.                             draggingParts[i].Move(initDragX + draggingParts[i].dragXOff * scaleFactor, initDragY + draggingParts[i].dragYOff * scaleFactor);
  1427.                             if (draggingParts[i] is PrismaticJoint) {
  1428.                                 draggingParts[i].initLength = draggingParts[i].initInitLength * scaleFactor;
  1429.                             }
  1430.                         } else if (draggingParts[i] is TextPart) {
  1431.                             draggingParts[i].w = draggingParts[i].initW * scaleFactor;
  1432.                             draggingParts[i].h = draggingParts[i].initH * scaleFactor;
  1433.                             draggingParts[i].x = initDragX + draggingParts[i].dragXOff * scaleFactor - draggingParts[i].w / 2;
  1434.                             draggingParts[i].y = initDragY + draggingParts[i].dragYOff * scaleFactor - draggingParts[i].h / 2;
  1435.                         } else if (draggingParts[i] is Thrusters) {
  1436.                             draggingParts[i].Move(initDragX + draggingParts[i].dragXOff * scaleFactor, initDragY + draggingParts[i].dragYOff * scaleFactor);
  1437.                         }
  1438.                     }
  1439.                     mostRecentScaleFactor = scaleFactor;
  1440.                 }
  1441.                
  1442.                 // finalize a joint
  1443.                 if (curAction == FINALIZING_JOINT && Util.GetDist(candidateJointX, candidateJointY, mouseXWorldPhys, mouseYWorldPhys) > 0.5 * 30 / m_physScale) {
  1444.                     if (candidateJointType == NEW_REVOLUTE_JOINT) {
  1445.                         var rjoint:RevoluteJoint = new RevoluteJoint(potentialJointPart1, potentialJointPart2, candidateJointX, candidateJointY);
  1446.                         if (copiedJoint is RevoluteJoint) rjoint.SetJointProperties(copiedJoint as RevoluteJoint);
  1447.                         allParts.push(rjoint);
  1448.                         AddAction(new CreateAction(rjoint));
  1449.                         m_sidePanel.ShowJointPanel(rjoint);
  1450.                         selectedParts = new Array();
  1451.                         selectedParts.push(rjoint);
  1452.                         curAction = -1;
  1453.                         potentialJointPart1.highlightForJoint = false;
  1454.                         potentialJointPart2.highlightForJoint = false;
  1455.                         curRobotID = "";
  1456.                         if (centerOnSelected) CenterOnSelected();
  1457.                         redrawRobot = true;
  1458.                         PlayJointSound();
  1459.                     } else if (candidateJointType == NEW_FIXED_JOINT) {
  1460.                         var fjoint:JointPart = new FixedJoint(potentialJointPart1, potentialJointPart2, candidateJointX, candidateJointY);
  1461.                         allParts.push(fjoint);
  1462.                         AddAction(new CreateAction(fjoint));
  1463.                         m_sidePanel.ShowJointPanel(fjoint);
  1464.                         selectedParts = new Array();
  1465.                         selectedParts.push(fjoint);
  1466.                         curAction = -1;
  1467.                         potentialJointPart1.highlightForJoint = false;
  1468.                         potentialJointPart2.highlightForJoint = false;
  1469.                         curRobotID = "";
  1470.                         if (centerOnSelected) CenterOnSelected();
  1471.                         redrawRobot = true;
  1472.                         PlayJointSound();
  1473.                     } else if (candidateJointType == NEW_THRUSTERS) {
  1474.                         var t:Thrusters = new Thrusters(potentialJointPart1, candidateJointX, candidateJointY);
  1475.                         if (copiedThrusters) {
  1476.                             t.strength = copiedThrusters.strength;
  1477.                             t.angle = copiedThrusters.angle;
  1478.                             t.thrustKey = copiedThrusters.thrustKey;
  1479.                             t.autoOn = copiedThrusters.autoOn;
  1480.                         }
  1481.                         allParts.push(t);
  1482.                         AddAction(new CreateAction(t));
  1483.                         m_sidePanel.ShowThrustersPanel(t);
  1484.                         selectedParts = new Array();
  1485.                         selectedParts.push(t);
  1486.                         curAction = -1;
  1487.                         potentialJointPart1.highlightForJoint = false;
  1488.                         curRobotID = "";
  1489.                         if (centerOnSelected) CenterOnSelected();
  1490.                         redrawRobot = true;
  1491.                         PlayJointSound();
  1492.                     } else if (candidateJointType == NEW_PRISMATIC_JOINT && actionStep == 0) {
  1493.                         jointPart = potentialJointPart1;
  1494.                         firstClickX = candidateJointX;
  1495.                         firstClickY = candidateJointY;
  1496.                         curAction = NEW_PRISMATIC_JOINT;
  1497.                         actionStep++;
  1498.                         PlayJointSound();
  1499.                     } else if (candidateJointType == NEW_PRISMATIC_JOINT) {
  1500.                         var pjoint:PrismaticJoint = new PrismaticJoint(jointPart, potentialJointPart1, firstClickX, firstClickY, candidateJointX, candidateJointY);
  1501.                         if (copiedJoint is PrismaticJoint) pjoint.SetJointProperties(copiedJoint as PrismaticJoint);
  1502.                         allParts.push(pjoint);
  1503.                         AddAction(new CreateAction(pjoint));
  1504.                         m_sidePanel.ShowJointPanel(pjoint);
  1505.                         selectedParts = new Array();
  1506.                         selectedParts.push(pjoint);
  1507.                         curAction = -1;
  1508.                         jointPart.highlightForJoint = false;
  1509.                         potentialJointPart1.highlightForJoint = false;
  1510.                         curRobotID = "";
  1511.                         if (centerOnSelected) CenterOnSelected();
  1512.                         redrawRobot = true;
  1513.                         PlayJointSound();
  1514.                     }
  1515.                 }
  1516.                
  1517.                 // resize text
  1518.                 if (curAction == RESIZING_TEXT) {
  1519.                     (draggingPart as TextPart).Resize(mouseXWorldPhys - initDragX, mouseYWorldPhys - initDragY);
  1520.                     redrawRobot = true;
  1521.                 }
  1522.             } else if (!paused && (((this is ControllerSandbox) && !(this is ControllerChallenge)) || ((this is ControllerChallenge) && ControllerChallenge.challenge.mouseDragAllowed))) {
  1523.                 // mouse press
  1524.                 if (Input.mouseDown && !m_mouseJoint) {
  1525.                     var body:b2Body = GetBodyAtMouse();
  1526.                    
  1527.                     if (!playingReplay && body) {
  1528.                         var md:b2MouseJointDef = new b2MouseJointDef();
  1529.                         md.body1 = m_world.m_groundBody;
  1530.                         md.body2 = body;
  1531.                         md.target.Set(mouseXWorldPhys, mouseYWorldPhys);
  1532.                         md.maxForce = 300.0 * body.m_mass;
  1533.                         md.timeStep = m_timeStep;
  1534.                         m_mouseJoint = m_world.CreateJoint(md) as b2MouseJoint;
  1535.                         body.WakeUp();
  1536.                     }
  1537.                 }
  1538.            
  1539.                 // mouse move
  1540.                 if (m_mouseJoint) {
  1541.                     var p2:b2Vec2 = new b2Vec2(mouseXWorldPhys, mouseYWorldPhys);
  1542.                     m_mouseJoint.SetTarget(p2);
  1543.                 }
  1544.            
  1545.                 // mouse release
  1546.                 if (!Input.mouseDown) {
  1547.                     if (m_mouseJoint) {
  1548.                         m_world.DestroyJoint(m_mouseJoint);
  1549.                         m_mouseJoint = null;
  1550.                     }
  1551.                 }
  1552.             }
  1553.            
  1554.             if (simStarted && Input.mouseDown && !m_guiMenu.MouseOverMenu(mouseXWorld, mouseYWorld) && mouseYWorld >= 100 && (mouseXWorld >= 120 || !m_sidePanel.visible) && (mouseXWorld >= 230 || mouseYWorld >= 340 || !m_sidePanel.ColourWindowShowing()) && curAction != BOX_SELECTING && !m_mouseJoint) {
  1555.                 if ((!m_tutorialDialog || !m_tutorialDialog.MouseOver(mouseXWorld, mouseYWorld)) && !draggingTutorial) {
  1556.                     // dragging the world around
  1557.                     var change:Boolean = (mouseXWorld != prevMouseXWorld || mouseYWorld != prevMouseYWorld);
  1558.                     draw.m_drawXOff -= (mouseXWorld - prevMouseXWorld);
  1559.                     draw.m_drawYOff -= (mouseYWorld - prevMouseYWorld);
  1560.                     autoPanning = false;
  1561.                    
  1562.                     if (change) {
  1563.                         hasPanned = true;
  1564.                         cameraMovements.push(new CameraMovement(frameCounter, draw.m_drawXOff, draw.m_drawYOff, m_physScale));
  1565.                     }
  1566.                 }
  1567.             }
  1568.            
  1569.             // make sure they haven't gone beyond the boundaries
  1570.             var minY:Number = Screen2WorldY(85);
  1571.             var maxY:Number = Screen2WorldY(600);
  1572.             if (minY < GetMinY()) {
  1573.                 draw.m_drawYOff += World2ScreenY(GetMinY()) - World2ScreenY(minY);
  1574.             } else if (maxY > GetMaxY()) {
  1575.                 draw.m_drawYOff -= World2ScreenY(maxY) - World2ScreenY(GetMaxY());
  1576.             }
  1577.            
  1578.             var minX:Number = Screen2WorldX(0);
  1579.             var maxX:Number = Screen2WorldX(800);
  1580.             if (minX < GetMinX()) {
  1581.                 draw.m_drawXOff += World2ScreenX(GetMinX()) - World2ScreenX(minX);
  1582.                 hasPanned = true;
  1583.             } else if (maxX > GetMaxX()) {
  1584.                 draw.m_drawXOff -= World2ScreenX(maxX) - World2ScreenX(GetMaxX());
  1585.                 hasPanned = true;
  1586.             }
  1587.            
  1588.             wasMouseDown = Input.mouseDown;
  1589.         }
  1590.  
  1591.         public override function keyInput(key:int, up:Boolean):void {
  1592.             var recorded:Boolean = false;
  1593.             for (var i:int = 0; i < allParts.length; i++) {
  1594.                 allParts[i].KeyInput(key, up, playingReplay);
  1595.                 if (!recorded && up && !playingReplay && ((allParts[i] is TextPart && key == allParts[i].displayKey) || (allParts[i] is Cannon && key == allParts[i].fireKey))) {
  1596.                     recorded = true;
  1597.                     keyPresses.push(new KeyPress(frameCounter, key));
  1598.                 }
  1599.             }
  1600.         }
  1601.        
  1602.         public function keyPress(key:int, up:Boolean):void {
  1603.             if (!paused && !playingReplay) {
  1604.                 keyInput(key, up);
  1605.             }
  1606.            
  1607.             if (!simStarted && !m_sidePanel.EnteringInput() && !m_fader.visible) {
  1608.                 if (up && key == 49) {
  1609.                     circleButton(new MouseEvent(""));
  1610.                 } else if (up && key == 50) {
  1611.                     rectButton(new MouseEvent(""));
  1612.                 } else if (up && key == 51) {
  1613.                     triangleButton(new MouseEvent(""));
  1614.                 } else if (up && key == 52) {
  1615.                     fjButton(new MouseEvent(""));
  1616.                 } else if (up && key == 53) {
  1617.                     rjButton(new MouseEvent(""));
  1618.                 } else if (up && key == 54) {
  1619.                     pjButton(new MouseEvent(""));
  1620.                 } else if (up && key == 55) {
  1621.                     textButton(new MouseEvent(""));
  1622.                 } else if (up && key == 82) {
  1623.                     rotateButton(new MouseEvent(""));
  1624.                 } else if (up && key == 88) {
  1625.                     cutButton(new MouseEvent(""));
  1626.                 } else if (up && key == 67) {
  1627.                     copyButton(new MouseEvent(""));
  1628.                 } else if (up && key == 86) {
  1629.                     pasteButton(new MouseEvent(""));
  1630.                 } else if (up && (key == 8 || key == 46)) {
  1631.                     if (selectedParts.length == 1 && !selectedParts[0] is TextPart) deleteButton(new MouseEvent(""));
  1632.                     else multiDeleteButton(new MouseEvent(""));
  1633.                 } else if (up && key == 89) {
  1634.                     redoButton(new MouseEvent(""));
  1635.                 } else if (up && key == 90) {
  1636.                     undoButton(new MouseEvent(""));
  1637.                 } else if (up && (key == 107 || key == 187)) {
  1638.                     zoomInButton(new MouseEvent(""));
  1639.                 } else if (up && (key == 109 || key == 189)) {
  1640.                     zoomOutButton(new MouseEvent(""));
  1641.                 } else if (up && key == 80) {
  1642.                     playButton(new MouseEvent(""));
  1643.                 }
  1644.             }
  1645.            
  1646.             if (up && key == 27) {
  1647.                 if (m_chooserWindow && m_chooserWindow.visible && !m_chooserWindow.fader.visible) {
  1648.                     m_chooserWindow.visible = false;
  1649.                     m_fader.visible = false;
  1650.                 }
  1651.                 if (m_challengeWindow && m_challengeWindow.visible && !m_challengeWindow.fader.visible) {
  1652.                     m_challengeWindow.visible = false;
  1653.                     m_fader.visible = false;
  1654.                 }
  1655.                 if (m_sidePanel.visible && !m_fader.visible) {
  1656.                     m_sidePanel.visible = false;
  1657.                 }
  1658.                 if (m_scoreWindow && m_scoreWindow.visible) {
  1659.                     m_scoreWindow.visible = false;
  1660.                     m_fader.visible = false;
  1661.                 }
  1662.                 if (m_progressDialog && m_progressDialog.visible) {
  1663.                     m_progressDialog.visible = false;
  1664.                     if (m_chooserWindow && m_chooserWindow.visible) {
  1665.                         m_chooserWindow.HideFader();
  1666.                     } else if (m_challengeWindow && m_challengeWindow.visible) {
  1667.                         m_challengeWindow.HideFader();
  1668.                     } else if (m_loginWindow && m_loginWindow.visible) {
  1669.                         m_loginWindow.HideFader();
  1670.                     } else if (m_newUserWindow && m_newUserWindow.visible) {
  1671.                         m_newUserWindow.HideFader();
  1672.                     } else {
  1673.                         m_fader.visible = false;
  1674.                     }
  1675.                 }
  1676.                 if (m_tutorialDialog && m_tutorialDialog.visible) {
  1677.                     m_tutorialDialog.closeWindow(new MouseEvent(""));
  1678.                 }
  1679.                 if (m_linkDialog && m_linkDialog.visible) {
  1680.                     m_linkDialog.visible = false;
  1681.                     if (m_chooserWindow && m_chooserWindow.visible) {
  1682.                         m_chooserWindow.HideFader();
  1683.                     } else {
  1684.                         m_fader.visible = false;
  1685.                     }
  1686.                 }
  1687.                 if (m_loginWindow && m_loginWindow.visible && !m_loginWindow.fader.visible) {
  1688.                     m_loginWindow.cancelButtonPressed(new MouseEvent(""));
  1689.                 }
  1690.                 if (m_newUserWindow && m_newUserWindow.visible) {
  1691.                     m_newUserWindow.cancelButtonPressed(new MouseEvent(""));
  1692.                 }
  1693.             }
  1694.         }
  1695.        
  1696.         public function mouseMove(x:int, y:int):void {
  1697.             Main.mouseCursor.x = x;
  1698.             Main.mouseCursor.y = y;
  1699.             Main.mouseHourglass.x = x;
  1700.             Main.mouseHourglass.y = y;
  1701.         }
  1702.        
  1703.         public function mouseClick(up:Boolean):void {
  1704.             m_guiMenu.MouseClick(up, mouseXWorld, mouseYWorld);
  1705.             var part:ShapePart;
  1706.            
  1707.             if (up && delayedSelection) {
  1708.                 delayedSelection = false;
  1709.                 if (mouseXWorldPhys == initDragX && mouseYWorldPhys == initDragY) {
  1710.                     var p:Part = GetPartAtMouse();
  1711.                     if (!Util.ObjectInArray(p, selectedParts)) {
  1712.                         if (!Input.isKeyDown(16)) {
  1713.                             selectedParts = new Array();
  1714.                         }
  1715.                         selectedParts.push(p);
  1716.                     } else if (Input.isKeyDown(16)) {
  1717.                         selectedParts = Util.RemoveFromArray(p, selectedParts);
  1718.                     }
  1719.                     redrawRobot = true;
  1720.                     RefreshSidePanel();
  1721.                 }
  1722.             }
  1723.            
  1724.             if (up && rotatingPart != null) {
  1725.                 curAction = -1;
  1726.                 AddAction(new RotateAction((rotatingPart as Part), rotatingParts, Util.NormalizeAngle(Math.atan2(mouseYWorldPhys - rotatingPart.centerY, mouseXWorldPhys - rotatingPart.centerX) - initRotatingAngle)));
  1727.                 CheckIfPartsFit();
  1728.                 rotatingPart = null;
  1729.             } else if (up && draggingPart != null) {
  1730.                 if (!ignoreAClick) {
  1731.                     if (curAction != PASTE && curAction != RESIZING_TEXT && (mouseXWorldPhys != initDragX || mouseYWorldPhys != initDragY)) AddAction(new MoveAction(draggingPart, draggingParts, mouseXWorldPhys - initDragX, mouseYWorldPhys - initDragY));
  1732.                     if (curAction == RESIZING_TEXT) {
  1733.                         var tPart:TextPart = (draggingPart as TextPart);
  1734.                         AddAction(new ResizeTextAction(tPart, tPart.x - tPart.initX, tPart.y - tPart.initY, tPart.w - tPart.initW, tPart.h - tPart.initH));
  1735.                     }
  1736.                     CheckIfPartsFit();
  1737.                     if (curAction == PASTE) {
  1738.                         var hasShape:Boolean = false;
  1739.                         for (var i:int = 0; i < draggingParts.length; i++) {
  1740.                             if (draggingParts[i] is ShapePart) {
  1741.                                 hasShape = true;
  1742.                                 break;
  1743.                             }
  1744.                         }
  1745.                         if (hasShape) PlayShapeSound();
  1746.                     }
  1747.                     if (curAction < 14) curAction = -1;
  1748.                     draggingPart = null;
  1749.                 } else {
  1750.                     ignoreAClick = false;
  1751.                 }
  1752.             } else if (!up && curAction == RESIZING_SHAPES) {
  1753.                 if (!ignoreAClick) {
  1754.                     curAction = -1;
  1755.                     AddAction(new ResizeShapesAction(draggingParts, mostRecentScaleFactor));
  1756.                     draggingParts = new Array();
  1757.                     CheckIfPartsFit();
  1758.                 } else {
  1759.                     ignoreAClick = false;
  1760.                 }
  1761.             } else if (!up && (curAction == DRAWING_BUILD_BOX || curAction == DRAWING_BOX || curAction == DRAWING_HORIZONTAL_LINE || curAction == DRAWING_VERTICAL_LINE) && actionStep == 0 && mouseYWorld > 100 && !m_guiMenu.MouseOverMenu(mouseXWorld, mouseYWorld) && (!m_tutorialDialog || !m_tutorialDialog.MouseOver(mouseXWorld, mouseYWorld))) {
  1762.                 firstClickX = mouseXWorldPhys;
  1763.                 firstClickY = mouseYWorldPhys;
  1764.                 actionStep++;
  1765.             } else if ((curAction == DRAWING_BOX || curAction == DRAWING_HORIZONTAL_LINE || curAction == DRAWING_VERTICAL_LINE) && actionStep == 1) {
  1766.                 if (Math.abs(firstClickX - mouseXWorldPhys) > 0.1 || Math.abs(firstClickY - mouseYWorldPhys) > 0.1) {
  1767.                     curAction = -1;
  1768.                     m_conditionsDialog.visible = true;
  1769.                     m_fader.visible = true;
  1770.                     selectingCondition = false;
  1771.                     m_conditionsDialog.FinishDrawingCondition(firstClickX, firstClickY, mouseXWorldPhys, mouseYWorldPhys);
  1772.                     boxText.visible = false;
  1773.                     horizLineText.visible = false;
  1774.                     vertLineText.visible = false;
  1775.                     redrawRobot = true;
  1776.                 }
  1777.             } else if (curAction == DRAWING_BUILD_BOX && actionStep == 1) {
  1778.                 if (Math.abs(firstClickX - mouseXWorldPhys) > 0.5 || Math.abs(firstClickY - mouseYWorldPhys) > 0.5) {
  1779.                     curAction = -1;
  1780.                     var buildArea:b2AABB = new b2AABB();
  1781.                     buildArea.lowerBound = Util.Vector(Math.min(firstClickX, mouseXWorldPhys), Math.min(firstClickY, mouseYWorldPhys));
  1782.                     buildArea.upperBound = Util.Vector(Math.max(firstClickX, mouseXWorldPhys), Math.max(firstClickY, mouseYWorldPhys));
  1783.                     ControllerChallenge.challenge.buildAreas.push(buildArea);
  1784.                     selectedBuildArea = ControllerChallenge.challenge.buildAreas[ControllerChallenge.challenge.buildAreas.length - 1];
  1785.                     m_sidePanel.ShowBuildBoxPanel();
  1786.                     BuildBuildArea();
  1787.                     redrawRobot = true;
  1788.                     redrawBuildArea = true;
  1789.                 }
  1790.             }
  1791.            
  1792.             if (!up && !draggingTutorial && m_tutorialDialog && m_tutorialDialog.MouseOver(mouseXWorld, mouseYWorld)) {
  1793.                 draggingTutorial = true;
  1794.                 initDragX = mouseXWorld - m_tutorialDialog.x;
  1795.                 initDragY = mouseYWorld - m_tutorialDialog.y;
  1796.                 return;
  1797.             }
  1798.             if (!curRobotEditable || mouseYWorld < 100 || (mouseXWorld < 120 && m_sidePanel.visible) || m_guiMenu.MouseOverMenu(mouseXWorld, mouseYWorld) || (mouseXWorld < 230 && mouseYWorld < 340 && m_sidePanel.ColourWindowShowing()) || (m_tutorialDialog && m_tutorialDialog.MouseOver(mouseXWorld, mouseYWorld))) return;
  1799.            
  1800.             if (up && selectedParts.length == 1 && centerOnSelected) {
  1801.                 CenterOnSelected();
  1802.             } else if (selectedParts.length == 0 && curAction == -1 && this is ControllerChallenge && !ControllerChallenge.playChallengeMode) {
  1803.                 for (i = 0; i < ControllerChallenge.challenge.buildAreas.length; i++) {
  1804.                     if (mouseXWorldPhys > ControllerChallenge.challenge.buildAreas[i].lowerBound.x && mouseXWorldPhys < ControllerChallenge.challenge.buildAreas[i].upperBound.x && mouseYWorldPhys > ControllerChallenge.challenge.buildAreas[i].lowerBound.y && mouseYWorldPhys < ControllerChallenge.challenge.buildAreas[i].upperBound.y) {
  1805.                         selectedBuildArea = ControllerChallenge.challenge.buildAreas[i];
  1806.                         m_sidePanel.ShowBuildBoxPanel();
  1807.                         break;
  1808.                     }
  1809.                 }
  1810.             }
  1811.            
  1812.             if (curAction == NEW_CIRCLE) {
  1813.                 if (!up && actionStep == 0) {
  1814.                     firstClickX = mouseXWorldPhys;
  1815.                     firstClickY = mouseYWorldPhys;
  1816.                     actionStep++;
  1817.                 } else if (up && actionStep == 1) {
  1818.                     var radius:Number = Util.GetDist(firstClickX, firstClickY, mouseXWorldPhys, mouseYWorldPhys);
  1819.                     if (radius > 0) {
  1820.                         curAction = -1;
  1821.                         var circ:ShapePart = new Circle(firstClickX, firstClickY, radius);
  1822.                         allParts.push(circ);
  1823.                         selectedParts = new Array();
  1824.                         selectedParts.push(circ);
  1825.                         AddAction(new CreateAction(circ));
  1826.                         CheckIfPartsFit();
  1827.                         m_sidePanel.ShowObjectPanel(circ);
  1828.                         curRobotID = "";
  1829.                         if (centerOnSelected) CenterOnSelected();
  1830.                         redrawRobot = true;
  1831.                         PlayShapeSound();
  1832.                     }
  1833.                 }
  1834.             } else if (curAction == NEW_RECT) {
  1835.                 if (!up && actionStep == 0) {
  1836.                     firstClickX = mouseXWorldPhys;
  1837.                     firstClickY = mouseYWorldPhys;
  1838.                     actionStep++;
  1839.                 } else if (up && actionStep == 1) {
  1840.                     if (mouseXWorldPhys != firstClickX || mouseYWorldPhys != firstClickY) {
  1841.                         curAction = -1;
  1842.                         rect = new Rectangle(firstClickX, firstClickY, mouseXWorldPhys - firstClickX, mouseYWorldPhys - firstClickY);
  1843.                         allParts.push(rect);
  1844.                         selectedParts = new Array();
  1845.                         selectedParts.push(rect);
  1846.                         AddAction(new CreateAction(rect));
  1847.                         CheckIfPartsFit();
  1848.                         m_sidePanel.ShowObjectPanel(rect);
  1849.                         curRobotID = "";
  1850.                         if (centerOnSelected) CenterOnSelected();
  1851.                         redrawRobot = true;
  1852.                         PlayShapeSound();
  1853.                     }
  1854.                 }
  1855.             } else if (curAction == NEW_CANNON) {
  1856.                 if (!up && actionStep == 0) {
  1857.                     firstClickX = mouseXWorldPhys;
  1858.                     firstClickY = mouseYWorldPhys;
  1859.                     actionStep++;
  1860.                 } else if (up && actionStep == 1) {
  1861.                     if (mouseXWorldPhys != firstClickX || mouseYWorldPhys != firstClickY) {
  1862.                         curAction = -1;
  1863.                         var positive:Boolean = (mouseXWorldPhys >= firstClickX || mouseYWorldPhys >= firstClickY);
  1864.                         var w:Number = (positive ? Math.max(mouseXWorldPhys - firstClickX, 2 * (mouseYWorldPhys - firstClickY)) : Math.min(mouseXWorldPhys - firstClickX, 2 * (mouseYWorldPhys - firstClickY)));
  1865.                         var cannon:ShapePart = new Cannon(firstClickX, firstClickY, w);
  1866.                         allParts.push(cannon);
  1867.                         selectedParts = new Array();
  1868.                         selectedParts.push(cannon);
  1869.                         AddAction(new CreateAction(cannon));
  1870.                         CheckIfPartsFit();
  1871.                         m_sidePanel.ShowCannonPanel((cannon as Cannon));
  1872.                         curRobotID = "";
  1873.                         if (centerOnSelected) CenterOnSelected();
  1874.                         redrawRobot = true;
  1875.                         PlayShapeSound();
  1876.                     }
  1877.                 }
  1878.             } else if (curAction == NEW_TRIANGLE) {
  1879.                 if (!up && actionStep == 0) {
  1880.                     firstClickX = mouseXWorldPhys;
  1881.                     firstClickY = mouseYWorldPhys;
  1882.                     actionStep++;
  1883.                 } else if (up && actionStep == 1) {
  1884.                     if (mouseXWorldPhys != firstClickX || mouseYWorldPhys != firstClickY) {
  1885.                         var x2:Number = mouseXWorldPhys;
  1886.                         var y2:Number = mouseYWorldPhys;
  1887.                        
  1888.                         var sideLen:Number = Util.GetDist(firstClickX, firstClickY, mouseXWorldPhys, mouseYWorldPhys);
  1889.                         var angle:Number;
  1890.                         if (sideLen < Triangle.MIN_SIDE_LENGTH) {
  1891.                             angle = Math.atan2(firstClickY - mouseYWorldPhys, mouseXWorldPhys - firstClickX);
  1892.                             x2 = firstClickX + Triangle.MIN_SIDE_LENGTH * Math.cos(angle);
  1893.                             y2 = firstClickY - Triangle.MIN_SIDE_LENGTH * Math.sin(angle);
  1894.                         } else if (sideLen > Triangle.MAX_SIDE_LENGTH) {
  1895.                             angle = Math.atan2(firstClickY - mouseYWorldPhys, mouseXWorldPhys - firstClickX);
  1896.                             x2 = firstClickX + Triangle.MAX_SIDE_LENGTH * Math.cos(angle);
  1897.                             y2 = firstClickY - Triangle.MAX_SIDE_LENGTH * Math.sin(angle);
  1898.                         }
  1899.                         secondClickX = x2;
  1900.                         secondClickY = y2;
  1901.                         actionStep++;
  1902.                         PlayShapeSound();
  1903.                     }
  1904.                 } else if (up && actionStep == 2) {
  1905.                     if ((mouseXWorldPhys != firstClickX || mouseYWorldPhys != firstClickY) && (mouseXWorldPhys != secondClickX || mouseYWorldPhys != secondClickY)) {
  1906.                         var sideLen1:Number = Util.GetDist(firstClickX, firstClickY, mouseXWorldPhys, mouseYWorldPhys);
  1907.                         var sideLen2:Number = Util.GetDist(secondClickX, secondClickY, mouseXWorldPhys, mouseYWorldPhys);
  1908.                         var sideLen0:Number = Util.GetDist(firstClickX, firstClickY, secondClickX, secondClickY);
  1909.                         var angle1:Number = Util.NormalizeAngle(Math.acos((sideLen0 * sideLen0 + sideLen1 * sideLen1 - sideLen2 * sideLen2) / (2 * sideLen0 * sideLen1)));
  1910.                        
  1911.                         var angle2:Number = Util.NormalizeAngle(Math.acos((sideLen0 * sideLen0 + sideLen2 * sideLen2 - sideLen1 * sideLen1) / (2 * sideLen0 * sideLen2)));
  1912.                        
  1913.                         var angle3:Number = Util.NormalizeAngle(Math.acos((sideLen1 * sideLen1 + sideLen2 * sideLen2 - sideLen0 * sideLen0) / (2 * sideLen1 * sideLen2)));
  1914.                        
  1915.                         if (sideLen1 <= Triangle.MAX_SIDE_LENGTH && sideLen1 >= Triangle.MIN_SIDE_LENGTH && sideLen2 <= Triangle.MAX_SIDE_LENGTH && sideLen2 >= Triangle.MIN_SIDE_LENGTH && angle1 >= Triangle.MIN_TRIANGLE_ANGLE && angle2 >= Triangle.MIN_TRIANGLE_ANGLE && angle3 >= Triangle.MIN_TRIANGLE_ANGLE) {
  1916.                             curAction = -1;
  1917.                             var tri:ShapePart = new Triangle(firstClickX, firstClickY, secondClickX, secondClickY, mouseXWorldPhys, mouseYWorldPhys);
  1918.                             allParts.push(tri);
  1919.                             selectedParts = new Array();
  1920.                             selectedParts.push(tri);
  1921.                             AddAction(new CreateAction(tri));
  1922.                             CheckIfPartsFit();
  1923.                             m_sidePanel.ShowObjectPanel(tri);
  1924.                             curRobotID = "";
  1925.                             if (centerOnSelected) CenterOnSelected();
  1926.                             redrawRobot = true;
  1927.                             PlayShapeSound();
  1928.                         }
  1929.                     }
  1930.                 }
  1931.                
  1932.             } else if (up && actionStep == 0 && curAction == NEW_PRISMATIC_JOINT) {
  1933.                 MaybeStartCreatingPrismaticJoint();
  1934.             } else if (up && actionStep == 1 && curAction == NEW_PRISMATIC_JOINT) {
  1935.                 if (Util.GetDist(firstClickX, firstClickY, mouseXWorldPhys, mouseYWorldPhys) > 0.3) MaybeFinishCreatingPrismaticJoint();
  1936.             } else if (up && actionStep == 0 && (curAction == NEW_REVOLUTE_JOINT || curAction == NEW_FIXED_JOINT)) {
  1937.                 MaybeCreateJoint();
  1938.             } else if (up && curAction == BOX_SELECTING) {
  1939.                 selectedParts = new Array();
  1940.                 for (i = 0; i < allParts.length; i++) {
  1941.                     if (allParts[i].isEditable && allParts[i].IntersectsBox(Math.min(firstClickX, mouseXWorldPhys), Math.min(firstClickY, mouseYWorldPhys), Math.abs(firstClickX - mouseXWorldPhys), Math.abs(firstClickY - mouseYWorldPhys))) {
  1942.                         selectedParts.push(allParts[i]);
  1943.                     }
  1944.                 }
  1945.                
  1946.                 if (selectedParts.length == 0) {
  1947.                     m_sidePanel.visible = false;
  1948.                 } else if (selectedParts.length == 1 && selectedParts[0] is Cannon) {
  1949.                     m_sidePanel.ShowCannonPanel(selectedParts[0]);
  1950.                 } else if (selectedParts.length == 1 && selectedParts[0] is ShapePart) {
  1951.                     m_sidePanel.ShowObjectPanel(selectedParts[0]);
  1952.                 } else if (selectedParts.length == 1 && selectedParts[0] is JointPart) {
  1953.                     m_sidePanel.ShowJointPanel(selectedParts[0]);
  1954.                 } else if (selectedParts.length == 1 && selectedParts[0] is TextPart) {
  1955.                     m_sidePanel.ShowTextPanel(selectedParts[0]);
  1956.                 } else if (selectedParts.length == 1 && selectedParts[0] is Thrusters) {
  1957.                     m_sidePanel.ShowThrustersPanel(selectedParts[0]);
  1958.                 } else {
  1959.                     m_sidePanel.ShowMultiSelectPanel(selectedParts);
  1960.                 }
  1961.                 curAction = -1;
  1962.                 redrawRobot = true;
  1963.             } else if (up && curAction == FINALIZING_JOINT) {
  1964.                 if (candidateJointType == NEW_PRISMATIC_JOINT || candidateJointType == NEW_THRUSTERS) {
  1965.                     potentialJointPart1.highlightForJoint = false;
  1966.                     var index:int = -1;
  1967.                     for (i = 0; i < candidateJointParts.length; i++) {
  1968.                         if (potentialJointPart1 == candidateJointParts[i]) index = i;
  1969.                     }
  1970.                     index++;
  1971.                     if (index == candidateJointParts.length) index = 0;
  1972.                     potentialJointPart1 = candidateJointParts[index];
  1973.                     potentialJointPart1.highlightForJoint = true;
  1974.                 } else {
  1975.                     potentialJointPart1.highlightForJoint = false;
  1976.                     potentialJointPart2.highlightForJoint = false;
  1977.                     var index1:int = -1, index2:int = -1;
  1978.                     for (i = 0; i < candidateJointParts.length; i++) {
  1979.                         if (potentialJointPart1 == candidateJointParts[i]) index1 = i;
  1980.                         if (potentialJointPart2 == candidateJointParts[i]) index2 = i;
  1981.                     }
  1982.                     if (index1 == candidateJointParts.length - 2 && index2 == candidateJointParts.length - 1) {
  1983.                         index1 = 0;
  1984.                         index2 = 1;
  1985.                     } else {
  1986.                         index2++;
  1987.                         if (index2 == candidateJointParts.length) {
  1988.                             index1++;
  1989.                             index2 = index1 + 1;
  1990.                         }
  1991.                     }
  1992.                     potentialJointPart1 = candidateJointParts[index1];
  1993.                     potentialJointPart2 = candidateJointParts[index2];
  1994.                    
  1995.                     potentialJointPart1.highlightForJoint = true;
  1996.                     potentialJointPart2.highlightForJoint = true;
  1997.                 }
  1998.             } else if (!up && curAction == NEW_TEXT && actionStep == 0) {
  1999.                 firstClickX = mouseXWorldPhys;
  2000.                 firstClickY = mouseYWorldPhys;
  2001.                 actionStep++;
  2002.             } else if (up && curAction == NEW_TEXT && actionStep == 1) {
  2003.                 var finalClickX:Number = mouseXWorldPhys;
  2004.                 var finalClickY:Number = mouseYWorldPhys;
  2005.                 if (Math.abs(finalClickX - firstClickX) < 1 || Math.abs(finalClickY - firstClickY) < 0.5) {
  2006.                     var avgX:Number = (firstClickX + finalClickX) / 2.0;
  2007.                     var avgY:Number = (firstClickY + finalClickY) / 2.0;
  2008.                     firstClickX = avgX - 2;
  2009.                     firstClickY = avgY - 1;
  2010.                     finalClickX = avgX + 2;
  2011.                     finalClickY = avgY + 1;
  2012.                 }
  2013.                 var text:TextPart = new TextPart(this, Math.min(firstClickX, finalClickX), Math.min(firstClickY, finalClickY), Math.max(firstClickX, finalClickX) - Math.min(firstClickX, finalClickX), Math.max(firstClickY, finalClickY) - Math.min(firstClickY, finalClickY), "New Text");
  2014.                 selectedParts.push(text);
  2015.                 allParts.push(text);
  2016.                 AddAction(new CreateAction(text));
  2017.                 curAction = -1;
  2018.                 curRobotID = "";
  2019.                 m_sidePanel.ShowTextPanel(text);
  2020.                 redrawRobot = true;
  2021.             } else if (up && curAction == NEW_THRUSTERS) {
  2022.                 MaybeCreateThrusters();
  2023.             } else if (up && curAction == RESIZING_TEXT) {
  2024.                 curAction = -1;
  2025.             }
  2026.         }
  2027.        
  2028.         public function RefreshSidePanel():void {
  2029.             if (selectedParts.length == 0 || selectingCondition) {
  2030.                 m_sidePanel.visible = false;
  2031.             } else if (selectedParts.length == 1 && selectedParts[0] is Cannon) {
  2032.                 m_sidePanel.ShowCannonPanel(selectedParts[0] as Cannon);
  2033.                 lastSelectedShape = null;
  2034.             } else if (selectedParts.length == 1 && selectedParts[0] is ShapePart) {
  2035.                 m_sidePanel.ShowObjectPanel(selectedParts[0] as ShapePart);
  2036.                 lastSelectedShape = null;
  2037.             } else if (selectedParts.length == 1 && selectedParts[0] is TextPart) {
  2038.                 m_sidePanel.ShowTextPanel(selectedParts[0] as TextPart);
  2039.                 lastSelectedText = null;
  2040.             } else if (selectedParts.length == 1 && selectedParts[0] is JointPart) {
  2041.                 m_sidePanel.ShowJointPanel(selectedParts[0] as JointPart);
  2042.                 lastSelectedJoint = null;
  2043.             } else if (selectedParts.length == 1 && selectedParts[0] is Thrusters) {
  2044.                 m_sidePanel.ShowThrustersPanel(selectedParts[0] as Thrusters);
  2045.                 lastSelectedThrusters = null;
  2046.             } else {
  2047.                 m_sidePanel.ShowMultiSelectPanel(selectedParts);
  2048.             }
  2049.         }
  2050.        
  2051.         public function AddAction(a:Action):void {
  2052.             while (lastAction + 1 != actions.length) {
  2053.                 actions.pop();
  2054.             }
  2055.             lastAction = actions.length;
  2056.             actions.push(a);
  2057.         }
  2058.        
  2059.         public function CenterOnSelected():void {
  2060.             if (selectedParts.length == 1) {
  2061.                 var centerX:Number, centerY:Number;
  2062.                 if (selectedParts[0] is ShapePart || selectedParts[0] is Thrusters) {
  2063.                     centerX = selectedParts[0].centerX;
  2064.                     centerY = selectedParts[0].centerY;
  2065.                 } else if (selectedParts[0] is JointPart) {
  2066.                     centerX = selectedParts[0].anchorX;
  2067.                     centerY = selectedParts[0].anchorY;
  2068.                 } else if (selectedParts[0] is TextPart) {
  2069.                     centerX = selectedParts[0].x + selectedParts[0].w / 2;
  2070.                     centerY = selectedParts[0].y + selectedParts[0].h / 2;
  2071.                 }
  2072.                
  2073.                 var oldX:Number = draw.m_drawXOff;
  2074.                 var oldY:Number = draw.m_drawYOff;
  2075.                 draw.m_drawXOff += World2ScreenX(centerX) - ZOOM_FOCUS_X;
  2076.                 draw.m_drawYOff += World2ScreenY(centerY) - ZOOM_FOCUS_Y;
  2077.                 if (oldX != draw.m_drawXOff || oldY != draw.m_drawYOff) {
  2078.                     hasPanned = true;
  2079.                 }
  2080.             }
  2081.         }
  2082.        
  2083.         // BUTTON LISTENERS
  2084.        
  2085.         public virtual function circleButton(e:MouseEvent):void {
  2086.             if (!curRobotEditable || selectingCondition) return;
  2087.             if (curAction == NEW_CIRCLE) {
  2088.                 curAction = -1;
  2089.                 redrawRobot = true;
  2090.             } else {
  2091.                 curAction = NEW_CIRCLE;
  2092.                 actionStep = 0;
  2093.                 selectedParts = new Array();
  2094.                 m_sidePanel.visible = false;
  2095.             }
  2096.         }
  2097.        
  2098.         public virtual function rectButton(e:MouseEvent):void {
  2099.             if (!curRobotEditable || selectingCondition) return;
  2100.             if (curAction == NEW_RECT) {
  2101.                 curAction = -1;
  2102.                 redrawRobot = true;
  2103.             } else {
  2104.                 curAction = NEW_RECT;
  2105.                 actionStep = 0;
  2106.                 selectedParts = new Array();
  2107.                 m_sidePanel.visible = false;
  2108.             }
  2109.         }
  2110.        
  2111.         public virtual function triangleButton(e:MouseEvent):void {
  2112.             if (!curRobotEditable || selectingCondition) return;
  2113.             if (curAction == NEW_TRIANGLE) {
  2114.                 curAction = -1;
  2115.                 redrawRobot = true;
  2116.             } else {
  2117.                 curAction = NEW_TRIANGLE;
  2118.                 actionStep = 0;
  2119.                 selectedParts = new Array();
  2120.                 m_sidePanel.visible = false;
  2121.             }
  2122.         }
  2123.        
  2124.         public virtual function fjButton(e:MouseEvent):void {
  2125.             if (!curRobotEditable || selectingCondition) return;
  2126.             if (curAction == NEW_FIXED_JOINT) {
  2127.                 curAction = -1;
  2128.                 redrawRobot = true;
  2129.             } else {
  2130.                 curAction = NEW_FIXED_JOINT;
  2131.                 actionStep = 0;
  2132.                 selectedParts = new Array();
  2133.                 m_sidePanel.visible = false;
  2134.                 potentialJointPart1 = null;
  2135.                 potentialJointPart2 = null;
  2136.                 copiedJoint = null;
  2137.             }
  2138.         }
  2139.        
  2140.         public virtual function rjButton(e:MouseEvent):void {
  2141.             if (!curRobotEditable || selectingCondition) return;
  2142.             if (curAction == NEW_REVOLUTE_JOINT) {
  2143.                 curAction = -1;
  2144.                 redrawRobot = true;
  2145.             } else {
  2146.                 curAction = NEW_REVOLUTE_JOINT;
  2147.                 actionStep = 0;
  2148.                 selectedParts = new Array();
  2149.                 m_sidePanel.visible = false;
  2150.                 potentialJointPart1 = null;
  2151.                 potentialJointPart2 = null;
  2152.                 copiedJoint = null;
  2153.             }
  2154.         }
  2155.        
  2156.         public virtual function pjButton(e:MouseEvent):void {
  2157.             if (!curRobotEditable || selectingCondition) return;
  2158.             if (curAction == NEW_PRISMATIC_JOINT) {
  2159.                 curAction = -1;
  2160.                 redrawRobot = true;
  2161.             } else {
  2162.                 curAction = NEW_PRISMATIC_JOINT;
  2163.                 actionStep = 0;
  2164.                 selectedParts = new Array();
  2165.                 m_sidePanel.visible = false;
  2166.                 potentialJointPart1 = null;
  2167.                 potentialJointPart2 = null;
  2168.                 copiedJoint = null;
  2169.             }
  2170.         }
  2171.        
  2172.         public virtual function textButton(e:MouseEvent):void {
  2173.             if (!curRobotEditable || selectingCondition) return;
  2174.             if (curAction == NEW_TEXT) {
  2175.                 curAction = -1;
  2176.                 redrawRobot = true;
  2177.             } else {
  2178.                 curAction = NEW_TEXT;
  2179.                 actionStep = 0;
  2180.                 selectedParts = new Array();
  2181.                 m_sidePanel.visible = false;
  2182.             }
  2183.         }
  2184.        
  2185.         public virtual function thrustersButton(e:MouseEvent):void {
  2186.             if (/*Main.premiumMode*/ true) {
  2187.                 if (!curRobotEditable || selectingCondition) return;
  2188.                 curAction = NEW_THRUSTERS;
  2189.                 actionStep = 0;
  2190.                 selectedParts = new Array();
  2191.                 m_sidePanel.visible = false;
  2192.                 copiedThrusters = null;
  2193.             } else {
  2194.                 m_fader.visible = true;
  2195.                 ShowConfirmDialog("That feature is only available to IncrediBots supporters. Become an IncrediBots supporter?", 8);
  2196.             }
  2197.         }
  2198.  
  2199.         public virtual function cannonButton(e:MouseEvent):void {
  2200.             if (/*Main.premiumMode*/ true) {
  2201.                 if (!curRobotEditable || selectingCondition) return;
  2202.                 curAction = NEW_CANNON;
  2203.                 actionStep = 0;
  2204.                 selectedParts = new Array();
  2205.                 m_sidePanel.visible = false;
  2206.             } else {
  2207.                 m_fader.visible = true;
  2208.                 ShowConfirmDialog("That feature is only available to IncrediBots supporters. Become an IncrediBots supporter?", 8);
  2209.             }
  2210.         }
  2211.  
  2212.         private function mochiAdStarted():void {
  2213.             adStarted = true;
  2214.         }
  2215.        
  2216.         private function mochiAdFinished():void {
  2217.             adStarted = false;
  2218.             playButton(new MouseEvent(""), false);
  2219.         }
  2220.        
  2221.         public virtual function playButton(e:MouseEvent, maybeShowAd:Boolean = true):void {
  2222.             if (selectingCondition) return;
  2223.             /*var time:int = getTimer();
  2224.             if (!Main.DEBUG_VERSION && !Main.premiumMode && maybeShowAd && time > Main.lastAdTime + 30 * 60 * 1000) {
  2225.                 MochiAd.showInterLevelAd({clip:root, id:"1913f89f65e17063", res:"800x600", ad_started:mochiAdStarted, ad_finished:mochiAdFinished});
  2226.                 Main.lastAdTime = time;
  2227.             }*/
  2228.            
  2229.             if (!adStarted) {
  2230.                 CheckIfPartsFit();
  2231.                 var tooManyShapes:Boolean = TooManyShapes();
  2232.                 if ((partsFit && !tooManyShapes) || playingReplay) {
  2233.                     m_guiPanel.ShowGamePanel();
  2234.                     m_sidePanel.visible = false;
  2235.                     selectedParts = new Array();
  2236.                     curAction = -1;
  2237.                     paused = false;
  2238.                     if (!simStarted) {
  2239.                         frameCounter = 0;
  2240.                         m_guiPanel.SetTimer(frameCounter);
  2241.                         cameraMovements = new Array();
  2242.                         cameraMovements.push(new CameraMovement(0, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, m_physScale));
  2243.                         keyPresses = new Array();
  2244.                         syncPoints = new Array();
  2245.                         cannonballs = new Array();
  2246.                         if (playingReplay) {
  2247.                             replay.syncPointIndex = 0;
  2248.                             replay.cameraMovementIndex = 0;
  2249.                             replay.keyPressIndex = 0;
  2250.                             if (replay.syncPoints.length > 0) {
  2251.                                 replaySplineXs = ComputeReplaySplines(0);
  2252.                                 replaySplineYs = ComputeReplaySplines(1);
  2253.                                 replaySplineAngles = ComputeReplaySplines(2);
  2254.                             }
  2255.                         }
  2256.                         simStarted = true;
  2257.                         autoPanning = true;
  2258.                         canSaveReplay = true;
  2259.                         for (var i:int = 0; i < allParts.length; i++) {
  2260.                             allParts[i].checkedCollisionGroup = false;
  2261.                         }
  2262.                         for (i = 0; i < allParts.length; i++) {
  2263.                             if (allParts[i] is ShapePart) allParts[i].SetCollisionGroup(-(i + 1));
  2264.                         }
  2265.                        
  2266.                         CreateWorld();
  2267.    
  2268.                         for (i = allParts.length; i >= 0; i--) {
  2269.                             if (allParts[i] is ShapePart || allParts[i] is TextPart) allParts[i].Init(m_world);
  2270.                         }
  2271.                         collisionGroup = 0x0001;
  2272.                         for (i = 0; i < allParts.length; i++) {
  2273.                             if (allParts[i] is PrismaticJoint) collisionGroup *= 2;
  2274.                             if (allParts[i] is JointPart || allParts[i] is Thrusters) allParts[i].Init(m_world);
  2275.                         }
  2276.                        
  2277.                         cameraPart = null;
  2278.                         for (i = 0; i < allParts.length; i++) {
  2279.                             if (allParts[i] is ShapePart && allParts[i].isCameraFocus && allParts[i].isEnabled) cameraPart = allParts[i];
  2280.                         }
  2281.                         if (!cameraPart) cameraPart = FindCenterOfRobot();
  2282.                         savedDrawXOff = Screen2WorldX(ZOOM_FOCUS_X);
  2283.                         savedDrawYOff = Screen2WorldY(ZOOM_FOCUS_Y);
  2284.                     }
  2285.                 } else {
  2286.                     m_fader.visible = true;
  2287.                     if (!partsFit) ShowDialog3("You must fit your robot inside the starting box first!");
  2288.                     else if (tooManyShapes) ShowDialog3("Your robot contains too many shapes!  (Limit 500)");
  2289.                     m_progressDialog.ShowOKButton();
  2290.                     m_progressDialog.StopTimer();
  2291.                 }
  2292.             }
  2293.         }
  2294.        
  2295.         public virtual function editButton(e:MouseEvent, confirmed:Boolean = false):void {
  2296.            
  2297.         }
  2298.        
  2299.         public function pauseButton(e:MouseEvent):void {
  2300.             if (playingReplay && replay.Update(frameCounter)) ShowPostReplayWindow();
  2301.             m_guiPanel.ShowPausePanel(!playingReplay);
  2302.             paused = true;
  2303.         }
  2304.        
  2305.         public virtual function resetButton(e:MouseEvent, rateRobot:Boolean = true):void {
  2306.             if (playingReplay) {
  2307.                 for (var i:int = 0; i < allParts.length; i++) {
  2308.                     allParts[i].UnInit(m_world);
  2309.                 }
  2310.                 simStarted = false;
  2311.                 playButton(e, false);
  2312.             } else {
  2313.                 m_guiPanel.ShowEditPanel();
  2314.                 paused = true;
  2315.                 simStarted = false;
  2316.                 playingReplay = false;
  2317.                 for (i = 0; i < allParts.length; i++) {
  2318.                     allParts[i].UnInit(m_world);
  2319.                 }
  2320.                 draw.m_drawXOff = savedDrawXOff * m_physScale - ZOOM_FOCUS_X;
  2321.                 draw.m_drawYOff = savedDrawYOff * m_physScale - ZOOM_FOCUS_Y;
  2322.                 hasPanned = true;
  2323.                 if (rateRobot) {
  2324.                     if (curChallengeID != "" && curChallengePublic && !ratedCurChallenge && !LSOManager.HasRatedChallenge(curChallengeID)) {
  2325.                         ratedCurChallenge = true;
  2326.                         if (m_rateDialog) removeChild(m_rateDialog);
  2327.                         m_rateDialog = new RateWindow(this, 2, 0, true);
  2328.                         addChild(m_rateDialog);
  2329.                         m_fader.visible = true;
  2330.                     } else if (curRobotID != "" && curRobotPublic && !ratedCurRobot && !LSOManager.HasRatedRobot(curRobotID)) {
  2331.                         ratedCurRobot = true;
  2332.                         if (m_rateDialog) removeChild(m_rateDialog);
  2333.                         m_rateDialog = new RateWindow(this, 0, 0, true);
  2334.                         addChild(m_rateDialog);
  2335.                         m_fader.visible = true;
  2336.                         paused = true;
  2337.                     }
  2338.                 }
  2339.             }
  2340.             wonChallenge = false;
  2341.             redrawBuildArea = true;
  2342.         }
  2343.        
  2344.         public virtual function rewindButton(e:MouseEvent, makeThemRate:Boolean = true):void {
  2345.             if (!playingReplay) {
  2346.                 resetButton(e, false);
  2347.                 playButton(e);
  2348.             } else if (viewingUnsavedReplay) {
  2349.                 paused = true;
  2350.                 simStarted = false;
  2351.                 playingReplay = false;
  2352.                 wonChallenge = false;
  2353.                 viewingUnsavedReplay = false;
  2354.                 m_guiPanel.ShowEditPanel(true);
  2355.                 for (var i:int = 0; i < allParts.length; i++) {
  2356.                     allParts[i].UnInit(m_world);
  2357.                 }
  2358.                 draw.m_drawXOff = savedDrawXOff * m_physScale - ZOOM_FOCUS_X;
  2359.                 draw.m_drawYOff = savedDrawYOff * m_physScale - ZOOM_FOCUS_Y;
  2360.                 hasPanned = true;
  2361.                 redrawBuildArea = true;
  2362.             } else {
  2363.                 if (makeThemRate && curReplayID != "" && !ratedCurReplay && curReplayPublic && !LSOManager.HasRatedReplay(curReplayID)) {
  2364.                     ratedCurReplay = true;
  2365.                     if (m_rateDialog) removeChild(m_rateDialog);
  2366.                     m_rateDialog = new RateWindow(this, 1, 5);
  2367.                     addChild(m_rateDialog);
  2368.                     m_fader.visible = true;
  2369.                 } else {
  2370.                     Main.changeControllers = true;
  2371.                     playingReplay = false;
  2372.                     showTutorial = false;
  2373.                     replayParts = new Array();
  2374.                     curRobotID = "";
  2375.                     curRobotEditable = true;
  2376.                     curReplayID = "";
  2377.                 }
  2378.             }
  2379.         }
  2380.        
  2381.         public function reportButton(e:MouseEvent):void {
  2382.             if (selectingCondition) return;
  2383.             if (playingReplay && curReplayID != "" && curReplayPublic) {
  2384.                 if (userName == "_Public") {
  2385.                     clickedReport = true;
  2386.                     loginButton(e, true, false);
  2387.                 } else {
  2388.                     if (m_reportWindow) removeChild(m_reportWindow);
  2389.                     m_reportWindow = new ReportWindow(this, 1, curReplayID);
  2390.                     addChild(m_reportWindow);
  2391.                     m_fader.visible = true;
  2392.                     m_guiPanel.ShowPausePanel(!playingReplay);
  2393.                     paused = true;
  2394.                 }
  2395.             } else if (curChallengeID != "" && curChallengePublic) {
  2396.                 if (userName == "_Public") {
  2397.                     clickedReport = true;
  2398.                     loginButton(e, true, false);
  2399.                 } else {
  2400.                     if (m_reportWindow) removeChild(m_reportWindow);
  2401.                     m_reportWindow = new ReportWindow(this, 2, curChallengeID);
  2402.                     addChild(m_reportWindow);
  2403.                     m_fader.visible = true;
  2404.                     m_guiPanel.ShowPausePanel(!playingReplay);
  2405.                     paused = true;
  2406.                 }
  2407.             } else if (curRobotID != "" && curRobotPublic) {
  2408.                 if (userName == "_Public") {
  2409.                     clickedReport = true;
  2410.                     loginButton(e, true, false);
  2411.                 } else {
  2412.                     if (m_reportWindow) removeChild(m_reportWindow);
  2413.                     m_reportWindow = new ReportWindow(this, 0, curRobotID);
  2414.                     addChild(m_reportWindow);
  2415.                     m_fader.visible = true;
  2416.                     m_guiPanel.ShowPausePanel(!playingReplay);
  2417.                     paused = true;
  2418.                 }
  2419.             } else {
  2420.                 m_fader.visible = true;
  2421.                 ShowDialog3("You can only report publicly saved robots.");
  2422.                 m_progressDialog.ShowOKButton();
  2423.                 m_progressDialog.StopTimer();
  2424.             }
  2425.         }
  2426.        
  2427.         public function finishReporting(e:Event):void {
  2428.             var threadID:int = Database.FinishReporting(e);
  2429.             if (threadID != -1) {
  2430.                 ShowDialog3("Thank you, the moderators have been notified.");
  2431.                 m_progressDialog.ShowOKButton();
  2432.                 m_progressDialog.StopTimer();
  2433.                 Main.ShowMouse();
  2434.             }
  2435.         }
  2436.        
  2437.         public function featureButton(e:MouseEvent):void {
  2438.             if (selectingCondition) return;
  2439.             if (playingReplay && curReplayID != "" && curReplayPublic) {
  2440.                 Database.FeatureReplay(curReplayID, !curReplayFeatured, finishFeaturing);
  2441.                 m_fader.visible = true;
  2442.                 ShowDialog("Featuring...");
  2443.                 Main.ShowHourglass();
  2444.             } else if (curChallengeID != "" && curChallengePublic) {
  2445.                 Database.FeatureChallenge(curChallengeID, !curChallengeFeatured, finishFeaturing);
  2446.                 m_fader.visible = true;
  2447.                 ShowDialog("Featuring...");
  2448.                 Main.ShowHourglass();
  2449.             } else if (curRobotID != "" && curRobotPublic) {
  2450.                 Database.FeatureRobot(curRobotID, !curRobotFeatured, finishFeaturing);
  2451.                 m_fader.visible = true;
  2452.                 ShowDialog("Featuring...");
  2453.                 Main.ShowHourglass();
  2454.             } else {
  2455.                 m_fader.visible = true;
  2456.                 ShowDialog3("You can only feature publicly saved robots.");
  2457.                 m_progressDialog.ShowOKButton();
  2458.                 m_progressDialog.StopTimer();
  2459.             }
  2460.         }
  2461.        
  2462.         private function finishFeaturing(e:Event):void {
  2463.             var retVal:Boolean = Database.FinishFeaturing(e);
  2464.             if (retVal) {
  2465.                 m_progressDialog.SetMessage("Success!");
  2466.                 m_progressDialog.HideInXSeconds(1);
  2467.                 m_fader.visible = false;
  2468.                 Main.ShowMouse();
  2469.                 if (playingReplay) curReplayFeatured = !curReplayFeatured;
  2470.                 else if (curChallengeID != "") curChallengeFeatured = !curChallengeFeatured;
  2471.                 else curRobotFeatured = !curRobotFeatured;
  2472.             }
  2473.         }
  2474.        
  2475.         public function rateButton(e:MouseEvent):void {
  2476.             if (selectingCondition) return;
  2477.             if (curRobotID != "" && curRobotPublic && !LSOManager.HasRatedRobot(curRobotID)) {
  2478.                 m_fader.visible = true;
  2479.                 if (m_rateDialog) removeChild(m_rateDialog);
  2480.                 m_rateDialog = new RateWindow(this, 0);
  2481.                 addChild(m_rateDialog);
  2482.             } else if (curRobotID == "" || !curRobotPublic) {
  2483.                 m_fader.visible = true;
  2484.                 ShowDialog3("You need to save your robot publicly first!");
  2485.                 m_progressDialog.ShowOKButton();
  2486.                 m_progressDialog.StopTimer();
  2487.             } else {
  2488.                 m_fader.visible = true;
  2489.                 ShowDialog3("You've already rated this robot!");
  2490.                 m_progressDialog.ShowOKButton();
  2491.                 m_progressDialog.StopTimer();
  2492.             }
  2493.         }
  2494.        
  2495.         public function rateWindowClosed(rating:int, redirect:int):void {
  2496.             m_rateDialog.visible = false;
  2497.             if (playingReplay && curReplayID != "" && curReplayPublic) {
  2498.                 Database.RateReplay(curReplayID, rating, finishRatingReplay);
  2499.             } else if (curChallengeID != "" && curChallengePublic) {
  2500.                 Database.RateChallenge(curChallengeID, rating, finishRatingChallenge);
  2501.             } else {
  2502.                 Database.RateRobot(curRobotID, rating, finishRatingRobot);
  2503.             }
  2504.             redirectAfterRating = redirect;
  2505.             m_fader.visible = true;
  2506.             ShowDialog("Rating...");
  2507.             Main.ShowHourglass();
  2508.             curAction = -1;
  2509.         }
  2510.        
  2511.         public function conditionsButton(e:MouseEvent):void {
  2512.             curAction = -1;
  2513.             boxText.visible = false;
  2514.             horizLineText.visible = false;
  2515.             vertLineText.visible = false;
  2516.             shapeText.visible = false;
  2517.             m_sidePanel.visible = false;
  2518.             if (m_conditionsDialog) removeChild(m_conditionsDialog);
  2519.             m_conditionsDialog = new ConditionsWindow(this as ControllerChallenge);
  2520.             addChild(m_conditionsDialog);
  2521.             m_fader.visible = true;
  2522.         }
  2523.  
  2524.         public function restrictionsButton(e:MouseEvent):void {
  2525.             if (selectingCondition) return;
  2526.             m_sidePanel.visible = false;
  2527.             if (m_restrictionsDialog) removeChild(m_restrictionsDialog);
  2528.             m_restrictionsDialog = new RestrictionsWindow(this as ControllerChallenge);
  2529.             addChild(m_restrictionsDialog);
  2530.             m_fader.visible = true;
  2531.             saveAfterRestrictions = false;
  2532.         }
  2533.  
  2534.         public function buildBoxButton(e:MouseEvent):void {
  2535.             if (selectingCondition) return;
  2536.             /*if (ControllerChallenge.challenge.buildAreas.length != 0) {
  2537.                 m_fader.visible = true;
  2538.                 if (m_progressDialog) removeChild(m_progressDialog);
  2539.                 m_progressDialog = new DialogWindow(this, "One or more build boxes already exists.  Would you like to keep them or delete them?", true, false, true);
  2540.                 m_progressDialog.ShowBuildBoxButtons();
  2541.                 addChild(m_progressDialog);
  2542.             }*/
  2543.             curAction = DRAWING_BUILD_BOX;
  2544.             actionStep = 0;
  2545.         }
  2546.        
  2547.         public function sandboxSettingsButton(e:MouseEvent):void {
  2548.             if (!curRobotEditable || selectingCondition) return;
  2549.             if (!simStarted) {
  2550.                 if (this is ControllerSandbox && (!(this is ControllerChallenge) || !ControllerChallenge.playOnlyMode)) {
  2551.                     m_sandboxWindow = new AdvancedSandboxWindow(this, ControllerSandbox.settings);
  2552.                     m_fader.visible = true;
  2553.                     addChild(m_sandboxWindow);
  2554.                 } else {
  2555.                     m_fader.visible = true;
  2556.                     ShowDialog3("That feature is only available in Sandbox mode!");
  2557.                     m_progressDialog.ShowOKButton();
  2558.                     m_progressDialog.StopTimer();
  2559.                 }
  2560.             }
  2561.         }
  2562.        
  2563.         public virtual override function commentButton(e:MouseEvent, robotID:String = "", robotPublic:Boolean = false):void {
  2564.             if (selectingCondition) return;
  2565.             if (robotID == "") {
  2566.                 robotID = curRobotID;
  2567.                 robotPublic = curRobotPublic;
  2568.             }
  2569.             if (robotID != "" && robotPublic) {
  2570.                 Database.CommentOnRobot(robotID, finishCommenting);
  2571.                 m_fader.visible = true;
  2572.                 ShowDialog("Connecting to forum...");
  2573.                 Main.ShowHourglass();
  2574.                 curAction = -1;
  2575.             } else {
  2576.                 m_fader.visible = true;
  2577.                 ShowDialog3("You need to save your robot publicly first!");
  2578.                 m_progressDialog.ShowOKButton();
  2579.                 m_progressDialog.StopTimer();
  2580.             }
  2581.         }
  2582.  
  2583.         public function finishCommenting(e:Event):void {
  2584.             if (!Database.waitingForResponse || (Database.curTransactionType != Database.ACTION_COMMENT_ROBOT && Database.curTransactionType != Database.ACTION_COMMENT_REPLAY)) return;
  2585.             var threadID:int = Database.FinishCommenting(e);
  2586.             if (threadID != -1) {
  2587.                 if (m_chooserWindow && m_chooserWindow.visible) m_chooserWindow.HideFader();
  2588.                 else m_fader.visible = false;
  2589.                 m_progressDialog.visible = false;
  2590.                 Main.BrowserRedirect("http://www.incredibots.com/forums/posting.php?mode=reply&t=" + threadID + (userName == "_Public" ? "" : "&sid=" + sessionID), true);
  2591.                 Main.ShowMouse();
  2592.             }
  2593.         }
  2594.        
  2595.         public function finishRatingRobot(e:Event):void {
  2596.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_RATE_ROBOT) return;
  2597.             var retVal:Boolean = Database.FinishRating(e);
  2598.             if (retVal) {
  2599.                 LSOManager.SetRobotRated(curRobotID);
  2600.                 m_progressDialog.SetMessage("Success!");
  2601.                 m_progressDialog.HideInXSeconds(1);
  2602.                 if (m_postReplayWindow && m_postReplayWindow.visible) m_postReplayWindow.HideFader();
  2603.                 else m_fader.visible = false;
  2604.                 m_rateDialog.visible = false;
  2605.                 Main.ShowMouse();
  2606.             }
  2607.             if (redirectAfterRating == 1) {
  2608.                 loadButton(new MouseEvent(""));
  2609.             } else if (redirectAfterRating == 2) {
  2610.                 loadRobotButton(new MouseEvent(""));               
  2611.             } else if (redirectAfterRating == 3) {
  2612.                 loadReplayButton(new MouseEvent(""));              
  2613.             } else if (redirectAfterRating == 4) {
  2614.                 loadChallengeButton(new MouseEvent(""));               
  2615.             } else if (redirectAfterRating == 5) {
  2616.                 rewindButton(new MouseEvent(""));              
  2617.             }
  2618.             redirectAfterRating = 0;
  2619.         }
  2620.  
  2621.         public function finishRatingReplay(e:Event):void {
  2622.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_RATE_REPLAY) return;
  2623.             var retVal:Boolean = Database.FinishRating(e);
  2624.             if (retVal) {
  2625.                 LSOManager.SetReplayRated(curReplayID);
  2626.                 m_progressDialog.SetMessage("Success!");
  2627.                 m_progressDialog.HideInXSeconds(1);
  2628.                 if (m_postReplayWindow && m_postReplayWindow.visible) m_postReplayWindow.HideFader();
  2629.                 else m_fader.visible = false;
  2630.                 m_rateDialog.visible = false;
  2631.                 Main.ShowMouse();
  2632.             }
  2633.             if (redirectAfterRating == 1) {
  2634.                 loadButton(new MouseEvent(""));
  2635.             } else if (redirectAfterRating == 2) {
  2636.                 loadRobotButton(new MouseEvent(""));               
  2637.             } else if (redirectAfterRating == 3) {
  2638.                 loadReplayButton(new MouseEvent(""));              
  2639.             } else if (redirectAfterRating == 4) {
  2640.                 loadChallengeButton(new MouseEvent(""));               
  2641.             } else if (redirectAfterRating == 5) {
  2642.                 rewindButton(new MouseEvent(""));              
  2643.             }
  2644.             redirectAfterRating = 0;
  2645.         }
  2646.  
  2647.         public function finishRatingChallenge(e:Event):void {
  2648.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_RATE_CHALLENGE) return;
  2649.             var retVal:Boolean = Database.FinishRating(e);
  2650.             if (retVal) {
  2651.                 LSOManager.SetChallengeRated(curChallengeID);
  2652.                 m_progressDialog.SetMessage("Success!");
  2653.                 m_progressDialog.HideInXSeconds(1);
  2654.                 if (m_postReplayWindow && m_postReplayWindow.visible) m_postReplayWindow.HideFader();
  2655.                 else m_fader.visible = false;
  2656.                 m_rateDialog.visible = false;
  2657.                 Main.ShowMouse();
  2658.             }
  2659.             if (redirectAfterRating == 1) {
  2660.                 loadButton(new MouseEvent(""));
  2661.             } else if (redirectAfterRating == 2) {
  2662.                 loadRobotButton(new MouseEvent(""));               
  2663.             } else if (redirectAfterRating == 3) {
  2664.                 loadReplayButton(new MouseEvent(""));              
  2665.             } else if (redirectAfterRating == 4) {
  2666.                 loadChallengeButton(new MouseEvent(""));               
  2667.             } else if (redirectAfterRating == 5) {
  2668.                 rewindButton(new MouseEvent(""));              
  2669.             }
  2670.             redirectAfterRating = 0;
  2671.         }
  2672.        
  2673.         public virtual override function embedButton(e:MouseEvent, robotID:String = "", robotPublic:Boolean = false):void {
  2674.             if (selectingCondition) return;
  2675.             if (robotID == "") {
  2676.                 robotID = curRobotID;
  2677.                 robotPublic = curRobotPublic;
  2678.             }
  2679.             if (robotID != "" && robotPublic) {
  2680.                 m_fader.visible = true;
  2681.                 ShowLinkDialog("Copy the HTML below into your\n  website to embed this robot.", null, false, robotID);
  2682.             } else {
  2683.                 m_fader.visible = true;
  2684.                 ShowDialog3("You need to save your robot publicly first!");
  2685.                 m_progressDialog.ShowOKButton();
  2686.                 m_progressDialog.StopTimer();
  2687.             }
  2688.         }
  2689.        
  2690.         public virtual override function linkButton(e:MouseEvent, robotID:String = "", robotPublic:Boolean = false):void {
  2691.             if (selectingCondition) return;
  2692.             if (robotID == "") {
  2693.                 robotID = curRobotID;
  2694.                 robotPublic = curRobotPublic;
  2695.             }
  2696.             if (robotID != "" && robotPublic) {
  2697.                 m_fader.visible = true;
  2698.                 ShowLinkDialog("     Use the link below to\n        link to this robot.", "http://incredibots2.com/?robotID=" + robotID);
  2699.             } else {
  2700.                 m_fader.visible = true;
  2701.                 ShowDialog3("You need to save your robot publicly first!");
  2702.                 m_progressDialog.ShowOKButton();
  2703.                 m_progressDialog.StopTimer();
  2704.             }
  2705.         }
  2706.        
  2707.         public function rateReplayButton(e:MouseEvent):void {
  2708.             if (selectingCondition) return;
  2709.             if (curReplayID != "" && curReplayPublic && !LSOManager.HasRatedReplay(curReplayID)) {
  2710.                 m_fader.visible = true;
  2711.                 if (m_rateDialog) removeChild(m_rateDialog);
  2712.                 m_rateDialog = new RateWindow(this, 1);
  2713.                 addChild(m_rateDialog);
  2714.             } else if (curReplayID == "" || !curReplayPublic) {
  2715.                 m_fader.visible = true;
  2716.                 ShowDialog3("You need to save your replay publicly first!");
  2717.                 m_progressDialog.ShowOKButton();
  2718.                 m_progressDialog.StopTimer();
  2719.             } else {
  2720.                 m_fader.visible = true;
  2721.                 ShowDialog3("You've already rated this replay!");
  2722.                 m_progressDialog.ShowOKButton();
  2723.                 m_progressDialog.StopTimer();
  2724.             }
  2725.         }
  2726.        
  2727.         public virtual override function commentReplayButton(e:MouseEvent, replayID:String = "", replayPublic:Boolean = false):void {
  2728.             if (replayID == "") {
  2729.                 replayID = curReplayID;
  2730.                 replayPublic = curReplayPublic;
  2731.             }
  2732.             if (replayID != "" && replayPublic) {
  2733.                 Database.CommentOnReplay(replayID, finishCommenting);
  2734.                 m_fader.visible = true;
  2735.                 ShowDialog("Connecting to forum...");
  2736.                 Main.ShowHourglass();
  2737.                 curAction = -1;
  2738.             } else {
  2739.                 m_fader.visible = true;
  2740.                 ShowDialog3("You need to save your replay publicly first!");
  2741.                 m_progressDialog.ShowOKButton();
  2742.                 m_progressDialog.StopTimer();
  2743.             }
  2744.         }
  2745.        
  2746.         public virtual override function embedReplayButton(e:MouseEvent, replayID:String = "", replayPublic:Boolean = false):void {
  2747.             if (replayID == "") {
  2748.                 replayID = curReplayID;
  2749.                 replayPublic = curReplayPublic;
  2750.             }
  2751.             if (replayID != "" && replayPublic) {
  2752.                 m_fader.visible = true;
  2753.                 ShowLinkDialog("Copy the HTML below into your\n  website to embed this replay.", null, true, replayID);
  2754.             } else {
  2755.                 m_fader.visible = true;
  2756.                 ShowDialog3("You need to save your replay publicly first!");
  2757.                 m_progressDialog.ShowOKButton();
  2758.                 m_progressDialog.StopTimer();
  2759.             }
  2760.         }
  2761.  
  2762.         public virtual override function linkReplayButton(e:MouseEvent, replayID:String = "", replayPublic:Boolean = false):void {
  2763.             if (replayID == "") {
  2764.                 replayID = curReplayID;
  2765.                 replayPublic = curReplayPublic;
  2766.             }
  2767.             if (replayID != "" && replayPublic) {
  2768.                 m_fader.visible = true;
  2769.                 ShowLinkDialog("     Use the link below to\n       link to this replay.", "http://incredibots2.com/?replayID=" + replayID);
  2770.             } else {
  2771.                 m_fader.visible = true;
  2772.                 ShowDialog3("You need to save your replay publicly first!");
  2773.                 m_progressDialog.ShowOKButton();
  2774.                 m_progressDialog.StopTimer();
  2775.             }
  2776.         }
  2777.  
  2778.         public function rateChallengeButton(e:MouseEvent):void {
  2779.             if (selectingCondition) return;
  2780.             if (curChallengeID != "" && curChallengePublic && !LSOManager.HasRatedChallenge(curChallengeID)) {
  2781.                 m_fader.visible = true;
  2782.                 if (m_rateDialog) removeChild(m_rateDialog);
  2783.                 m_rateDialog = new RateWindow(this, 2);
  2784.                 addChild(m_rateDialog);
  2785.             } else if (curChallengeID == "" || !curChallengePublic) {
  2786.                 m_fader.visible = true;
  2787.                 ShowDialog3("You need to save your challenge publicly first!");
  2788.                 m_progressDialog.ShowOKButton();
  2789.                 m_progressDialog.StopTimer();
  2790.             } else {
  2791.                 m_fader.visible = true;
  2792.                 ShowDialog3("You've already rated this challenge!");
  2793.                 m_progressDialog.ShowOKButton();
  2794.                 m_progressDialog.StopTimer();
  2795.             }
  2796.         }
  2797.  
  2798.         public virtual override function commentChallengeButton(e:MouseEvent, challengeID:String = "", challengePublic:Boolean = false):void {
  2799.             if (selectingCondition) return;
  2800.             if (challengeID == "") {
  2801.                 challengeID = curChallengeID;
  2802.                 challengePublic = curChallengePublic;
  2803.             }
  2804.             if (challengeID != "" && challengePublic) {
  2805.                 Database.CommentOnChallenge(challengeID, finishCommenting);
  2806.                 m_fader.visible = true;
  2807.                 ShowDialog("Connecting to forum...");
  2808.                 Main.ShowHourglass();
  2809.                 curAction = -1;
  2810.             } else {
  2811.                 m_fader.visible = true;
  2812.                 ShowDialog3("You need to save your challenge publicly first!");
  2813.                 m_progressDialog.ShowOKButton();
  2814.                 m_progressDialog.StopTimer();
  2815.             }
  2816.         }
  2817.        
  2818.         public virtual override function embedChallengeButton(e:MouseEvent, challengeID:String = "", challengePublic:Boolean = false):void {
  2819.             if (selectingCondition) return;
  2820.             if (challengeID == "") {
  2821.                 challengeID = curChallengeID;
  2822.                 challengePublic = curChallengePublic;
  2823.             }
  2824.             if (challengeID != "" && challengePublic) {
  2825.                 m_fader.visible = true;
  2826.                 ShowLinkDialog("Copy the HTML below into your\n  website to embed this challenge.", null, false, challengeID, true);
  2827.             } else {
  2828.                 m_fader.visible = true;
  2829.                 ShowDialog3("You need to save your challenge publicly first!");
  2830.                 m_progressDialog.ShowOKButton();
  2831.                 m_progressDialog.StopTimer();
  2832.             }
  2833.         }
  2834.  
  2835.         public virtual override function linkChallengeButton(e:MouseEvent, challengeID:String = "", challengePublic:Boolean = false):void {
  2836.             if (selectingCondition) return;
  2837.             if (challengeID == "") {
  2838.                 challengeID = curChallengeID;
  2839.                 challengePublic = curChallengePublic;
  2840.             }
  2841.             if (challengeID != "" && challengePublic) {
  2842.                 m_fader.visible = true;
  2843.                 ShowLinkDialog("     Use the link below to\n       link to this challenge.", "http://incredibots2.com/?challengeID=" + challengeID);
  2844.             } else {
  2845.                 m_fader.visible = true;
  2846.                 ShowDialog3("You need to save your challenge publicly first!");
  2847.                 m_progressDialog.ShowOKButton();
  2848.                 m_progressDialog.StopTimer();
  2849.             }
  2850.         }
  2851.        
  2852.         public virtual function tutorialButton(e:MouseEvent):void {
  2853.             if (m_tutorialDialog) {
  2854.                 m_tutorialDialog.visible = true;
  2855.                 m_tutorialDialog.ResetPosition();
  2856.             }
  2857.         }
  2858.        
  2859.         public virtual function rotateButton(e:MouseEvent):void {
  2860.             if (!curRobotEditable) return;
  2861.             for (var i:int = selectedParts.length - 1; i >= 0; i--) {
  2862.                 if (selectedParts[i] is TextPart) {
  2863.                     selectedParts = Util.RemoveFromArray(selectedParts[i], selectedParts);
  2864.                 }
  2865.             }
  2866.             if (selectedParts.length == 0) return;
  2867.             curAction = ROTATE;
  2868.             rotatingPart = null;
  2869.             for (i = 0; i < selectedParts.length; i++) {
  2870.                 if ((selectedParts[i] is ShapePart && (!rotatingPart || (rotatingPart is Thrusters) || selectedParts[i].GetMass() > rotatingPart.GetMass())) || (selectedParts[i] is Thrusters && !rotatingPart)) {
  2871.                     rotatingPart = selectedParts[i];
  2872.                 }
  2873.             }
  2874.             if (rotatingPart != null) {
  2875.                 rotatingParts = new Array();
  2876.                 if (selectedParts.length == 1 && rotatingPart is Thrusters) {
  2877.                     rotatingParts.push(rotatingPart);
  2878.                 } else {
  2879.                     for (i = 0; i < selectedParts.length; i++) {
  2880.                         rotatingParts = rotatingParts.concat(selectedParts[i].GetAttachedParts());
  2881.                     }
  2882.                     rotatingParts = Util.RemoveDuplicates(rotatingParts);
  2883.                 }
  2884.                 for (i = 0; i < rotatingParts.length; i++) {
  2885.                     if (rotatingParts[i] is ShapePart || rotatingParts[i] is Thrusters) {
  2886.                         rotatingParts[i].rotateAngle = Math.atan2(rotatingParts[i].centerY - rotatingPart.centerY, rotatingParts[i].centerX - rotatingPart.centerX);
  2887.                         rotatingParts[i].rotateOrientation = rotatingParts[i].angle;
  2888.                     } else {
  2889.                         rotatingParts[i].rotateAngle = Math.atan2(rotatingParts[i].anchorY - rotatingPart.centerY, rotatingParts[i].anchorX - rotatingPart.centerX);
  2890.                         if (rotatingParts[i] is PrismaticJoint) {
  2891.                             rotatingParts[i].rotateOrientation = Util.GetAngle(rotatingParts[i].axis);
  2892.                         }
  2893.                     }
  2894.                 }
  2895.                 initRotatingAngle = Math.atan2(mouseYWorldPhys - rotatingPart.centerY, mouseXWorldPhys - rotatingPart.centerX);
  2896.             }
  2897.         }
  2898.        
  2899.         public function mirrorHorizontal(e:MouseEvent):void {
  2900.             if (/*Main.premiumMode*/ true) {
  2901.                 if (!curRobotEditable || selectingCondition) return;
  2902.                 if (simStarted) return;
  2903.                 if (selectedParts.length == 0) return;
  2904.                 var newParts:Array = new Array();
  2905.                 var centerX:Number = (selectedParts[0] is JointPart ? selectedParts[0].anchorX : (selectedParts[0] is TextPart ? selectedParts[0].x + selectedParts[0].w / 2 : selectedParts[0].centerX));
  2906.                 var centerY:Number = (selectedParts[0] is JointPart ? selectedParts[0].anchorY : (selectedParts[0] is TextPart ? selectedParts[0].y + selectedParts[0].h / 2 : selectedParts[0].centerY));
  2907.                 var partMapping:Array = new Array();
  2908.                 for (var i:int = 0; i < selectedParts.length; i++) {
  2909.                     if (selectedParts[i] is Circle) {
  2910.                         var c:Circle = new Circle(centerX - (selectedParts[i].centerX - centerX), selectedParts[i].centerY, selectedParts[i].radius);
  2911.                         c.angle = Math.PI - selectedParts[i].angle;
  2912.                         c.isStatic = selectedParts[i].isStatic;
  2913.                         c.density = selectedParts[i].density;
  2914.                         c.collide = selectedParts[i].collide;
  2915.                         c.red = selectedParts[i].red;
  2916.                         c.green = selectedParts[i].green;
  2917.                         c.blue = selectedParts[i].blue;
  2918.                         c.opacity = selectedParts[i].opacity;
  2919.                         c.outline = selectedParts[i].outline;
  2920.                         c.terrain = selectedParts[i].terrain;
  2921.                         c.undragable = selectedParts[i].undragable;
  2922.                         newParts.push(c);
  2923.                         partMapping.push(c);
  2924.                     } else if (selectedParts[i] is Rectangle) {
  2925.                         var r:Rectangle = new Rectangle(centerX - (selectedParts[i].x - centerX), selectedParts[i].y, -selectedParts[i].w, selectedParts[i].h);
  2926.                         r.angle = Math.PI - selectedParts[i].angle;
  2927.                         r.isStatic = selectedParts[i].isStatic;
  2928.                         r.density = selectedParts[i].density;
  2929.                         r.collide = selectedParts[i].collide;
  2930.                         r.red = selectedParts[i].red;
  2931.                         r.green = selectedParts[i].green;
  2932.                         r.blue = selectedParts[i].blue;
  2933.                         r.opacity = selectedParts[i].opacity;
  2934.                         r.outline = selectedParts[i].outline;
  2935.                         r.terrain = selectedParts[i].terrain;
  2936.                         r.undragable = selectedParts[i].undragable;
  2937.                         newParts.push(r);
  2938.                         partMapping.push(r);
  2939.                     } else if (selectedParts[i] is Triangle) {
  2940.                         var verts:Array = selectedParts[i].GetVertices();
  2941.                         var t:Triangle = new Triangle(centerX - (verts[0].x - centerX), verts[0].y, centerX - (verts[1].x - centerX), verts[1].y, centerX - (verts[2].x - centerX), verts[2].y);
  2942.                         t.isStatic = selectedParts[i].isStatic;
  2943.                         t.density = selectedParts[i].density;
  2944.                         t.collide = selectedParts[i].collide;
  2945.                         t.red = selectedParts[i].red;
  2946.                         t.green = selectedParts[i].green;
  2947.                         t.blue = selectedParts[i].blue;
  2948.                         t.opacity = selectedParts[i].opacity;
  2949.                         t.outline = selectedParts[i].outline;
  2950.                         t.terrain = selectedParts[i].terrain;
  2951.                         t.undragable = selectedParts[i].undragable;
  2952.                         newParts.push(t);
  2953.                         partMapping.push(t);
  2954.                     } else if (selectedParts[i] is Cannon) {
  2955.                         var ca:Cannon = new Cannon(centerX - (selectedParts[i].x - centerX) - selectedParts[i].w, selectedParts[i].y, selectedParts[i].w);
  2956.                         ca.angle = Math.PI - selectedParts[i].angle;
  2957.                         ca.isStatic = selectedParts[i].isStatic;
  2958.                         ca.density = selectedParts[i].density;
  2959.                         ca.collide = selectedParts[i].collide;
  2960.                         ca.red = selectedParts[i].red;
  2961.                         ca.green = selectedParts[i].green;
  2962.                         ca.blue = selectedParts[i].blue;
  2963.                         ca.opacity = selectedParts[i].opacity;
  2964.                         ca.outline = selectedParts[i].outline;
  2965.                         ca.terrain = selectedParts[i].terrain;
  2966.                         ca.undragable = selectedParts[i].undragable;
  2967.                         ca.fireKey = selectedParts[i].fireKey;
  2968.                         ca.strength = selectedParts[i].strength;
  2969.                         newParts.push(ca);
  2970.                         partMapping.push(ca);
  2971.                     } else if (selectedParts[i] is TextPart) {
  2972.                         var te:TextPart = new TextPart(this, centerX - (selectedParts[i].x + selectedParts[i].w / 2 - centerX), selectedParts[i].y, selectedParts[i].w, selectedParts[i].h, selectedParts[i].text, selectedParts[i].inFront);
  2973.                         te.red = selectedParts[i].red;
  2974.                         te.green = selectedParts[i].green;
  2975.                         te.blue = selectedParts[i].blue;
  2976.                         te.size = selectedParts[i].size;
  2977.                         te.alwaysVisible = selectedParts[i].alwaysVisible;
  2978.                         te.inFront = selectedParts[i].inFront;
  2979.                         te.scaleWithZoom = selectedParts[i].scaleWithZoom;
  2980.                         te.displayKey = selectedParts[i].displayKey;
  2981.                         newParts.push(te);
  2982.                         partMapping.push(-1);
  2983.                     } else if (selectedParts[i] is JointPart || selectedParts[i] is Thrusters) {
  2984.                         partMapping.push(-1);
  2985.                     }
  2986.                 }
  2987.                 for (i = 0; i < selectedParts.length; i++) {
  2988.                     var index1:int = -1, index2:int = -1;
  2989.                     if (selectedParts[i] is JointPart) {
  2990.                         for (var j:int = 0; j < selectedParts.length; j++) {
  2991.                             if (selectedParts[j] == selectedParts[i].part1) index1 = j;
  2992.                             if (selectedParts[j] == selectedParts[i].part2) index2 = j;
  2993.                         }
  2994.                         if (index1 == -1 || index2 == -1) continue;
  2995.                     } else if (selectedParts[i] is Thrusters) {
  2996.                         for (j = 0; j < selectedParts.length; j++) {
  2997.                             if (selectedParts[j] == selectedParts[i].shape) index1 = j;
  2998.                         }
  2999.                         if (index1 == -1) continue;
  3000.                     }
  3001.                     if (selectedParts[i] is FixedJoint) {
  3002.                         var fj:FixedJoint = new FixedJoint(partMapping[index1], partMapping[index2], centerX - (selectedParts[i].anchorX - centerX), selectedParts[i].anchorY);
  3003.                         newParts.push(fj);
  3004.                     } else if (selectedParts[i] is RevoluteJoint) {
  3005.                         var rj:RevoluteJoint = new RevoluteJoint(partMapping[index1], partMapping[index2], centerX - (selectedParts[i].anchorX - centerX), selectedParts[i].anchorY);
  3006.                         rj.enableMotor = selectedParts[i].enableMotor;
  3007.                         rj.motorCWKey = selectedParts[i].motorCCWKey;
  3008.                         rj.motorCCWKey = selectedParts[i].motorCWKey;
  3009.                         rj.motorStrength = selectedParts[i].motorStrength;
  3010.                         rj.motorSpeed = selectedParts[i].motorSpeed;
  3011.                         rj.motorLowerLimit = -selectedParts[i].motorUpperLimit;
  3012.                         rj.motorUpperLimit = -selectedParts[i].motorLowerLimit;
  3013.                         rj.isStiff = selectedParts[i].isStiff;
  3014.                         rj.autoCW = selectedParts[i].autoCCW;
  3015.                         rj.autoCCW = selectedParts[i].autoCW;
  3016.                         newParts.push(rj);
  3017.                     } else if (selectedParts[i] is PrismaticJoint) {
  3018.                         var pj:PrismaticJoint = new PrismaticJoint(partMapping[index1], partMapping[index2], 0, 0, 1, 1);
  3019.                         pj.anchorX = centerX - (selectedParts[i].anchorX - centerX);
  3020.                         pj.anchorY = selectedParts[i].anchorY;
  3021.                         var axisAngle:Number = Math.atan2(selectedParts[i].axis.y, selectedParts[i].axis.x);
  3022.                         axisAngle = Util.NormalizeAngle(Math.PI - axisAngle);
  3023.                         pj.axis = new b2Vec2(Math.cos(axisAngle), Math.sin(axisAngle));
  3024.                         pj.axis.Normalize();
  3025.                         pj.initLength = selectedParts[i].initLength;
  3026.                         pj.enablePiston = selectedParts[i].enablePiston;
  3027.                         pj.pistonUpKey = selectedParts[i].pistonUpKey;
  3028.                         pj.pistonDownKey = selectedParts[i].pistonDownKey;
  3029.                         pj.pistonStrength = selectedParts[i].pistonStrength;
  3030.                         pj.pistonSpeed = selectedParts[i].pistonSpeed;
  3031.                         pj.isStiff = selectedParts[i].isStiff;
  3032.                         pj.autoOscillate = selectedParts[i].autoOscillate;
  3033.                         pj.red = selectedParts[i].red;
  3034.                         pj.green = selectedParts[i].green;
  3035.                         pj.blue = selectedParts[i].blue;
  3036.                         pj.opacity = selectedParts[i].opacity;
  3037.                         pj.outline = selectedParts[i].outline;
  3038.                         pj.collide = selectedParts[i].collide;
  3039.                         newParts.push(pj);
  3040.                     } else if (selectedParts[i] is Thrusters) {
  3041.                         var th:Thrusters = new Thrusters(partMapping[index1], centerX - (selectedParts[i].centerX - centerX), selectedParts[i].centerY);
  3042.                         th.angle = Math.PI - selectedParts[i].angle;
  3043.                         th.strength = selectedParts[i].strength;
  3044.                         th.thrustKey = selectedParts[i].thrustKey;
  3045.                         th.autoOn = selectedParts[i].autoOn;
  3046.                         newParts.push(th);
  3047.                     }
  3048.                 }
  3049.                 if (newParts.length > 0) {
  3050.                     selectedParts = new Array();
  3051.                     draggingParts = new Array();
  3052.                     for (i = 0; i < newParts.length; i++) {
  3053.                         newParts[i].dragXOff = centerX - (newParts[i] is JointPart ? newParts[i].anchorX : (newParts[i] is TextPart ? newParts[i].x - newParts[i].w / 2 : newParts[i].centerX));
  3054.                         newParts[i].dragYOff = centerY - (newParts[i] is JointPart ? newParts[i].anchorY : (newParts[i] is TextPart ? newParts[i].y - newParts[i].h / 2 : newParts[i].centerY));
  3055.                         selectedParts.push(newParts[i]);
  3056.                         draggingParts.push(newParts[i]);
  3057.                         allParts.push(newParts[i]);
  3058.                     }
  3059.                     initDragX = mouseXWorldPhys;
  3060.                     initDragY = mouseYWorldPhys;
  3061.                     draggingPart = selectedParts[0];
  3062.                     draggingPart.Move(mouseXWorldPhys, mouseYWorldPhys);
  3063.                     RefreshSidePanel();
  3064.                     AddAction(new MassCreateAction(selectedParts));
  3065.                     curAction = PASTE;
  3066.                     curRobotID = "";
  3067.                 }
  3068.             } else {
  3069.                 m_fader.visible = true;
  3070.                 ShowConfirmDialog("That feature is only available to IncrediBots supporters. Become an IncrediBots supporter?", 8);
  3071.             }
  3072.         }
  3073.        
  3074.         public function mirrorVertical(e:MouseEvent):void {
  3075.             if (/*Main.premiumMode*/ true) {
  3076.                 if (!curRobotEditable || selectingCondition) return;
  3077.                 if (simStarted) return;
  3078.                 if (selectedParts.length == 0) return;
  3079.                 var newParts:Array = new Array();
  3080.                 var centerX:Number = (selectedParts[0] is JointPart ? selectedParts[0].anchorX : (selectedParts[0] is TextPart ? selectedParts[0].x + selectedParts[0].w / 2 : selectedParts[0].centerX));
  3081.                 var centerY:Number = (selectedParts[0] is JointPart ? selectedParts[0].anchorY : (selectedParts[0] is TextPart ? selectedParts[0].y + selectedParts[0].h / 2 : selectedParts[0].centerY));
  3082.                 var partMapping:Array = new Array();
  3083.                 for (var i:int = 0; i < selectedParts.length; i++) {
  3084.                     if (selectedParts[i] is Circle) {
  3085.                         var c:Circle = new Circle(selectedParts[i].centerX, centerY - (selectedParts[i].centerY - centerY), selectedParts[i].radius);
  3086.                         c.angle = 2 * Math.PI - selectedParts[i].angle;
  3087.                         c.isStatic = selectedParts[i].isStatic;
  3088.                         c.density = selectedParts[i].density;
  3089.                         c.collide = selectedParts[i].collide;
  3090.                         c.red = selectedParts[i].red;
  3091.                         c.green = selectedParts[i].green;
  3092.                         c.blue = selectedParts[i].blue;
  3093.                         c.opacity = selectedParts[i].opacity;
  3094.                         c.outline = selectedParts[i].outline;
  3095.                         c.terrain = selectedParts[i].terrain;
  3096.                         c.undragable = selectedParts[i].undragable;
  3097.                         newParts.push(c);
  3098.                         partMapping.push(c);
  3099.                     } else if (selectedParts[i] is Rectangle) {
  3100.                         var r:Rectangle = new Rectangle(selectedParts[i].x, centerY - (selectedParts[i].y - centerY), selectedParts[i].w, -selectedParts[i].h);
  3101.                         r.angle = 2 * Math.PI - selectedParts[i].angle;
  3102.                         r.isStatic = selectedParts[i].isStatic;
  3103.                         r.density = selectedParts[i].density;
  3104.                         r.collide = selectedParts[i].collide;
  3105.                         r.red = selectedParts[i].red;
  3106.                         r.green = selectedParts[i].green;
  3107.                         r.blue = selectedParts[i].blue;
  3108.                         r.opacity = selectedParts[i].opacity;
  3109.                         r.outline = selectedParts[i].outline;
  3110.                         r.terrain = selectedParts[i].terrain;
  3111.                         r.undragable = selectedParts[i].undragable;
  3112.                         newParts.push(r);
  3113.                         partMapping.push(r);
  3114.                     } else if (selectedParts[i] is Triangle) {
  3115.                         var verts:Array = selectedParts[i].GetVertices();
  3116.                         var t:Triangle = new Triangle(verts[0].x, centerY - (verts[0].y - centerY), verts[1].x, centerY - (verts[1].y - centerY), verts[2].x, centerY - (verts[2].y - centerY));
  3117.                         t.isStatic = selectedParts[i].isStatic;
  3118.                         t.density = selectedParts[i].density;
  3119.                         t.collide = selectedParts[i].collide;
  3120.                         t.red = selectedParts[i].red;
  3121.                         t.green = selectedParts[i].green;
  3122.                         t.blue = selectedParts[i].blue;
  3123.                         t.opacity = selectedParts[i].opacity;
  3124.                         t.outline = selectedParts[i].outline;
  3125.                         t.terrain = selectedParts[i].terrain;
  3126.                         t.undragable = selectedParts[i].undragable;
  3127.                         newParts.push(t);
  3128.                         partMapping.push(t);
  3129.                     } else if (selectedParts[i] is Cannon) {
  3130.                         var ca:Cannon = new Cannon(selectedParts[i].x, centerY - (selectedParts[i].y - centerY) - selectedParts[i].w / 2, selectedParts[i].w);
  3131.                         ca.angle = 2 * Math.PI - selectedParts[i].angle;
  3132.                         ca.isStatic = selectedParts[i].isStatic;
  3133.                         ca.density = selectedParts[i].density;
  3134.                         ca.collide = selectedParts[i].collide;
  3135.                         ca.red = selectedParts[i].red;
  3136.                         ca.green = selectedParts[i].green;
  3137.                         ca.blue = selectedParts[i].blue;
  3138.                         ca.opacity = selectedParts[i].opacity;
  3139.                         ca.outline = selectedParts[i].outline;
  3140.                         ca.terrain = selectedParts[i].terrain;
  3141.                         ca.undragable = selectedParts[i].undragable;
  3142.                         ca.fireKey = selectedParts[i].fireKey;
  3143.                         ca.strength = selectedParts[i].strength;
  3144.                         newParts.push(ca);
  3145.                         partMapping.push(ca);
  3146.                     } else if (selectedParts[i] is TextPart) {
  3147.                         var te:TextPart = new TextPart(this, selectedParts[i].x, centerY - (selectedParts[i].y + selectedParts[i].h / 2 - centerY), selectedParts[i].w, selectedParts[i].h, selectedParts[i].text, selectedParts[i].inFront);
  3148.                         te.red = selectedParts[i].red;
  3149.                         te.green = selectedParts[i].green;
  3150.                         te.blue = selectedParts[i].blue;
  3151.                         te.size = selectedParts[i].size;
  3152.                         te.alwaysVisible = selectedParts[i].alwaysVisible;
  3153.                         te.inFront = selectedParts[i].inFront;
  3154.                         te.scaleWithZoom = selectedParts[i].scaleWithZoom;
  3155.                         te.displayKey = selectedParts[i].displayKey;
  3156.                         newParts.push(te);
  3157.                         partMapping.push(-1);
  3158.                     } else if (selectedParts[i] is JointPart || selectedParts[i] is Thrusters) {
  3159.                         partMapping.push(-1);
  3160.                     }
  3161.                 }
  3162.                 for (i = 0; i < selectedParts.length; i++) {
  3163.                     var index1:int = -1, index2:int = -1;
  3164.                     if (selectedParts[i] is JointPart) {
  3165.                         for (var j:int = 0; j < selectedParts.length; j++) {
  3166.                             if (selectedParts[j] == selectedParts[i].part1) index1 = j;
  3167.                             if (selectedParts[j] == selectedParts[i].part2) index2 = j;
  3168.                         }
  3169.                         if (index1 == -1 || index2 == -1) continue;
  3170.                     } else if (selectedParts[i] is Thrusters) {
  3171.                         for (j = 0; j < selectedParts.length; j++) {
  3172.                             if (selectedParts[j] == selectedParts[i].shape) index1 = j;
  3173.                         }
  3174.                         if (index1 == -1) continue;
  3175.                     }
  3176.                     if (selectedParts[i] is FixedJoint) {
  3177.                         var fj:FixedJoint = new FixedJoint(partMapping[index1], partMapping[index2], selectedParts[i].anchorX, centerY - (selectedParts[i].anchorY - centerY));
  3178.                         newParts.push(fj);
  3179.                     } else if (selectedParts[i] is RevoluteJoint) {
  3180.                         var rj:RevoluteJoint = new RevoluteJoint(partMapping[index1], partMapping[index2], selectedParts[i].anchorX, centerY - (selectedParts[i].anchorY - centerY));
  3181.                         rj.enableMotor = selectedParts[i].enableMotor;
  3182.                         rj.motorCWKey = selectedParts[i].motorCCWKey;
  3183.                         rj.motorCCWKey = selectedParts[i].motorCWKey;
  3184.                         rj.motorStrength = selectedParts[i].motorStrength;
  3185.                         rj.motorSpeed = selectedParts[i].motorSpeed;
  3186.                         rj.motorLowerLimit = -selectedParts[i].motorUpperLimit;
  3187.                         rj.motorUpperLimit = -selectedParts[i].motorLowerLimit;
  3188.                         rj.isStiff = selectedParts[i].isStiff;
  3189.                         rj.autoCW = selectedParts[i].autoCCW;
  3190.                         rj.autoCCW = selectedParts[i].autoCW;
  3191.                         newParts.push(rj);
  3192.                     } else if (selectedParts[i] is PrismaticJoint) {
  3193.                         var pj:PrismaticJoint = new PrismaticJoint(partMapping[index1], partMapping[index2], 0, 0, 1, 1);
  3194.                         pj.anchorX = selectedParts[i].anchorX;
  3195.                         pj.anchorY = centerY - (selectedParts[i].anchorY - centerY);
  3196.                         var axisAngle:Number = Math.atan2(selectedParts[i].axis.y, selectedParts[i].axis.x);
  3197.                         axisAngle = Util.NormalizeAngle(2 * Math.PI - axisAngle);
  3198.                         pj.axis = new b2Vec2(Math.cos(axisAngle), Math.sin(axisAngle));
  3199.                         pj.axis.Normalize();
  3200.                         pj.initLength = selectedParts[i].initLength;
  3201.                         pj.enablePiston = selectedParts[i].enablePiston;
  3202.                         pj.pistonUpKey = selectedParts[i].pistonUpKey;
  3203.                         pj.pistonDownKey = selectedParts[i].pistonDownKey;
  3204.                         pj.pistonStrength = selectedParts[i].pistonStrength;
  3205.                         pj.pistonSpeed = selectedParts[i].pistonSpeed;
  3206.                         pj.isStiff = selectedParts[i].isStiff;
  3207.                         pj.autoOscillate = selectedParts[i].autoOscillate;
  3208.                         pj.red = selectedParts[i].red;
  3209.                         pj.green = selectedParts[i].green;
  3210.                         pj.blue = selectedParts[i].blue;
  3211.                         pj.opacity = selectedParts[i].opacity;
  3212.                         pj.outline = selectedParts[i].outline;
  3213.                         pj.collide = selectedParts[i].collide;
  3214.                         newParts.push(pj);
  3215.                     } else if (selectedParts[i] is Thrusters) {
  3216.                         var th:Thrusters = new Thrusters(partMapping[index1], selectedParts[i].centerX, centerY - (selectedParts[i].centerY - centerY));
  3217.                         th.angle = 2 * Math.PI - selectedParts[i].angle;
  3218.                         th.strength = selectedParts[i].strength;
  3219.                         th.thrustKey = selectedParts[i].thrustKey;
  3220.                         th.autoOn = selectedParts[i].autoOn;
  3221.                         newParts.push(th);
  3222.                     }
  3223.                 }
  3224.                 if (newParts.length > 0) {
  3225.                     selectedParts = new Array();
  3226.                     draggingParts = new Array();
  3227.                     for (i = 0; i < newParts.length; i++) {
  3228.                         newParts[i].dragXOff = centerX - (newParts[i] is JointPart ? newParts[i].anchorX : (newParts[i] is TextPart ? newParts[i].x - newParts[i].w / 2 : newParts[i].centerX));
  3229.                         newParts[i].dragYOff = centerY - (newParts[i] is JointPart ? newParts[i].anchorY : (newParts[i] is TextPart ? newParts[i].y - newParts[i].h / 2 : newParts[i].centerY));
  3230.                         selectedParts.push(newParts[i]);
  3231.                         draggingParts.push(newParts[i]);
  3232.                         allParts.push(newParts[i]);
  3233.                     }
  3234.                     initDragX = mouseXWorldPhys;
  3235.                     initDragY = mouseYWorldPhys;
  3236.                     draggingPart = selectedParts[0];
  3237.                     draggingPart.Move(mouseXWorldPhys, mouseYWorldPhys);
  3238.                     RefreshSidePanel();
  3239.                     AddAction(new MassCreateAction(selectedParts));
  3240.                     curAction = PASTE;
  3241.                     curRobotID = "";
  3242.                 }
  3243.             } else {
  3244.                 m_fader.visible = true;
  3245.                 ShowConfirmDialog("That feature is only available to IncrediBots supporters. Become an IncrediBots supporter?", 8);
  3246.             }
  3247.         }
  3248.        
  3249.         public function scaleButton(e:MouseEvent):void {
  3250.             if (/*Main.premiumMode*/ true) {
  3251.                 if (!curRobotEditable || selectingCondition) return;
  3252.                 if (simStarted) return;
  3253.                 if (selectedParts.length == 0) return;
  3254.                 initDragX = (selectedParts[0] is JointPart ? selectedParts[0].anchorX : (selectedParts[0] is TextPart ? selectedParts[0].x + selectedParts[0].w / 2 : selectedParts[0].centerX));
  3255.                 initDragY = (selectedParts[0] is JointPart ? selectedParts[0].anchorY : (selectedParts[0] is TextPart ? selectedParts[0].y + selectedParts[0].h / 2 : selectedParts[0].centerY));
  3256.                 firstClickX = mouseXWorld;
  3257.                 firstClickY = mouseYWorld;
  3258.                 draggingParts = new Array();
  3259.                 for (var i:int = 0; i < selectedParts.length; i++) {
  3260.                     draggingParts = Util.RemoveDuplicates(draggingParts.concat(selectedParts[i].GetAttachedParts()));
  3261.                 }
  3262.                 for (i = 0; i < draggingParts.length; i++) {
  3263.                     draggingParts[i].dragXOff = (draggingParts[i] is JointPart ? draggingParts[i].anchorX : (draggingParts[i] is TextPart ? draggingParts[i].x + draggingParts[i].w / 2 : draggingParts[i].centerX)) - initDragX;
  3264.                     draggingParts[i].dragYOff = (draggingParts[i] is JointPart ? draggingParts[i].anchorY : (draggingParts[i] is TextPart ? draggingParts[i].y + draggingParts[i].h / 2 : draggingParts[i].centerY)) - initDragY;
  3265.                     draggingParts[i].PrepareForResizing();
  3266.                 }
  3267.                 curAction = RESIZING_SHAPES;
  3268.             } else {
  3269.                 m_fader.visible = true;
  3270.                 ShowConfirmDialog("That feature is only available to IncrediBots supporters. Become an IncrediBots supporter?", 8);
  3271.             }
  3272.         }
  3273.        
  3274.         public function deleteButton(e:MouseEvent):void {
  3275.             if (!curRobotEditable) return;
  3276.             if (simStarted) return;
  3277.             if (selectedParts.length == 1) {
  3278.                 DeletePart(selectedParts[0]);
  3279.                 curAction = -1;
  3280.                 m_sidePanel.visible = false;
  3281.                 curRobotID = "";
  3282.                 redrawRobot = true;
  3283.             }
  3284.         }
  3285.        
  3286.         public function deleteBuildBoxButton(e:MouseEvent):void {
  3287.             if (!curRobotEditable) return;
  3288.             if (simStarted) return;
  3289.             if (selectedBuildArea) {
  3290.                 ControllerChallenge.challenge.buildAreas = Util.RemoveFromArray(selectedBuildArea, ControllerChallenge.challenge.buildAreas);
  3291.                 BuildBuildArea();
  3292.                 redrawBuildArea = true;
  3293.             }
  3294.             m_sidePanel.visible = false;
  3295.         }
  3296.        
  3297.         public virtual function multiDeleteButton(e:MouseEvent):void {
  3298.             if (!curRobotEditable) return;
  3299.             if (simStarted) return;
  3300.             var affectedJoints:Array = new Array();
  3301.             for (var i:int = 0; i < selectedParts.length; i++) {
  3302.                 if (selectedParts[i] is ShapePart) {
  3303.                     affectedJoints = affectedJoints.concat(selectedParts[i].GetActiveJoints());
  3304.                     affectedJoints = affectedJoints.concat(selectedParts[i].GetActiveThrusters());
  3305.                 }
  3306.                 DeletePart(selectedParts[i], false, false);
  3307.             }
  3308.             if (selectedParts.length != 0) {
  3309.                 var deletedParts:Array = Util.RemoveDuplicates(selectedParts.concat(affectedJoints));
  3310.                 AddAction(new ClearAction(deletedParts));
  3311.                 for (i = 0; i < deletedParts.length; i++) {
  3312.                     selectedParts = Util.RemoveFromArray(deletedParts[i], selectedParts);
  3313.                 }
  3314.                 CheckIfPartsFit();
  3315.                 m_sidePanel.visible = false;
  3316.                 curRobotID = "";
  3317.                 redrawRobot = true;
  3318.             }
  3319.         }
  3320.        
  3321.         public function densitySlider(e:Event):void {
  3322.             if (selectedParts.length == 1 && selectedParts[0] is ShapePart) {
  3323.                 var oldDensity:Number = (selectedParts[0] as ShapePart).density;
  3324.                 (selectedParts[0] as ShapePart).density = e.target.value;
  3325.                 curRobotID = "";
  3326.                 m_sidePanel.SetDensity(e.target.value);
  3327.                 if (oldDensity != e.target.value) AddAction(new ChangeSliderAction(selectedParts[0], ChangeSliderAction.DENSITY_TYPE, e.target.value - oldDensity));
  3328.             }
  3329.         }
  3330.        
  3331.         public function densityText(e:Event):void {
  3332.             if (lastSelectedShape is ShapePart) {
  3333.                 var oldDensity:Number = (lastSelectedShape as ShapePart).density;
  3334.                 var density:Number = Number(e.target.text);
  3335.                 if (density < minDensity) density = minDensity;
  3336.                 if (density > maxDensity) density = maxDensity;
  3337.                 if (isNaN(density)) {
  3338.                     if (minDensity > 15.0) {
  3339.                         density = minDensity;
  3340.                     } else if (maxDensity < 15.0) {
  3341.                         density = maxDensity;
  3342.                     } else {
  3343.                         density = 15.0;
  3344.                     }
  3345.                 }
  3346.                 lastSelectedShape.density = density;
  3347.                 curRobotID = "";
  3348.                 m_sidePanel.SetDensity(density);
  3349.                 if (oldDensity != density) AddAction(new ChangeSliderAction(selectedParts[0], ChangeSliderAction.DENSITY_TYPE, density - oldDensity));
  3350.             }
  3351.             m_sidePanel.TextAreaLostFocus();
  3352.         }
  3353.        
  3354.         public function strengthText(e:Event):void {
  3355.             if (lastSelectedJoint is JointPart) {
  3356.                 var oldStrength:Number;
  3357.                 if (lastSelectedJoint is RevoluteJoint) oldStrength = (lastSelectedJoint as RevoluteJoint).motorStrength;
  3358.                 if (lastSelectedJoint is PrismaticJoint) oldStrength = (lastSelectedJoint as PrismaticJoint).pistonStrength;
  3359.                 var strength:Number = Number(e.target.text);
  3360.                 if (lastSelectedJoint is RevoluteJoint) {
  3361.                     if (strength < 1.0) strength = 1.0;
  3362.                     if (strength > maxRJStrength) strength = maxRJStrength;
  3363.                     if (isNaN(strength)) strength = Math.min(15.0, maxRJStrength);
  3364.                 }
  3365.                 if (lastSelectedJoint is PrismaticJoint) {
  3366.                     if (strength < 1.0) strength = 1.0;
  3367.                     if (strength > maxSJStrength) strength = maxSJStrength;
  3368.                     if (isNaN(strength)) strength = Math.min(15.0, maxSJStrength);
  3369.                 }
  3370.                 if (lastSelectedJoint is RevoluteJoint) (lastSelectedJoint as RevoluteJoint).motorStrength = strength;
  3371.                 if (lastSelectedJoint is PrismaticJoint) (lastSelectedJoint as PrismaticJoint).pistonStrength = strength;
  3372.                 curRobotID = "";
  3373.                 m_sidePanel.SetStrength(strength);
  3374.                 if (oldStrength != strength) AddAction(new ChangeSliderAction(lastSelectedJoint, ChangeSliderAction.STRENGTH_TYPE, strength - oldStrength));
  3375.             }
  3376.             m_sidePanel.TextAreaLostFocus();
  3377.         }
  3378.        
  3379.         public function speedText(e:Event):void {
  3380.             if (lastSelectedJoint is JointPart) {
  3381.                 var oldSpeed:Number;
  3382.                 if (lastSelectedJoint is RevoluteJoint) oldSpeed = (lastSelectedJoint as RevoluteJoint).motorSpeed;
  3383.                 if (lastSelectedJoint is PrismaticJoint) oldSpeed = (lastSelectedJoint as PrismaticJoint).pistonSpeed;
  3384.                 var speed:Number = Number(e.target.text);
  3385.                 if (lastSelectedJoint is RevoluteJoint) {
  3386.                     if (speed < 1.0) speed = 1.0;
  3387.                     if (speed > maxRJSpeed) speed = maxRJSpeed;
  3388.                     if (isNaN(speed)) speed = Math.min(15.0, maxRJSpeed);
  3389.                 }
  3390.                 if (lastSelectedJoint is PrismaticJoint) {
  3391.                     if (speed < 1.0) speed = 1.0;
  3392.                     if (speed > maxSJSpeed) speed = maxSJSpeed;
  3393.                     if (isNaN(speed)) speed = Math.min(15.0, maxSJSpeed);
  3394.                 }
  3395.                 if (lastSelectedJoint is RevoluteJoint) (lastSelectedJoint as RevoluteJoint).motorSpeed = speed;
  3396.                 if (lastSelectedJoint is PrismaticJoint) (lastSelectedJoint as PrismaticJoint).pistonSpeed = speed;
  3397.                 curRobotID = "";
  3398.                 m_sidePanel.SetSpeed(speed);
  3399.                 if (oldSpeed != speed) AddAction(new ChangeSliderAction(lastSelectedJoint, ChangeSliderAction.SPEED_TYPE, speed - oldSpeed));
  3400.             }
  3401.             m_sidePanel.TextAreaLostFocus();
  3402.         }
  3403.  
  3404.         public function thrustText(e:Event):void {
  3405.             if (lastSelectedThrusters is Thrusters) {
  3406.                 var oldStrength:Number;
  3407.                 oldStrength = lastSelectedThrusters.strength;
  3408.                 var strength:Number = Number(e.target.text);
  3409.                 if (strength < 1.0) strength = 1.0;
  3410.                 if (strength > maxThrusterStrength) strength = maxThrusterStrength;
  3411.                 if (isNaN(strength)) strength = Math.min(15.0, maxThrusterStrength);
  3412.                 lastSelectedThrusters.strength = strength;
  3413.                 curRobotID = "";
  3414.                 m_sidePanel.SetThrust(strength);
  3415.                 if (oldStrength != strength) AddAction(new ChangeSliderAction(lastSelectedThrusters, ChangeSliderAction.SPEED_TYPE, strength - oldStrength));
  3416.             }
  3417.             m_sidePanel.TextAreaLostFocus();
  3418.         }
  3419.  
  3420.         public function cannonText(e:Event):void {
  3421.             if (lastSelectedShape is Cannon) {
  3422.                 var oldStrength:Number;
  3423.                 oldStrength = (lastSelectedShape as Cannon).strength;
  3424.                 var strength:Number = Number(e.target.text);
  3425.                 if (strength < 1.0) strength = 1.0;
  3426.                 if (strength > 30) strength = 30;
  3427.                 if (isNaN(strength)) strength = 15;
  3428.                 (lastSelectedShape as Cannon).strength = strength;
  3429.                 curRobotID = "";
  3430.                 m_sidePanel.SetCannon(strength);
  3431.                 if (oldStrength != strength) AddAction(new ChangeSliderAction(lastSelectedShape, ChangeSliderAction.STRENGTH_TYPE, strength - oldStrength));
  3432.             }
  3433.             m_sidePanel.TextAreaLostFocus();
  3434.         }
  3435.  
  3436.         public function cameraBox(e:Event):void {
  3437.             if (selectedParts.length == 1 && selectedParts[0] is ShapePart) {
  3438.                 (selectedParts[0] as ShapePart).isCameraFocus = e.target.selected;
  3439.                 curRobotID = "";
  3440.                 var oldCameraPart:ShapePart = null;
  3441.                 if (e.target.selected) {
  3442.                     for (var i:int = 0; i < allParts.length; i++) {
  3443.                         if (allParts[i] is ShapePart && allParts[i] != selectedParts[0]) {
  3444.                             if (allParts[i].isCameraFocus) {
  3445.                                 allParts[i].isCameraFocus = false;
  3446.                                 oldCameraPart = allParts[i];
  3447.                             }
  3448.                         }
  3449.                     }
  3450.                 }
  3451.                 AddAction(new CameraAction(selectedParts[0], e.target.selected, oldCameraPart));
  3452.             }
  3453.         }
  3454.        
  3455.         public function collisionBox(e:Event):void {
  3456.             if (selectedParts.length == 1 && selectedParts[0] is ShapePart) {
  3457.                 (selectedParts[0] as ShapePart).collide = e.target.selected;
  3458.                 curRobotID = "";
  3459.                 AddAction(new ShapeCheckboxAction(selectedParts[0], ShapeCheckboxAction.COLLIDE_TYPE, e.target.selected));
  3460.             } else if (selectedParts.length == 1 && selectedParts[0] is PrismaticJoint) {
  3461.                 (selectedParts[0] as PrismaticJoint).collide = e.target.selected;
  3462.                 curRobotID = "";
  3463.                 AddAction(new ShapeCheckboxAction(selectedParts[0], ShapeCheckboxAction.COLLIDE_TYPE, e.target.selected));
  3464.             } else if (selectedParts.length > 1) {
  3465.                 var affectedParts:Array = new Array();
  3466.                 for (var i:int = 0; i < selectedParts.length; i++) {
  3467.                     if ((selectedParts[i] is ShapePart || selectedParts[i] is PrismaticJoint) && selectedParts[i].collide != e.target.selected) {
  3468.                         selectedParts[i].collide = e.target.selected;
  3469.                         affectedParts.push(selectedParts[i]);
  3470.                     }
  3471.                 }
  3472.                 if (affectedParts.length > 0) {
  3473.                     curRobotID = "";
  3474.                     redrawRobot = true;
  3475.                     AddAction(new MultiCollideAction(affectedParts, e.target.selected));
  3476.                 }
  3477.             }
  3478.         }
  3479.  
  3480.         public function fixateBox(e:Event):void {
  3481.             if (selectedParts.length == 1 && selectedParts[0] is ShapePart) {
  3482.                 (selectedParts[0] as ShapePart).isStatic = e.target.selected;
  3483.                 curRobotID = "";
  3484.                 redrawRobot = true;
  3485.                 AddAction(new ShapeCheckboxAction(selectedParts[0], ShapeCheckboxAction.FIXATE_TYPE, e.target.selected));
  3486.             } else if (selectedParts.length > 1) {
  3487.                 var affectedParts:Array = new Array();
  3488.                 for (var i:int = 0; i < selectedParts.length; i++) {
  3489.                     if (selectedParts[i] is ShapePart && selectedParts[i].isStatic != e.target.selected) {
  3490.                         selectedParts[i].isStatic = e.target.selected;
  3491.                         affectedParts.push(selectedParts[i]);
  3492.                     }
  3493.                 }
  3494.                 if (affectedParts.length > 0) {
  3495.                     curRobotID = "";
  3496.                     redrawRobot = true;
  3497.                     AddAction(new MultiFixateAction(affectedParts, e.target.selected));
  3498.                 }
  3499.             }
  3500.         }
  3501.        
  3502.         public function outlineBox(e:Event):void {
  3503.             if (selectedParts.length == 1 && (selectedParts[0] is ShapePart || selectedParts[0] is PrismaticJoint)) {
  3504.                 selectedParts[0].outline = e.target.selected;
  3505.                 curRobotID = "";
  3506.                 redrawRobot = true;
  3507.                 AddAction(new ShapeCheckboxAction(selectedParts[0], ShapeCheckboxAction.OUTLINE_TYPE, e.target.selected));
  3508.             } else if (selectedParts.length > 1) {
  3509.                 var affectedParts:Array = new Array();
  3510.                 for (var i:int = 0; i < selectedParts.length; i++) {
  3511.                     if ((selectedParts[i] is ShapePart || selectedParts[i] is PrismaticJoint) && selectedParts[i].outline != e.target.selected) {
  3512.                         selectedParts[i].outline = e.target.selected;
  3513.                         affectedParts.push(selectedParts[i]);
  3514.                     }
  3515.                 }
  3516.                 if (affectedParts.length > 0) {
  3517.                     curRobotID = "";
  3518.                     redrawRobot = true;
  3519.                     AddAction(new MultiOutlineAction(affectedParts, e.target.selected));
  3520.                 }
  3521.             }
  3522.         }
  3523.  
  3524.         public function terrainBox(e:Event):void {
  3525.             if (selectedParts.length == 1 && selectedParts[0] is ShapePart) {
  3526.                 selectedParts[0].terrain = e.target.selected;
  3527.                 curRobotID = "";
  3528.                 redrawRobot = true;
  3529.                 AddAction(new ShapeCheckboxAction(selectedParts[0], ShapeCheckboxAction.TERRAIN_TYPE, e.target.selected));
  3530.             } else if (selectedParts.length > 1) {
  3531.                 var affectedParts:Array = new Array();
  3532.                 for (var i:int = 0; i < selectedParts.length; i++) {
  3533.                     if ((selectedParts[i] is ShapePart) && selectedParts[i].terrain != e.target.selected) {
  3534.                         selectedParts[i].terrain = e.target.selected;
  3535.                         affectedParts.push(selectedParts[i]);
  3536.                     }
  3537.                 }
  3538.                 if (affectedParts.length > 0) {
  3539.                     curRobotID = "";
  3540.                     redrawRobot = true;
  3541.                     AddAction(new MultiTerrainAction(affectedParts, e.target.selected));
  3542.                 }
  3543.             }
  3544.         }
  3545.  
  3546.         public function undragableBox(e:Event):void {
  3547.             if (selectedParts.length == 1 && selectedParts[0] is ShapePart) {
  3548.                 selectedParts[0].undragable = e.target.selected;
  3549.                 curRobotID = "";
  3550.                 AddAction(new ShapeCheckboxAction(selectedParts[0], ShapeCheckboxAction.UNDRAGABLE_TYPE, e.target.selected));
  3551.             } else if (selectedParts.length > 1) {
  3552.                 var affectedParts:Array = new Array();
  3553.                 for (var i:int = 0; i < selectedParts.length; i++) {
  3554.                     if ((selectedParts[i] is ShapePart) && selectedParts[i].undragable != e.target.selected) {
  3555.                         selectedParts[i].undragable = e.target.selected;
  3556.                         affectedParts.push(selectedParts[i]);
  3557.                     }
  3558.                 }
  3559.                 if (affectedParts.length > 0) {
  3560.                     curRobotID = "";
  3561.                     redrawRobot = true;
  3562.                     AddAction(new MultiUndragableAction(affectedParts, e.target.selected));
  3563.                 }
  3564.             }
  3565.         }
  3566.  
  3567.         public virtual function frontButton(e:MouseEvent):void {
  3568.             if (simStarted) return;
  3569.             if (selectedParts.length == 1 && (selectedParts[0] is ShapePart || selectedParts[0] is PrismaticJoint)) {
  3570.                 var oldIndex:int = -1;
  3571.                 for (var i:int = 0; i < allParts.length; i++) {
  3572.                     if (allParts[i] == selectedParts[0]) oldIndex = i;
  3573.                 }
  3574.                 allParts = Util.RemoveFromArray(selectedParts[0], allParts);
  3575.                 allParts.push(selectedParts[0]);
  3576.                 curRobotID = "";
  3577.                 AddAction(new MoveZAction(selectedParts[0], MoveZAction.FRONT_TYPE, oldIndex));
  3578.             } else if (selectedParts.length == 1 && selectedParts[0] is TextPart) {
  3579.                 if (!selectedParts[0].inFront) {
  3580.                     selectedParts[0].inFront = true;
  3581.                     removeChild(selectedParts[0].m_textField);
  3582.                     addChildAt(selectedParts[0].m_textField, getChildIndex(m_canvas) + 1);
  3583.                     AddAction(new MoveZAction(selectedParts[0], MoveZAction.FRONT_TYPE));
  3584.                 }
  3585.             }
  3586.             redrawRobot = true;
  3587.         }
  3588.        
  3589.         public virtual function backButton(e:MouseEvent):void {
  3590.             if (simStarted) return;
  3591.             if (selectedParts.length == 1 && (selectedParts[0] is ShapePart || selectedParts[0] is PrismaticJoint)) {
  3592.                 var oldIndex:int = -1;
  3593.                 var foundIt:Boolean = false;
  3594.                 for (var i:int = allParts.length - 1; i > 0; i--) {
  3595.                     if (allParts[i] == selectedParts[0]) {
  3596.                         oldIndex = i;
  3597.                         foundIt = true;
  3598.                     }
  3599.                     if (foundIt) {
  3600.                         if (!allParts[i - 1].isEditable) {
  3601.                             break;
  3602.                         }
  3603.                         allParts[i] = allParts[i - 1];
  3604.                     }
  3605.                 }
  3606.                 allParts[i] = selectedParts[0];
  3607.                 curRobotID = "";
  3608.                 AddAction(new MoveZAction(selectedParts[0], MoveZAction.BACK_TYPE, oldIndex));
  3609.             } else if (selectedParts.length == 1 && selectedParts[0] is TextPart) {
  3610.                 if (selectedParts[0].inFront) {
  3611.                     selectedParts[0].inFront = false;
  3612.                     removeChild(selectedParts[0].m_textField);
  3613.                     addChildAt(selectedParts[0].m_textField, getChildIndex(m_canvas));
  3614.                     AddAction(new MoveZAction(selectedParts[0], MoveZAction.BACK_TYPE));
  3615.                 }
  3616.             }
  3617.             redrawRobot = true;
  3618.         }
  3619.        
  3620.         public function scaleWithZoomBox(e:Event):void {
  3621.             if (selectedParts.length == 1 && selectedParts[0] is TextPart) {
  3622.                 (selectedParts[0] as TextPart).scaleWithZoom = e.target.selected;
  3623.                 curRobotID = "";
  3624.                 AddAction(new TextCheckboxAction(selectedParts[0], TextCheckboxAction.SCALE_TYPE, e.target.selected));
  3625.             }
  3626.         }
  3627.        
  3628.         public function alwaysVisibleBox(e:Event):void {
  3629.             if (selectedParts.length == 1 && selectedParts[0] is TextPart) {
  3630.                 (selectedParts[0] as TextPart).alwaysVisible = e.target.selected;
  3631.                 curRobotID = "";
  3632.                 m_sidePanel.EnableTextStuff(!e.target.selected);
  3633.                 AddAction(new TextCheckboxAction(selectedParts[0], TextCheckboxAction.DISPLAY_TYPE, e.target.selected));
  3634.             }
  3635.         }
  3636.        
  3637.         public function textKeyBox(e:KeyboardEvent):void {
  3638.             if (e.currentTarget.enabled) {
  3639.                 var str:String;
  3640.                 if (selectedParts[0] is TextPart) {
  3641.                     var oldKey:int = (selectedParts[0] as TextPart).displayKey;
  3642.                     (selectedParts[0] as TextPart).displayKey = e.keyCode;
  3643.                     if (oldKey != e.keyCode) AddAction(new ControlKeyAction(selectedParts[0], ControlKeyAction.TEXT_TYPE, oldKey, e.keyCode));
  3644.                 }
  3645.                 str = Input.getKeyString(e.keyCode);
  3646.                 if (str == null) str = "Unk: " + e.keyCode;
  3647.                 e.target.text = str;
  3648.                 e.target.setSelection(0, 10);
  3649.                 curRobotID = "";
  3650.             }
  3651.         }
  3652.        
  3653.         public function textEntered(e:Event):void {
  3654.             if (selectedParts[0] is ShapePart) {
  3655.                 lastSelectedShape = selectedParts[0];
  3656.             } else if (selectedParts[0] is JointPart) {
  3657.                 lastSelectedJoint = selectedParts[0];
  3658.             } else if (selectedParts[0] is TextPart) {
  3659.                 lastSelectedText = selectedParts[0];
  3660.             } else if (selectedParts[0] is Thrusters) {
  3661.                 lastSelectedThrusters = selectedParts[0];
  3662.             }
  3663.         }
  3664.        
  3665.         public function colourButton(red:int, green:int, blue:int, opacity:int, defaultColour:Boolean):void {
  3666.             var oldRed:int, oldGreen:int, oldBlue:int, oldOpacity:int;
  3667.             if (defaultColour) {
  3668.                 defaultR = red;
  3669.                 defaultG = green;
  3670.                 defaultB = blue;
  3671.                 defaultO = opacity;
  3672.             }
  3673.             if (selectedParts.length == 1) {
  3674.                 if (selectedParts[0] is ShapePart || selectedParts[0] is PrismaticJoint || selectedParts[0] is TextPart) {
  3675.                     oldRed = selectedParts[0].red;
  3676.                     oldGreen = selectedParts[0].green;
  3677.                     oldBlue = selectedParts[0].blue;
  3678.                     selectedParts[0].red = red;
  3679.                     selectedParts[0].green = green;
  3680.                     selectedParts[0].blue = blue;
  3681.                     if (!(selectedParts[0] is TextPart)) {
  3682.                         oldOpacity = selectedParts[0].opacity;
  3683.                         selectedParts[0].opacity = opacity;
  3684.                     }
  3685.                     if (oldRed != selectedParts[0].red || oldGreen != selectedParts[0].green || oldBlue != selectedParts[0].blue || (!(selectedParts[0] is TextPart) && oldOpacity != selectedParts[0].opacity)) {
  3686.                         AddAction(new ColourChangeAction(selectedParts[0], selectedParts[0].red - oldRed, selectedParts[0].green - oldGreen, selectedParts[0].blue - oldBlue, (selectedParts[0] is TextPart ? 0 : selectedParts[0].opacity - oldOpacity)));
  3687.                         curRobotID = "";
  3688.                         redrawRobot = true;
  3689.                     }
  3690.                 }
  3691.             } else if (selectedParts.length > 1) {
  3692.                 var affectedParts:Array = new Array();
  3693.                 var oldReds:Array = new Array();
  3694.                 var oldGreens:Array = new Array();
  3695.                 var oldBlues:Array = new Array();
  3696.                 var oldOpacities:Array = new Array();
  3697.                 for (var i:int = 0; i < selectedParts.length; i++) {
  3698.                     if (selectedParts[i] is ShapePart || selectedParts[i] is PrismaticJoint || selectedParts[i] is TextPart) {
  3699.                         if (selectedParts[i].red != red || selectedParts[i].green != green || selectedParts[i].blue != blue || (!(selectedParts[i] is TextPart) && selectedParts[i].opacity != opacity)) {
  3700.                             oldReds.push(selectedParts[i].red);
  3701.                             oldGreens.push(selectedParts[i].green);
  3702.                             oldBlues.push(selectedParts[i].blue);
  3703.                             oldOpacities.push(selectedParts[i] is TextPart ? 0 : selectedParts[i].opacity);
  3704.                             selectedParts[i].red = red;
  3705.                             selectedParts[i].green = green;
  3706.                             selectedParts[i].blue = blue;
  3707.                             if (!(selectedParts[i] is TextPart)) selectedParts[i].opacity = opacity;
  3708.                             affectedParts.push(selectedParts[i]);
  3709.                         }
  3710.                     }
  3711.                 }
  3712.                 if (affectedParts.length > 0) {
  3713.                     curRobotID = "";
  3714.                     redrawRobot = true;
  3715.                     AddAction(new MultiColourChangeAction(affectedParts, red, green, blue, opacity, oldReds, oldGreens, oldBlues, oldOpacities));
  3716.                 }
  3717.             }
  3718.         }
  3719.  
  3720.         public function textTextStart(e:Event):void {
  3721.             if (selectedParts.length == 1 && selectedParts[0] is TextPart) {
  3722.                 oldText = selectedParts[0].text;
  3723.             }
  3724.         }
  3725.  
  3726.         public function textText(e:Event):void {
  3727.             textEntered(e);
  3728.             if (lastSelectedText is TextPart) {
  3729.                 newText = e.target;
  3730.                 curRobotID = "";
  3731.                 redrawRobot = true;
  3732.             }
  3733.         }
  3734.  
  3735.         public function textTextFinish(e:Event):void {
  3736.             if (lastSelectedText is TextPart) {
  3737.                 AddAction(new EnterTextAction(lastSelectedText, oldText, lastSelectedText.text));
  3738.             }
  3739.         }
  3740.  
  3741.         public function sizeText(e:Event):void {
  3742.             if (lastSelectedText is TextPart) {
  3743.                 var oldSize:int = lastSelectedText.size;
  3744.                 lastSelectedText.size = parseInt(e.target.text);
  3745.                 if (lastSelectedText.size < 4) lastSelectedText.size = 4;
  3746.                 if (lastSelectedText.size > 36) lastSelectedText.size = 36;
  3747.                 e.target.text = lastSelectedText.size + "";
  3748.                 curRobotID = "";
  3749.                 redrawRobot = true;
  3750.                 if (oldSize != lastSelectedText.size) AddAction(new TextSizeChangeAction(lastSelectedText, lastSelectedText.size - oldSize));
  3751.             }
  3752.             m_sidePanel.TextAreaLostFocus();
  3753.         }
  3754.        
  3755.         public function minLimitText(e:Event):void {
  3756.             var limit:Number = Number(e.target.text.replace("\n", ""));
  3757.             if (e.target.text == "") limit = NaN;
  3758.            
  3759.             if (lastSelectedJoint is RevoluteJoint) {
  3760.                 if (isNaN(limit)) {
  3761.                     limit = -Number.MAX_VALUE;
  3762.                     e.target.text = "None";
  3763.                 } else if (limit >= 0.0) {
  3764.                     limit = 0;
  3765.                     e.target.text = 0;
  3766.                 }
  3767.                 var oldLimit:Number = (lastSelectedJoint as RevoluteJoint).motorLowerLimit;
  3768.                 (lastSelectedJoint as RevoluteJoint).motorLowerLimit = limit;
  3769.                 if (limit != oldLimit) AddAction(new LimitChangeAction(lastSelectedJoint, LimitChangeAction.MIN_TYPE, oldLimit, limit));
  3770.             }
  3771.             m_sidePanel.TextAreaLostFocus();
  3772.             curRobotID = "";
  3773.         }
  3774.        
  3775.         public function maxLimitText(e:Event):void {
  3776.             var limit:Number = Number(e.target.text.replace("\n", ""));
  3777.             if (e.target.text == "") limit = NaN;
  3778.            
  3779.             if (lastSelectedJoint is RevoluteJoint) {
  3780.                 if (isNaN(limit)) {
  3781.                     limit = Number.MAX_VALUE;
  3782.                     e.target.text = "None";
  3783.                 } else if (limit <= 0.0) {
  3784.                     limit = 0;
  3785.                     e.target.text = 0;
  3786.                 }
  3787.                 var oldLimit:Number = (lastSelectedJoint as RevoluteJoint).motorUpperLimit;
  3788.                 (lastSelectedJoint as RevoluteJoint).motorUpperLimit = limit;
  3789.                 if (limit != oldLimit) AddAction(new LimitChangeAction(lastSelectedJoint, LimitChangeAction.MAX_TYPE, oldLimit, limit));
  3790.             }
  3791.             m_sidePanel.TextAreaLostFocus();
  3792.             curRobotID = "";
  3793.         }
  3794.        
  3795.         public function controlKeyText1(e:KeyboardEvent):void {
  3796.             if (e.currentTarget.enabled) {
  3797.                 var str:String;
  3798.                 var oldKey:int;
  3799.                 if (selectedParts[0] is RevoluteJoint) {
  3800.                     oldKey = (selectedParts[0] as RevoluteJoint).motorCWKey;
  3801.                     (selectedParts[0] as RevoluteJoint).motorCWKey = e.keyCode;
  3802.                     if (oldKey != e.keyCode) AddAction(new ControlKeyAction(selectedParts[0], ControlKeyAction.CW_TYPE, oldKey, e.keyCode));
  3803.                 } else {
  3804.                     oldKey = (selectedParts[0] as PrismaticJoint).pistonUpKey;
  3805.                     (selectedParts[0] as PrismaticJoint).pistonUpKey = e.keyCode;
  3806.                     if (oldKey != e.keyCode) AddAction(new ControlKeyAction(selectedParts[0], ControlKeyAction.EXPAND_TYPE, oldKey, e.keyCode));
  3807.                 }
  3808.                 str = Input.getKeyString(e.keyCode);
  3809.                 if (str == null) str = "Unk: " + e.keyCode;
  3810.                 e.target.text = str;
  3811.                 e.target.setSelection(0, 10);
  3812.                 curRobotID = "";
  3813.             }
  3814.         }
  3815.        
  3816.         public function controlKeyText2(e:KeyboardEvent):void {
  3817.             if (e.currentTarget.enabled) {
  3818.                 var str:String;
  3819.                 var oldKey:int;
  3820.                 if (selectedParts[0] is RevoluteJoint) {
  3821.                     oldKey = (selectedParts[0] as RevoluteJoint).motorCCWKey;
  3822.                     (selectedParts[0] as RevoluteJoint).motorCCWKey = e.keyCode;
  3823.                     if (oldKey != e.keyCode) AddAction(new ControlKeyAction(selectedParts[0], ControlKeyAction.CCW_TYPE, oldKey, e.keyCode));
  3824.                 } else {
  3825.                     oldKey = (selectedParts[0] as PrismaticJoint).pistonDownKey;
  3826.                     (selectedParts[0] as PrismaticJoint).pistonDownKey = e.keyCode;
  3827.                     if (oldKey != e.keyCode) AddAction(new ControlKeyAction(selectedParts[0], ControlKeyAction.CONTRACT_TYPE, oldKey, e.keyCode));
  3828.                 }
  3829.                 str = Input.getKeyString(e.keyCode);
  3830.                 if (str == null) str = "Unk: " + e.keyCode;
  3831.                 e.target.text = str;
  3832.                 e.target.setSelection(0, 10);
  3833.                 curRobotID = "";
  3834.             }
  3835.         }
  3836.        
  3837.         public function thrustKeyText(e:KeyboardEvent):void {
  3838.             if (e.currentTarget.enabled) {
  3839.                 var str:String;
  3840.                 var oldKey:int;
  3841.                 if (selectedParts[0] is Thrusters) {
  3842.                     oldKey = (selectedParts[0] as Thrusters).thrustKey;
  3843.                     (selectedParts[0] as Thrusters).thrustKey = e.keyCode;
  3844.                     if (oldKey != e.keyCode) AddAction(new ControlKeyAction(selectedParts[0], ControlKeyAction.THRUSTERS_TYPE, oldKey, e.keyCode));
  3845.                 }
  3846.                 str = Input.getKeyString(e.keyCode);
  3847.                 if (str == null) str = "Unk: " + e.keyCode;
  3848.                 e.target.text = str;
  3849.                 e.target.setSelection(0, 10);
  3850.                 curRobotID = "";
  3851.             }
  3852.         }
  3853.        
  3854.         public function fireKeyText(e:KeyboardEvent):void {
  3855.             if (e.currentTarget.enabled) {
  3856.                 var str:String;
  3857.                 var oldKey:int;
  3858.                 if (selectedParts[0] is Cannon) {
  3859.                     oldKey = (selectedParts[0] as Cannon).fireKey;
  3860.                     (selectedParts[0] as Cannon).fireKey = e.keyCode;
  3861.                     if (oldKey != e.keyCode) AddAction(new ControlKeyAction(selectedParts[0], ControlKeyAction.CANNON_TYPE, oldKey, e.keyCode));
  3862.                 }
  3863.                 str = Input.getKeyString(e.keyCode);
  3864.                 if (str == null) str = "Unk: " + e.keyCode;
  3865.                 e.target.text = str;
  3866.                 e.target.setSelection(0, 10);
  3867.                 curRobotID = "";
  3868.             }
  3869.         }
  3870.        
  3871.         public function autoBox1(e:MouseEvent):void  {
  3872.             if (selectedParts[0] is RevoluteJoint) {
  3873.                 var sideEffect:Boolean = (e.target.selected && (selectedParts[0] as RevoluteJoint).autoCCW);
  3874.                 (selectedParts[0] as RevoluteJoint).autoCW = e.target.selected;
  3875.                 if (e.target.selected) {
  3876.                     (selectedParts[0] as RevoluteJoint).autoCCW = false;
  3877.                     m_sidePanel.deselectBox2();
  3878.                 }
  3879.                 AddAction(new JointCheckboxAction(selectedParts[0], JointCheckboxAction.AUTO_CW_TYPE, e.target.selected, sideEffect));
  3880.             } else if (selectedParts[0] is PrismaticJoint) {
  3881.                 (selectedParts[0] as PrismaticJoint).autoOscillate = e.target.selected;
  3882.                 AddAction(new JointCheckboxAction(selectedParts[0], JointCheckboxAction.AUTO_OSCILLATE_TYPE, e.target.selected));
  3883.             } else if (selectedParts[0] is Thrusters) {
  3884.                 (selectedParts[0] as Thrusters).autoOn = e.target.selected;
  3885.                 AddAction(new JointCheckboxAction(selectedParts[0], JointCheckboxAction.AUTO_ON_TYPE, e.target.selected));
  3886.             }
  3887.             curRobotID = "";
  3888.         }
  3889.        
  3890.         public function autoBox2(e:MouseEvent):void  {
  3891.             if (selectedParts[0] is RevoluteJoint) {
  3892.                 var sideEffect:Boolean = (e.target.selected && (selectedParts[0] as RevoluteJoint).autoCW);
  3893.                 (selectedParts[0] as RevoluteJoint).autoCCW = e.target.selected;
  3894.                 if (e.target.selected) {
  3895.                     (selectedParts[0] as RevoluteJoint).autoCW = false;
  3896.                     m_sidePanel.deselectBox1();
  3897.                 }
  3898.                 AddAction(new JointCheckboxAction(selectedParts[0], JointCheckboxAction.AUTO_CCW_TYPE, e.target.selected, sideEffect));
  3899.             }
  3900.             curRobotID = "";
  3901.         }
  3902.        
  3903.         public function motorBox(e:MouseEvent):void {
  3904.             if (selectedParts[0] is RevoluteJoint) {
  3905.                 (selectedParts[0] as RevoluteJoint).enableMotor = e.target.selected;
  3906.             } else if (selectedParts[0] is PrismaticJoint) {
  3907.                 (selectedParts[0] as PrismaticJoint).enablePiston = e.target.selected;
  3908.             }
  3909.             m_sidePanel.EnableMotorStuff(e.target.selected);
  3910.             curRobotID = "";
  3911.             AddAction(new JointCheckboxAction(selectedParts[0], JointCheckboxAction.ENABLE_TYPE, e.target.selected));
  3912.         }
  3913.        
  3914.         public function rigidBox(e:MouseEvent):void {
  3915.             if (selectedParts[0] is RevoluteJoint) {
  3916.                 (selectedParts[0] as RevoluteJoint).isStiff = !e.target.selected;
  3917.             } else if (selectedParts[0] is PrismaticJoint) {
  3918.                 (selectedParts[0] as PrismaticJoint).isStiff = !e.target.selected;
  3919.             }
  3920.             curRobotID = "";
  3921.             AddAction(new JointCheckboxAction(selectedParts[0], JointCheckboxAction.RIGID_TYPE, e.target.selected));
  3922.         }
  3923.        
  3924.         public function strengthSlider(e:Event):void {
  3925.             var oldStrength:Number;
  3926.             if (selectedParts[0] is RevoluteJoint) {
  3927.                 oldStrength = (selectedParts[0] as RevoluteJoint).motorStrength;
  3928.                 (selectedParts[0] as RevoluteJoint).motorStrength = e.target.value;
  3929.                 if (oldStrength != e.target.value) AddAction(new ChangeSliderAction(selectedParts[0], ChangeSliderAction.STRENGTH_TYPE, e.target.value - oldStrength));
  3930.             } else if (selectedParts[0] is PrismaticJoint) {
  3931.                 oldStrength = (selectedParts[0] as PrismaticJoint).pistonStrength;
  3932.                 (selectedParts[0] as PrismaticJoint).pistonStrength = e.target.value;
  3933.                 if (oldStrength != e.target.value) AddAction(new ChangeSliderAction(selectedParts[0], ChangeSliderAction.STRENGTH_TYPE, e.target.value - oldStrength));
  3934.             }
  3935.             curRobotID = "";
  3936.             m_sidePanel.SetStrength(e.target.value);
  3937.         }
  3938.        
  3939.         public function speedSlider(e:Event):void {
  3940.             var oldSpeed:Number;
  3941.             if (selectedParts[0] is RevoluteJoint) {
  3942.                 oldSpeed = (selectedParts[0] as RevoluteJoint).motorSpeed;
  3943.                 (selectedParts[0] as RevoluteJoint).motorSpeed = e.target.value;
  3944.                 if (oldSpeed != e.target.value) AddAction(new ChangeSliderAction(selectedParts[0], ChangeSliderAction.SPEED_TYPE, e.target.value - oldSpeed));
  3945.             } else if (selectedParts[0] is PrismaticJoint) {
  3946.                 oldSpeed = (selectedParts[0] as PrismaticJoint).pistonSpeed;
  3947.                 (selectedParts[0] as PrismaticJoint).pistonSpeed = e.target.value;
  3948.                 if (oldSpeed != e.target.value) AddAction(new ChangeSliderAction(selectedParts[0], ChangeSliderAction.SPEED_TYPE, e.target.value - oldSpeed));
  3949.             }
  3950.             curRobotID = "";
  3951.             m_sidePanel.SetSpeed(e.target.value);
  3952.         }
  3953.  
  3954.         public function thrustSlider(e:Event):void {
  3955.             var oldStrength:Number;
  3956.             if (selectedParts[0] is Thrusters) {
  3957.                 oldStrength = (selectedParts[0] as Thrusters).strength;
  3958.                 (selectedParts[0] as Thrusters).strength = e.target.value;
  3959.                 if (oldStrength != e.target.value) AddAction(new ChangeSliderAction(selectedParts[0], ChangeSliderAction.STRENGTH_TYPE, e.target.value - oldStrength));
  3960.             }
  3961.             curRobotID = "";
  3962.             m_sidePanel.SetThrust(e.target.value);
  3963.         }
  3964.  
  3965.         public function cannonSlider(e:Event):void {
  3966.             var oldStrength:Number;
  3967.             if (selectedParts[0] is Cannon) {
  3968.                 oldStrength = (selectedParts[0] as Cannon).strength;
  3969.                 (selectedParts[0] as Cannon).strength = e.target.value;
  3970.                 if (oldStrength != e.target.value) AddAction(new ChangeSliderAction(selectedParts[0], ChangeSliderAction.STRENGTH_TYPE, e.target.value - oldStrength));
  3971.             }
  3972.             curRobotID = "";
  3973.             m_sidePanel.SetCannon(e.target.value);
  3974.         }
  3975.  
  3976.         public virtual function zoomInButton(e:MouseEvent):void {
  3977.             Zoom(true);
  3978.         }
  3979.  
  3980.         public virtual function zoomOutButton(e:MouseEvent):void {
  3981.             Zoom(false);
  3982.         }
  3983.  
  3984.         public function clearButton(e:MouseEvent):void {
  3985.             if (simStarted) return;
  3986.             if (selectingCondition) return;
  3987.             var deletedParts:Array = allParts.filter(PartIsEditable);
  3988.             for (var i:int = 0; i < deletedParts.length; i++) {
  3989.                 if (deletedParts[i] is ShapePart || deletedParts[i] is TextPart) {
  3990.                     DeletePart(deletedParts[i], false);
  3991.                 }
  3992.             }
  3993.             if (deletedParts.length != 0) {
  3994.                 if (curRobotEditable) AddAction(new ClearAction(deletedParts));
  3995.                 CheckIfPartsFit();
  3996.                 curRobotID = "";
  3997.                 redrawRobot = true;
  3998.             }
  3999.             if (!curRobotEditable) curRobotEditable = true;
  4000.             if (m_sidePanel && m_sidePanel.visible) m_sidePanel.visible = false;
  4001.         }
  4002.  
  4003.         public virtual function undoButton(e:MouseEvent):void {
  4004.             if (selectingCondition) return;
  4005.             if (curRobotEditable && lastAction != -1 && !simStarted) {
  4006.                 actions[lastAction].UndoAction();
  4007.                 lastAction--;
  4008.                 curAction = -1;
  4009.                 curRobotID = "";
  4010.                 CheckIfPartsFit();
  4011.                 if (selectedParts.length == 0) m_sidePanel.visible = false;
  4012.                 RefreshSidePanel();
  4013.                 redrawRobot = true;
  4014.             }
  4015.         }
  4016.        
  4017.         public virtual function redoButton(e:MouseEvent):void {
  4018.             if (selectingCondition) return;
  4019.             if (curRobotEditable && lastAction < actions.length - 1 && !simStarted) {
  4020.                 actions[lastAction + 1].RedoAction();
  4021.                 lastAction++;
  4022.                 curAction = -1;
  4023.                 curRobotID = "";
  4024.                 CheckIfPartsFit();
  4025.                 if (selectedParts.length == 0) m_sidePanel.visible = false;
  4026.                 RefreshSidePanel();
  4027.                 redrawRobot = true;
  4028.             }
  4029.         }
  4030.        
  4031.         public function cutButton(e:MouseEvent):void {
  4032.             if (selectingCondition) return;
  4033.             if (simStarted) return;
  4034.             copiedJoint = null;
  4035.             copiedThrusters = null;
  4036.             if (selectedParts.length == 1) {
  4037.                 clipboardParts = new Array();
  4038.                 if (selectedParts[0] is ShapePart || selectedParts[0] is TextPart) {
  4039.                     clipboardParts.push(selectedParts[0].MakeCopy());
  4040.                 } else if (selectedParts[0] is JointPart) {
  4041.                     copiedJoint = selectedParts[0];
  4042.                 } else if (selectedParts[0] is Thrusters) {
  4043.                     copiedThrusters = selectedParts[0];
  4044.                 }
  4045.                 DeletePart(selectedParts[0]);
  4046.                 m_sidePanel.visible = false;
  4047.                 curAction = -1;
  4048.                 curRobotID = "";
  4049.                 redrawRobot = true;
  4050.             } else if (selectedParts.length > 1) {
  4051.                 clipboardParts = new Array();
  4052.                 var partMapping:Array = new Array();
  4053.                 var affectedJoints:Array = new Array();
  4054.                 for (var i:int = 0; i < selectedParts.length; i++) {
  4055.                     if (selectedParts[i] is ShapePart) {
  4056.                         var copiedPart:ShapePart = (selectedParts[i] as ShapePart).MakeCopy();
  4057.                         clipboardParts.push(copiedPart);
  4058.                         partMapping.push(copiedPart);
  4059.                         affectedJoints = affectedJoints.concat(selectedParts[i].GetActiveJoints());
  4060.                         DeletePart(selectedParts[i], false, false);
  4061.                     } else if (selectedParts[i] is TextPart) {
  4062.                         clipboardParts.push((selectedParts[i] as TextPart).MakeCopy());
  4063.                         partMapping.push(-1);
  4064.                         DeletePart(selectedParts[i], false, false);
  4065.                     } else {
  4066.                         partMapping.push(-1);
  4067.                     }
  4068.                 }
  4069.                 for (i = 0; i < selectedParts.length; i++) {
  4070.                     if (selectedParts[i] is JointPart) {
  4071.                         var index1:int = -1, index2:int = -1;
  4072.                         for (var j:int = 0; j < selectedParts.length; j++) {
  4073.                             if (selectedParts[j] == (selectedParts[i] as JointPart).part1) index1 = j;
  4074.                             if (selectedParts[j] == (selectedParts[i] as JointPart).part2) index2 = j;
  4075.                         }
  4076.                         if (index1 != -1 && index2 != -1) clipboardParts.push((selectedParts[i] as JointPart).MakeCopy(partMapping[index1], partMapping[index2]));
  4077.                         DeletePart(selectedParts[i], false, false);
  4078.                     } else if (selectedParts[i] is Thrusters) {
  4079.                         index1 = -1;
  4080.                         for (j = 0; j < selectedParts.length; j++) {
  4081.                             if (selectedParts[j] == (selectedParts[i] as Thrusters).shape) index1 = j;
  4082.                         }
  4083.                         if (index1 != -1) clipboardParts.push((selectedParts[i] as Thrusters).MakeCopy(partMapping[index1]));
  4084.                         DeletePart(selectedParts[i], false, false);
  4085.                     }
  4086.                 }
  4087.                 var deletedParts:Array = Util.RemoveDuplicates(selectedParts.concat(affectedJoints));
  4088.                 AddAction(new ClearAction(deletedParts));
  4089.                 selectedParts = new Array();
  4090.                 m_sidePanel.visible = false;
  4091.                 CheckIfPartsFit();
  4092.                 curAction = -1;
  4093.                 curRobotID = "";
  4094.                 redrawRobot = true;
  4095.             }
  4096.         }
  4097.        
  4098.         public virtual function copyButton(e:MouseEvent):void {
  4099.             if (selectingCondition) return;
  4100.             if (simStarted) return;
  4101.             copiedJoint = null;
  4102.             copiedThrusters = null;
  4103.             if (selectedParts.length == 1) {
  4104.                 clipboardParts = new Array();
  4105.                 if (selectedParts[0] is ShapePart || selectedParts[0] is TextPart) {
  4106.                     clipboardParts.push(selectedParts[0].MakeCopy());
  4107.                 } else if (selectedParts[0] is JointPart) {
  4108.                     copiedJoint = selectedParts[0];
  4109.                 } else if (selectedParts[0] is Thrusters) {
  4110.                     copiedThrusters = selectedParts[0];
  4111.                 }
  4112.                 curAction = -1;
  4113.             } else if (selectedParts.length > 1) {
  4114.                 clipboardParts = new Array();
  4115.                 var partMapping:Array = new Array();
  4116.                 for (var i:int = 0; i < selectedParts.length; i++) {
  4117.                     if (selectedParts[i] is ShapePart) {
  4118.                         var copiedPart:ShapePart = (selectedParts[i] as ShapePart).MakeCopy();
  4119.                         clipboardParts.push(copiedPart);
  4120.                         partMapping.push(copiedPart);
  4121.                     } else if (selectedParts[i] is TextPart) {
  4122.                         clipboardParts.push((selectedParts[i] as TextPart).MakeCopy());
  4123.                         partMapping.push(-1);
  4124.                     } else {
  4125.                         partMapping.push(-1);
  4126.                     }
  4127.                 }
  4128.                 for (i = 0; i < selectedParts.length; i++) {
  4129.                     if (selectedParts[i] is JointPart) {
  4130.                         var index1:int = -1, index2:int = -1;
  4131.                         for (var j:int = 0; j < selectedParts.length; j++) {
  4132.                             if (selectedParts[j] == (selectedParts[i] as JointPart).part1) index1 = j;
  4133.                             if (selectedParts[j] == (selectedParts[i] as JointPart).part2) index2 = j;
  4134.                         }
  4135.                         if (index1 != -1 && index2 != -1) clipboardParts.push((selectedParts[i] as JointPart).MakeCopy(partMapping[index1], partMapping[index2]));
  4136.                     } else if (selectedParts[i] is Thrusters) {
  4137.                         index1 = -1;
  4138.                         for (j = 0; j < selectedParts.length; j++) {
  4139.                             if (selectedParts[j] == (selectedParts[i] as Thrusters).shape) index1 = j;
  4140.                         }
  4141.                         if (index1 != -1) clipboardParts.push((selectedParts[i] as Thrusters).MakeCopy(partMapping[index1]));
  4142.                     }
  4143.                 }
  4144.                 curAction = -1;
  4145.             }
  4146.         }
  4147.        
  4148.         public virtual function pasteButton(e:MouseEvent):void {
  4149.             if (selectingCondition) return;
  4150.             if (!curRobotEditable) return;
  4151.             if (simStarted) return;
  4152.             var hasCircles:Boolean = false;
  4153.             var hasRects:Boolean = false;
  4154.             var hasTriangles:Boolean = false;
  4155.             var hasFJs:Boolean = false;
  4156.             var hasRJs:Boolean = false;
  4157.             var hasSJs:Boolean = false;
  4158.             var hasThrusters:Boolean = false;
  4159.             var hasCannons:Boolean = false;
  4160.             var hasStatic:Boolean = false;
  4161.             for (var i:int = 0; i < clipboardParts.length; i++) {
  4162.                 if (clipboardParts[i].isStatic) hasStatic = true;
  4163.                 if (clipboardParts[i] is Circle) hasCircles = true;
  4164.                 if (clipboardParts[i] is Rectangle) hasRects = true;
  4165.                 if (clipboardParts[i] is Triangle) hasTriangles = true;
  4166.                 if (clipboardParts[i] is FixedJoint) hasFJs = true;
  4167.                 if (clipboardParts[i] is RevoluteJoint) hasRJs = true;
  4168.                 if (clipboardParts[i] is PrismaticJoint) hasSJs = true;
  4169.                 if (clipboardParts[i] is Thrusters) hasThrusters = true;
  4170.                 if (clipboardParts[i] is Cannon) hasCannons = true;
  4171.             }
  4172.             if (this is ControllerChallenge && ControllerChallenge.playChallengeMode && ((hasStatic && !ControllerChallenge.challenge.fixateAllowed) || (hasCircles && !ControllerChallenge.challenge.circlesAllowed) || (hasRects && !ControllerChallenge.challenge.rectanglesAllowed) || (hasTriangles && !ControllerChallenge.challenge.trianglesAllowed) || (hasFJs && !ControllerChallenge.challenge.fixedJointsAllowed) || (hasRJs && !ControllerChallenge.challenge.rotatingJointsAllowed) || (hasSJs && !ControllerChallenge.challenge.slidingJointsAllowed) || (hasThrusters && !ControllerChallenge.challenge.thrustersAllowed) || (hasCannons && !ControllerChallenge.challenge.cannonsAllowed))) {
  4173.                 m_fader.visible = true;
  4174.                 ShowDialog3("Sorry, some of the copied parts are not allowed in this challenge!");
  4175.                 m_progressDialog.ShowOKButton();
  4176.                 m_progressDialog.StopTimer();
  4177.                 Main.ShowMouse();
  4178.                 return;
  4179.             } else if (/*!Main.premiumMode && (hasThrusters || copiedThrusters)*/ false) {
  4180.                 m_fader.visible = true;
  4181.                 ShowDialog3("Sorry, only supporters are allowed to paste thrusters!");
  4182.                 m_progressDialog.ShowOKButton();
  4183.                 m_progressDialog.StopTimer();
  4184.                 Main.ShowMouse();
  4185.                 return;
  4186.             } else if (/*!Main.premiumMode && hasCannons*/ false) {
  4187.                 m_fader.visible = true;
  4188.                 ShowDialog3("Sorry, only supporters are allowed to paste cannons!");
  4189.                 m_progressDialog.ShowOKButton();
  4190.                 m_progressDialog.StopTimer();
  4191.                 Main.ShowMouse();
  4192.                 return;
  4193.             }
  4194.             if (clipboardParts.length == 1 && clipboardParts[0] is ShapePart) {
  4195.                 clipboardParts[0].Move(mouseXWorldPhys, mouseYWorldPhys);
  4196.                 allParts.push(clipboardParts[0]);
  4197.                 selectedParts = new Array();
  4198.                 selectedParts.push(clipboardParts[0]);
  4199.                 draggingPart = clipboardParts[0];
  4200.                 initDragX = mouseXWorldPhys;
  4201.                 initDragY = mouseYWorldPhys;
  4202.                 draggingParts = draggingPart.GetAttachedParts();
  4203.                 draggingPart.dragXOff = 0;
  4204.                 draggingPart.dragYOff = 0;
  4205.                 if (clipboardParts[0] is Cannon) m_sidePanel.ShowCannonPanel(clipboardParts[0]);
  4206.                 else m_sidePanel.ShowObjectPanel(clipboardParts[0]);
  4207.                 AddAction(new CreateAction(clipboardParts[0]));
  4208.                 clipboardParts[0] = clipboardParts[0].MakeCopy();
  4209.                 curAction = PASTE;
  4210.                 curRobotID = "";
  4211.             } else if (copiedJoint) {
  4212.                 if (copiedJoint is FixedJoint) {
  4213.                     curAction = NEW_FIXED_JOINT;
  4214.                 } else if (copiedJoint is RevoluteJoint) {
  4215.                     curAction = NEW_REVOLUTE_JOINT;
  4216.                 } else {
  4217.                     curAction = NEW_PRISMATIC_JOINT;
  4218.                 }
  4219.                 actionStep = 0;
  4220.             } else if (copiedThrusters) {
  4221.                 curAction = NEW_THRUSTERS;
  4222.             } else {
  4223.                 draggingPart = null;
  4224.                 m_sidePanel.visible = false;
  4225.                 selectedParts = new Array();
  4226.                 draggingParts = new Array();
  4227.                 for (i = 0; i < clipboardParts.length; i++) {
  4228.                     if (clipboardParts[i] is ShapePart) {
  4229.                         if (!draggingPart || draggingPart is TextPart || clipboardParts[i].GetMass() > (draggingPart as ShapePart).GetMass()) draggingPart = clipboardParts[i];
  4230.                     } else if (clipboardParts[i] is TextPart && !draggingPart) {
  4231.                         draggingPart = clipboardParts[i];
  4232.                     }
  4233.                 }
  4234.  
  4235.                 var oldClipboardParts:Array = new Array();
  4236.                 for (i = 0; i < clipboardParts.length; i++) {
  4237.                     oldClipboardParts.push(clipboardParts[i]);
  4238.                 }
  4239.                 for (i = 0; i < clipboardParts.length; i++) {
  4240.                     if (clipboardParts[i] is ShapePart) {
  4241.                         clipboardParts[i].dragXOff = (draggingPart as ShapePart).centerX - clipboardParts[i].centerX;
  4242.                         clipboardParts[i].dragYOff = (draggingPart as ShapePart).centerY - clipboardParts[i].centerY;
  4243.                         allParts.push(clipboardParts[i]);
  4244.                         selectedParts.push(clipboardParts[i]);
  4245.                         draggingParts = Util.RemoveDuplicates(draggingParts.concat(clipboardParts[i].GetAttachedParts()));
  4246.                         clipboardParts[i] = clipboardParts[i].MakeCopy();
  4247.                         if (oldClipboardParts[i] != draggingPart) oldClipboardParts[i].Move(oldClipboardParts[i].centerX - (draggingPart as ShapePart).centerX + mouseXWorldPhys, oldClipboardParts[i].centerY - (draggingPart as ShapePart).centerY + mouseYWorldPhys);
  4248.                     } else if (clipboardParts[i] is TextPart) {
  4249.                         if (draggingPart is ShapePart) {
  4250.                             clipboardParts[i].dragXOff = (draggingPart as ShapePart).centerX - clipboardParts[i].x;
  4251.                             clipboardParts[i].dragYOff = (draggingPart as ShapePart).centerY - clipboardParts[i].y;
  4252.                         } else {
  4253.                             clipboardParts[i].dragXOff = (draggingPart as TextPart).x - clipboardParts[i].x;
  4254.                             clipboardParts[i].dragYOff = (draggingPart as TextPart).y - clipboardParts[i].y;
  4255.                         }
  4256.                         allParts.push(clipboardParts[i]);
  4257.                         selectedParts.push(clipboardParts[i]);
  4258.                         draggingParts = draggingParts.concat(clipboardParts[i].GetAttachedParts());
  4259.                         clipboardParts[i] = clipboardParts[i].MakeCopy();
  4260.                         if (oldClipboardParts[i] != draggingPart) {
  4261.                             if (draggingPart is ShapePart) {
  4262.                                 oldClipboardParts[i].Move(oldClipboardParts[i].x - (draggingPart as ShapePart).centerX + mouseXWorldPhys, oldClipboardParts[i].y - (draggingPart as ShapePart).centerY + mouseYWorldPhys);
  4263.                             } else {
  4264.                                 oldClipboardParts[i].Move(oldClipboardParts[i].x - (draggingPart as TextPart).x + mouseXWorldPhys, oldClipboardParts[i].y - (draggingPart as TextPart).y + mouseYWorldPhys);
  4265.                             }
  4266.                         }
  4267.                     }
  4268.                 }
  4269.                 for (i = 0; i < clipboardParts.length; i++) {
  4270.                     if (clipboardParts[i] is JointPart) {
  4271.                         clipboardParts[i].dragXOff = (draggingPart as ShapePart).centerX - clipboardParts[i].anchorX;
  4272.                         clipboardParts[i].dragYOff = (draggingPart as ShapePart).centerY - clipboardParts[i].anchorY;
  4273.                         allParts.push(clipboardParts[i]);
  4274.                         selectedParts.push(clipboardParts[i]);
  4275.                         var index1:int = -1, index2:int = -1;
  4276.                         for (var j:int = 0; j < oldClipboardParts.length; j++) {
  4277.                             if (oldClipboardParts[j] == (clipboardParts[i] as JointPart).part1) index1 = j;
  4278.                             if (oldClipboardParts[j] == (clipboardParts[i] as JointPart).part2) index2 = j;
  4279.                         }
  4280.                         clipboardParts[i] = clipboardParts[i].MakeCopy(clipboardParts[index1], clipboardParts[index2]);
  4281.                         oldClipboardParts[i].Move(oldClipboardParts[i].anchorX - (draggingPart as ShapePart).centerX + mouseXWorldPhys, oldClipboardParts[i].anchorY - (draggingPart as ShapePart).centerY + mouseYWorldPhys);
  4282.                     } else if (clipboardParts[i] is Thrusters) {
  4283.                         clipboardParts[i].dragXOff = (draggingPart as ShapePart).centerX - clipboardParts[i].centerX;
  4284.                         clipboardParts[i].dragYOff = (draggingPart as ShapePart).centerY - clipboardParts[i].centerY;
  4285.                         allParts.push(clipboardParts[i]);
  4286.                         selectedParts.push(clipboardParts[i]);
  4287.                         index1 = -1;
  4288.                         for (j = 0; j < oldClipboardParts.length; j++) {
  4289.                             if (oldClipboardParts[j] == (clipboardParts[i] as Thrusters).shape) index1 = j;
  4290.                         }
  4291.                         clipboardParts[i] = clipboardParts[i].MakeCopy(clipboardParts[index1]);
  4292.                         oldClipboardParts[i].Move(oldClipboardParts[i].centerX - (draggingPart as ShapePart).centerX + mouseXWorldPhys, oldClipboardParts[i].centerY - (draggingPart as ShapePart).centerY + mouseYWorldPhys);
  4293.                     }
  4294.                 }
  4295.                 if (draggingPart) {
  4296.                     initDragX = mouseXWorldPhys;
  4297.                     initDragY = mouseYWorldPhys;
  4298.                     draggingPart.Move(mouseXWorldPhys, mouseYWorldPhys);
  4299.                     m_sidePanel.ShowMultiSelectPanel(selectedParts);
  4300.                     AddAction(new MassCreateAction(selectedParts));
  4301.                     curAction = PASTE;
  4302.                     curRobotID = "";
  4303.                 }
  4304.             }
  4305.         }
  4306.        
  4307.         public virtual function centerBox(e:MouseEvent):void {
  4308.             snapToCenter = !snapToCenter;
  4309.         }
  4310.        
  4311.         public function jointBox(e:MouseEvent):void {
  4312.             showJoints = !showJoints
  4313.             redrawRobot = true;
  4314.         }
  4315.        
  4316.         public function globalOutlineBox(e:MouseEvent):void {
  4317.             showOutlines = !showOutlines;
  4318.             redrawRobot = true;
  4319.         }
  4320.        
  4321.         public function colourBox(e:MouseEvent):void {
  4322.             showColours = !showColours;
  4323.             if (showColours) draw.m_fillAlpha = 1.0;
  4324.             else draw.m_fillAlpha = 0.5;
  4325.             redrawRobot = true;
  4326.         }
  4327.        
  4328.         public function centerOnSelectedBox(e:MouseEvent):void {
  4329.             centerOnSelected = !centerOnSelected;
  4330.             if (centerOnSelected && selectedParts.length == 1) {
  4331.                 CenterOnSelected();
  4332.             }
  4333.         }
  4334.        
  4335.         public function ConfirmNewRobot(e:MouseEvent):void {
  4336.             Main.changeControllers = true;
  4337.             Main.nextControllerType = -1;
  4338.             playingReplay = false;
  4339.             viewingUnsavedReplay = false;
  4340.         }
  4341.        
  4342.         public virtual override function loginButton(e:MouseEvent, displayMessage:Boolean = false, backToSave:Boolean = false, saveLoadWindowOpen:Boolean = false):void {
  4343.             if (selectingCondition) return;
  4344.             if (Main.inIFrame) {
  4345.                 m_fader.visible = true;
  4346.                 ShowConfirmDialog("Redirect to incredibots2.com?", 7);
  4347.             } else {
  4348.                 m_fader.visible = true;
  4349.                 if (m_loginWindow) removeChild(m_loginWindow);
  4350.                 m_loginWindow = new LoginWindow(this);
  4351.                 if (displayMessage) m_loginWindow.displayMessage();
  4352.                 addChild(m_loginWindow);
  4353.                 backToSaveWindow = backToSave;
  4354.             }
  4355.         }
  4356.        
  4357.         public function logoutButton(e:MouseEvent):void {
  4358.             m_fader.visible = true;
  4359.             ShowConfirmDialog("Are you sure you want to log " + userName +  " out?", 12);
  4360.         }
  4361.        
  4362.         public override function ConfirmLogout(e:MouseEvent):void {
  4363.             Main.premiumMode = false;
  4364.             userName = "_Public";
  4365.             m_guiPanel.ShowLogin();
  4366.             ShowDialog3("You are now logged out.");
  4367.             m_progressDialog.ShowOKButton();
  4368.             m_progressDialog.StopTimer();
  4369.             m_fader.visible = true;
  4370.         }
  4371.        
  4372.         public function loginHidden(e:Event, success:Boolean):void {
  4373.             if (clickedSave) {
  4374.                 clickedSave = false;
  4375.                 saveButton(new MouseEvent(""));
  4376.             } else if (clickedSaveReplay) {
  4377.                 clickedSaveReplay = false;
  4378.                 saveReplayButton(new MouseEvent(""));
  4379.             } else if (clickedSaveChallenge) {
  4380.                 clickedSaveChallenge = false;
  4381.                 saveButton(new MouseEvent(""));
  4382.             } else if (clickedSubmitScore) {
  4383.                 AddSyncPoint();
  4384.                 if (viewingUnsavedReplay) Database.SaveReplay(userName, password, replay, "_ScoreReplay", "This replay is saved for a score", curRobotID, new Robot(allParts, ControllerSandbox.settings), (ChallengeOver() ? GetScore() : -1), curChallengeID, 1, finishSavingReplay);
  4385.                 else Database.SaveReplay(userName, password, new Replay(cameraMovements, syncPoints, keyPresses, frameCounter, Database.VERSION_STRING_FOR_REPLAYS), "_ScoreReplay", "This replay is saved for a score", curRobotID, new Robot(allParts, ControllerSandbox.settings), (ChallengeOver() ? GetScore() : -1), curChallengeID, 1, finishSavingReplay);
  4386.                 m_scoreWindow.ShowFader();
  4387.                 ShowDialog("Submitting score...");
  4388.                 Main.ShowHourglass();
  4389.             } else if (clickedReport) {
  4390.                 clickedReport = false;
  4391.                 reportButton(new MouseEvent(""));
  4392.             } else if (backToSaveWindow) {
  4393.                 m_fader.visible = true;
  4394.                 if (m_chooserWindow.visible) {
  4395.                     if (success) {
  4396.                         m_chooserWindow.reportClicked(new MouseEvent(""));
  4397.                     } else {
  4398.                         m_chooserWindow.HideFader();
  4399.                     }
  4400.                 } else {
  4401.                     m_chooserWindow.visible = true;
  4402.                     if (m_chooserWindow.dataType == SaveLoadWindow.HIGH_SCORE_TYPE) {
  4403.                         Database.GetScoreData(userName, password, Database.highScoresChallenge, m_chooserWindow.m_scoreTypeBox.selectedIndex == 1, m_chooserWindow.m_scoreTypeBox.selectedIndex == 2, (success && m_chooserWindow.m_scoreTypeBox.selectedIndex == 2 ? Database.SORT_BY_SCORE : Database.highScoresSortType), (success && m_chooserWindow.m_scoreTypeBox.selectedIndex == 2 ? 1 : Database.curScorePage), (success && m_chooserWindow.m_scoreTypeBox && m_chooserWindow.m_scoreTypeBox.selectedIndex == 2 ? "" : Database.curSearch), finishGettingScoreData);
  4404.                         ShowDialog("Getting scores...");
  4405.                     } else if (m_chooserWindow.dataType == SaveLoadWindow.LOAD_ROBOT_TYPE) {
  4406.                         Database.GetRobotData(userName, password, !m_chooserWindow.yourRobotsBox.selected, (success && m_chooserWindow.yourRobotsBox.selected ? Database.SORT_BY_EDIT_TIME : Database.curSortType), (success && m_chooserWindow.yourRobotsBox.selected ? Database.SORT_PERIOD_ALLTIME : Database.curSortPeriod), (success && m_chooserWindow.yourRobotsBox.selected ? 1 : Database.curRobotPage), (success && m_chooserWindow.m_scoreTypeBox && m_chooserWindow.m_scoreTypeBox.selectedIndex == 2 ? "" : Database.curSearch), finishGettingLoadRobotData);
  4407.                         ShowDialog("Getting robots...");
  4408.                     } else if (m_chooserWindow.dataType == SaveLoadWindow.LOAD_CHALLENGE_TYPE) {
  4409.                         if (Database.curSortPeriod == Database.SORT_PERIOD_PROP) Database.curSortPeriod = Database.SORT_PERIOD_ALLTIME;
  4410.                         Database.GetChallengeData(userName, password, !m_chooserWindow.yourRobotsBox.selected, (success && m_chooserWindow.yourRobotsBox.selected ? Database.SORT_BY_EDIT_TIME : Database.curSortType), (success && m_chooserWindow.yourRobotsBox.selected ? Database.SORT_PERIOD_ALLTIME : Database.curSortPeriod), (success && m_chooserWindow.yourRobotsBox.selected ? 1 : Database.curReplayPage), (success && m_chooserWindow.m_scoreTypeBox && m_chooserWindow.m_scoreTypeBox.selectedIndex == 2 ? "" : Database.curSearch), finishGettingLoadChallengeData);
  4411.                         ShowDialog("Getting challenges...");
  4412.                     } else {
  4413.                         if (Database.curSortPeriod == Database.SORT_PERIOD_PROP) Database.curSortPeriod = Database.SORT_PERIOD_ALLTIME;
  4414.                         Database.GetReplayData(userName, password, !m_chooserWindow.yourRobotsBox.selected, (success && m_chooserWindow.yourRobotsBox.selected ? Database.SORT_BY_EDIT_TIME : Database.curSortType), (success && m_chooserWindow.yourRobotsBox.selected ? Database.SORT_PERIOD_ALLTIME : Database.curSortPeriod), (success && m_chooserWindow.yourRobotsBox.selected ? 1 : Database.curReplayPage), (success && m_chooserWindow.m_scoreTypeBox && m_chooserWindow.m_scoreTypeBox.selectedIndex == 2 ? "" : Database.curSearch), finishGettingLoadReplayData);
  4415.                         ShowDialog("Getting replays...");
  4416.                     }
  4417.                     m_chooserWindow.ShowFader();
  4418.                     Main.ShowHourglass();
  4419.                 }
  4420.             }
  4421.         }
  4422.        
  4423.         public function viewReplayButton(e:MouseEvent):void {
  4424.             if (viewingUnsavedReplay) {
  4425.                 m_fader.visible = false;
  4426.                 m_scoreWindow.visible = false;
  4427.                 resetButton(e);
  4428.             } else {
  4429.                 resetButton(e);
  4430.                 replay = new Replay(cameraMovements, syncPoints, keyPresses, frameCounter, Database.VERSION_STRING_FOR_REPLAYS);
  4431.                 replayParts = allParts.filter(IsPartOfRobot);
  4432.                 playingReplay = true;
  4433.                 Main.changeControllers = true;
  4434.                 viewingUnsavedReplay = true;
  4435.             }
  4436.         }
  4437.        
  4438.         public function newButton(e:MouseEvent):void {
  4439.             if (Main.inIFrame) {
  4440.                 m_fader.visible = true;
  4441.                 ShowConfirmDialog("Redirect to incredibots2.com?", 7);
  4442.             } else {
  4443.                 var partsExist:Boolean = false;
  4444.                 for (var i:int = 0; i < allParts.length; i++) {
  4445.                     if (allParts[i].isEditable) {
  4446.                         partsExist = true;
  4447.                         break;
  4448.                     }
  4449.                 }
  4450.                 if (this is ControllerTutorial || this is ControllerHomeMovies || this is ControllerRubeGoldberg || this is ControllerNewFeatures || this is ControllerChallengeEditor || (curRobotID != "" && (!(this is ControllerChallenge) || curChallengeID != "")) || (!partsExist && !(this is ControllerChallenge))) {
  4451.                     ConfirmNewRobot(e);
  4452.                 } else {
  4453.                     m_fader.visible = true;
  4454.                     if (m_scoreWindow && m_scoreWindow.visible) m_scoreWindow.ShowFader();
  4455.                     ShowConfirmDialog("Exit to main menu?     (Unsaved changes will be lost)", 4);
  4456.                 }
  4457.             }
  4458.         }
  4459.        
  4460.         public virtual function saveButton(e:MouseEvent):void {
  4461.             if (selectingCondition) return;
  4462.             if (Main.inIFrame) {
  4463.                 m_fader.visible = true;
  4464.                 ShowConfirmDialog("Redirect to incredibots2.com?", 7);
  4465.             } else {
  4466.                 if (!curRobotEditable || playingReplay) return;
  4467.                 if (true || userName != "_Public") {
  4468.                     if (/*!Main.premiumMode*/ false) {
  4469.                         for (var i:int = 0; i < allParts.length; i++) {
  4470.                             if (allParts[i] is Thrusters) {
  4471.                                 m_fader.visible = true;
  4472.                                 ShowDialog3("Sorry, only supporters are allowed to save robots containing thrusters!");
  4473.                                 m_progressDialog.ShowOKButton();
  4474.                                 m_progressDialog.StopTimer();
  4475.                                 Main.ShowMouse();
  4476.                                 return;
  4477.                             }
  4478.                             if (allParts[i] is Cannon) {
  4479.                                 m_fader.visible = true;
  4480.                                 ShowDialog3("Sorry, only supporters are allowed to save robots containing cannons!");
  4481.                                 m_progressDialog.ShowOKButton();
  4482.                                 m_progressDialog.StopTimer();
  4483.                                 Main.ShowMouse();
  4484.                                 return;
  4485.                             }
  4486.                         }
  4487.                     }
  4488.                     if (this is ControllerChallenge && !ControllerChallenge.playChallengeMode) {
  4489.                         if (m_restrictionsDialog) removeChild(m_restrictionsDialog);
  4490.                         m_restrictionsDialog = new RestrictionsWindow(this as ControllerChallenge);
  4491.                         addChild(m_restrictionsDialog);
  4492.                         saveAfterRestrictions = true;
  4493.                     } else {
  4494.                         //Database.GetRobotData(userName, password, false, Database.curSortType, (Database.curSortPeriod == Database.SORT_PERIOD_FEATURED ? Database.SORT_PERIOD_ALLTIME : Database.curSortPeriod), 1, "", finishGettingSaveRobotData);
  4495.                         //ShowDialog("Getting robots...");
  4496.                         //Main.ShowHourglass();
  4497.                         Database.ExportRobot(new Robot(allParts.filter(PartIsEditable), ControllerSandbox.settings, draw.m_drawXOff, draw.m_drawYOff, m_physScale), "", "", 1, 1, 0, finishExporting);
  4498.                     }
  4499.                     m_fader.visible = true;
  4500.                     curAction = -1;
  4501.                 } else {
  4502.                     clickedSave = true;
  4503.                     loginButton(e, true, false);
  4504.                 }
  4505.             }
  4506.         }
  4507.        
  4508.         public function loadAndInsertButton(e:MouseEvent):void {
  4509.             if (curRobotEditable && !selectingCondition && !playingReplay) {
  4510.                 loadAndInsert = true;
  4511.                 loadRobotButton(e);
  4512.             }
  4513.         }
  4514.        
  4515.         public virtual function loadButton(e:MouseEvent, makeThemRate:Boolean = true):void {
  4516.             if (selectingCondition) return;
  4517.             if (Main.inIFrame) {
  4518.                 m_fader.visible = true;
  4519.                 ShowConfirmDialog("Redirect to incredibots2.com?", 7);
  4520.             } else if (makeThemRate && playingReplay && curReplayID != "" && curReplayPublic && !ratedCurReplay && !LSOManager.HasRatedReplay(curReplayID)) {
  4521.                 ratedCurReplay = true;
  4522.                 if (m_rateDialog) removeChild(m_rateDialog);
  4523.                 m_rateDialog = new RateWindow(this, 1, 1);
  4524.                 addChild(m_rateDialog);
  4525.                 m_fader.visible = true;
  4526.                 m_guiPanel.ShowPausePanel(!playingReplay);
  4527.                 paused = true;
  4528.             } else if (makeThemRate && !playingReplay && curChallengeID != "" && curChallengePublic && !ratedCurChallenge && !LSOManager.HasRatedChallenge(curChallengeID)) {
  4529.                 ratedCurChallenge = true;
  4530.                 if (m_rateDialog) removeChild(m_rateDialog);
  4531.                 m_rateDialog = new RateWindow(this, 2, 1);
  4532.                 addChild(m_rateDialog);
  4533.                 m_fader.visible = true;
  4534.                 if (simStarted) {
  4535.                     m_guiPanel.ShowPausePanel(!playingReplay);
  4536.                     paused = true;
  4537.                 }
  4538.             } else if (makeThemRate && !playingReplay && curRobotID != "" && curRobotPublic && !ratedCurRobot && !LSOManager.HasRatedRobot(curRobotID)) {
  4539.                 ratedCurRobot = true;
  4540.                 if (m_rateDialog) removeChild(m_rateDialog);
  4541.                 m_rateDialog = new RateWindow(this, 0, 1);
  4542.                 addChild(m_rateDialog);
  4543.                 m_fader.visible = true;
  4544.                 if (simStarted) {
  4545.                     m_guiPanel.ShowPausePanel(!playingReplay);
  4546.                     paused = true;
  4547.                 }
  4548.             } else {
  4549.                 m_fader.visible = true;
  4550.                 if (m_loadWindow) removeChild(m_loadWindow);
  4551.                 m_loadWindow = new LoadWindow(this);
  4552.                 addChild(m_loadWindow);
  4553.             }
  4554.         }
  4555.        
  4556.         public function loadRobotButton(e:MouseEvent, makeThemRate:Boolean = true):void {
  4557.             if (selectingCondition) return;
  4558.             if (Main.inIFrame) {
  4559.                 m_fader.visible = true;
  4560.                 ShowConfirmDialog("Redirect to incredibots2.com?", 7);
  4561.             } else if (makeThemRate && playingReplay && curReplayID != "" && curReplayPublic && !ratedCurReplay && !LSOManager.HasRatedReplay(curReplayID)) {
  4562.                 ratedCurReplay = true;
  4563.                 if (m_rateDialog) removeChild(m_rateDialog);
  4564.                 m_rateDialog = new RateWindow(this, 1, 2);
  4565.                 addChild(m_rateDialog);
  4566.                 m_fader.visible = true;
  4567.                 m_guiPanel.ShowPausePanel(!playingReplay);
  4568.                 paused = true;
  4569.             } else if (makeThemRate && !playingReplay && curChallengeID != "" && curChallengePublic && !ratedCurChallenge && !LSOManager.HasRatedChallenge(curChallengeID)) {
  4570.                 ratedCurChallenge = true;
  4571.                 if (m_rateDialog) removeChild(m_rateDialog);
  4572.                 m_rateDialog = new RateWindow(this, 2, 2);
  4573.                 addChild(m_rateDialog);
  4574.                 m_fader.visible = true;
  4575.                 if (simStarted) {
  4576.                     m_guiPanel.ShowPausePanel(!playingReplay);
  4577.                     paused = true;
  4578.                 }
  4579.             } else if (makeThemRate && !playingReplay && curRobotID != "" && curRobotPublic && !ratedCurRobot && !LSOManager.HasRatedRobot(curRobotID)) {
  4580.                 ratedCurRobot = true;
  4581.                 if (m_rateDialog) removeChild(m_rateDialog);
  4582.                 m_rateDialog = new RateWindow(this, 0, 2);
  4583.                 addChild(m_rateDialog);
  4584.                 m_fader.visible = true;
  4585.                 m_guiPanel.ShowPausePanel(!playingReplay);
  4586.                 paused = true;
  4587.             } else {
  4588.                 Database.GetRobotData(userName, password, Database.curShared, Database.curSortType, Database.curSortPeriod, (Database.curShared ? Database.curRobotPage : 1), "", finishGettingLoadRobotData);
  4589.                 m_fader.visible = true;
  4590.                 ShowDialog("Getting robots...");
  4591.                 Main.ShowHourglass();
  4592.                 curAction = -1;
  4593.             }
  4594.         }
  4595.        
  4596.         public function finishSaving(e:Event):void {
  4597.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_SAVE_ROBOT) return;
  4598.             var robotID:String = Database.FinishSavingRobot(e);
  4599.             if (robotID != "") {
  4600.                 curRobotID = robotID;
  4601.                 ratedCurRobot = true;
  4602.                 curRobotPublic = potentialRobotPublic;
  4603.                 curRobotFeatured = potentialRobotFeatured;
  4604.                 m_progressDialog.SetMessage("Save successful!");
  4605.                 m_progressDialog.HideInXSeconds(1);
  4606.                 m_chooserWindow.visible = false;
  4607.                 removeChild(m_chooserWindow);
  4608.                 m_chooserWindow = null;
  4609.                 m_fader.visible = false;
  4610.             }
  4611.         }
  4612.        
  4613.         public function finishGettingSaveRobotData(e:Event):void {
  4614.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_GET_ROBOT_DATA) return;
  4615.             if (Database.FinishGettingRobotData(e)) {
  4616.                 m_progressDialog.visible = false;
  4617.                 if (m_chooserWindow) removeChild(m_chooserWindow);
  4618.                 m_chooserWindow = new SaveLoadWindow(this, SaveLoadWindow.SAVE_ROBOT_TYPE);
  4619.                 addChild(m_chooserWindow);
  4620.             }
  4621.         }
  4622.        
  4623.         public override function finishGettingLoadRobotData(e:Event):void {
  4624.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_GET_ROBOT_DATA) return;
  4625.             if (Database.FinishGettingRobotData(e)) {
  4626.                 m_progressDialog.visible = false;
  4627.                 if (m_chooserWindow) removeChild(m_chooserWindow);
  4628.                 m_chooserWindow = new SaveLoadWindow(this, SaveLoadWindow.LOAD_ROBOT_TYPE);
  4629.                 addChild(m_chooserWindow);
  4630.             }
  4631.         }
  4632.        
  4633.         public override function finishLoading(e:Event):void {
  4634.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_LOAD_ROBOT) return;
  4635.             var robot:Robot = Database.FinishLoadingRobot(e);
  4636.             processLoadedRobot(robot);
  4637.         }
  4638.        
  4639.         public override function processLoadedRobot(robot:Robot):void {
  4640.             if (robot) {
  4641.                 var newParts:Array = robot.allParts;
  4642.                 if (loadAndInsert) {
  4643.                     loadAndInsert = false;
  4644.                     var hasCircles:Boolean = false;
  4645.                     var hasRects:Boolean = false;
  4646.                     var hasTriangles:Boolean = false;
  4647.                     var hasFJs:Boolean = false;
  4648.                     var hasRJs:Boolean = false;
  4649.                     var hasSJs:Boolean = false;
  4650.                     var hasThrusters:Boolean = false;
  4651.                     var hasCannons:Boolean = false;
  4652.                     var hasStatic:Boolean = false;
  4653.                     for (var i:int = 0; i < newParts.length; i++) {
  4654.                         if (newParts[i].isStatic) hasStatic = true;
  4655.                         if (newParts[i] is Circle) hasCircles = true;
  4656.                         if (newParts[i] is Rectangle) hasRects = true;
  4657.                         if (newParts[i] is Triangle) hasTriangles = true;
  4658.                         if (newParts[i] is FixedJoint) hasFJs = true;
  4659.                         if (newParts[i] is RevoluteJoint) hasRJs = true;
  4660.                         if (newParts[i] is PrismaticJoint) hasSJs = true;
  4661.                         if (newParts[i] is Thrusters) hasThrusters = true;
  4662.                         if (newParts[i] is Cannon) hasCannons = true;
  4663.                     }
  4664.                     if (this is ControllerChallenge && ((hasStatic && !ControllerChallenge.challenge.fixateAllowed) || (hasCircles && !ControllerChallenge.challenge.circlesAllowed) || (hasRects && !ControllerChallenge.challenge.rectanglesAllowed) || (hasTriangles && !ControllerChallenge.challenge.trianglesAllowed) || (hasFJs && !ControllerChallenge.challenge.fixedJointsAllowed) || (hasRJs && !ControllerChallenge.challenge.rotatingJointsAllowed) || (hasSJs && !ControllerChallenge.challenge.slidingJointsAllowed) || (hasThrusters && !ControllerChallenge.challenge.thrustersAllowed) || (hasCannons && !ControllerChallenge.challenge.cannonsAllowed))) {
  4665.                         m_fader.visible = true;
  4666.                         loadAndInsert = true;
  4667.                         ShowDialog3("Sorry, that robot contains parts that are not allowed in this challenge!");
  4668.                         m_progressDialog.ShowOKButton();
  4669.                         m_progressDialog.StopTimer();
  4670.                         Main.ShowMouse();
  4671.                         return;
  4672.                     } else {
  4673.                         curRobotID = "";
  4674.                         allParts = allParts.concat(newParts);
  4675.                         CheckIfPartsFit();
  4676.                         m_progressDialog.SetMessage("Load successful!");
  4677.                         m_progressDialog.HideInXSeconds(1);
  4678.                         if (m_chooserWindow) {
  4679.                             m_chooserWindow.visible = false;
  4680.                             removeChild(m_chooserWindow);
  4681.                             m_chooserWindow = null;
  4682.                         }
  4683.                         m_fader.visible = false;
  4684.                         curRobotEditable = (potentialRobotEditable/* && ((!hasThrusters && !hasCannons) || Main.premiumMode)*/);
  4685.                         curRobotPublic = false;
  4686.                         curRobotFeatured = false;
  4687.                         redrawRobot = true;
  4688.                         CenterOnLoadedRobot();
  4689.                     }
  4690.                 } else {
  4691.                     curRobotID = potentialRobotID;
  4692.                     ratedCurRobot = false;
  4693.                     curRobotEditable = (potentialRobotEditable/* && ((!hasThrusters && !hasCannons) || Main.premiumMode)*/);
  4694.                     curRobotPublic = potentialRobotPublic;
  4695.                     curRobotFeatured = potentialRobotFeatured;
  4696.                     curReplayID = "";
  4697.                     loadedParts = newParts;
  4698.                     Main.changeControllers = true;
  4699.                     playingReplay = false;
  4700.                     initX = robot.cameraX;
  4701.                     initY = robot.cameraY;
  4702.                     initZoom = robot.zoomLevel;
  4703.                     if (robot.challenge) {
  4704.                         Main.nextControllerType = 1;
  4705.                         ControllerChallenge.challenge = robot.challenge;
  4706.                         ControllerChallenge.playChallengeMode = true;
  4707.                         ControllerChallenge.playOnlyMode = true;
  4708.                         ControllerSandbox.settings = robot.challenge.settings;
  4709.                         curChallengeID = potentialChallengeID;
  4710.                         ratedCurChallenge = false;
  4711.                         curChallengePublic = false;
  4712.                         curChallengeFeatured = false;
  4713.                         justLoadedRobotWithChallenge = true;
  4714.                     } else {
  4715.                         Main.nextControllerType = 0;
  4716.                         ControllerSandbox.settings = robot.settings;
  4717.                         curChallengeID = "";
  4718.                     }
  4719.                 }
  4720.             }
  4721.         }
  4722.        
  4723.         public override function finishDeleting(e:Event):void {
  4724.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_DELETE_ROBOT) return;
  4725.             var id:String = Database.FinishDeletingRobot(e);
  4726.             if (id != "") {
  4727.                 if (curRobotID == id) curRobotID = "";
  4728.                 m_progressDialog.SetMessage("Delete successful!");
  4729.                 m_progressDialog.HideInXSeconds(1);
  4730.                 var type:int = m_chooserWindow.dataType;
  4731.                 removeChild(m_chooserWindow);
  4732.                 m_chooserWindow = new SaveLoadWindow(this, type);
  4733.                 addChild(m_chooserWindow);
  4734.                 removeChild(m_progressDialog);
  4735.                 addChild(m_progressDialog);
  4736.             }
  4737.         }
  4738.        
  4739.         public override function finishExporting(exportStr:String, robotStr:String):void {
  4740.             if (m_chooserWindow) m_chooserWindow.visible = false;
  4741.             if (m_exportDialog) removeChild(m_exportDialog);
  4742.             m_exportDialog = new ExportWindow(this, exportStr, robotStr);
  4743.             m_fader.visible = true;
  4744.             addChild(m_exportDialog);
  4745.         }
  4746.        
  4747.         public virtual function saveReplayButton(e:MouseEvent):void {
  4748.             if (Main.inIFrame) {
  4749.                 m_fader.visible = true;
  4750.                 ShowConfirmDialog("Redirect to incredibots2.com?", 7);
  4751.             } else {
  4752.                 pauseButton(e);
  4753.                 if (canSaveReplay) {
  4754.                     if (true || userName != "_Public") {
  4755.                         //if (Database.curSortPeriod == Database.SORT_PERIOD_PROP) Database.curSortPeriod = Database.SORT_PERIOD_ALLTIME;
  4756.                         //Database.GetReplayData(userName, password, false, Database.curSortType, (Database.curSortPeriod == Database.SORT_PERIOD_FEATURED ? Database.SORT_PERIOD_ALLTIME : Database.curSortPeriod), 1, "", finishGettingSaveReplayData);
  4757.                         //ShowDialog("Getting replays...");
  4758.                         //Main.ShowHourglass();
  4759.                         //m_fader.visible = true;
  4760.                         AddSyncPoint();
  4761.                         if (viewingUnsavedReplay) Database.ExportReplay(replay, "", "", curRobotID, new Robot(allParts, ControllerSandbox.settings), -1, "", 1, finishExporting);
  4762.                         else Database.ExportReplay(new Replay(cameraMovements, syncPoints, keyPresses, frameCounter, Database.VERSION_STRING_FOR_REPLAYS), "", "", curRobotID, new Robot(allParts, ControllerSandbox.settings), -1, "", 1, finishExporting);
  4763.                     } else {
  4764.                         clickedSaveReplay = true;
  4765.                         loginButton(e, true, false);
  4766.                     }
  4767.                 } else {
  4768.                     m_fader.visible = true;
  4769.                     if (frameCounter >= 9000) ShowDialog3("Sorry, you can only save replays that are under 5 minutes in length.");
  4770.                     else ShowDialog3("Sorry, you can only save replays that contain 500 or fewer cannonballs.");
  4771.                     m_progressDialog.ShowOKButton();
  4772.                     m_progressDialog.StopTimer();
  4773.                 }
  4774.             }
  4775.         }
  4776.        
  4777.         public virtual function loadReplayButton(e:MouseEvent, makeThemRate:Boolean = true):void {
  4778.             if (selectingCondition) return;
  4779.             if (Main.inIFrame) {
  4780.                 m_fader.visible = true;
  4781.                 ShowConfirmDialog("Redirect to incredibots2.com?", 7);
  4782.             } else if (makeThemRate && playingReplay && curReplayID != "" && curReplayPublic && !ratedCurReplay && !LSOManager.HasRatedReplay(curReplayID)) {
  4783.                 ratedCurReplay = true;
  4784.                 if (m_rateDialog) removeChild(m_rateDialog);
  4785.                 m_rateDialog = new RateWindow(this, 1, 3);
  4786.                 addChild(m_rateDialog);
  4787.                 m_fader.visible = true;
  4788.                 m_guiPanel.ShowPausePanel(!playingReplay);
  4789.                 paused = true;
  4790.             } else if (makeThemRate && !playingReplay && curChallengeID != "" && curChallengePublic && !ratedCurChallenge && !LSOManager.HasRatedChallenge(curChallengeID)) {
  4791.                 ratedCurChallenge = true;
  4792.                 if (m_rateDialog) removeChild(m_rateDialog);
  4793.                 m_rateDialog = new RateWindow(this, 2, 3);
  4794.                 addChild(m_rateDialog);
  4795.                 m_fader.visible = true;
  4796.                 if (simStarted) {
  4797.                     m_guiPanel.ShowPausePanel(!playingReplay);
  4798.                     paused = true;
  4799.                 }
  4800.             } else if (makeThemRate && !playingReplay && curRobotID != "" && curRobotPublic && !ratedCurRobot && !LSOManager.HasRatedRobot(curRobotID)) {
  4801.                 ratedCurRobot = true;
  4802.                 if (m_rateDialog) removeChild(m_rateDialog);
  4803.                 m_rateDialog = new RateWindow(this, 0, 3);
  4804.                 addChild(m_rateDialog);
  4805.                 m_fader.visible = true;
  4806.                 m_guiPanel.ShowPausePanel(!playingReplay);
  4807.                 paused = true;
  4808.             } else {
  4809.                 if (Database.curSortPeriod == Database.SORT_PERIOD_PROP) Database.curSortPeriod = Database.SORT_PERIOD_ALLTIME;
  4810.                 Database.GetReplayData(userName, password, Database.curShared, Database.curSortType, Database.curSortPeriod, (Database.curShared ? Database.curReplayPage : 1), "", finishGettingLoadReplayData);
  4811.                 ShowDialog("Getting replays...");
  4812.                 Main.ShowHourglass();
  4813.                 m_fader.visible = true;
  4814.                 curAction = -1;
  4815.             }
  4816.         }
  4817.        
  4818.         public virtual function loadChallengeButton(e:MouseEvent, makeThemRate:Boolean = true):void {
  4819.             if (selectingCondition) return;
  4820.             if (Main.inIFrame) {
  4821.                 m_fader.visible = true;
  4822.                 ShowConfirmDialog("Redirect to incredibots2.com?", 7);
  4823.             } else if (makeThemRate && playingReplay && curReplayID != "" && curReplayPublic && !ratedCurReplay && !LSOManager.HasRatedReplay(curReplayID)) {
  4824.                 ratedCurReplay = true;
  4825.                 if (m_rateDialog) removeChild(m_rateDialog);
  4826.                 m_rateDialog = new RateWindow(this, 1, 4);
  4827.                 addChild(m_rateDialog);
  4828.                 m_fader.visible = true;
  4829.                 m_guiPanel.ShowPausePanel(!playingReplay);
  4830.                 paused = true;
  4831.             } else if (makeThemRate && !playingReplay && curChallengeID != "" && curChallengePublic && !ratedCurChallenge && !LSOManager.HasRatedChallenge(curChallengeID)) {
  4832.                 ratedCurChallenge = true;
  4833.                 if (m_rateDialog) removeChild(m_rateDialog);
  4834.                 m_rateDialog = new RateWindow(this, 2, 4);
  4835.                 addChild(m_rateDialog);
  4836.                 m_fader.visible = true;
  4837.                 if (simStarted) {
  4838.                     m_guiPanel.ShowPausePanel(!playingReplay);
  4839.                     paused = true;
  4840.                 }
  4841.             } else if (makeThemRate && !playingReplay && curRobotID != "" && curRobotPublic && !ratedCurRobot && !LSOManager.HasRatedRobot(curRobotID)) {
  4842.                 ratedCurRobot = true;
  4843.                 if (m_rateDialog) removeChild(m_rateDialog);
  4844.                 m_rateDialog = new RateWindow(this, 0, 4);
  4845.                 addChild(m_rateDialog);
  4846.                 m_fader.visible = true;
  4847.                 m_guiPanel.ShowPausePanel(!playingReplay);
  4848.                 paused = true;
  4849.             } else {
  4850.                 if (Database.curSortPeriod == Database.SORT_PERIOD_PROP) Database.curSortPeriod = Database.SORT_PERIOD_ALLTIME;
  4851.                 Database.GetChallengeData(userName, password, Database.curShared, Database.curSortType, Database.curSortPeriod, (Database.curShared ? Database.curReplayPage : 1), "", finishGettingLoadChallengeData);
  4852.                 ShowDialog("Getting challenges...");
  4853.                 Main.ShowHourglass();
  4854.                 m_fader.visible = true;
  4855.                 curAction = -1;
  4856.             }
  4857.         }
  4858.        
  4859.         public function LoadReplayNow(replayID:String):void {
  4860.             Database.LoadReplayByID(replayID, finishLoadingReplay);
  4861.             ShowDialog("Loading Replay...");
  4862.             m_fader.visible = true;
  4863.         }
  4864.        
  4865.         public function LoadRobotNow(robotID:String):void {
  4866.             Database.LoadRobotByID(robotID, finishLoading);
  4867.             ShowDialog("Loading Robot...");
  4868.             m_fader.visible = true;
  4869.         }
  4870.        
  4871.         public function LoadChallengeNow(challengeID:String):void {
  4872.             Database.LoadChallengeByID(challengeID, finishLoadingChallenge);
  4873.             ShowDialog("Loading Challenge...");
  4874.             m_fader.visible = true;
  4875.         }
  4876.        
  4877.         public function highScoresButton(e:MouseEvent):void {
  4878.             if (selectingCondition) return;
  4879.             if (Main.inIFrame) {
  4880.                 m_fader.visible = true;
  4881.                 ShowConfirmDialog("Redirect to incredibots2.com?", 7);
  4882.             } else {
  4883.                 if (curChallengeID == "") {
  4884.                     Database.GetChallengeData(ControllerGame.userName, ControllerGame.password, true, Database.curSortType, Database.curSortPeriod, Database.curChallengePage, "", finishGettingLoadChallengeForScoreData);
  4885.                     ShowDialog("Getting challenges...");
  4886.                 } else {
  4887.                     Database.GetScoreData(userName, password, curChallengeID, Database.highScoresDaily, Database.highScoresPersonal, Database.highScoresSortType, Database.curScorePage, "", finishGettingScoreData);
  4888.                     ShowDialog("Getting high scores...");
  4889.                 }
  4890.                 Main.ShowHourglass();
  4891.                 m_fader.visible = true;
  4892.                 curAction = -1;
  4893.             }
  4894.         }
  4895.        
  4896.         public virtual function submitButton(e:MouseEvent):void {
  4897.             if (Main.inIFrame) {
  4898.                 m_fader.visible = true;
  4899.                 ShowConfirmDialog("Redirect to incredibots2.com?", 7);
  4900.             } else {
  4901.                 if (!curRobotEditable) return;
  4902.                 if (userName != "_Public") {
  4903.                     AddSyncPoint();
  4904.                     if (viewingUnsavedReplay) Database.SaveReplay(userName, password, replay, "_ScoreReplay", "This replay is saved for a score", curRobotID, new Robot(allParts, ControllerSandbox.settings), (ChallengeOver() ? GetScore() : -1), curChallengeID, 1, finishSavingReplay);
  4905.                     else Database.SaveReplay(userName, password, new Replay(cameraMovements, syncPoints, keyPresses, frameCounter, Database.VERSION_STRING_FOR_REPLAYS), "_ScoreReplay", "This replay is saved for a score", curRobotID, new Robot(allParts, ControllerSandbox.settings), (ChallengeOver() ? GetScore() : -1), curChallengeID, 1, finishSavingReplay);
  4906.                     m_scoreWindow.ShowFader();
  4907.                     ShowDialog("Submitting score...");
  4908.                     clickedSubmitScore = true;
  4909.                 } else {
  4910.                     clickedSubmitScore = true;
  4911.                     loginButton(e, true, false);
  4912.                 }
  4913.             }
  4914.         }
  4915.        
  4916.         public override function finishAddingUser(e:Event):void {
  4917.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_ADD_USER) return;
  4918.             var retVal:String = Database.FinishAddingUser(e);
  4919.             if (retVal != "") {
  4920.                 m_progressDialog.SetMessage("Success!");
  4921.                 m_progressDialog.HideInXSeconds(1);
  4922.                 if (m_loginWindow) m_loginWindow.visible = false;
  4923.                 m_newUserWindow.visible = false;
  4924.                 if (!m_scoreWindow || !m_scoreWindow.visible) m_fader.visible = false;
  4925.                 Main.premiumMode = false;
  4926.                 userName = retVal.substring(retVal.indexOf("user: ") + 6, retVal.indexOf("password: ") - 1);
  4927.                 password = retVal.substring(retVal.indexOf("password: ") + 10, retVal.indexOf("session: ") - 1);
  4928.                 sessionID = retVal.substr(retVal.indexOf("session: ") + 9);
  4929.                 m_guiPanel.ShowLogout();
  4930.                 loginHidden(e, true);
  4931.             }
  4932.         }
  4933.                
  4934.         public override function finishLoggingIn(e:Event):void {
  4935.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_LOGIN) return;
  4936.             var retVal:String = Database.FinishLoggingIn(e);
  4937.             if (retVal != "") {
  4938.                 m_progressDialog.SetMessage("Success!");
  4939.                 m_progressDialog.HideInXSeconds(1);
  4940.                 m_loginWindow.visible = false;
  4941.                 if (!m_scoreWindow || !m_scoreWindow.visible) m_fader.visible = false;
  4942.                 if (retVal.indexOf("premium") == 0) Main.premiumMode = true;
  4943.                 else Main.premiumMode = false;
  4944.                 userName = retVal.substring(retVal.indexOf("user: ") + 6, retVal.indexOf("password: ") - 1);
  4945.                 password = retVal.substring(retVal.indexOf("password: ") + 10, retVal.indexOf("session: ") - 1);
  4946.                 sessionID = retVal.substr(retVal.indexOf("session: ") + 9);
  4947.                 //m_guiPanel.ShowFeatureButton();
  4948.                 m_guiPanel.ShowLogout();
  4949.                 loginHidden(e, true);
  4950.             }
  4951.             Main.ShowMouse();
  4952.         }
  4953.        
  4954.         public function finishSavingReplay(e:Event):void {
  4955.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_SAVE_REPLAY) return;
  4956.             var robotID:String = Database.FinishSavingReplay(e);
  4957.             if (robotID != "") {
  4958.                 curRobotID = robotID;
  4959.                 ratedCurRobot = true;
  4960.                 curRobotPublic = false;
  4961.                 m_progressDialog.SetMessage("Save successful!");
  4962.                 m_progressDialog.HideInXSeconds(1);
  4963.                 if (m_chooserWindow) {
  4964.                     m_chooserWindow.visible = false;
  4965.                     removeChild(m_chooserWindow);
  4966.                     m_chooserWindow = null;
  4967.                 }
  4968.                 if (!m_scoreWindow || !m_scoreWindow.visible) m_fader.visible = false;
  4969.                 else {
  4970.                     if (clickedSubmitScore) {
  4971.                         clickedSubmitScore = false;
  4972.                         m_progressDialog.visible = false;
  4973.                         highScoresButton(new MouseEvent(""));
  4974.                     } else {
  4975.                         m_scoreWindow.HideFader();
  4976.                         Main.ShowMouse();
  4977.                     }
  4978.                 }
  4979.             }
  4980.         }
  4981.    
  4982.         public function finishGettingSaveReplayData(e:Event):void {
  4983.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_GET_REPLAY_DATA) return;
  4984.             if (Database.FinishGettingReplayData(e)) {
  4985.                 m_progressDialog.visible = false;
  4986.                 if (m_chooserWindow) removeChild(m_chooserWindow);
  4987.                 m_chooserWindow = new SaveLoadWindow(this, SaveLoadWindow.SAVE_REPLAY_TYPE);
  4988.                 addChild(m_chooserWindow);
  4989.                 m_fader.visible = true;
  4990.             }
  4991.         }
  4992.  
  4993.         public override function finishGettingLoadReplayData(e:Event):void {
  4994.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_GET_REPLAY_DATA) return;
  4995.             if (Database.FinishGettingReplayData(e)) {
  4996.                 m_progressDialog.visible = false;
  4997.                 if (m_chooserWindow) removeChild(m_chooserWindow);
  4998.                 m_chooserWindow = new SaveLoadWindow(this, SaveLoadWindow.LOAD_REPLAY_TYPE);
  4999.                 addChild(m_chooserWindow);
  5000.                 m_fader.visible = true;
  5001.             }
  5002.         }
  5003.        
  5004.         public override function finishLoadingReplay(e:Event):void {
  5005.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_LOAD_REPLAY) return;
  5006.             var replayAndRobot:Array = Database.FinishLoadingReplay(e);
  5007.             processLoadedReplay(replayAndRobot);
  5008.         }
  5009.            
  5010.         public override function processLoadedReplay(replayAndRobot:Array):void {
  5011.             if (replayAndRobot) {
  5012.                 replay = replayAndRobot[0];
  5013.                 if (replay.version != Database.VERSION_STRING_FOR_REPLAYS) {
  5014.                     if (replayDirectlyLinked) {
  5015.                         if (Main.inIFrame) Main.BrowserRedirect("http://incredibots.com/old/" + replay.version + "/incredibots.php?replayID=" + potentialReplayID);
  5016.                         else Main.BrowserRedirect("http://incredibots.com/old/" + replay.version + "/?replayID=" + potentialReplayID);
  5017.                     } else {
  5018.                         ShowConfirmDialog("This replay was saved using an older version of IncrediBots.  Redirect there now?", 6);
  5019.                         Main.ShowMouse();
  5020.                     }
  5021.                 } else {
  5022.                     var robot:Robot = replayAndRobot[1];
  5023.                     replayParts = robot.allParts;
  5024.                     ControllerSandbox.settings = robot.settings;
  5025.                     playingReplay = true;
  5026.                     viewingUnsavedReplay = false;
  5027.                     Main.changeControllers = true;
  5028.                     Main.nextControllerType = 0;
  5029.                     curRobotID = potentialRobotID;
  5030.                     ratedCurReplay = true;
  5031.                     curReplayID = potentialReplayID;
  5032.                     ratedCurReplay = false;
  5033.                     curReplayPublic = potentialReplayPublic;
  5034.                     curReplayFeatured = potentialReplayFeatured;
  5035.                     curChallengeID = "";
  5036.                     curChallengePublic = false;
  5037.                     curChallengeFeatured = false;
  5038.                 }
  5039.             }
  5040.         }
  5041.        
  5042.         public override function finishDeletingReplay(e:Event):void {
  5043.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_DELETE_REPLAY) return;
  5044.             if (Database.FinishDeletingReplay(e)) {
  5045.                 m_progressDialog.SetMessage("Delete successful!");
  5046.                 m_progressDialog.HideInXSeconds(1);
  5047.                 var type:int = m_chooserWindow.dataType;
  5048.                 removeChild(m_chooserWindow);
  5049.                 m_chooserWindow = new SaveLoadWindow(this, type);
  5050.                 addChild(m_chooserWindow);
  5051.                 removeChild(m_progressDialog);
  5052.                 addChild(m_progressDialog);
  5053.             }
  5054.         }
  5055.        
  5056.         public function finishSavingChallenge(e:Event):void {
  5057.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_SAVE_CHALLENGE) return;
  5058.             var challengeID:String = Database.FinishSavingChallenge(e);
  5059.             if (challengeID != "") {
  5060.                 curChallengeID = challengeID;
  5061.                 ratedCurChallenge = true;
  5062.                 curChallengePublic = false;
  5063.                 curChallengeFeatured = false;
  5064.                 m_progressDialog.SetMessage("Save successful!");
  5065.                 m_progressDialog.HideInXSeconds(1);
  5066.                 if (m_chooserWindow) {
  5067.                     m_chooserWindow.visible = false;
  5068.                     removeChild(m_chooserWindow);
  5069.                     m_chooserWindow = null;
  5070.                 }
  5071.                 if (!m_scoreWindow || !m_scoreWindow.visible) m_fader.visible = false;
  5072.                 else {
  5073.                     m_scoreWindow.HideFader();
  5074.                     Main.ShowMouse();
  5075.                 }
  5076.             }
  5077.         }
  5078.        
  5079.         public override function finishLoadingChallenge(e:Event):void {
  5080.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_LOAD_CHALLENGE) return;
  5081.             var challenge:Challenge = Database.FinishLoadingChallenge(e);
  5082.             processLoadedChallenge(challenge);
  5083.         }
  5084.        
  5085.         public override function processLoadedChallenge(challenge:Challenge):void {
  5086.             if (challenge) {
  5087.                 Main.changeControllers = true;
  5088.                 Main.nextControllerType = 1;
  5089.                 playingReplay = false;
  5090.  
  5091.                 ControllerChallenge.challenge = challenge;
  5092.                 ControllerChallenge.playChallengeMode = !potentialChallengeEditable;
  5093.                 ControllerChallenge.playOnlyMode = !potentialChallengeEditable;
  5094.                 ControllerSandbox.settings = challenge.settings;
  5095.                 curChallengeID = potentialChallengeID;
  5096.                 ratedCurChallenge = false;
  5097.                 curChallengePublic = potentialChallengePublic;
  5098.                 curChallengeFeatured = potentialChallengeFeatured;
  5099.                 curRobotID = "";
  5100.                 curReplayID = "";
  5101.                 loadedParts = challenge.allParts;
  5102.                 initX = challenge.cameraX;
  5103.                 initY = challenge.cameraY;
  5104.                 initZoom = challenge.zoomLevel;
  5105.             }
  5106.         }
  5107.        
  5108.         public function finishGettingSaveChallengeData(e:Event):void {
  5109.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_GET_CHALLENGE_DATA) return;
  5110.             if (Database.FinishGettingChallengeData(e)) {
  5111.                 m_progressDialog.visible = false;
  5112.                 if (m_chooserWindow) removeChild(m_chooserWindow);
  5113.                 m_chooserWindow = new SaveLoadWindow(this, SaveLoadWindow.SAVE_CHALLENGE_TYPE);
  5114.                 addChild(m_chooserWindow);
  5115.                 m_fader.visible = true;
  5116.             }
  5117.         }
  5118.        
  5119.         public override function finishGettingLoadChallengeData(e:Event):void {
  5120.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_GET_CHALLENGE_DATA) return;
  5121.             if (Database.FinishGettingChallengeData(e)) {
  5122.                 m_progressDialog.visible = false;
  5123.                 if (m_chooserWindow) removeChild(m_chooserWindow);
  5124.                 m_chooserWindow = new SaveLoadWindow(this, SaveLoadWindow.LOAD_CHALLENGE_TYPE);
  5125.                 addChild(m_chooserWindow);
  5126.                 m_fader.visible = true;
  5127.             }
  5128.         }
  5129.        
  5130.         public override function finishGettingLoadChallengeForScoreData(e:Event):void {
  5131.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_GET_CHALLENGE_DATA) return;
  5132.             if (Database.FinishGettingChallengeData(e)) {
  5133.                 m_progressDialog.visible = false;
  5134.                 if (m_challengeWindow) removeChild(m_challengeWindow);
  5135.                 m_challengeWindow = new ChooseChallengeWindow(this);
  5136.                 addChild(m_challengeWindow);
  5137.                 m_fader.visible = true;
  5138.             }
  5139.         }
  5140.        
  5141.         public override function finishDeletingChallenge(e:Event):void {
  5142.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_DELETE_CHALLENGE) return;
  5143.             if (Database.FinishDeletingChallenge(e)) {
  5144.                 m_progressDialog.SetMessage("Delete successful!");
  5145.                 m_progressDialog.HideInXSeconds(1);
  5146.                 var type:int = m_chooserWindow.dataType;
  5147.                 removeChild(m_chooserWindow);
  5148.                 m_chooserWindow = new SaveLoadWindow(this, type);
  5149.                 addChild(m_chooserWindow);
  5150.                 removeChild(m_progressDialog);
  5151.                 addChild(m_progressDialog);
  5152.             }
  5153.         }
  5154.        
  5155.         public override function finishGettingScoreData(e:Event):void {
  5156.             if (!Database.waitingForResponse || Database.curTransactionType != Database.ACTION_GET_SCORE_DATA) return;
  5157.             if (Database.FinishGettingScoreData(e)) {
  5158.                 m_progressDialog.visible = false;
  5159.                 if (m_chooserWindow) removeChild(m_chooserWindow);
  5160.                 m_chooserWindow = new SaveLoadWindow(this, SaveLoadWindow.HIGH_SCORE_TYPE);
  5161.                 addChild(m_chooserWindow);
  5162.                 m_fader.visible = true;
  5163.             }
  5164.         }
  5165.        
  5166.         public function ConfirmSaveRobot(e:MouseEvent):void {
  5167.             m_chooserWindow.saveRobotButtonPressed(e, true);
  5168.         }
  5169.        
  5170.         public function ConfirmSaveReplay(e:MouseEvent):void {
  5171.             m_chooserWindow.saveReplayButtonPressed(e, true);
  5172.         }
  5173.        
  5174.         public function ConfirmSaveChallenge(e:MouseEvent):void {
  5175.             m_chooserWindow.saveChallengeButtonPressed(e, true);
  5176.         }
  5177.        
  5178.         public override function ConfirmDeleteRobot(e:MouseEvent):void {
  5179.             m_chooserWindow.deleteRobotButtonPressed(e, true);
  5180.         }
  5181.        
  5182.         public override function ConfirmDeleteReplay(e:MouseEvent):void {
  5183.             m_chooserWindow.deleteReplayButtonPressed(e, true);
  5184.         }
  5185.        
  5186.         public override function ConfirmDeleteChallenge(e:MouseEvent):void {
  5187.             m_chooserWindow.deleteChallengeButtonPressed(e, true);
  5188.         }
  5189.        
  5190.         public override function ShowImportWindow(type:int):void {
  5191.             if (m_importDialog) removeChild(m_importDialog);
  5192.             m_importDialog = new ImportWindow(this, type);
  5193.             m_fader.visible = true;
  5194.             addChild(m_importDialog);
  5195.         }
  5196.        
  5197.         public override function ShowConfirmDialog(msg:String, type:int):void {
  5198.             if (m_progressDialog) removeChild(m_progressDialog);
  5199.             m_progressDialog = new DialogWindow(this, msg, true, false, (type == 8));
  5200.             addChild(m_progressDialog);
  5201.             m_progressDialog.ShowOKAndCancelButton(type);
  5202.         }
  5203.        
  5204.         public function ShowDisabledDialog():void {
  5205.             m_fader.visible = true;
  5206.             if (m_progressDialog) removeChild(m_progressDialog);
  5207.             m_progressDialog = new DialogWindow(this, "That feature has been disabled for this level.", true);
  5208.             m_progressDialog.ShowOKButton();
  5209.             m_progressDialog.StopTimer();
  5210.             addChild(m_progressDialog);
  5211.         }
  5212.        
  5213.         public override function ShowDialog(msg:String):void {
  5214.             if (m_progressDialog) removeChild(m_progressDialog);
  5215.             m_progressDialog = new DialogWindow(this, msg);
  5216.             addChild(m_progressDialog);
  5217.         }
  5218.        
  5219.         public override function ShowDialog2(msg:String):void {
  5220.             if (m_progressDialog) removeChild(m_progressDialog);
  5221.             m_progressDialog = new DialogWindow(this, msg, true, true);
  5222.             addChild(m_progressDialog);
  5223.         }
  5224.        
  5225.         public override function ShowDialog3(msg:String):void {
  5226.             if (m_progressDialog) removeChild(m_progressDialog);
  5227.             m_progressDialog = new DialogWindow(this, msg, true);
  5228.             addChild(m_progressDialog);
  5229.         }
  5230.        
  5231.         public function ShowTutorialWindow(phraseNum:int, x:int, y:int, moreButton:Boolean = false):void {
  5232.             if (m_tutorialDialog) removeChild(m_tutorialDialog);
  5233.             m_tutorialDialog = new TutorialWindow(this, x, y, phraseNum, moreButton);
  5234.             addChild(m_tutorialDialog);
  5235.         }
  5236.        
  5237.         public virtual function CloseTutorialDialog(phraseNum:int):void {
  5238.             m_tutorialDialog.visible = false;
  5239.         }
  5240.        
  5241.         public override function ShowLinkDialog(msg1:String, msg2:String, isEmbedReplay:Boolean = false, id:String = "", isEmbedChallenge:Boolean = false):void {
  5242.             if (m_linkDialog) removeChild(m_linkDialog);
  5243.             m_linkDialog = new LinkWindow(this, msg1, msg2, isEmbedReplay, id, isEmbedChallenge);
  5244.             addChild(m_linkDialog);
  5245.         }
  5246.        
  5247.         public override function DialogOK(e:Event):void {
  5248.             m_progressDialog.visible = false;
  5249.             if (m_chooserWindow && m_chooserWindow.visible) m_chooserWindow.HideFader();
  5250.             if (m_challengeWindow && m_challengeWindow.visible) m_challengeWindow.HideFader();
  5251.             if (m_newUserWindow && m_newUserWindow.visible) m_newUserWindow.HideFader();
  5252.             if (m_loginWindow && m_loginWindow.visible) m_loginWindow.HideFader();
  5253.             if (m_scoreWindow && m_scoreWindow.visible) m_scoreWindow.HideFader();
  5254.             if (m_restrictionsDialog && m_restrictionsDialog.visible) m_restrictionsDialog.HideFader();
  5255.             if (m_conditionsDialog && m_conditionsDialog.visible) m_conditionsDialog.HideFader();
  5256.         }
  5257.        
  5258.         public virtual override function HideDialog(e:Event):void {
  5259.             if (Database.nonfatalErrorOccurred) {
  5260.                 Database.nonfatalErrorOccurred = false;
  5261.                 if (m_chooserWindow) m_chooserWindow.HideFader();
  5262.                 if (m_challengeWindow) m_challengeWindow.HideFader();
  5263.                 if (m_newUserWindow && m_newUserWindow.visible) m_newUserWindow.HideFader();
  5264.                 else if (m_loginWindow) m_loginWindow.HideFader();
  5265.             } else {
  5266.                 m_fader.visible = false;
  5267.                 if (m_chooserWindow && m_chooserWindow.visible) {
  5268.                     m_fader.visible = true;
  5269.                     m_chooserWindow.HideFader();
  5270.                 }
  5271.                 if (m_challengeWindow && m_challengeWindow.visible) {
  5272.                     m_fader.visible = true;
  5273.                     m_challengeWindow.HideFader();
  5274.                 }
  5275.                 if (m_newUserWindow && m_newUserWindow.visible) m_newUserWindow.visible = false;
  5276.                 else if (m_loginWindow && m_loginWindow.visible) m_loginWindow.visible = false;
  5277.                 else if (m_scoreWindow && m_scoreWindow.visible) {
  5278.                     m_fader.visible = true;
  5279.                     m_scoreWindow.HideFader();
  5280.                 } else if (m_postReplayWindow && m_postReplayWindow.visible) {
  5281.                     m_fader.visible = true;
  5282.                     m_postReplayWindow.HideFader();
  5283.                 }
  5284.             }
  5285.             m_progressDialog.visible = false;
  5286.             if (failedChallenge) resetButton(new MouseEvent(""));
  5287.             failedChallenge = false;
  5288.         }
  5289.        
  5290.         public override function HideLinkDialog(e:Event):void {
  5291.             m_linkDialog.visible = false;
  5292.             if (m_chooserWindow && m_chooserWindow.visible) {
  5293.                 m_chooserWindow.HideFader();
  5294.             } else {
  5295.                 m_fader.visible = false;
  5296.             }
  5297.         }
  5298.        
  5299.         public override function HideExportDialog(e:Event):void {
  5300.             m_exportDialog.visible = false;
  5301.             if (m_chooserWindow && m_chooserWindow.visible) {
  5302.                 m_chooserWindow.HideFader();
  5303.             }
  5304.             m_fader.visible = false;
  5305.         }
  5306.        
  5307.         public override function HideImportDialog(e:Event):void {
  5308.             m_importDialog.visible = false;
  5309.             m_fader.visible = false;
  5310.         }
  5311.        
  5312.         public override function HideConfirmDialog(e:Event):void {
  5313.             m_progressDialog.visible = false;
  5314.             if (m_chooserWindow && m_chooserWindow.visible) m_chooserWindow.HideFader();
  5315.             else if (m_scoreWindow && m_scoreWindow.visible) m_scoreWindow.HideFader();
  5316.             else m_fader.visible = false;
  5317.         }
  5318.        
  5319.         public function ShowPostReplayWindow():void {
  5320.             if (m_postReplayWindow) removeChild(m_postReplayWindow);
  5321.             m_postReplayWindow = new PostReplayWindow(this);
  5322.             addChild(m_postReplayWindow);
  5323.             m_fader.visible = true;
  5324.         }
  5325.        
  5326.         public function DeletePart(part:Part, addAction:Boolean = true, clearFromSelected:Boolean = true):void {
  5327.             allParts = Util.RemoveFromArray(part, allParts);
  5328.             if (clearFromSelected) selectedParts = Util.RemoveFromArray(part, selectedParts);
  5329.             part.isEnabled = false;
  5330.            
  5331.             var affectedJoints:Array = new Array();
  5332.             if (part is ShapePart) {
  5333.                 var jointFound:Boolean;
  5334.                 do {
  5335.                     jointFound = false;
  5336.                     for (var i:int = 0; i < allParts.length; i++) {
  5337.                         if (jointFound) {
  5338.                             if (i != allParts.length - 1) {
  5339.                                 allParts[i] = allParts[i + 1];
  5340.                             }
  5341.                         } else if (allParts[i] is JointPart) {
  5342.                             var p:JointPart = (allParts[i] as JointPart);
  5343.                             if (p.part1 == part || p.part2 == part) {
  5344.                                 jointFound = true;
  5345.                                 affectedJoints.push(p);
  5346.                                 p.isEnabled = false;
  5347.                                 if (clearFromSelected) selectedParts = Util.RemoveFromArray(p, selectedParts);
  5348.                                 if (i != allParts.length - 1) allParts[i] = allParts[i + 1];
  5349.                             }
  5350.                         } else if (allParts[i] is Thrusters) {
  5351.                             var t:Thrusters = (allParts[i] as Thrusters);
  5352.                             if (t.shape == part) {
  5353.                                 jointFound = true;
  5354.                                 affectedJoints.push(t);
  5355.                                 t.isEnabled = false;
  5356.                                 if (clearFromSelected) selectedParts = Util.RemoveFromArray(t, selectedParts);
  5357.                                 if (i != allParts.length - 1) allParts[i] = allParts[i + 1];
  5358.                             }
  5359.                         }
  5360.                     }
  5361.                     if (jointFound) allParts.pop();
  5362.                 } while (jointFound);
  5363.             } else if (part is TextPart) {
  5364.                 (part as TextPart).m_textField.visible = false;
  5365.             }
  5366.             if (addAction) AddAction(new DeleteAction(part, affectedJoints));
  5367.             CheckIfPartsFit();
  5368.             curRobotID = "";
  5369.         }      
  5370.        
  5371.         // Private Part:
  5372.        
  5373.         private function CreateWorld():void {
  5374.             var worldAABB:b2AABB = new b2AABB();
  5375.             worldAABB.lowerBound.Set(-300.0, -200.0);
  5376.             worldAABB.upperBound.Set(300.0, 200.0);
  5377.            
  5378.             // Construct a world object
  5379.             m_world = new b2World(worldAABB, GetGravity(), true);
  5380.            
  5381.             var filter:ContactFilter = new ContactFilter();
  5382.             m_world.SetContactFilter(filter);
  5383.             var listener:ContactListener = new ContactListener(this);
  5384.             m_world.SetContactListener(listener);
  5385.         }
  5386.        
  5387.         protected virtual function GetGravity():b2Vec2 {
  5388.             return new b2Vec2(0.0, 15.0);
  5389.         }
  5390.         private function TooManyShapes():Boolean {
  5391.             return (allParts.filter(PartIsPhysical).length > Number.POSITIVE_INFINITY);
  5392.         }
  5393.  
  5394.         protected function IsPartOfRobot(p:Part, index:int, array:Array):Boolean {
  5395.             return p.drawAnyway;
  5396.         }
  5397.  
  5398.         protected function PartIsEditable(p:Part, index:int, array:Array):Boolean {
  5399.             return p.isEditable;
  5400.         }
  5401.        
  5402.         private function PartIsShape(p:Part, index:int, array:Array):Boolean {
  5403.             return (p is ShapePart);
  5404.         }
  5405.        
  5406.         private function PartIsPhysical(p:Part, index:int, array:Array):Boolean {
  5407.             return (p is ShapePart || p is PrismaticJoint);
  5408.         }
  5409.        
  5410.         protected function FindCenterOfRobot():ShapePart {
  5411.             var heaviestGroup:Array = null;
  5412.             var massOfHeaviestGroup:Number = 0;
  5413.             for (var i:int = 0; i < allParts.length; i++) {
  5414.                 if (allParts[i].isEditable && allParts[i] is ShapePart && allParts[i].isEnabled && allParts[i].m_collisionGroup == -(i + 1)) {
  5415.                     var attachedParts:Array = allParts[i].GetAttachedParts().filter(PartIsShape);
  5416.                     var groupMass:Number = 0;
  5417.                     var bodiesUsed:Array = new Array();
  5418.                     var partsUsed:Array = new Array();
  5419.                     for (var j:int = 0; j < attachedParts.length; j++) {
  5420.                         if (!Util.ObjectInArray(attachedParts[j].GetBody(), bodiesUsed)) {
  5421.                             groupMass += attachedParts[j].GetMass();
  5422.                             bodiesUsed.push(attachedParts[j].GetBody());
  5423.                             partsUsed.push(attachedParts[j]);
  5424.                         }
  5425.                     }
  5426.                     if (groupMass > massOfHeaviestGroup) {
  5427.                         massOfHeaviestGroup = groupMass;
  5428.                         heaviestGroup = partsUsed;
  5429.                     }
  5430.                 }
  5431.             }
  5432.            
  5433.             if (!heaviestGroup) return null;
  5434.            
  5435.             var bestIndex:int = -1;
  5436.             var bestMass:Number = 0;
  5437.             for (i = 0; i < heaviestGroup.length; i++) {
  5438.                 var mass:Number = heaviestGroup[i].GetMass();
  5439.                 if (mass > bestMass) {
  5440.                     bestMass = mass;
  5441.                     bestIndex = i;
  5442.                 }
  5443.             }
  5444.             if (bestIndex == -1) return null;
  5445.             return heaviestGroup[bestIndex];
  5446.         }
  5447.        
  5448.         private function Zoom(zoomIn:Boolean):void {
  5449.             var oldScale:Number = m_physScale;
  5450.             var centerX:Number = (ZOOM_FOCUS_X + draw.m_drawXOff) / m_physScale;
  5451.             var centerY:Number = (ZOOM_FOCUS_Y + draw.m_drawYOff) / m_physScale;
  5452.             if (zoomIn) {
  5453.                 m_physScale *= 4.0 / 3.0;
  5454.                 if (m_physScale > MAX_ZOOM_VAL) m_physScale = MAX_ZOOM_VAL;
  5455.             } else {
  5456.                 m_physScale *= 3.0 / 4.0;
  5457.                 if (m_physScale < MIN_ZOOM_VAL) m_physScale = MIN_ZOOM_VAL;
  5458.             }
  5459.             draw.m_drawXOff = centerX * m_physScale - ZOOM_FOCUS_X;
  5460.             draw.m_drawYOff = centerY * m_physScale - ZOOM_FOCUS_Y;
  5461.            
  5462.             if (oldScale != m_physScale) hasZoomed = true;
  5463.             if (simStarted) cameraMovements.push(new CameraMovement(frameCounter, (autoPanning ? Number.POSITIVE_INFINITY : draw.m_drawXOff), (autoPanning ? Number.POSITIVE_INFINITY : draw.m_drawYOff), m_physScale));
  5464.         }
  5465.        
  5466.         private function MaybeCreateJoint():void {
  5467.             var candidateParts:Array = new Array();
  5468.  
  5469.             var jointX:Number = mouseXWorldPhys;
  5470.             var jointY:Number = mouseYWorldPhys;
  5471.             var snapPart:ShapePart = FindPartToSnapTo();
  5472.             if (snapToCenter && snapPart) {
  5473.                 jointX = snapPart.centerX;
  5474.                 jointY = snapPart.centerY;
  5475.             }
  5476.  
  5477.             for (var i:int = allParts.length - 1; i >= 0; i--) {
  5478.                 if (allParts[i] is ShapePart && allParts[i].isEditable && allParts[i].isEnabled) {
  5479.                     var part:ShapePart = ShapePart(allParts[i]);
  5480.                     if (part.InsideShape(jointX, jointY, m_physScale)) {
  5481.                         candidateParts.push(part);
  5482.                     }
  5483.                 }
  5484.             }
  5485.            
  5486.             if (candidateParts.length == 2) {
  5487.                 if (curAction == NEW_REVOLUTE_JOINT) {
  5488.                     var rjoint:RevoluteJoint = new RevoluteJoint(candidateParts[0], candidateParts[1], jointX, jointY);
  5489.                     if (copiedJoint is RevoluteJoint) rjoint.SetJointProperties(copiedJoint as RevoluteJoint);
  5490.                     allParts.push(rjoint);
  5491.                     AddAction(new CreateAction(rjoint));
  5492.                     m_sidePanel.ShowJointPanel(rjoint);
  5493.                     selectedParts = new Array();
  5494.                     selectedParts.push(rjoint);
  5495.                     curAction = -1;
  5496.                     if (centerOnSelected) CenterOnSelected();
  5497.                     PlayJointSound();
  5498.                 } else if (curAction == NEW_FIXED_JOINT) {
  5499.                     var fjoint:JointPart = new FixedJoint(candidateParts[0], candidateParts[1], jointX, jointY);
  5500.                     allParts.push(fjoint);
  5501.                     AddAction(new CreateAction(fjoint));
  5502.                     m_sidePanel.ShowJointPanel(fjoint);
  5503.                     selectedParts = new Array();
  5504.                     selectedParts.push(fjoint);
  5505.                     curAction = -1;
  5506.                     if (centerOnSelected) CenterOnSelected();
  5507.                     PlayJointSound();
  5508.                 }
  5509.                 curRobotID = "";
  5510.                 redrawRobot = true;
  5511.             } else if (candidateParts.length > 2) {
  5512.                 potentialJointPart1 = candidateParts[0];
  5513.                 potentialJointPart2 = candidateParts[1];
  5514.                 potentialJointPart1.highlightForJoint = true;
  5515.                 potentialJointPart2.highlightForJoint = true;
  5516.                 candidateJointX = jointX;
  5517.                 candidateJointY = jointY;
  5518.                 candidateJointType = curAction;
  5519.                 candidateJointParts = candidateParts;
  5520.                 curAction = FINALIZING_JOINT;
  5521.             } else {
  5522.                 curAction = -1;
  5523.                 redrawRobot = true;
  5524.             }
  5525.         }
  5526.  
  5527.         private function MaybeCreateThrusters():void {
  5528.             var candidateParts:Array = new Array();
  5529.  
  5530.             var jointX:Number = mouseXWorldPhys;
  5531.             var jointY:Number = mouseYWorldPhys;
  5532.             var snapPart:ShapePart = FindPartToSnapTo();
  5533.             if (snapToCenter && snapPart) {
  5534.                 jointX = snapPart.centerX;
  5535.                 jointY = snapPart.centerY;
  5536.             }
  5537.  
  5538.             for (var i:int = allParts.length - 1; i >= 0; i--) {
  5539.                 if (allParts[i] is ShapePart && allParts[i].isEditable && allParts[i].isEnabled) {
  5540.                     var part:ShapePart = ShapePart(allParts[i]);
  5541.                     if (part.InsideShape(jointX, jointY, m_physScale)) {
  5542.                         candidateParts.push(part);
  5543.                     }
  5544.                 }
  5545.             }
  5546.            
  5547.             if (candidateParts.length == 1) {
  5548.                 var t:Thrusters = new Thrusters(candidateParts[0], jointX, jointY);
  5549.                 if (copiedThrusters) {
  5550.                     t.strength = copiedThrusters.strength;
  5551.                     t.angle = copiedThrusters.angle;
  5552.                     t.thrustKey = copiedThrusters.thrustKey;
  5553.                     t.autoOn = copiedThrusters.autoOn;
  5554.                 }
  5555.                 allParts.push(t);
  5556.                 AddAction(new CreateAction(t));
  5557.                 m_sidePanel.ShowThrustersPanel(t);
  5558.                 selectedParts = new Array();
  5559.                 selectedParts.push(t);
  5560.                 curAction = -1;
  5561.                 if (centerOnSelected) CenterOnSelected();
  5562.                 curRobotID = "";
  5563.                 redrawRobot = true;
  5564.                 PlayJointSound();
  5565.             } else if (candidateParts.length > 1) {
  5566.                 potentialJointPart1 = candidateParts[0];
  5567.                 potentialJointPart1.highlightForJoint = true;
  5568.                 candidateJointX = jointX;
  5569.                 candidateJointY = jointY;
  5570.                 candidateJointType = curAction;
  5571.                 candidateJointParts = candidateParts;
  5572.                 curAction = FINALIZING_JOINT;
  5573.             } else {
  5574.                 curAction = -1;
  5575.                 redrawRobot = true;
  5576.             }
  5577.         }
  5578.  
  5579.         private function MaybeStartCreatingPrismaticJoint():void {
  5580.             var candidateParts:Array = new Array();
  5581.  
  5582.             var jointX:Number = mouseXWorldPhys;
  5583.             var jointY:Number = mouseYWorldPhys;
  5584.             var snapPart:ShapePart = FindPartToSnapTo();
  5585.             if (snapToCenter && snapPart) {
  5586.                 jointX = snapPart.centerX;
  5587.                 jointY = snapPart.centerY;
  5588.             }
  5589.  
  5590.             for (var i:int = allParts.length - 1; i >= 0; i--) {
  5591.                 if (allParts[i] is ShapePart && allParts[i].isEditable && allParts[i].isEnabled) {
  5592.                     var part:ShapePart = ShapePart(allParts[i]);
  5593.                     if (part.InsideShape(jointX, jointY, m_physScale)) {
  5594.                         candidateParts.push(part);
  5595.                     }
  5596.                 }
  5597.             }
  5598.            
  5599.             if (candidateParts.length == 0) {
  5600.                 curAction = -1;
  5601.                 redrawRobot = true;
  5602.             } else if (candidateParts.length == 1) {
  5603.                 jointPart = candidateParts[0];
  5604.                 firstClickX = jointX;
  5605.                 firstClickY = jointY;
  5606.                 actionStep++;
  5607.                 PlayJointSound();
  5608.             } else {
  5609.                 potentialJointPart1 = candidateParts[0];
  5610.                 potentialJointPart1.highlightForJoint = true;
  5611.                 candidateJointX = jointX;
  5612.                 candidateJointY = jointY;
  5613.                 candidateJointType = curAction;
  5614.                 candidateJointParts = candidateParts;
  5615.                 curAction = FINALIZING_JOINT;
  5616.             }
  5617.         }
  5618.        
  5619.         private function MaybeFinishCreatingPrismaticJoint():void {
  5620.             var candidateParts:Array = new Array();
  5621.  
  5622.             var jointX:Number = mouseXWorldPhys;
  5623.             var jointY:Number = mouseYWorldPhys;
  5624.             var snapPart:ShapePart = FindPartToSnapTo();
  5625.             if (snapToCenter && snapPart) {
  5626.                 jointX = snapPart.centerX;
  5627.                 jointY = snapPart.centerY;
  5628.             }
  5629.  
  5630.             for (var i:int = allParts.length - 1; i >= 0; i--) {
  5631.                 if (allParts[i] is ShapePart && allParts[i].isEditable && allParts[i] != jointPart) {
  5632.                     var part:ShapePart = ShapePart(allParts[i]);
  5633.                     if (part.InsideShape(jointX, jointY, m_physScale)) {
  5634.                         candidateParts.push(part);
  5635.                     }
  5636.                 }
  5637.             }
  5638.            
  5639.             if (candidateParts.length == 1) {
  5640.                 var pjoint:PrismaticJoint = new PrismaticJoint(jointPart, candidateParts[0], firstClickX, firstClickY, jointX, jointY);
  5641.                 if (copiedJoint is PrismaticJoint) pjoint.SetJointProperties(copiedJoint as PrismaticJoint);
  5642.                 allParts.push(pjoint);
  5643.                 AddAction(new CreateAction(pjoint));
  5644.                 m_sidePanel.ShowJointPanel(pjoint);
  5645.                 selectedParts = new Array();
  5646.                 selectedParts.push(pjoint);
  5647.                 curAction = -1;
  5648.                 jointPart.highlightForJoint = false;
  5649.                 curRobotID = "";
  5650.                 if (centerOnSelected) CenterOnSelected();
  5651.                 redrawRobot = true;
  5652.                 PlayJointSound();
  5653.             } else if (candidateParts.length > 1) {
  5654.                 potentialJointPart1 = candidateParts[0];
  5655.                 potentialJointPart1.highlightForJoint = true;
  5656.                 candidateJointX = jointX;
  5657.                 candidateJointY = jointY;
  5658.                 candidateJointType = curAction;
  5659.                 candidateJointParts = candidateParts;
  5660.                 curAction = FINALIZING_JOINT;
  5661.             } else if (candidateParts.length == 0) {
  5662.                 curAction = -1;
  5663.                 redrawRobot = true;
  5664.             }
  5665.         }
  5666.        
  5667.         private function FindPartToSnapTo(draggingPart:ShapePart = null):ShapePart {
  5668.             var closestPart:ShapePart = null;
  5669.             var closestDist:Number = Number.MAX_VALUE;
  5670.             for (var i:int = 0; i < allParts.length; i++) {
  5671.                 if (allParts[i] is ShapePart && allParts[i] != draggingPart && allParts[i].isEditable) {
  5672.                     var part:ShapePart = (allParts[i] as ShapePart);
  5673.                     var dist:Number = Util.GetDist(mouseXWorldPhys, mouseYWorldPhys, part.centerX, part.centerY);
  5674.                     if (dist < closestDist) {
  5675.                         closestDist = dist;
  5676.                         closestPart = part;
  5677.                     }
  5678.                 }
  5679.             }
  5680.            
  5681.             var DIST_THRESHHOLD:Number = 12.0 / m_physScale;
  5682.            
  5683.             if (closestDist < DIST_THRESHHOLD) return closestPart;
  5684.             return null;
  5685.         }
  5686.        
  5687.         private function GetBodyAtMouse():b2Body {
  5688.             // Make a small box.
  5689.             var mousePVec:b2Vec2 = new b2Vec2(mouseXWorldPhys, mouseYWorldPhys);
  5690.             var aabb:b2AABB = new b2AABB();
  5691.             aabb.lowerBound.Set(mouseXWorldPhys - 0.001, mouseYWorldPhys - 0.001);
  5692.             aabb.upperBound.Set(mouseXWorldPhys + 0.001, mouseYWorldPhys + 0.001);
  5693.            
  5694.             // Query the world for overlapping shapes.
  5695.             var k_maxCount:int = 10;
  5696.             var shapes:Array = new Array();
  5697.             var count:int = m_world.Query(aabb, shapes, k_maxCount);
  5698.             var body:b2Body = null;
  5699.             for (var i:int = 0; i < count; ++i) {
  5700.                 if (shapes[i].m_body.IsStatic() == false && !shapes[i].GetUserData().undragable && shapes[i].GetUserData().isPiston == -1) {
  5701.                     var tShape:b2Shape = shapes[i] as b2Shape;
  5702.                     var inside:Boolean = tShape.TestPoint(tShape.m_body.GetXForm(), mousePVec);
  5703.                     if (inside) {
  5704.                         body = tShape.m_body;
  5705.                         break;
  5706.                     }
  5707.                 }
  5708.             }
  5709.             return body;
  5710.         }
  5711.        
  5712.         private function MouseOverSelectedPart():Boolean {
  5713.             for (var i:int = 0; i < selectedParts.length; i++) {
  5714.                 if (selectedParts[i].InsideShape(mouseXWorldPhys, mouseYWorldPhys, m_physScale)) return true;
  5715.             }
  5716.             return false;
  5717.         }
  5718.        
  5719.         private function GetPartAtMouse():Part {
  5720.             for (var j:int = 0; j < allParts.length; j++) {
  5721.                 if (allParts[j].isEditable && allParts[j] is TextPart && allParts[j].InsideMoveBox(mouseXWorldPhys, mouseYWorldPhys, m_physScale)) return allParts[j];
  5722.             }
  5723.  
  5724.             var candidateParts:Array = new Array();
  5725.             var firstSelectedPart:int = -1;
  5726.             var allPartsSelected:Boolean = true;
  5727.             var noPartsSelected:Boolean = true;
  5728.             for (var i:int = allParts.length - 1; i >= 0; i--) {
  5729.                 if (allParts[i].isEditable && allParts[i].InsideShape(mouseXWorldPhys, mouseYWorldPhys, m_physScale)) {
  5730.                     if (Util.ObjectInArray(allParts[i], selectedParts)) {
  5731.                         noPartsSelected = false;
  5732.                         if (firstSelectedPart == -1) firstSelectedPart = candidateParts.length;
  5733.                     } else {
  5734.                         allPartsSelected = false;
  5735.                     }
  5736.                     candidateParts.push(allParts[i]);
  5737.                 }
  5738.             }
  5739.            
  5740.             if (candidateParts.length == 0) return null;
  5741.             if (candidateParts.length == 1 || allPartsSelected || noPartsSelected) return candidateParts[0];
  5742.             for (i = (firstSelectedPart + 1) % candidateParts.length; i != firstSelectedPart; i = (i + 1) % candidateParts.length) {
  5743.                 if (!Util.ObjectInArray(candidateParts[i], selectedParts)) return candidateParts[i];
  5744.             }
  5745.             return null;
  5746.         }
  5747.     }
  5748. }