//------------------------------------------------------------------------------
// Revenge Of The Cats: Ethernet
// Copyright notices are in the file named COPYING.
//------------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Torque Game Engine 
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

function EditorGui::addWindow(%control)
{
	EditorGui.add(%control);
	%control.onAddedAsWindow();
	Canvas.repaint();
}

function EditorGui::removeWindow(%control)
{
	%control.getParent().remove(%control);
	%control.onRemovedAsWindow();
	Canvas.repaint();
}

//-----------------------------------------------------------------------------

function EditorGui::getPrefs()
{
	// same defaults as WorldEditor ctor
	EWorldEditor.axisGizmoActive = getPrefSetting($pref::WorldEditor::axisGizmoActive, true);
	EWorldEditor.axisGizmoMaxScreenLen = getPrefSetting($pref::WorldEditor::axisGizmoMaxScreenLen, 200);
	EWorldEditor.boundingBoxCollision = getPrefSetting($pref::WorldEditor::boundingBoxCollision, true);
	EWorldEditor.defaultHandle = getPrefSetting($pref::WorldEditor::defaultHandle, "gui/Editor_DefaultHandle.png");
	EWorldEditor.dragRectColor = getPrefSetting($pref::WorldEditor::dragRectColor, "255 255 0");
	EWorldEditor.dropType = getPrefSetting($pref::WorldEditor::dropType, "screenCenter");
	EWorldEditor.faceSelectColor = getPrefSetting($pref::WorldEditor::faceSelectColor, "0 0 100 100");
	EWorldEditor.gridColor = getPrefSetting($pref::WorldEditor::gridColor, "255 255 255 20");
	EWorldEditor.gridSize = getPrefSetting($pref::WorldEditor::gridSize, "4 4 4");
	EWorldEditor.lockedHandle = getPrefSetting($pref::WorldEditor::lockedHandle, "gui/Editor_LockedHandle.png");
	EWorldEditor.maxScaleFactor = getPrefSetting($pref::WorldEditor::maxScaleFactor, 4000);
	EWorldEditor.minScaleFactor = getPrefSetting($pref::WorldEditor::minScaleFactor, 0.1);
	EWorldEditor.mouseMoveScale = getPrefSetting($pref::WorldEditor::mouseMoveScale, 0.1);
	EWorldEditor.mouseRotateScale = getPrefSetting($pref::WorldEditor::mouseRotateScale, 0.01);
	EWorldEditor.mouseScaleScale = getPrefSetting($pref::WorldEditor::mouseScaleScale, 0.01);
	EWorldEditor.objectsUseBoxCenter = getPrefSetting($pref::WorldEditor::objectsUseBoxCenter, true);
	EWorldEditor.objectTextColor = getPrefSetting($pref::WorldEditor::objectTextColor, "255 255 255");
	EWorldEditor.objMouseOverColor = getPrefSetting($pref::WorldEditor::objMouseOverColor, "0 255 0");
	EWorldEditor.objMouseOverSelectColor = getPrefSetting($pref::WorldEditor::objMouseOverSelectColor, "0 0 255");
	EWorldEditor.objSelectColor = getPrefSetting($pref::WorldEditor::objSelectColor, "255 0 0");
	EWorldEditor.planarMovement = getPrefSetting($pref::WorldEditor::planarMovement, true);
	EWorldEditor.planeDim = getPrefSetting($pref::WorldEditor::planeDim, 500);
	EWorldEditor.popupBackgroundColor = getPrefSetting($pref::WorldEditor::popupBackgroundColor, "100 100 100");
	EWorldEditor.popupTextColor = getPrefSetting($pref::WorldEditor::popupTextColor, "255 255 0");
	EWorldEditor.projectDistance = getPrefSetting($pref::WorldEditor::projectDistance, 2000);
	EWorldEditor.renderObjHandle = getPrefSetting($pref::WorldEditor::renderObjHandle, true);
	EWorldEditor.renderObjText = getPrefSetting($pref::WorldEditor::renderObjText, true);
	EWorldEditor.renderPlane = getPrefSetting($pref::WorldEditor::renderPlane, false);
	EWorldEditor.renderPlaneHashes = getPrefSetting($pref::WorldEditor::renderPlaneHashes, true);
	EWorldEditor.renderPopupBackground = getPrefSetting($pref::WorldEditor::renderPopupBackground, true);
	EWorldEditor.renderSelectionBox = getPrefSetting($pref::WorldEditor::renderSelectionBox, true);
	EWorldEditor.rotationSnap = getPrefSetting($pref::WorldEditor::rotationSnap, "15");
	EWorldEditor.selectHandle = getPrefSetting($pref::WorldEditor::selectHandle, "gui/Editor_SelectHandle.png");
	EWorldEditor.selectionBoxColor = getPrefSetting($pref::WorldEditor::selectionBoxColor, "255 255 0");
	EWorldEditor.showMousePopupInfo = getPrefSetting($pref::WorldEditor::showMousePopupInfo, true);
	EWorldEditor.snapRotations = getPrefSetting($pref::WorldEditor::snapRotations, true);
	EWorldEditor.snapToGrid = getPrefSetting($pref::WorldEditor::snapToGrid, true);
	EWorldEditor.undoLimit = getPrefSetting($pref::WorldEditor::undoLimit, 40);

	ETerrainEditor.softSelecting = 1;
	ETerrainEditor.currentAction = "raiseHeight";
	ETerrainEditor.currentMode = "select";
}

function EditorGui::setPrefs()
{
	$pref::WorldEditor::axisGizmoActive = EWorldEditor.axisGizmoActive;
	$pref::WorldEditor::axisGizmoMaxScreenLen = EWorldEditor.axisGizmoMaxScreenLen;
	$pref::WorldEditor::boundingBoxCollision = EWorldEditor.boundingBoxCollision;
	$pref::WorldEditor::defaultHandle = EWorldEditor.defaultHandle;
	$pref::WorldEditor::dragRectColor = EWorldEditor.dragRectColor;
	$Pref::WorldEditor::dropType = EWorldEditor.dropType;
	$pref::WorldEditor::gridColor = EWorldEditor.GridColor;
	$pref::WorldEditor::gridSize = EWorldEditor.GridSize;
	$pref::WorldEditor::lockedHandle = EWorldEditor.lockedHandle;
	$pref::WorldEditor::maxScaleFactor = EWorldEditor.maxScaleFactor;
	$pref::WorldEditor::minScaleFactor = EWorldEditor.minScaleFactor;
	$pref::WorldEditor::mouseMoveScale = EWorldEditor.mouseMoveScale;
	$pref::WorldEditor::mouseRotateScale = EWorldEditor.mouseRotateScale;
	$pref::WorldEditor::mouseScaleScale = EWorldEditor.mouseScaleScale;
	$pref::WorldEditor::objectsUseBoxCenter = EWorldEditor.objectsUseBoxCenter;
	$pref::WorldEditor::objectTextColor = EWorldEditor.ObjectTextColor;
	$pref::WorldEditor::objMouseOverColor = EWorldEditor.objMouseOverColor;
	$pref::WorldEditor::objMouseOverSelectColor = EWorldEditor.objMouseOverSelectColor;
	$pref::WorldEditor::objSelectColor = EWorldEditor.objSelectColor;
	$pref::WorldEditor::planarMovement = EWorldEditor.planarMovement;
	$pref::WorldEditor::planeDim = EWorldEditor.planeDim;
	$pref::WorldEditor::popupBackgroundColor = EWorldEditor.PopupBackgroundColor;
	$pref::WorldEditor::popupTextColor = EWorldEditor.PopupTextColor;
	$pref::WorldEditor::projectDistance = EWorldEditor.projectDistance;
	$pref::WorldEditor::raceSelectColor = EWorldEditor.faceSelectColor;
	$pref::WorldEditor::renderObjHandle = EWorldEditor.renderObjHandle;
	$pref::WorldEditor::renderObjText = EWorldEditor.renderObjText;
	$pref::WorldEditor::renderPlane = EWorldEditor.renderPlane;
	$pref::WorldEditor::renderPlaneHashes = EWorldEditor.renderPlaneHashes;
	$pref::WorldEditor::renderPopupBackground = EWorldEditor.renderPopupBackground;
	$pref::WorldEditor::renderSelectionBox = EWorldEditor.renderSelectionBox;
	$pref::WorldEditor::rotationSnap = EWorldEditor.rotationSnap;
	$pref::WorldEditor::selectHandle = EWorldEditor.selectHandle;
	$pref::WorldEditor::selectionBoxColor = EWorldEditor.selectionBoxColor;
	$pref::WorldEditor::showMousePopupInfo = EWorldEditor.showMousePopupInfo;
	$pref::WorldEditor::snapRotations = EWorldEditor.snapRotations;
	$pref::WorldEditor::snapToGrid = EWorldEditor.snapToGrid;
	$pref::WorldEditor::undoLimit = EWorldEditor.undoLimit;

}

function EditorGui::onSleep(%this)
{
	%this.setPrefs();
}

function EditorGui::init(%this)
{
	%this.getPrefs();

	if(!isObject("terraformer"))
		new Terraformer("terraformer");
		
	$SelectedOperation = -1;
	$NextOperationId	= 1;
	$HeightfieldDirtyRow = -1;

	EditorMenuBar.clearMenus();
	EditorMenuBar.addMenu("File", 0);
	//EditorMenuBar.addMenuItem("File", "New Mission...", 1);
	//EditorMenuBar.addMenuItem("File", "Open Mission...", 2, "Ctrl O");
	EditorMenuBar.addMenuItem("File", "Save Mission", 3, "Ctrl S");
	//EditorMenuBar.addMenuItem("File", "Save Mission As...", 4);
	//EditorMenuBar.addMenuItem("File", "-", 0);
	//EditorMenuBar.addMenuItem("File", "Import Terraform Data...", 6);
	//EditorMenuBar.addMenuItem("File", "Import Texture Data...", 5);
	EditorMenuBar.addMenuItem("File", "-", 0);
	EditorMenuBar.addMenuItem("File", "Export Terraform Bitmap...", 5);
	EditorMenuBar.addMenuItem("File", "-", 0);
	EditorMenuBar.addMenuItem("File", "Toggle Mission Editor", 7, "F11");
	//EditorMenuBar.addMenuItem("File", "Quit", 8);

	EditorMenuBar.addMenu("Edit", 1);
	EditorMenuBar.addMenuItem("Edit", "Undo", 1, "Ctrl Z");
	EditorMenuBar.setMenuItemBitmap("Edit", "Undo", 1);
	EditorMenuBar.addMenuItem("Edit", "Redo", 2, "Ctrl R");
	EditorMenuBar.setMenuItemBitmap("Edit", "Redo", 2);
	EditorMenuBar.addMenuItem("Edit", "-", 0);
	EditorMenuBar.addMenuItem("Edit", "Cut", 3, "Ctrl X");
	EditorMenuBar.setMenuItemBitmap("Edit", "Cut", 3);
	EditorMenuBar.addMenuItem("Edit", "Copy", 4, "Ctrl C");
	EditorMenuBar.setMenuItemBitmap("Edit", "Copy", 4);
	EditorMenuBar.addMenuItem("Edit", "Paste", 5, "Ctrl V");
	EditorMenuBar.setMenuItemBitmap("Edit", "Paste", 5);
	EditorMenuBar.addMenuItem("Edit", "-", 0);
	EditorMenuBar.addMenuItem("Edit", "Select All", 6, "Ctrl A");
	EditorMenuBar.addMenuItem("Edit", "Select None", 7, "Ctrl N");

	EditorMenuBar.addMenu("Camera", 7);
	EditorMenuBar.addMenuItem("Camera", "Drop Camera at Player", 1, "Alt Q");
	EditorMenuBar.addMenuItem("Camera", "Drop Player at Camera", 2, "Alt W");
	EditorMenuBar.addMenuItem("Camera", "Toggle Camera", 10, "Alt C");
	EditorMenuBar.addMenuItem("Camera", "-", 0);
	EditorMenuBar.addMenuItem("Camera", "Slowest", 3, "Shift 1", 1);
	EditorMenuBar.addMenuItem("Camera", "Very Slow", 4, "Shift 2", 1);
	EditorMenuBar.addMenuItem("Camera", "Slow", 5, "Shift 3", 1);
	EditorMenuBar.addMenuItem("Camera", "Medium Pace", 6, "Shift 4", 1);
	EditorMenuBar.addMenuItem("Camera", "Fast", 7, "Shift 5", 1);
	EditorMenuBar.addMenuItem("Camera", "Very Fast", 8, "Shift 6", 1);
	EditorMenuBar.addMenuItem("Camera", "Fastest", 9, "Shift 7", 1);

	EditorMenuBar.addMenu("World", 6);
	EditorMenuBar.addMenuItem("World", "Lock Selection", 10, "Ctrl L");
	EditorMenuBar.addMenuItem("World", "Unlock Selection", 11, "Ctrl Shift L");
	EditorMenuBar.addMenuItem("World", "-", 0);
	EditorMenuBar.addMenuItem("World", "Hide Selection", 12, "Ctrl H");
	EditorMenuBar.addMenuItem("World", "Show Selection", 13, "Ctrl Shift H");
	EditorMenuBar.addMenuItem("World", "-", 0);
	EditorMenuBar.addMenuItem("World", "Delete Selection", 17, "Delete");
	EditorMenuBar.addMenuItem("World", "Camera To Selection", 14);
	EditorMenuBar.addMenuItem("World", "Reset Transforms", 15);
	EditorMenuBar.addMenuItem("World", "Drop Selection", 16, "Ctrl D");
	EditorMenuBar.addMenuItem("World", "Add Selection to Instant Group", 17);
	EditorMenuBar.addMenuItem("World", "-", 0);
	EditorMenuBar.addMenuItem("World", "Drop at Origin", 0, "", 1);
	EditorMenuBar.addMenuItem("World", "Drop at Camera", 1, "", 1);
	EditorMenuBar.addMenuItem("World", "Drop at Camera w/Rot", 2, "", 1);
	EditorMenuBar.addMenuItem("World", "Drop below Camera", 3, "", 1);
	EditorMenuBar.addMenuItem("World", "Drop at Screen Center", 4, "", 1);
	EditorMenuBar.addMenuItem("World", "Drop at Centroid", 5, "", 1);
	EditorMenuBar.addMenuItem("World", "Drop to Ground", 6, "", 1);

	EditorMenuBar.addMenu("Action", 3);
	EditorMenuBar.addMenuItem("Action", "Select", 1, "", 1);
	EditorMenuBar.addMenuItem("Action", "Adjust Selection", 2, "", 1);
	EditorMenuBar.addMenuItem("Action", "-", 0);
	EditorMenuBar.addMenuItem("Action", "Add Dirt", 6, "", 1);
	EditorMenuBar.addMenuItem("Action", "Excavate", 6, "", 1);
	EditorMenuBar.addMenuItem("Action", "Adjust Height", 6, "", 1);
	EditorMenuBar.addMenuItem("Action", "Flatten", 4, "", 1);
	EditorMenuBar.addMenuItem("Action", "Smooth", 5, "", 1);
	EditorMenuBar.addMenuItem("Action", "Set Height", 7, "", 1);
	EditorMenuBar.addMenuItem("Action", "-", 0);
	EditorMenuBar.addMenuItem("Action", "Set Empty", 8, "", 1);
	EditorMenuBar.addMenuItem("Action", "Clear Empty", 8, "", 1);
	EditorMenuBar.addMenuItem("Action", "-", 0);
	EditorMenuBar.addMenuItem("Action", "Paint Material", 9, "", 1);

	EditorMenuBar.addMenu("Brush", 4);
	EditorMenuBar.addMenuItem("Brush", "Box Brush", 91, "", 1);
	EditorMenuBar.addMenuItem("Brush", "Circle Brush", 92, "", 1);
	EditorMenuBar.addMenuItem("Brush", "-", 0);
	EditorMenuBar.addMenuItem("Brush", "Soft Brush", 93, "", 2);
	EditorMenuBar.addMenuItem("Brush", "Hard Brush", 94, "", 2);
	EditorMenuBar.addMenuItem("Brush", "-", 0);
	EditorMenuBar.addMenuItem("Brush", "Size 1 x 1", 1, "Alt 1", 3);
	EditorMenuBar.addMenuItem("Brush", "Size 3 x 3", 3, "Alt 2", 3);
	EditorMenuBar.addMenuItem("Brush", "Size 5 x 5", 5, "Alt 3", 3);
	EditorMenuBar.addMenuItem("Brush", "Size 9 x 9", 9, "Alt 4", 3);
	EditorMenuBar.addMenuItem("Brush", "Size 15 x 15", 15, "Alt 5", 3);
	EditorMenuBar.addMenuItem("Brush", "Size 25 x 25", 25, "Alt 6", 3);

	EditorMenuBar.addMenu("Mode", 2);
	EditorMenuBar.addMenuItem("Mode", "World Editor", 2, "F2", 1);
	EditorMenuBar.addMenuItem("Mode", "World Editor Inspector", 3, "F3", 1);
	EditorMenuBar.addMenuItem("Mode", "World Editor Creator", 4, "F4", 1);
	EditorMenuBar.addMenuItem("Mode", "Mission Area Editor", 5, "F5", 1);
	EditorMenuBar.addMenuItem("Mode", "-", 0);
	EditorMenuBar.addMenuItem("Mode", "Terrain Editor", 6, "F6", 1);
	EditorMenuBar.addMenuItem("Mode", "Terrain Terraform Editor", 7, "F7", 1);
	EditorMenuBar.addMenuItem("Mode", "Terrain Texture Editor", 8, "F8", 1);
	EditorMenuBar.addMenuItem("Mode", "Terrain Texture Painter", 9, "", 1);

	EditorMenuBar.addMenu("Lighting", 8);
	EditorMenuBar.addMenuItem("Lighting", "Full Relight", 1, "Alt L");
	EditorMenuBar.addMenuItem("Lighting", "Filtered Relight", 2, "Alt F");
	EditorMenuBar.addMenuItem("Lighting", "-", 0);
	EditorMenuBar.addMenuItem("Lighting", "Production", 3, "", 1);
	EditorMenuBar.addMenuItem("Lighting", "Design", 4, "", 1);
	EditorMenuBar.addMenuItem("Lighting", "Draft", 5, "", 1);
	EditorMenuBar.addMenuItem("Lighting", "-", 0);
    EditorMenuBar.addMenuItem("Lighting", "Shadows", 6, "", 2);
	EditorMenuBar.addMenuItem("Lighting", "-", 0);
	EditorMenuBar.addMenuItem("Lighting", "Reset All Light Animation", 7);
 
	EditorMenuBar.addMenu("Interior", 9);
	EditorMenuBar.addMenuItem("Interior", "Render normal", 0, "", 1);
 	EditorMenuBar.addMenuItem("Interior", "Render wireframe", 1, "", 1);
 	EditorMenuBar.addMenuItem("Interior", "Show details", 2, "", 1);
   	EditorMenuBar.addMenuItem("Interior", "Show ambiguous", 3, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show orphans", 4, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show lightmaps", 5, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show textures only", 6, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show portal zones", 7, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show outside visible", 8, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show collision fans", 9, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show strips", 10, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show NULL surfaces", 11, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show large textures", 12, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show hull surfaces", 13, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show vehicle hull surfaces", 14, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show vertex colors", 15, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show detail level", 16, "", 1);
    EditorMenuBar.addMenuItem("Interior", "Show vertex normals", 17, "", 1);
    
	EditorMenuBar.addMenu("Windows", 10);
	EditorMenuBar.addMenuItem("Windows", "Light Editor", 0, "", 1);
	EditorMenuBar.addMenuItem("Windows", "World Editor Toolbox", 1, "", 5);
	EditorMenuBar.addMenuItem("Windows", "World Editor Settings", 2, "", 2);
	EditorMenuBar.addMenuItem("Windows", "Terrain Editor Settings", 3, "", 3);
	EditorMenuBar.addMenuItem("Windows", "Terrain Editor Soft Selection", 4, "", 4);

	EditorMenuBar.onActionMenuItemSelect(0, "Adjust Height");
	EditorMenuBar.onBrushMenuItemSelect(0, "Circle Brush");
	EditorMenuBar.onBrushMenuItemSelect(0, "Soft Brush");
	EditorMenuBar.onBrushMenuItemSelect(9, "Size 9 x 9");
	EditorMenuBar.onCameraMenuItemSelect(6, "Medium Pace");
	EditorMenuBar.onWorldMenuItemSelect(0, "Drop at Screen Center");
 
    EditorMenuBar.setMenuItemChecked("Lighting", 3 + $pref::LightManager::sgLightingProfileQuality, true);
    EditorMenuBar.setMenuItemChecked("Lighting", 6, $pref::LightManager::sgLightingProfileAllowShadows);

	EWorldEditor.init();
	ETerrainEditor.attachTerrain();
	TerraformerInit();
	TextureInit();

	//
	//Creator.init();
	EditorTree.init();
	ObjectBuilderGui.init();

	EWorldEditor.isDirty = false;
	ETerrainEditor.isDirty = false;
	ETerrainEditor.isMissionDirty = false;
	EditorGui.saveAs = false;
}

function EditorQuitMission()
{  
	if(ETerrainEditor.isMissionDirty || ETerrainEditor.isDirty || EWorldEditor.isDirty)
	{
		MessageBoxYesNo("Mission Modified", "Would you like to save your changes before quiting?", "EditorDoQuitMission(true);", "EditorDoQuitMission(false);");
	}
	else
		EditorDoQuitMission(false);
}

function EditorDoQuitMission(%saveFirst)
{
	if(%saveFirst)
	{
		EditorSaveMissionMenu();
		Editor.close("MainMenuGui");
		disconnect();
	}
	else
	{
		Editor.close("MainMenuGui");
		disconnect();
	}
}

function EditorNewMission()
{
	if(ETerrainEditor.isMissionDirty || ETerrainEditor.isDirty || EWorldEditor.isDirty)
	{
		MessageBoxYesNo("Mission Modified", "Would you like to save changes to the current mission environment \"" @
			$Server::MissionEnvironmentFile @ "\" before creating a new mission?", "EditorDoNewMission(true);", "EditorDoNewMission(false);");
	}
	else
		EditorDoNewMission(false);
}

function EditorSaveMissionMenu()
{
	//if (MissionInfo.type !$= "DemoScene") {
	if ($BlockSave!=1) {
		if(EditorGui.saveAs)
			EditorSaveMissionAs();
		else
			EditorSaveMission();
	}  else {
		echo("To enable mission saving, make \$BlockSave=1.");
		MessageBoxOK("Save Function Disabled","The Save Mission function has been disabled for this demo walkthrough.\n\n  If you are sure you want to make changes to this mission and save them, go to the console (tilde \"~\" key) and type \"$BlockSave=0;\" first.");
	}
}

function EditorSaveMission()
{
	// just save the mission without renaming it

	// first check for dirty and read-only files:
	if((EWorldEditor.isDirty || ETerrainEditor.isMissionDirty) && !isWriteableFileName($Server::MissionEnvironmentFile))
	{
		MessageBoxOK("Error", "Mission file \""@ $Server::MissionEnvironmentFile @ "\" is read-only.");
		return false;
	}
	if(ETerrainEditor.isDirty && !isWriteableFileName(Terrain.terrainFile))
	{
		MessageBoxOK("Error", "Terrain file \""@ Terrain.terrainFile @ "\" is read-only.");
		return false;
	}
  
	// now write the terrain and mission files out:

	if(EWorldEditor.isDirty || ETerrainEditor.isMissionDirty)
		MissionEnvironment.save($Server::MissionEnvironmentFile);
	if(ETerrainEditor.isDirty)
		Terrain.save(Terrain.terrainFile);
	EWorldEditor.isDirty = false;
	ETerrainEditor.isDirty = false;
	ETerrainEditor.isMissionDirty = false;
	EditorGui.saveAs = false;

	return true;
}

function EditorDoSaveAs(%missionName)
{
	ETerrainEditor.isDirty = true;
	EWorldEditor.isDirty = true;
	%saveMissionFile = $Server::MissionEnvironmentFile;
	%saveTerrName = Terrain.terrainFile;

	$Server::MissionEnvironmentFile = %missionName;
	Terrain.terrainFile = filePath(%missionName) @ "/" @ fileBase(%missionName) @ ".ter";

	if(!EditorSaveMission())
	{
		$Server::MissionEnvironmentFile = %saveMissionFile;
		Terrain.terrainFile = %saveTerrName;
	}
}

function EditorSaveMissionAs()
{
	if ($BlockSave!=1) {
		getSaveFilename("*.env", "EditorDoSaveAs", $Server::MissionEnvironmentFile);
	}  else {
		echo("To enable mission saving, make \$BlockSave=0.");
		MessageBoxOK("Save Function Disabled","The Save Mission function has been disabled for this demo walkthrough.\n\n  If you are sure you want to make changes to this mission and save them, go to the console (tilde \"~\" key) and type \"$BlockSave=0;\" first.");
	}
}

function EditorDoLoadMission(%file)
{
	// close the current editor, it will get cleaned up by MissionCleanup
	Editor.close();

	loadMission( %file, true ) ;

	// recreate and open the editor
	Editor::create();
	MissionCleanup.add(Editor);
	EditorGui.loadingMission = true;
	Editor.open();
}

function EditorSaveBeforeLoad()
{
	if(EditorSaveMission())
		getLoadFilename("*.env", "EditorDoLoadMission");
}

function EditorDoNewMission(%saveFirst)
{
	if(%saveFirst)
		EditorSaveMission();

	EditorDoLoadMission(expandFilename("~/data/newMission.env"));
	EditorGui.saveAs = true;
	EWorldEditor.isDirty = true;
	ETerrainEditor.isDirty = true;
}

function EditorOpenMission()
{
	if(ETerrainEditor.isMissionDirty || ETerrainEditor.isDirty || EWorldEditor.isDirty)
	{
		MessageBoxYesNo("Mission Modified", "Would you like to save changes to the current mission environment \"" @
			$Server::MissionEnvironmentFile @ "\" before opening a new mission?", "EditorSaveBeforeLoad();", "getLoadFilename(\"*.env\", \"EditorDoLoadMission\");");
	}
	else
		getLoadFilename("*.env", "EditorDoLoadMission");
}

function EditorMenuBar::onMenuSelect(%this, %menuId, %menu)
{
	if(%menu $= "File")
	{
		%editingHeightfield = ETerrainEditor.isVisible() && EHeightField.isVisible();
		EditorMenuBar.setMenuItemEnable("File", "Export Terraform Bitmap...", %editingHeightfield);
		EditorMenuBar.setMenuItemEnable("File", "Save Mission", ETerrainEditor.isDirty || ETerrainEditor.isMissionDirty || EWorldEditor.isDirty);
	}
	else if(%menu $= "Edit")
	{
		// enable/disable undo, redo, cut, copy, paste depending on editor settings

		if(EWorldEditor.isVisible())
		{
			// do actions based on world editor...
			EditorMenuBar.setMenuItemEnable("Edit", "Select All", true);
			EditorMenuBar.setMenuItemEnable("Edit", "Paste", EWorldEditor.canPasteSelection());
			%canCutCopy = EWorldEditor.getSelectionSize() > 0;

			EditorMenuBar.setMenuItemEnable("Edit", "Cut", %canCutCopy);
			EditorMenuBar.setMenuItemEnable("Edit", "Copy", %canCutCopy);

		}
		else if(ETerrainEditor.isVisible())
		{
			EditorMenuBar.setMenuItemEnable("Edit", "Cut", false);
			EditorMenuBar.setMenuItemEnable("Edit", "Copy", false);
			EditorMenuBar.setMenuItemEnable("Edit", "Paste", false);
			EditorMenuBar.setMenuItemEnable("Edit", "Select All", false);
		}
	}
	else if(%menu $= "World")
	{
		%selSize = EWorldEditor.getSelectionSize();
		%lockCount = EWorldEditor.getSelectionLockCount();
		%hideCount = EWorldEditor.getSelectionHiddenCount();

		EditorMenuBar.setMenuItemEnable("World", "Lock Selection", %lockCount < %selSize);
		EditorMenuBar.setMenuItemEnable("World", "Unlock Selection", %lockCount > 0);
		EditorMenuBar.setMenuItemEnable("World", "Hide Selection", %hideCount < %selSize);
		EditorMenuBar.setMenuItemEnable("World", "Show Selection", %hideCount > 0);

		EditorMenuBar.setMenuItemEnable("World", "Add Selection to Instant Group", %selSize > 0);
		EditorMenuBar.setMenuItemEnable("World", "Camera To Selection", %selSize > 0);
		EditorMenuBar.setMenuItemEnable("World", "Reset Transforms", %selSize > 0 && %lockCount == 0);
		EditorMenuBar.setMenuItemEnable("World", "Drop Selection", %selSize > 0 && %lockCount == 0);
		EditorMenuBar.setMenuItemEnable("World", "Delete Selection", %selSize > 0 && %lockCount == 0);
	}
}

function EditorMenuBar::onMenuItemSelect(%this, %menuId, %menu, %itemId, %item)
{
	switch$(%menu)
	{
		case "File":
			%this.onFileMenuItemSelect(%itemId, %item);
		case "Edit":
			%this.onEditMenuItemSelect(%itemId, %item);
		case "World":
			%this.onWorldMenuItemSelect(%itemId, %item);
		case "Mode":
			%this.onModeMenuItemSelect(%itemId, %item);
		case "Action":
			%this.onActionMenuItemSelect(%itemId, %item);
		case "Brush":
			%this.onBrushMenuItemSelect(%itemId, %item);
		case "Camera":
			%this.onCameraMenuItemSelect(%itemId, %item);
		case "Lighting":
			%this.onLightingMenuItemSelect(%itemId, %item);
		case "Interior":
			%this.onInteriorMenuItemSelect(%itemId, %item);
		case "Windows":
			%this.onWindowsMenuItemSelect(%itemId, %item);
	}
}

function EditorMenuBar::onFileMenuItemSelect(%this, %itemId, %item)
{
	switch$(%item)
	{
		case "New Mission...":
			EditorNewMission();
		case "Open Mission...":
			EditorOpenMission();
		case "Save Mission":
			EditorSaveMissionMenu();
		case "Save Mission As...":
			EditorSaveMissionAs();
		case "Import Texture Data...":
			Texture::import();
		case "Import Terraform Data...":
			Heightfield::import();
		case "Export Terraform Bitmap...":
			Heightfield::saveBitmap("");
		case "Toggle Mission Editor":
			Editor.close("Hud");
		case "Quit":
			EditorQuitMission();
	}
}

function EditorMenuBar::onCameraMenuItemSelect(%this, %itemId, %item)
{
	switch$(%item)
	{
		case "Drop Camera at Player":
			commandToServer('dropCameraAtPlayer');
		case "Drop Player at Camera":
			commandToServer('DropPlayerAtCamera');
		case "Toggle Camera":
			commandToServer('ToggleCamera');
		default:
			// all the rest are camera speeds:
			// item ids go from 3 (slowest) to 9 (fastest)
			%this.setMenuItemChecked("Camera", %itemId, true);
			// camera movement speed goes from 5 to 200:
			$Camera::movementSpeed = ((%itemId - 3) / 6.0) * 195 + 5;
	}
}

function EditorMenuBar::onActionMenuItemSelect(%this, %itemId, %item)
{
	EditorMenuBar.setMenuItemChecked("Action", %item, true);
	switch$(%item)
	{
		case "Select":
			ETerrainEditor.currentMode = "select";
			ETerrainEditor.selectionHidden = false;
			ETerrainEditor.renderVertexSelection = true;
			ETerrainEditor.setAction("select");
		case "Adjust Selection":
			ETerrainEditor.currentMode = "adjust";
			ETerrainEditor.selectionHidden = false;
			ETerrainEditor.setAction("adjustHeight");
			ETerrainEditor.currentAction = brushAdjustHeight;
			ETerrainEditor.renderVertexSelection = true;
		default:
			ETerrainEditor.currentMode = "paint";
			ETerrainEditor.selectionHidden = true;
			ETerrainEditor.setAction(ETerrainEditor.currentAction);
			switch$(%item)
			{
				case "Add Dirt":
					ETerrainEditor.currentAction = raiseHeight;
					ETerrainEditor.renderVertexSelection = true;
				case "Paint Material":
					ETerrainEditor.currentAction = paintMaterial;
					ETerrainEditor.renderVertexSelection = true;
				case "Excavate":
					ETerrainEditor.currentAction = lowerHeight;
					ETerrainEditor.renderVertexSelection = true;
				case "Set Height":
					ETerrainEditor.currentAction = setHeight;
					ETerrainEditor.renderVertexSelection = true;
				case "Adjust Height":
					ETerrainEditor.currentAction = brushAdjustHeight;
					ETerrainEditor.renderVertexSelection = true;
				case "Flatten":
					ETerrainEditor.currentAction = flattenHeight;
					ETerrainEditor.renderVertexSelection = true;
				case "Smooth":
					ETerrainEditor.currentAction = smoothHeight;
					ETerrainEditor.renderVertexSelection = true;
				case "Set Empty":
					ETerrainEditor.currentAction = setEmpty;
					ETerrainEditor.renderVertexSelection = false;
				case "Clear Empty":
					ETerrainEditor.currentAction = clearEmpty;
					ETerrainEditor.renderVertexSelection = false;
			}
			if(ETerrainEditor.currentMode $= "select")
				ETerrainEditor.processAction(ETerrainEditor.currentAction);
			else if(ETerrainEditor.currentMode $= "paint")
				ETerrainEditor.setAction(ETerrainEditor.currentAction);
	}
}

function EditorMenuBar::onBrushMenuItemSelect(%this, %itemId, %item)
{
	EditorMenuBar.setMenuItemChecked("Brush", %item, true);
	switch$(%item)
	{
		case "Box Brush":
			ETerrainEditor.setBrushType(box);
		case "Circle Brush":
			ETerrainEditor.setBrushType(ellipse);
		case "Soft Brush":
			ETerrainEditor.enableSoftBrushes = true;
		case "Hard Brush":
			ETerrainEditor.enableSoftBrushes = false;
		default:
			// the rest are brush sizes:
			ETerrainEditor.brushSize = %itemId;
			
			ETerrainEditor.setBrushSize(%itemId, %itemId);
	}
}

function EditorMenuBar::onWorldMenuItemSelect(%this, %itemId, %item)
{
	// edit commands for world editor...
	switch$(%item)
	{
		case "Lock Selection":
			EWorldEditor.lockSelection(true);
		case "Unlock Selection":
			EWorldEditor.lockSelection(false);
		case "Hide Selection":
			EWorldEditor.hideSelection(true);
		case "Show Selection":
			EWorldEditor.hideSelection(false);
		case "Camera To Selection":
			EWorldEditor.dropCameraToSelection();
		case "Reset Transforms":
			EWorldEditor.resetTransforms();
		case "Drop Selection":
			EWorldEditor.dropSelection();
		case "Delete Selection":
			EWorldEditor.deleteSelection();
			Inspector.uninspect();
		case "Add Selection to Instant Group":
			EWorldEditor.addSelectionToAddGroup();
		default:
			EditorMenuBar.setMenuItemChecked("World", %item, true);
			switch$(%item)
			{
				case "Drop at Origin":
					EWorldEditor.dropType = "atOrigin";
				case "Drop at Camera":
					EWorldEditor.dropType = "atCamera";
				case "Drop at Camera w/Rot":
					EWorldEditor.dropType = "atCameraRot";
				case "Drop below Camera":
					EWorldEditor.dropType = "belowCamera";
				case "Drop at Screen Center":
					EWorldEditor.dropType = "screenCenter";
				case "Drop to Ground":
					EWorldEditor.dropType = "toGround";
				case "Drop at Centroid":
					EWorldEditor.dropType = "atCentroid";
			}
	}
}

function EditorMenuBar::onEditMenuItemSelect(%this, %itemId, %item)
{
	if(%item $= "Relight Scene")
		lightScene("", forceAlways);
	else if(EWorldEditor.isVisible())
	{
		// edit commands for world editor...
		switch$(%item)
		{
			case "Undo":
				EWorldEditor.undo();
			case "Redo":
				EWorldEditor.redo();
			case "Copy":
				EWorldEditor.copySelection();
			case "Cut":
				EWorldEditor.copySelection();
				EWorldEditor.deleteSelection();
				Inspector.uninspect();
			case "Paste":
				EWorldEditor.pasteSelection();
			case "Select All":
			case "Select None":
		}
	}
	else if(ETerrainEditor.isVisible())
	{
		// do some terrain stuffin'
		switch$(%item)
		{
			case "Undo":
				ETerrainEditor.undo();
			case "Redo":
				ETerrainEditor.redo();
			case "Select None":
				ETerrainEditor.clearSelection();
		}
	}
}

function EditorMenuBar::onLightingMenuItemSelect(%this, %itemId, %item)
{
	switch$(%item)
	{
		case "Filtered Relight":
        	$SceneLighting::sgFilterRelight = "true";
        	$SceneLighting::sgFilterRelightByDistance = "true";
        	lightScene("filteredRelightComplete", forceAlways);
         
		case "Full Relight":
			lightScene("filteredRelightComplete", forceAlways);
   
		case "Production":
        	$pref::LightManager::sgLightingProfileQuality = 0;
            EditorMenuBar.setMenuItemChecked("Lighting", %item, true);
            
		case "Design":
        	$pref::LightManager::sgLightingProfileQuality = 1;
            EditorMenuBar.setMenuItemChecked("Lighting", %item, true);
            
		case "Draft":
        	$pref::LightManager::sgLightingProfileQuality = 2;
            EditorMenuBar.setMenuItemChecked("Lighting", %item, true);
            
		case "Shadows":
            %value = !$pref::LightManager::sgLightingProfileAllowShadows;
            $pref::LightManager::sgLightingProfileAllowShadows = %value;
            EditorMenuBar.setMenuItemChecked("Lighting", %item, %value);
            
		case "Reset All Light Animation":
        	%count = LightSet.getCount();
        	//echo(%count);
        	for(%i=0; %i<%count; %i++)
        	{
        		%light = LightSet.getObject(%i);
        		if(isObject(%light))
        			%light.reset();
        	}
	}
}

function EditorMenuBar::onModeMenuItemSelect(%this, %itemId, %item)
{
	EditorGui.setEditor(%item);
}

function EditorMenuBar::onInteriorMenuItemSelect(%this, %itemId, %item)
{
    if(!setInteriorRenderMode(%itemId))
        MessageBoxOK("Denied", "This is not allowed in multiplayer mode.");
}

function EditorMenuBar::onWindowsMenuItemSelect(%this, %itemId, %item)
{
	switch$(%item)
	{
		case "Light Editor":
            EditorGui::addWindow(sgLightEditor);
		case "World Editor Toolbox":
            EditorGui::addWindow(WorldEditorToolbox);            
		case "World Editor Settings":
            EditorGui::addWindow(WorldEditorSettings);
		case "Terrain Editor Settings":
            EditorGui::addWindow(TerrainEditorSettings);
		case "Terrain Editor Soft Selection":
            EditorGui::addWindow(TerrainEditorSoftSelection);

	}
}

function Creator::onWake(%this)
{
	Creator.init();
}

function EditorGui::setWorldEditorVisible(%this)
{
	EWorldEditor.setVisible(true);
	ETerrainEditor.setVisible(false);
	EditorMenuBar.setMenuVisible("World", true);
	EditorMenuBar.setMenuVisible("Action", false);
	EditorMenuBar.setMenuVisible("Brush", false);
	EWorldEditor.makeFirstResponder(true);
	EditorTree.open(MissionEnvironment,true);
}

function EditorGui::setTerrainEditorVisible(%this)
{
	EWorldEditor.setVisible(false);
	ETerrainEditor.setVisible(true);
	ETerrainEditor.attachTerrain();
	EHeightField.setVisible(false);
	ETexture.setVisible(false);
	EditorMenuBar.setMenuVisible("World", false);
	EditorMenuBar.setMenuVisible("Action", true);
	EditorMenuBar.setMenuVisible("Brush", true);
	ETerrainEditor.makeFirstResponder(true);
	EPainter.setVisible(false);
}

function EditorGui::setEditor(%this, %editor)
{
	EditorMenuBar.setMenuItemBitmap("Mode", %this.currentEditor, -1);
	EditorMenuBar.setMenuItemBitmap("Mode", %editor, 0);
	%this.currentEditor = %editor;

	switch$(%editor)
	{
		case "World Editor":
			EWFrame.setVisible(false);
			EWMissionArea.setVisible(false);
			%this.setWorldEditorVisible();
		case "World Editor Inspector":
			EWFrame.setVisible(true);
			EWMissionArea.setVisible(false);
			EWCreatorPane.setVisible(false);
			EWInspectorPane.setVisible(true);
			%this.setWorldEditorVisible();
		case "World Editor Creator":
			EWFrame.setVisible(true);
			EWMissionArea.setVisible(false);
			EWCreatorPane.setVisible(true);
			EWInspectorPane.setVisible(false);
			%this.setWorldEditorVisible();
		case "Mission Area Editor":
			EWFrame.setVisible(false);
			EWMissionArea.setVisible(true);
			%this.setWorldEditorVisible();
		case "Terrain Editor":
			%this.setTerrainEditorVisible();
		case "Terrain Terraform Editor":
			%this.setTerrainEditorVisible();
			EHeightField.setVisible(true);
		case "Terrain Texture Editor":
			%this.setTerrainEditorVisible();
			ETexture.setVisible(true);
		case "Terrain Texture Painter":
			%this.setTerrainEditorVisible();
			EPainter.setVisible(true);
			EPainter.setup();

	}
}

function EditorGui::getHelpPage(%this)
{
	switch$(%this.currentEditor)
	{
		case "World Editor" or "World Editor Inspector" or "World Editor Creator":
			return "5. World Editor";
		case "Mission Area Editor":
			return "6. Mission Area Editor";
		case "Terrain Editor":
			return "7. Terrain Editor";
		case "Terrain Terraform Editor":
			return "8. Terrain Terraform Editor";
		case "Terrain Texture Editor":
			return "9. Terrain Texture Editor";
		case "Terrain Texture Painter":
			return "10. Terrain Texture Painter";
	}
}


function ETerrainEditor::setPaintMaterial(%this, %matIndex)
{
	ETerrainEditor.paintMaterial = EPainter.mat[%matIndex];
}

function ETerrainEditor::changeMaterial(%this, %matIndex)
{
	EPainter.matIndex = %matIndex;
	getLoadFilename("*.png\t*.jpg", EPainterChangeMat);
}

function EPainterChangeMat(%file)
{
	// make sure the material isn't already in the terrain.
	%file = filePath(%file) @ "/" @ fileBase(%file);
	for(%i = 0; %i < 6; %i++)
		if(EPainter.mat[%i] $= %file)
			return;

	EPainter.mat[EPainter.matIndex] = %file;
	%mats = "";
	for(%i = 0; %i < 6; %i++)
		%mats = %mats @ EPainter.mat[%i] @ "\n";
	ETerrainEditor.setTerrainMaterials(%mats);
	EPainter.setup();
	("ETerrainMaterialPaint" @ EPainter.matIndex).performClick();
}

function EPainter::setup(%this)
{
	EditorMenuBar.onActionMenuItemSelect(0, "Paint Material");
	%mats = ETerrainEditor.getTerrainMaterials();
	%valid = true;
	for(%i = 0; %i < 6; %i++)
	{
		%mat = getRecord(%mats, %i);
		%this.mat[%i] = %mat;
		("ETerrainMaterialText" @ %i).setText(fileBase(%mat));
		("ETerrainMaterialBitmap" @ %i).setBitmap(%mat);
		("ETerrainMaterialChange" @ %i).setActive(true);
		("ETerrainMaterialPaint" @ %i).setActive(%mat !$= "");
		if(%mat $= "")
		{
			("ETerrainMaterialChange" @ %i).setText("Add...");
			if(%valid)
				%valid = false;
			else
				("ETerrainMaterialChange" @ %i).setActive(false);
		}
		else
			("ETerrainMaterialChange" @ %i).setText("Change...");
	}
	ETerrainMaterialPaint0.performClick();
}

function EditorGui::onWake(%this)
{
    pushActionMap(MoveMap);
    pushActionMap(EditorMap);

	%this.setEditor(%this.currentEditor);
	
	if (DemoEditorAlert.helpTag<2) Canvas.pushDialog(DemoEditorAlert);

}

function EditorGui::onSleep(%this)
{
    popActionMap(EditorMap);
	popActionMap(MoveMap);
	$Server::CurrentScene.open();
}

function AreaEditor::onUpdate(%this, %area)
{
	AreaEditingText.setValue( "X: " @ getWord(%area,0) @ " Y: " @ getWord(%area,1) @ " W: " @ getWord(%area,2) @ " H: " @ getWord(%area,3));
}

function AreaEditor::onWorldOffset(%this, %offset)
{
}

function WorldEditor::onDelete(%this)
{
	EditorTree.deleteSelection();
	Inspector.uninspect();
}

function WorldEditor::onSelect(%this,%obj)
{
	EditorTree.addSelection(%obj); 
}

function WorldEditor::onUnSelect(%this,%obj)
{ 
	EditorTree.removeSelection(%obj);
	Inspector.uninspect();
}

function WorldEditor::onClearSelected(%this)
{
	EditorTree.clearSelection();
	Inspector.uninspect();
}

function WorldEditor::onClearSelection(%this)
{
	EditorTree.clearSelection();
	Inspector.uninspect();
}

function EditorTree::onObjectDeleteCompleted(%this)
{
	EWorldEditor.copySelection();
	EWorldEditor.deleteSelection();
	Inspector.uninspect();
}

function EditorTree::onClearSelected(%this)
{
	WorldEditor.clearSelection();
}

function EditorTree::init(%this)
{
	//%this.open(MissionEnvironment);

	// context menu
	new GuiControl(ETContextPopupDlg)
	{
	 profile = "GuiModelessDialogProfile";
		horizSizing = "width";
		vertSizing = "height";
		position = "0 0";
		extent = "640 480";
		minExtent = "8 8";
		visible = "1";
		setFirstResponder = "0";
		modal = "1";
		
		new GuiPopUpMenuCtrl(ETContextPopup)
		{
			profile = "GuiScrollProfile";
			position = "0 0";
			extent = "0 0";
			minExtent = "0 0";
			maxPopupHeight = "200";
			command = "canvas.popDialog(ETContextPopupDlg);";
		};
	};
	ETContextPopup.setVisible(false);
}

function EditorTree::onInspect(%this, %obj)
{
	Inspector.inspect(%obj);
	InspectorNameEdit.setValue(%obj.getName());
}
function EditorTree::onAddSelection(%this, %obj)
{
	if($AIEdit)	
		aiEdit.selectObject(%obj);
	else
		EWorldEditor.selectObject(%obj);
}
function EditorTree::onRemoveSelection(%this, %obj)
{
	if($AIEdit)	
		aiEdit.selectObject(%obj);
	else
		EWorldEditor.unselectObject(%obj);
}
function EditorTree::onSelect(%this, %obj)
{
	if($AIEdit)	
		aiEdit.selectObject(%obj);
	else {
		EWorldEditor.selectObject(%obj);	  
	}

}

function EditorTree::onUnselect(%this, %obj)
{
	if($AIEdit)
		aiEdit.unselectObject(%obj);
	else
		EWorldEditor.unselectObject(%obj);
}

function ETContextPopup::onSelect(%this, %index, %value)
{
	switch(%index)
	{
		case 0:
			EditorTree.contextObj.delete();
	}
}

//------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------

function WorldEditor::init(%this)
{
	// add objclasses which we do not want to collide with
	%this.ignoreObjClass(TerrainBlock, Sky, AIObjective);

	// editing modes
	%this.numEditModes = 3;
	%this.editMode[0]	 = "move";
	%this.editMode[1]	 = "rotate";
	%this.editMode[2]	 = "scale";

	// context menu
	new GuiControl(WEContextPopupDlg)
	{
		profile = "GuiModelessDialogProfile";
		horizSizing = "width";
		vertSizing = "height";
		position = "0 0";
		extent = "640 480";
		minExtent = "8 8";
		visible = "1";
		setFirstResponder = "0";
		modal = "1";
		
		new GuiPopUpMenuCtrl(WEContextPopup)
		{
			profile = "GuiScrollProfile";
			position = "0 0";
			extent = "0 0";
			minExtent = "0 0";
			maxPopupHeight = "200";
			command = "canvas.popDialog(WEContextPopupDlg);";
		};
	};
	WEContextPopup.setVisible(false);
}

//------------------------------------------------------------------------------

function WorldEditor::onDblClick(%this, %obj)
{
	// Commented out because making someone double click to do this is stupid
	// and has the possibility of moving hte object
	
	//Inspector.inspect(%obj);
	//InspectorNameEdit.setValue(%obj.getName());
}

function WorldEditor::onClick( %this, %obj )
{
	Inspector.inspect( %obj );
	InspectorNameEdit.setValue( %obj.getName() );
}

function WorldEditor::onEndDrag( %this, %obj )
{
	Inspector.inspect( %obj );
	InspectorNameEdit.setValue( %obj.getName() );
}

//------------------------------------------------------------------------------

function WorldEditor::export(%this)
{
	getSaveFilename("~/editor/*.mac", %this @ ".doExport", "selection.mac");
}

function WorldEditor::doExport(%this, %file)
{
	MissionEnvironment.save("~/editor/" @ %file, true);
}

function WorldEditor::import(%this)
{
	getLoadFilename("~/editor/*.mac", %this @ ".doImport");
}

function WorldEditor::doImport(%this, %file)
{
	exec("~/editor/" @ %file);
}

function WorldEditor::onGuiUpdate(%this, %text)
{
}

function WorldEditor::getSelectionLockCount(%this)
{
	%ret = 0;
	for(%i = 0; %i < %this.getSelectionSize(); %i++)
	{
		%obj = %this.getSelectedObject(%i);
		if(%obj.locked $= "true")
			%ret++;
	}
	return %ret;
}

function WorldEditor::getSelectionHiddenCount(%this)
{
	%ret = 0;
	for(%i = 0; %i < %this.getSelectionSize(); %i++)
	{
		%obj = %this.getSelectedObject(%i);
		if(%obj.hidden $= "true")
			%ret++;
	}
	return %ret;
}

function WorldEditor::dropCameraToSelection(%this)
{
	if(%this.getSelectionSize() == 0)
		return;

	%pos = %this.getSelectionCentroid();
	%cam = LocalClientConnection.camera.getTransform();

	// set the pnt
	%cam = setWord(%cam, 0, getWord(%pos, 0));
	%cam = setWord(%cam, 1, getWord(%pos, 1));
	%cam = setWord(%cam, 2, getWord(%pos, 2));

	LocalClientConnection.camera.setTransform(%cam);
}

// * pastes the selection at the same place (used to move obj from a group to another)
function WorldEditor::moveSelectionInPlace(%this)
{
	%saveDropType = %this.dropType;
	%this.dropType = "atCentroid";
	%this.copySelection();
	%this.deleteSelection();
	%this.pasteSelection();
	%this.dropType = %saveDropType;
}

function WorldEditor::addSelectionToAddGroup(%this)
{
	for(%i = 0; %i < %this.getSelectionSize(); %i++) 
	{
		%obj = %this.getSelectedObject(%i);
		$InstantGroup.add(%obj);
	}
}	

// resets the scale and rotation on the selection set
function WorldEditor::resetTransforms(%this)
{
	%this.addUndoState();

	for(%i = 0; %i < %this.getSelectionSize(); %i++)
	{
		%obj = %this.getSelectedObject(%i);
		%transform = %obj.getTransform();

		%transform = setWord(%transform, 3, "0");
		%transform = setWord(%transform, 4, "0");
		%transform = setWord(%transform, 5, "1");
		%transform = setWord(%transform, 6, "0");
			
		//
		%obj.setTransform(%transform);
		%obj.setScale("1 1 1");
	}
}


function WorldEditorToolbarDlg::init(%this)
{
	WorldEditorInspectorCheckBox.setValue(WorldEditorToolFrameSet.isMember("EditorToolInspectorGui"));
	WorldEditorMissionAreaCheckBox.setValue(WorldEditorToolFrameSet.isMember("EditorToolMissionAreaGui"));
	WorldEditorTreeCheckBox.setValue(WorldEditorToolFrameSet.isMember("EditorToolTreeViewGui"));
	WorldEditorCreatorCheckBox.setValue(WorldEditorToolFrameSet.isMember("EditorToolCreatorGui"));
}

function Creator::init( %this ) 
{
	//%this.clear();
	$InstantGroup = "MissionEnvironment";

	// ---------- INTERIORS	 
	%base = %this.insertItem( 0, "Interiors" );

	// walk all the interiors and add them to the correct group
	%interiorId = "";
	%file = findFirstFile( "*.dif" );
	
	while( %file !$= "" ) 
	{
		// Determine which group to put the file in
		// and build the group hierarchy as we go
		%split	 = strreplace(%file, "/", " ");
		%dirCount = getWordCount(%split)-1;
		%parentId = %base;
		
		for(%i=0; %i<%dirCount; %i++)
		{
			%parent = getWords(%split, 0, %i);
			
			// if the group doesn't exist create it
			if ( !%interiorId[%parent] )
				%interiorId[%parent] = %this.insertItem( %parentId, getWord(%split, %i));
			%parentId = %interiorId[%parent];
		}
		
		// Add the file to the group
		%create = "createInterior(" @ "\"" @ %file @ "\"" @ ");";
		%this.insertItem( %parentId, fileBase( %file ), %create,"Interior" );
	
		%file = findNextFile( "*.dif" );
	}


	// ---------- SHAPES - add in all the shapes now...
	%base = %this.insertItem(0, "Shapes");
	%dataGroup = "DataBlockGroup";
	
	for(%i = 0; %i < %dataGroup.getCount(); %i++)
	{
		%obj = %dataGroup.getObject(%i);
		echo ("Obj: " @ %obj.getName() @ " - " @ %obj.category );
		if(%obj.category !$= "" || %obj.category != 0)
		{
			%id = %this.findItemByName(%obj.category);
			  if (%id  == 0) 
			  { 
				%grp = %this.insertItem(%base,%obj.category);
				%this.insertItem(%grp, %obj.getName(), %obj.getClassName() @ "::create(" @ %obj.getName() @ ");","Item");
			}
			else
			{
				%this.insertItem(%id, %obj.getName(), %obj.getClassName() @ "::create(" @ %obj.getName() @ ");","Item");
			}
		}
	}


	// ---------- Static Shapes	 
	%base = %this.insertItem( 0, "Static Shapes" );

	// walk all the statics and add them to the correct group
	%staticId = "";
	%file = findFirstFile( "*.dts" );
	while( %file !$= "" ) 
	{
		// Determine which group to put the file in
		// and build the group heirarchy as we go
		%split	 = strreplace(%file, "/", " ");
		%dirCount = getWordCount(%split)-1;
		%parentId = %base;
		
		for(%i=0; %i<%dirCount; %i++)
		{
			%parent = getWords(%split, 0, %i);
			// if the group doesn't exist create it
			if ( !%staticId[%parent] )
				%staticId[%parent] = %this.insertItem( %parentId, getWord(%split, %i));
			%parentId = %staticId[%parent];
		}
		// Add the file to the group
		%create = "TSStatic::create(\"" @ %file @ "\");";
		%this.insertItem( %parentId, fileBase( %file ), %create,"TSStatic" );
	
		%file = findNextFile( "*.dts" );
	}


	// *** OBJECTS - do the objects now...
	%objGroup[0] = "Environment";
	%objGroup[1] = "Mission";
	%objGroup[2] = "System";
	//%objGroup[3] = "AI";

	%Environment_Item[0]  = "Sky";
	%Environment_Item[1]  = "Sun";
	%Environment_Item[2]  = "Lightning";
	%Environment_Item[3]  = "Water";
	%Environment_Item[4]  = "Terrain";
	%Environment_Item[5]  = "AudioEmitter";
	%Environment_Item[6]  = "Precipitation";
	%Environment_Item[7]  = "ParticleEmitter";
	%Environment_Item[8]  = "fxSunLight";
	%Environment_Item[9]  = "fxShapeReplicator";
	%Environment_Item[10] = "fxFoliageReplicator";
	%Environment_Item[11] = "fxLight";
	
	%Environment_Item[12] = "sgLightObject";
	%Environment_Item[13] = "VolumeLight";
	%Environment_Item[14] = "sgMissionLightingFilter";
	%Environment_Item[15] = "sgDecalProjector";
	
	%Mission_Item[0] = "MissionArea";
	%Mission_Item[1] = "Path";
	%Mission_Item[2] = "PathMarker";
	%Mission_Item[3] = "Trigger";
	%Mission_Item[4] = "PhysicalZone";
	%Mission_Item[5] = "Camera";
	//%Mission_Item[5] = "GameType";
	//%Mission_Item[6] = "Forcefield";

	%System_Item[0] = "SimGroup";

	//%AI_Item[0] = "Objective";
	//%AI_Item[1] = "NavigationGraph";

	// objects group
	%base = %this.insertItem(0, "Mission Objects");

	// create 'em
	for(%i = 0; %objGroup[%i] !$= ""; %i++)
	{
		%grp = %this.insertItem(%base, %objGroup[%i]);

		%groupTag = "%" @ %objGroup[%i] @ "_Item";

		%done = false;
		for(%j = 0; !%done; %j++)
		{
			eval("%itemTag = " @ %groupTag @ %j @ ";");
			
			if(%itemTag $= "")
				%done = true;
			else 
			{
				//echo("itemTag:" @ %itemTag @ " j:" @ %j);
				%this.insertItem(%grp, %itemTag, "ObjectBuilderGui.build" @ %itemTag @ "();",%itemTag);
			}
		}
	}
}

function createInterior(%name)
{
	%obj = new InteriorInstance()
	{
		position = "0 0 0";
		rotation = "0 0 0";
		interiorFile = %name;
	};
	
	return(%obj);
}

//function Creator::onAction(%this)
//{
//	%this.currentSel = -1;
//	%this.currentRoot = -1;
//	%this.currentObj = -1;

  // %sel = %this.getSelected();
  // if(%sel == -1 || %this.isGroup(%sel) || !$missionRunning)
  //	 return;
		
	// the value is the callback function..
  // if(%this.getValue(%sel) $= "")
  //	 return;

//	%this.currentSel = %sel;
//	%this.currentRoot = %this.getRootGroup(%sel);

  // %this.create(%sel);
//}

function WorldEditor::onAddSelected(%this,%obj)
{
	EditorTree.addSelection(%obj);
}

function Creator::onSelect(%this)
{
	Creator.clearSelection();
}

function Creator::onInspect(%this,%obj)
{
	if(!$missionRunning)
		return;
		
	%objId = eval(%this.getItemValue(%obj));
		
	// drop it from the editor - only SceneObjects can be selected...	
	Creator.removeSelection(%obj);
	
	EditorTree.clearSelection();
	EWorldEditor.clearSelection();
	EWorldEditor.selectObject(%objId);
	EWorldEditor.dropSelection();
}

function Creator::create(%this, %sel)
{
	// create the obj and add to the instant group
	%obj = eval(%this.getItemValue(%sel));

	if(%obj == -1)
		return;

//	%this.currentObj = %obj;

	$InstantGroup.add(%obj);
		
	// drop it from the editor - only SceneObjects can be selected...
	EWorldEditor.clearSelection();
	EWorldEditor.selectObject(%obj);
	EWorldEditor.dropSelection();
}


function TSStatic::create(%shapeName)
{
	%obj = new TSStatic() 
	{
		shapeName = %shapeName;
	};
	return(%obj);
}

function TSStatic::damage(%this)
{
	// prevent console error spam
}


//function Creator::getRootGroup(%sel)
//{
//	if(%sel == -1 || %sel == 0)
//		return(-1);
//
//	%parent = %this.getParent(%sel);
//	while(%parent != 0 || %parent != -1)
//	{
//		%sel = %parent;
//		%parent = %this.getParent(%sel);
//	}
//
//	return(%sel);
//}
//	
//function Creator::getLastItem(%rootGroup)
//{
//	%traverse = %rootGroup + 1;
//	while(%this.getRootGroup(%traverse) == %rootGroup)
//		%traverse++;
//	return(%traverse - 1);
//}
//
//function Creator::createNext(%this)
//{
//	if(%this.currentSel == -1 || %this.currentRoot == -1 || %this.currentObj == -1)
//		return;
//
//	%sel = %this.currentSel;
//	%this.currentSel++;
//
//	while(%this.currentSel != %sel)
//	{
//		if(%this.getRootGroup(%this.currentSel) != %this.currentRoot)
//			%this.currentSel = %this.currentRoot + 1;
//
//		if(%this.isGroup(%this.currentSel))
//			%this.currentSel++;
//		else
//			%sel = %this.currentSel;
//	}
//
//	//
//	%this.currentObj.delete();
//	%this.create(%sel);
//}
//
//function Creator::createPrevious(%this)
//{
//	if(%this.currentSel == -1 || %this.currentGroup == -1 || %this.currentObj == -1)
//		return;
//
//	%sel = %this.currentSel;
//	%this.currentSel--;
//
//	while(%this.currentSel != %sel)
//	{
//		if(%this.getRootGroup(%this.currentSel) != %this.currentRoot)
//			%this.currentSel = getLastItem(%this.currentRoot);
//
//		if(%this.isGroup(%this.currentSel))
//			%this.currentSel--;
//		else
//			%sel = %this.currentSel;
//	}
//
//	//
//	%this.currentObj.delete();
//	%this.create(%sel);
//}


function TerraformerGui::init(%this)
{
	TerraformerHeightfieldGui.init();
	TerraformerTextureGui.init();
}

function TerraformerGui::onWake(%this)
{
	// Only the canvas level gui's get wakes, so udpate manually.
	TerraformerTextureGui.update();
}

function TerraformerGui::onSleep(%this)
{
	%this.setPrefs();
}

$nextTextureId = 1;
$nextTextureRegister = 1000;
$selectedMaterial = -1;
$selectedTextureOperation = -1;
$TerraformerTextureDir = "creator/editor/textureScripts";

//--------------------------------------

function TextureInit()
{
	// Assumes the terrain object is called terrain
	
	Texture_operation_menu.clear();
	Texture_operation_menu.setText("Placement Operations");
	Texture_operation_menu.add("Place by Fractal", 1);
	Texture_operation_menu.add("Place by Height", 2);
	Texture_operation_menu.add("Place by Slope", 3);
	Texture_operation_menu.add("Place by Water Level", 4);

	$HeightfieldSrcRegister = Heightfield_operation.rowCount()-1;

	// sync up the preview windows
	TexturePreview.setValue(HeightfieldPreview.getValue());
	%script = terrain.getTextureScript();
	if(%script !$= "")
		Texture::loadFromScript(%script);

	if (Texture_material.rowCount() == 0)
	{
		Texture_operation.clear();
		$nextTextureRegister = 1000;
	}
	else
	{
		// it's difficult to tell if the heightfield was modified so 
		// just in case flag all dependent operations as dirty.
		%rowCount = Texture_material.rowCount();
		for (%row = 0; %row < %rowCount; %row++)
		{
			%data = Texture_material.getRowText(%row);
			%entry= getRecord(%data,0);
			%reg  = getField(%entry,1);
			$dirtyTexture[ %reg ] = true;

			%opCount = getRecordCount(%data);
			for (%op = 2; %op < %opCount; %op++)
			{
				%entry= getRecord(%data,%op);
				%label= getField(%entry,0);
				if (%label !$= "Place by Fractal" && %label !$= "Fractal Distortion")
				{
					%reg  = getField(%entry,2);
					$dirtyTexture[ %reg ] = true;
				}
			}
		}
		Texture::previewMaterial();	
	}
}

function TerraformerTextureGui::refresh(%this)
{
}	


//--------------------------------------
function Texture_material_menu::onSelect(%this, %id, %text)
{
	%this.setText("Materials");

	// FORMAT
	//	material name
	//	register
	//	  operation
	//		 name
	//		 tab name
	//		 register
	//		 distortion register
	//		 {field,value}, ...
	//	  operation
	//		 ...
	Texture::saveMaterial();
	Texture::hideTab();	
	%id = Texture::addMaterial(%text @ "\t" @ $nextTextureRegister++);
	
	if (%id != -1)
	{
		Texture_material.setSelectedById(%id);
		Texture::addOperation("Fractal Distortion\ttab_DistortMask\t" @ $nextTextureRegister++ @ "\t0\tdmask_interval\t20\tdmask_rough\t0\tdmask_seed\t" @ terraFormer.generateSeed() @ "\tdmask_filter\t0.00000 0.00000 0.13750 0.487500 0.86250 1.00000 1.00000");
	}
}	


function Texture::addMaterialTexture()
{
	%root = filePath(terrain.terrainFile);
	getLoadFilename("*.png\t*.jpg", addLoadedMaterial);
}

function addLoadedMaterial(%file)
{
	Texture::saveMaterial();
	Texture::hideTab();	
	%text = filePath(%file) @ "/" @ fileBase(%file);
	%id = Texture::addMaterial(%text @ "\t" @ $nextTextureRegister++);
	if (%id != -1)
	{
		Texture_material.setSelectedById(%id);
		Texture::addOperation("Fractal Distortion\ttab_DistortMask\t" @ $nextTextureRegister++ @ "\t0\tdmask_interval\t20\tdmask_rough\t0\tdmask_seed\t" @ terraFormer.generateSeed() @ "\tdmask_filter\t0.00000 0.00000 0.13750 0.487500 0.86250 1.00000 1.00000");
	}
	Texture::save();
}

//--------------------------------------
function Texture_material::onSelect(%this, %id, %text) 
{
	Texture::saveMaterial();
	if (%id != $selectedMaterial)
	{
		$selectedTextureOperation = -1;
		Texture_operation.clear();
		
		Texture::hideTab();
		Texture::restoreMaterial(%id);
	}

	%matName = getField(%text, 0);
	ETerrainEditor.paintMaterial = %matName;

	Texture::previewMaterial(%id);
	$selectedMaterial = %id;
	$selectedTextureOperation = -1;
	Texture_operation.clearSelection();
}	


//--------------------------------------
function Texture_operation_menu::onSelect(%this, %id, %text)
{
	%this.setText("Placement Operations");
	%id = -1;

	if ($selectedMaterial == -1)
		return;

	%dreg = getField(Texture_operation.getRowText(0),2);
							
	switch$ (%text)
	{
		case "Place by Fractal":
			%id = Texture::addOperation("Place by Fractal\ttab_FractalMask\t" @ $nextTextureRegister++ @ "\t" @ %dreg @ "\tfbmmask_interval\t16\tfbmmask_rough\t0.000\tfbmmask_seed\t" @ terraFormer.generateSeed() @ "\tfbmmask_filter\t0.000000 0.166667 0.333333 0.500000 0.666667 0.833333 1.000000\tfBmDistort\ttrue");

		case "Place by Height":
			%id = Texture::addOperation("Place by Height\ttab_HeightMask\t" @ $nextTextureRegister++ @ "\t" @ %dreg @ "\ttextureHeightFilter\t0 0.2 0.4 0.6 0.8 1.0\theightDistort\ttrue");

		case "Place by Slope":
			%id = Texture::addOperation("Place by Slope\ttab_SlopeMask\t" @ $nextTextureRegister++ @ "\t" @ %dreg @ "\ttextureSlopeFilter\t0 0.2 0.4 0.6 0.8 1.0\tslopeDistort\ttrue");

		case "Place by Water Level":
			%id = Texture::addOperation("Place by Water Level\ttab_WaterMask\t" @ $nextTextureRegister++ @ "\t" @ %dreg @ "\twaterDistort\ttrue");
	}

	// select it
	Texture::hideTab();
	if (%id != -1)
		Texture_operation.setSelectedById(%id);
}	


//--------------------------------------
function Texture_operation::onSelect(%this, %id, %text)
{
	Texture::saveOperation();	
	if (%id !$= $selectedTextureOperation)	
	{
		Texture::hideTab();	
		Texture::restoreOperation(%id);
		Texture::showTab(%id);	
	}

	Texture::previewOperation(%id);
	$selectedTextureOperation = %id;
}	


//--------------------------------------
function Texture::deleteMaterial(%id)
{
	if (%id $= "")
		%id = $selectedMaterial;
	if (%id == -1)	
		return;
	
	%row = Texture_material.getRowNumById(%id);
	
	Texture_material.removeRow(%row);

	// find the next row to select
	%rowCount = Texture_material.rowCount()-1;
	if (%row > %rowCount)
		%row = %rowCount;

	if (%id == $selectedMaterial)
		$selectedMaterial = -1;

	Texture_operation.clear();
	%id = Texture_material.getRowId(%row);
	Texture_material.setSelectedById(%id);
	Texture::save();
}	


//--------------------------------------
function Texture::deleteOperation(%id)
{
	if (%id $= "")
		%id = $selectedTextureOperation;
	if (%id == -1)	
		return;
	
	%row = Texture_operation.getRowNumById(%id);
	
	// don't delete the first entry
	if (%row == 0)
		return;
	
	Texture_operation.removeRow(%row);

	// find the next row to select
	%rowCount = Texture_operation.rowCount()-1;
	if (%row > %rowCount)
		%row = %rowCount;

	if (%id == $selectedTextureOperation)
		$selectedTextureOperation = -1;

	%id = Texture_operation.getRowId(%row);
	Texture_operation.setSelectedById(%id);
	Texture::save();
}	


//--------------------------------------
function Texture::applyMaterials()
{
	Texture::saveMaterial();
	%count = Texture_material.rowCount();
	if (%count > 0)	
	{
		%data = getRecord(Texture_material.getRowText(0),0);
		%mat_list = getField( %data, 0);
		%reg_list = getField( %data, 1);
		Texture::evalMaterial(Texture_material.getRowId(0));
		
		for (%i=1; %i<%count; %i++)
		{
			Texture::evalMaterial(Texture_material.getRowId(%i));
			%data = getRecord(Texture_material.getRowText(%i),0);
			%mat_list = %mat_list @ " " @ getField( %data, 0);
			%reg_list = %reg_list @ " " @ getField( %data, 1);
		}
		terraformer.setMaterials(%reg_list, %mat_list);
	}
}	


//--------------------------------------
function Texture::previewMaterial(%id)
{
	if (%id $= "")
		%id = $selectedMaterial;
	if (%id == -1)
		return;

	%data = Texture_material.getRowTextById(%id);
	%row  = Texture_material.getRowNumById(%id);
	%reg  = getField(getRecord(%data,0),1);

	Texture::evalMaterial(%id);

	terraformer.preview(TexturePreview, %reg);
}	


//--------------------------------------
function Texture::evalMaterial(%id)
{
	if (%id $= "")
		%id = $selectedMaterial;
	if (%id == -1)	
		return;

	%data = Texture_material.getRowTextbyId(%id);
	%reg  = getField(getRecord(%data,0), 1);

	// make sure all operation on this material are up to date
	// and accumulate register data for each
	%opCount = getRecordCount(%data);
	if (%opCount >= 2)	 // record0=material record1=fractal
	{
		%entry = getRecord(%data, 1);
		Texture::evalOperationData(%entry, 1);
		for (%op=2; %op<%opCount; %op++)
		{
			%entry = getRecord(%data, %op);
			%reg_list = %reg_list @ getField(%entry, 2) @ " ";
			Texture::evalOperationData(%entry, %op);
		}
		// merge the masks in to the dst reg
		terraformer.mergeMasks(%reg_list, %reg);
	}
	Texture::save();
}	


//--------------------------------------
function Texture::evalOperation(%id)
{
	if (%id $= "")
		%id = $selectedTextureOperation;
	if (%id == -1)	
		return;
	
	%data	= Texture_operation.getRowTextById(%id);
	%row	 = Texture_operation.getRowNumById(%id);
	
	if (%row != 0)	 
		Texture::evalOperation( Texture_operation.getRowId(0) );

	Texture::evalOperationData(%data, %row);
	Texture::save();
}	


//--------------------------------------
function Texture::evalOperationData(%data, %row)
{
	%label  = getField(%data, 0);
	%reg	 = getField(%data, 2);
	%dreg	= getField(%data, 3);
	%id	  = Texture_material.getRowId(%row);

	// Simple hack to make sure the water mask gets updated
	if (%label $= "Place by Water Level" && $worldWaterDirty == true)
	{
		$dirtyTexture[%reg] = true;
		$worldWaterDirty = false;
	}

	if ( $dirtyTexture[%reg] == false )
	{
		return;
	}

	switch$ (%label)
	{
		case "Fractal Distortion":
			terraformer.maskFBm( %reg, getField(%data,5), getField(%data,7), getField(%data,9), getField(%data,11), false, 0 );

		case "Place by Fractal":
			terraformer.maskFBm( %reg, getField(%data,5), getField(%data,7), getField(%data,9), getField(%data,11), getField(%data,13), %dreg );

		case "Place by Height":
			terraformer.maskHeight( $HeightfieldSrcRegister, %reg, getField(%data,5), getField(%data,7), %dreg );

		case "Place by Slope":
			terraformer.maskSlope( $HeightfieldSrcRegister, %reg, getField(%data,5), getField(%data,7), %dreg );

		case "Place by Water Level":
			terraformer.maskWater( $HeightfieldSrcRegister, %reg, getField(%data,5), %dreg );
	}


	$dirtyTexture[%reg] = false;
}	



//--------------------------------------
function Texture::previewOperation(%id)
{
	if (%id $= "")
		%id = $selectedTextureOperation;
	if (%id == -1)
		return;

	%row  = Texture_operation.getRowNumById(%id);
	%data = Texture_operation.getRowText(%row);
	%reg  = getField(%data,2);

	Texture::evalOperation(%id);
	terraformer.preview(TexturePreview, %reg);
}	



//--------------------------------------
function Texture::restoreMaterial(%id)
{
	if (%id == -1)
		return;

	%data = Texture_material.getRowTextById(%id);
	
	Texture_operation.clear();
	%recordCount = getRecordCount(%data);
	for (%record=1; %record<%recordCount; %record++)
	{
		%entry = getRecord(%data, %record);
		Texture_operation.addRow($nextTextureId++, %entry);
	}
}	


//--------------------------------------
function Texture::saveMaterial()
{
	%id = $selectedMaterial;
	if (%id == -1)
		return;

	Texture::SaveOperation();
	%data = Texture_Material.getRowTextById(%id);
	%newData = getRecord(%data,0);

	%rowCount = Texture_Operation.rowCount();
	for (%row=0; %row<%rowCount; %row++)
		%newdata = %newdata @ "\n" @ Texture_Operation.getRowText(%row);

	Texture_Material.setRowById(%id, %newdata);
	Texture::save();
}	


//--------------------------------------
function Texture::restoreOperation(%id)
{
	if (%id == -1)
		return;

	%data = Texture_operation.getRowTextById(%id);

	%fieldCount = getFieldCount(%data);
	for (%field=4; %field<%fieldCount; %field += 2)
	{
		%obj = getField(%data, %field);
		%obj.setValue( getField(%data, %field+1) );
	}
	Texture::save();
}	


//--------------------------------------
function Texture::saveOperation()
{
	%id = $selectedTextureOperation;
	if (%id == -1)
		return;

	%data = Texture_operation.getRowTextById(%id);
	%newData = getField(%data,0) @ "\t" @ getField(%data,1) @ "\t" @ getField(%data,2) @ "\t" @ getField(%data,3); 

	// go through each object and update its value
	%fieldCount = getFieldCount(%data);
	for (%field=4; %field<%fieldCount; %field += 2)
	{
		%obj = getField(%data, %field);
		%newdata = %newdata @ "\t" @ %obj @ "\t" @ %obj.getValue();
	}

	%dirty = (%data !$= %newdata);
	%reg	= getField(%data, 2);
	$dirtyTexture[%reg] = %dirty;
		
	Texture_operation.setRowById(%id, %newdata);

	// mark the material register as dirty too
	if (%dirty == true)
	{
		%data = Texture_Material.getRowTextById($selectedMaterial);
		%reg  = getField(getRecord(%data,0), 1);
		$dirtyTexture[ %reg ] = true;
	}

	// if row is zero the fractal mask was modified
	// mark everything else in the list as dirty
	 %row = Texture_material.getRowNumById(%id);
	 if (%row == 0)
	 {
		 %rowCount = Texture_operation.rowCount();
		 for (%r=1; %r<%rowCount; %r++)
		 {
			 %data = Texture_operation.getRowText(%r);
			 $dirtyTexture[ getField(%data,2) ] = true;
		 }
	}
	Texture::save();
}	


//--------------------------------------
function Texture::addMaterial(%entry)
{
	%id = $nextTextureId++;
	Texture_material.addRow(%id, %entry);
	
	%reg = getField(%entry, 1);
	$dirtyTexture[%reg] = true;

	Texture::save();
	return %id;
}	

//--------------------------------------
function Texture::addOperation(%entry)
{
	// Assumes: operation is being added to selected material

	%id = $nextTextureId++;
	Texture_operation.addRow(%id, %entry);

	%reg = getField(%entry, 2);
	$dirtyTexture[%reg] = true;

	Texture::save();
	return %id;
}	


//--------------------------------------
function Texture::save()
{
	%script = "";

	// loop through each operation and save it to disk
	%rowCount = Texture_material.rowCount();
	for(%row = 0; %row < %rowCount; %row++)
	{
		if(%row != 0)
			%script = %script @ "\n";
		%data = expandEscape(Texture_material.getRowText(%row));
		%script = %script @ %data;
	}
	terrain.setTextureScript(%script);
	ETerrainEditor.isDirty = true;
}

//--------------------------------------
function Texture::import()
{
	getLoadFilename("*.ter", "Texture::doLoadTexture");
}	

function Texture::loadFromScript(%script)
{
	Texture_material.clear();
	Texture_operation.clear();
	$selectedMaterial = -1;
	$selectedTextureOperation = -1;

	%i = 0;
	for(%rec = getRecord(%script, %i); %rec !$= ""; %rec = getRecord(%script, %i++))
		Texture::addMaterial(collapseEscape(%rec));
	// initialize dirty register array
	// patch up register usage
	// ...and deterime what the next register should be.
	$nextTextureRegister = 1000;
	%rowCount = Texture_material.rowCount();
	for (%row = 0; %row < %rowCount; %row++)
	{
		$dirtyTexture[ $nextTextureRegister ] = true;
		%data	 = Texture_material.getRowText(%row);
		%rec	  = getRecord(%data, 0);
		%rec	  = setField(%rec, 1, $nextTextureRegister);
		%data	 = setRecord(%data, 0, %rec);
		$nextTextureRegister++;
		
		%opCount = getRecordCount(%data);
		for (%op = 1; %op < %opCount; %op++)
		{
			if (%op == 1)
				%frac_reg = $nextTextureRegister;
			$dirtyTexture[ $nextTextureRegister ] = true;
			%rec  = getRecord(%data,%op);
			%rec  = setField(%rec, 2, $nextTextureRegister);
			%rec  = setField(%rec, 3, %frac_reg);
			%data = setRecord(%data, %op, %rec);
			$nextTextureRegister++;
		}
		%id = Texture_material.getRowId(%row);
		Texture_material.setRowById(%id, %data);
	}

	$selectedMaterial = -1;
	Texture_material.setSelectedById(Texture_material.getRowId(0));
}

//--------------------------------------
function Texture::doLoadTexture(%name)
{
	// ok, we're getting a terrain file...
	%newTerr = new TerrainBlock() // unnamed - since we'll be deleting it shortly:
	{
		position = "0 0 0";
		terrainFile = %name;
		squareSize = 8;
		visibleDistance = 100;
	};
	if(isObject(%newTerr))
	{
		%script = %newTerr.getTextureScript();
		if(%script !$= "")
			Texture::loadFromScript(%script);
		%newTerr.delete();
	}	
}	



//--------------------------------------
function Texture::hideTab()
{
	tab_DistortMask.setVisible(false);	
	tab_FractalMask.setVisible(false);	
	tab_HeightMask.setVisible(false);	
	tab_SlopeMask.setVisible(false);	
	tab_waterMask.setVisible(false);	
}	


//--------------------------------------
function Texture::showTab(%id)
{
	Texture::hideTab();
	%data = Texture_operation.getRowTextById(%id);
	%tab  = getField(%data,1);
	%tab.setVisible(true);
}	

function tab_Blend::reset(%this)
{
	blend_option.clear();
	blend_option.add("Add", 0);
	blend_option.add("Subtract", 1);
	blend_option.add("Max", 2);
	blend_option.add("Min", 3);
	blend_option.add("Multiply", 4);
}

function tab_fBm::reset(%this)
{
	fBm_detail.clear();
	fBm_detail.add("Very Low", 0);
	fBm_detail.add("Low", 1);
	fBm_detail.add("Normal", 2);
	fBm_detail.add("High", 3);
	fBm_detail.add("Very High", 4);
}

function tab_RMF::reset(%this)
{
	rmf_detail.clear();
	rmf_detail.add("Very Low", 0);
	rmf_detail.add("Low", 1);
	rmf_detail.add("Normal", 2);
	rmf_detail.add("High", 3);
	rmf_detail.add("Very High", 4);
}

function tab_terrainFile::reset(%this)
{
	// update tab controls..
	terrainFile_textList.clear();

	%filespec = $TerraformerHeightfieldDir @ "/*.ter";

	for(%file = findFirstFile(%filespec); %file !$= ""; %file = findNextFile(%filespec))
	{
		terrainFile_textList.addRow(%i++, fileBase(%file) @ fileExt(%file));
	}
}

function tab_canyon::reset()
{
}

function tab_smooth::reset()
{
}

function tab_smoothWater::reset()
{
}

function tab_smoothRidge::reset()
{
}

function tab_filter::reset()
{
}

function tab_turbulence::reset()
{
}

function tab_thermal::reset()
{
}

function tab_hydraulic::reset()
{
}

function tab_general::reset()
{
}

function tab_bitmap::reset()
{
}

function tab_sinus::reset()
{
}


//--------------------------------------

function Heightfield::resetTabs()
{
	tab_terrainFile.reset();
	tab_fbm.reset();
	tab_rmf.reset();
	tab_canyon.reset();
	tab_smooth.reset();
	tab_smoothWater.reset();
	tab_smoothRidge.reset();
	tab_filter.reset();
	tab_turbulence.reset();
	tab_thermal.reset();
	tab_hydraulic.reset();
	tab_general.reset();
	tab_bitmap.reset();
	tab_blend.reset();
	tab_sinus.reset();
}

//--------------------------------------
function TerraformerInit()
{
	Heightfield_options.clear();	
	Heightfield_options.setText("Operation");	
	Heightfield_options.add("fBm Fractal",0);
	Heightfield_options.add("Rigid MultiFractal",1);
	Heightfield_options.add("Canyon Fractal",2);
	Heightfield_options.add("Sinus",3);
	Heightfield_options.add("Bitmap",4);
	Heightfield_options.add("Turbulence",5);
	Heightfield_options.add("Smoothing",6);
	Heightfield_options.add("Smooth Water",7);
	Heightfield_options.add("Smooth Ridges/Valleys", 8);
	Heightfield_options.add("Filter",9);
	Heightfield_options.add("Thermal Erosion",10);
	Heightfield_options.add("Hydraulic Erosion",11);
	Heightfield_options.add("Blend",12);
	Heightfield_options.add("Terrain File",13);

	Heightfield::resetTabs();

	%script = Terrain.getHeightfieldScript();
	if(%script !$= "")
		Heightfield::loadFromScript(%script,true);

	if (Heightfield_operation.rowCount() == 0)
	{
		Heightfield_operation.clear();
		%id1 = Heightfield::add("General\tTab_general\tgeneral_min_height\t50\tgeneral_scale\t300\tgeneral_water\t0.000\tgeneral_centerx\t0\tgeneral_centery\t0");
		Heightfield_operation.setSelectedById(%id1);
	}

	Heightfield::resetTabs();
	Heightfield::preview();
}	

//--------------------------------------
function Heightfield_options::onSelect(%this, %_id, %text)
{
	Heightfield_options.setText("Operation");
	%id = -1;

	%rowCount = Heightfield_operation.rowCount();

	// FORMAT
	//  item name
	//  tab name
	//	 control name 
	//	 control value
	switch$(%text)
	{
		case "Terrain File":
			%id = HeightField::add("Terrain File\ttab_terrainFile\tterrainFile_terrFileText\tterrains/terr1.ter\tterrainFile_textList\tterr1.ter");

		case "fBm Fractal":
			%id = Heightfield::add("fBm Fractal\ttab_fBm\tfbm_interval\t9\tfbm_rough\t0.000\tfBm_detail\tNormal\tfBm_seed\t" @ terraformer.generateSeed());

		case "Rigid MultiFractal":
			%id = Heightfield::add("Rigid MultiFractal\ttab_RMF\trmf_interval\t4\trmf_rough\t0.000\trmf_detail\tNormal\trmf_seed\t" @ terraformer.generateSeed());

		case "Canyon Fractal":
			%id = Heightfield::add("Canyon Fractal\ttab_Canyon\tcanyon_freq\t5\tcanyon_factor\t0.500\tcanyon_seed\t" @ terraformer.generateSeed());
	
		case "Sinus":
			%id = Heightfield::add("Sinus\ttab_Sinus\tsinus_filter\t1 0.83333 0.6666 0.5 0.33333 0.16666 0\tsinus_seed\t" @ terraformer.generateSeed());
	
		case "Bitmap":
			%id = Heightfield::add("Bitmap\ttab_Bitmap\tbitmap_name\t");
			Heightfield::setBitmap();
	}


	if (Heightfield_operation.rowCount() >= 1)
	{
		switch$(%text)
		{
			case "Smoothing":
				%id = Heightfield::add("Smoothing\ttab_Smooth\tsmooth_factor\t0.500\tsmooth_iter\t0");
	
			case "Smooth Water":
				%id = Heightfield::add("Smooth Water\ttab_SmoothWater\twatersmooth_factor\t0.500\twatersmooth_iter\t0");

			case "Smooth Ridges/Valleys":
				%id = Heightfield::add("Smooth Ridges/Valleys\ttab_SmoothRidge\tridgesmooth_factor\t0.8500\tridgesmooth_iter\t1");
	
			case "Filter":
				%id = Heightfield::add("Filter\ttab_Filter\tfilter\t0 0.16666667 0.3333333 0.5 0.6666667 0.8333333 1");
	
			case "Turbulence":
				%id = Heightfield::add("Turbulence\ttab_Turbulence\tturbulence_factor\t0.250\tturbulence_radius\t10");
	
			case "Thermal Erosion":
				%id = Heightfield::add("Thermal Erosion\ttab_Thermal\tthermal_slope\t30\tthermal_cons\t80.0\tthermal_iter\t0");
	
			case "Hydraulic Erosion":
				%id = Heightfield::add("Hydraulic Erosion\ttab_Hydraulic\thydraulic_iter\t0\thydraulic_filter\t0 0.16666667 0.3333333 0.5 0.6666667 0.8333333 1");
		}
	}

	if (Heightfield_operation.rowCount() >= 2)
	{
		if("Blend" $= %text)
			%id = Heightfield::add("Blend\ttab_Blend\tblend_factor\t0.500\tblend_srcB\t" @ %rowCount-2 @"\tblend_option\tadd");
	}

	
	// select it
	if (%id != -1)
		Heightfield_operation.setSelectedById(%id);
}	


//--------------------------------------
function Heightfield::eval(%id)
{
	if (%id == -1)	
		return;
	
	%data  = restWords(Heightfield_operation.getRowTextById(%id));
	%label = getField(%data,0);
	%row	= Heightfield_operation.getRowNumById(%id);
	 
	echo("Heightfield::eval:" @ %row @ "  " @ %label );

	switch$(%label)
	{
		case "General":
			if (Terrain.squareSize>0) %size = Terrain.squareSize;
			else %size = 8;
			terraformer.setTerrainInfo( 256, %size, getField(%data,3), getField(%data,5), getField(%data,7) );
			terraformer.setShift( getField(%data,9), getField(%data,11) );
			terraformer.terrainData(%row);

		case "Terrain File":
			terraformer.terrainFile(%row, getField(%data,3));

		case "fBm Fractal":
			terraformer.fBm( %row, getField(%data,3), getField(%data,5), getField(%data,7), getField(%data,9) );

		case "Sinus":
			terraformer.sinus( %row, getField(%data,3), getField(%data,5) );
	 
		case "Rigid MultiFractal":
			terraformer.rigidMultiFractal( %row, getField(%data,3), getField(%data,5), getField(%data,7), getField(%data,9) );
	 
		case "Canyon Fractal":
			terraformer.canyon( %row, getField(%data,3), getField(%data,5), getField(%data,7) );
	
		case "Smoothing":
			terraformer.smooth( %row-1, %row, getField(%data,3), getField(%data,5) );
		 
		case "Smooth Water":
			terraformer.smoothWater( %row-1, %row, getField(%data,3), getField(%data,5) );
		 
		case "Smooth Ridges/Valleys":
			terraformer.smoothRidges( %row-1, %row, getField(%data,3), getField(%data,5) );

		case "Filter":
			terraformer.filter( %row-1, %row, getField(%data,3) );
		 
		case "Turbulence":
			terraformer.turbulence( %row-1, %row, getField(%data,3), getField(%data,5) );
		 
		case "Thermal Erosion":
			terraformer.erodeThermal( %row-1, %row, getField(%data,3), getField(%data,5),getField(%data,7) );
		 
		case "Hydraulic Erosion":
			terraformer.erodeHydraulic( %row-1, %row, getField(%data,3), getField(%data,5) );
		 
		case "Bitmap":
			terraformer.loadGreyscale(%row, getField(%data,3));

		case "Blend":
			%rowCount = Heightfield_operation.rowCount();
			if(%rowCount > 2) 
			{
				%a = Heightfield_operation.getRowNumById(%id)-1;
				%b = getField(%data, 5);
				echo("Blend: " @ %data);
				echo("Blend: " @ getField(%data,3) @ "  " @ getField(%data,7));
				if(%a < %rowCount || %a > 0 || %b < %rowCount || %b > 0 ) 
					terraformer.blend(%a, %b, %row, getField(%data,3), getField(%data,7) );
				else
					echo("Heightfield Editor: Blend parameters out of range.");
			}
	}

}	

//--------------------------------------
function Heightfield::add(%entry)
{
	Heightfield::saveTab();
	Heightfield::hideTab();

	%id = $NextOperationId++;
	if ($selectedOperation != -1)
	{
		%row = Heightfield_operation.getRowNumById($selectedOperation) + 1;
		%entry = %row @ " " @ %entry;
		Heightfield_operation.addRow(%id, %entry, %row); // insert

		// adjust row numbers
		for(%i = %row+1; %i < Heightfield_operation.rowCount(); %i++)
		{
			%id = Heightfield_operation.getRowId(%i);
			%text = Heightfield_operation.getRowTextById(%id);
			%text = setWord(%text, 0, %i);
			Heightfield_operation.setRowById(%id, %text);
		}
	}
	else
	{
		%entry = Heightfield_operation.rowCount() @ " " @ %entry;
		Heightfield_operation.addRow(%id, %entry);	// add to end
	}

	%row = Heightfield_operation.getRowNumById(%id);
	if (%row <= $HeightfieldDirtyRow)
		$HeightfieldDirtyRow = %row;
	Heightfield::save();
	return %id;
}	


//--------------------------------------
function Heightfield::onDelete(%id)
{
	if (%id $= "")
		%id = $selectedOperation;

	%row = Heightfield_operation.getRowNumById(%id);
	
	// don't delete the first entry
	if (%row == 0)
		return;

	Heightfield_operation.removeRow(%row);
	
	// adjust row numbers
	for(%i = %row; %i < Heightfield_operation.rowCount(); %i++)
	{
		%id2 = Heightfield_operation.getRowId(%i);
		%text = Heightfield_operation.getRowTextById(%id2);
		%text = setWord(%text, 0, %i);
		Heightfield_operation.setRowById(%id2, %text);
	}

	// adjust the Dirty Row position
	if ($HeightfieldDirtyRow >= %row)
		$HeightfieldDirtyRow = %row;	
	
	// find the next row to select
	%rowCount = Heightfield_operation.rowCount()-1;
	if (%row > %rowCount)
		%row = %rowCount;

	if (%id == $selectedOperation)
		$selectedOperation = -1;

	%id = Heightfield_operation.getRowId(%row);
	Heightfield_operation.setSelectedById(%id);
	Heightfield::save();
}	


//--------------------------------------
function Heightfield_operation::onSelect(%this, %id, %text)
{
	Heightfield::saveTab();
	Heightfield::hideTab();

	$selectedOperation = %id; 
	Heightfield::restoreTab($selectedOperation);
	Heightfield::showTab($selectedOperation);
	Heightfield::preview($selectedOperation);
}	


//--------------------------------------
function Heightfield::restoreTab(%id)
{
	if (%id == -1)	
		return;

	Heightfield::hideTab();
	
	%data = restWords(Heightfield_operation.getRowTextById(%id));

	%fieldCount = getFieldCount(%data);
	for (%field=2; %field<%fieldCount; %field += 2)
	{
		%obj = getField(%data, %field);
		%obj.setValue( getField(%data, %field+1) );
	}
	
	// Hack to make sure the "meters" value is initially updated
	%label = getField(%data,0);
	
	if (%label $= "General")
		eval(general_water.command);
	
	Heightfield::save();
}  

 
//--------------------------------------
function Heightfield::saveTab()
{
	if ($selectedOperation == -1)	
		return;
	
	%data = Heightfield_operation.getRowTextById($selectedOperation);

	%rowNum = getWord(%data, 0);
	%data = restWords(%data);	
	%newdata = getField(%data,0) @ "\t" @ getField(%data,1);

	%fieldCount = getFieldCount(%data);
	for (%field=2; %field < %fieldCount; %field += 2)
	{
		%obj = getField(%data, %field);
		%newdata = %newdata @ "\t" @ %obj @ "\t" @ %obj.getValue();
	}
	// keep track of the top-most dirty operation
	// so we know who to evaluate later
	if (%data !$= %newdata)
	{
		%row = Heightfield_operation.getRowNumById($selectedOperation);
		if (%row <= $HeightfieldDirtyRow && %row > 0)
			$HeightfieldDirtyRow = %row;
	}

	Heightfield_operation.setRowById($selectedOperation, %rowNum @ " " @ %newdata);
	Heightfield::save();
}  


//--------------------------------------
function Heightfield::preview(%id)
{
	%rowCount = Heightfield_operation.rowCount();
	if (%id $= "")
		%id = Heightfield_operation.getRowId(%rowCount-1);

	%row = Heightfield_operation.getRowNumById(%id);

	Heightfield::refresh(%row);
	terraformer.previewScaled(HeightfieldPreview, %row);
}	


//--------------------------------------
function Heightfield::refresh(%last)
{
	if (%last $= "")	
		%last = Heightfield_operation.rowCount()-1;

	// always update the general info
	Heightfield::eval(Heightfield_operation.getRowId(0));

	for( 0; $HeightfieldDirtyRow<=%last; $HeightfieldDirtyRow++)
	{
		%id = Heightfield_operation.getRowId($HeightfieldDirtyRow);
		Heightfield::eval(%id);
	}
	Heightfield::save();
}	


//--------------------------------------
function Heightfield::apply(%id)
{
	%rowCount = Heightfield_operation.rowCount();
	if (%rowCount < 1)
		return;
	if (%id $= "")
		%id = Heightfield_operation.getRowId(%rowCount-1);

	%row = Heightfield_operation.getRowNumById(%id);

	HeightfieldPreview.setRoot();
	Heightfield::refresh(%row);
	terraformer.setTerrain(%row);

	terraformer.setCameraPosition(0,0,0); 
	ETerrainEditor.isDirty = true;
}	

//--------------------------------------
$TerraformerSaveRegister = 0;
function Heightfield::saveBitmap(%name)
{
	if(%name $= "")
		getSaveFilename("*.png", "Heightfield::doSaveBitmap",
			$TerraformerHeightfieldDir @ "/" @ fileBase($Client::MissionEnvironmentFile) @ ".png");
	else
		Heightfield::doSaveBitmap(%name);
}

function Heightfield::doSaveBitmap(%name)
{		  
	terraformer.saveGreyscale($TerraformerSaveRegister, %name);
}

//--------------------------------------

function Heightfield::save()
{
	%script = "";
	%rowCount = Heightfield_operation.rowCount();
	for(%row = 0; %row < %rowCount; %row++)
	{
		if(%row != 0)
			%script = %script @ "\n";
		%data = restWords(Heightfield_operation.getRowText(%row));
		%script = %script @ expandEscape(%data);
	}
	terrain.setHeightfieldScript(%script);
	ETerrainEditor.isDirty = true;
}

//--------------------------------------
function Heightfield::import()
{
	getLoadFilename("*.ter", "Heightfield::doLoadHeightfield");
}	


//--------------------------------------
function Heightfield::loadFromScript(%script,%leaveCamera)
{
	echo(%script);

	Heightfield_operation.clear();
	$selectedOperation = -1;
	$HeightfieldDirtyRow = -1;

	// zero out all shifting
	HeightfieldPreview.reset();

	for(%rec = getRecord(%script, %i); %rec !$= ""; %rec = getRecord(%script, %i++))
		Heightfield::add(collapseEscape(%rec));

	if (Heightfield_operation.rowCount() == 0)
	{
		// if there was a problem executing the script restore
		// the operations list to a known state
		Heightfield_operation.clear();
		Heightfield::add("General\tTab_general\tgeneral_min_height\t50\tgeneral_scale\t300\tgeneral_water\t0.000\tgeneral_centerx\t0\tgeneral_centery\t0");
	}
	%data = restWords(Heightfield_operation.getRowText(0));
	%x = getField(%data,7); 
	%y = getField(%data,9); 
	HeightfieldPreview.setOrigin(%x, %y);
	Heightfield_operation.setSelectedById(Heightfield_operation.getRowId(0));

	// Move the control object to the specified position
	if (!%leaveCamera)
		terraformer.setCameraPosition(%x,%y); 
}	

//--------------------------------------
function strip(%stripStr, %strToStrip)
{
	%len = strlen(%stripStr);
	if(strcmp(getSubStr(%strToStrip, 0, %len), %stripStr) == 0)
		return getSubStr(%strToStrip, %len, 100000);
	return %strToStrip;
}

function Heightfield::doLoadHeightfield(%name)
{
	// ok, we're getting a terrain file...

	%newTerr = new TerrainBlock() // unnamed - since we'll be deleting it shortly:
	{
		position = "0 0 -1000";
		terrainFile = strip("terrains/", %name);
		squareSize = 8;
		visibleDistance = 100;
	};
	if(isObject(%newTerr))
	{
		%script = %newTerr.getHeightfieldScript();
		if(%script !$= "")
			Heightfield::loadFromScript(%script);
		%newTerr.delete();
	}	
}	


//--------------------------------------
function Heightfield::setBitmap()
{
	getLoadFilename("*.png", "Heightfield::doSetBitmap");
}	

//--------------------------------------
function Heightfield::doSetBitmap(%name)
{
	bitmap_name.setValue(%name);
	Heightfield::saveTab();
	Heightfield::preview($selectedOperation);
}	


//--------------------------------------
function Heightfield::hideTab()
{
	tab_terrainFile.setVisible(false);
	tab_fbm.setvisible(false);
	tab_rmf.setvisible(false);
	tab_canyon.setvisible(false);
	tab_smooth.setvisible(false);
	tab_smoothWater.setvisible(false);
	tab_smoothRidge.setvisible(false);
	tab_filter.setvisible(false);
	tab_turbulence.setvisible(false);
	tab_thermal.setvisible(false);
	tab_hydraulic.setvisible(false);
	tab_general.setvisible(false);
	tab_bitmap.setvisible(false);
	tab_blend.setvisible(false);
	tab_sinus.setvisible(false);
}


//--------------------------------------
function Heightfield::showTab(%id)
{
	Heightfield::hideTab();
	%data = restWords(Heightfield_operation.getRowTextById(%id));
	%tab  = getField(%data,1);
	echo("Tab data: " @ %data @ " tab: " @ %tab);
	%tab.setVisible(true);
}


//--------------------------------------
function Heightfield::center()
{
	%camera = terraformer.getCameraPosition(); 
	%x = getWord(%camera, 0);
	%y = getWord(%camera, 1);

	HeightfieldPreview.setOrigin(%x, %y);

	%origin = HeightfieldPreview.getOrigin();
	%x = getWord(%origin, 0);
	%y = getWord(%origin, 1);

	%root = HeightfieldPreview.getRoot();
	%x += getWord(%root, 0);
	%y += getWord(%root, 1);

	general_centerx.setValue(%x);
	general_centery.setValue(%y);
	Heightfield::saveTab();
}	

function ExportHeightfield::onAction()
{
	error("Time to export the heightfield...");
	if (Heightfield_operation.getSelectedId() != -1) {
		$TerraformerSaveRegister = getWord(Heightfield_operation.getValue(), 0);
		Heightfield::saveBitmap("");
	}
}

//------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------
function onNeedRelight()
{
	if( RelightMessage.visible == false )
		RelightMessage.visible = true;
}

function TerrainEditor::onGuiUpdate(%this, %text)
{
	%mouseBrushInfo = " (Mouse Brush) #: " @ getWord(%text, 0) @ "  avg: " @ getWord(%text, 1);
	%selectionInfo = " (Selection) #: " @ getWord(%text, 2) @ "  avg: " @ getWord(%text, 3);
	
	TEMouseBrushInfo.setValue(%mouseBrushInfo);
	TEMouseBrushInfo1.setValue(%mouseBrushInfo);
	TESelectionInfo.setValue(%selectionInfo);
	TESelectionInfo1.setValue(%selectionInfo);
}

function TerrainEditor::offsetBrush(%this, %x, %y)
{
	%curPos = %this.getBrushPos();
	%this.setBrushPos(getWord(%curPos, 0) + %x, getWord(%curPos, 1) + %y);
}

function TerrainEditor::swapInLoneMaterial(%this, %name)
{
	// swapped?
	if(%this.baseMaterialsSwapped $= "true")
	{
		%this.baseMaterialsSwapped = "false";
		tEditor.popBaseMaterialInfo();
	}
	else
	{
		%this.baseMaterialsSwapped = "true";
		%this.pushBaseMaterialInfo();
		%this.setLoneBaseMaterial(%name);
	}
		
	//
	flushTextureCache();
}

//------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------


function TELoadTerrainButton::onAction(%this)
{
	getLoadFilename("terrains/*.ter", %this @ ".gotFileName");
}

function TELoadTerrainButton::gotFileName(%this, %name)
{
	//
	%pos = "0 0 0";
	%squareSize = "8";
	%visibleDistance = "1200";

	// delete current
	if(isObject(terrain))
	{
		%pos = terrain.position;
		%squareSize = terrain.squareSize;
		%visibleDistance = terrain.visibleDistance;

		terrain.delete();
	}

	// create new
	new TerrainBlock(terrain)
	{
		position = %pos;
		terrainFile = %name;
		squareSize = %squareSize;
		visibleDistance = %visibleDistance;
	};

	ETerrainEditor.attachTerrain();
}

function TerrainEditorSettingsGui::onWake(%this)
{
	TESoftSelectFilter.setValue(ETerrainEditor.softSelectFilter);
}

function TerrainEditorSettingsGui::onSleep(%this)
{
	ETerrainEditor.softSelectFilter = TESoftSelectFilter.getValue();
}

function TESettingsApplyButton::onAction(%this)
{
	ETerrainEditor.softSelectFilter = TESoftSelectFilter.getValue();
	ETerrainEditor.resetSelWeights(true);
	ETerrainEditor.processAction("softSelect");
}

function getPrefSetting(%pref, %default)
{
	// 
	if(%pref $= "")
		return(%default);
	else
		return(%pref);
}

//------------------------------------------------------------------------------

function Editor::open(%this)
{
	// prevent the mission editor from opening while the GuiEditor is open.
	if(Canvas.getContent() == GuiEditorGui.getId())
		return;
	showShellDlg(false);
	Canvas.setContent(EditorGui);
}

function Editor::close(%this, %gui)
{
	Canvas.setContent(%gui);
	MessageHud.close();
}

//------------------------------------------------------------------------------
