//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
function DecalEditorGui::onWake(%this)
{
%fixedWindow = DecalEditorWindow;
%fluidWindow = DecalPreviewWindow;
if(EditorSettings.value( "WorldEditor/forceSidebarToSide" ) == 1)
{
// Let's dock the side panel to the right side
%this.docked = false;
%this.resizing = true;
%this.dockSidePanel();
}
else
{
// Let's release the side panel so it can be moved
%this.docked = true;
%this.resizing = false;
%this.releaseSidePanel();
}
}
function DecalEditorGui::maxSize(%this, %window)
{
// Resize the windows to the max height
// and force these to the right side if set
if(EditorSettings.value( "WorldEditor/forceSidebarToSide" ) == 1 && %this.resizing == true)
{
// prevent onResize after a resize
%this.resizing = false;
%fixedWindow = DecalEditorWindow;
%fluidWindow = DecalPreviewWindow;
%offset = -1; // tweak the vertical offset so that it aligns neatly
%top = EditorGuiToolbar.extent.y + %offset;
%bottom = %top + 59;
%maxHeight = Canvas.extent.y - %top - %bottom;
// --- Fixed window (top) ------------------------------------------------
// put it back if it moved
%fixedWindow.position.x = Canvas.extent.x - %fixedWindow.extent.x;
%fixedWindow.position.y = %top;
// don't go beyond the canvas
if(%fixedWindow.extent.y > %maxHeight)
%fixedWindow.extent.y = %maxHeight - %fluidWindow.extent.y;
%position = %fixedWindow.position.x SPC %fixedWindow.position.y;
%extent = %window.extent.x SPC %fixedWindow.extent.y;
%fixedWindow.resize(%position.x, %position.y, %extent.x, %extent.y);
// --- Fluid window (bottom) ---------------------------------------------
// position is relative to the top window
%position = %fixedWindow.position.x SPC %fixedWindow.extent.y + %top;
%extent = %window.extent.x SPC Canvas.extent.y - %fixedWindow.extent.y - %bottom;
%fluidWindow.resize(%position.x, %position.y, %extent.x, %extent.y);
// --- AssetBrowser window ----------------------------------------------
if(isObject(AssetBrowserWindow))
{
// Only resize the AssetBrowser if it's docked
if(AssetBrowserWindow.docked == true)
{
// The width is relative to the sidepanel
%browserWidth = Canvas.extent.x - %extent.x;
%browserHeight = AssetBrowserWindow.extent.y;
%browserPosY = Canvas.extent.y - AssetBrowserWindow.extent.y - 33;
AssetBrowserWindow.resize(0, %browserPosY, %browserWidth, %browserHeight);
}
}
// --- Windowed Console --------------------------------------------------
if(isObject(windowConsoleControl))
{
// Only resize the AssetBrowser if it's docked
if(windowConsoleControl.docked == true)
{
// The width is relative to the sidepanel
%consoleWidth = Canvas.extent.x - %extent.x;
%consoleHeight = windowConsoleControl.extent.y;
%consolePosY = Canvas.extent.y - windowConsoleControl.extent.y - 33;
windowConsoleControl.resize(0, %consolePosY, %consoleWidth, %consoleHeight);
}
}
}
}
function DecalEditorWindow::onMouseDragged(%this)
{
%parent = DecalEditorGui;
if(%parent.panelHidden == true)
{
%parent.showSidePanel();
}
if(%parent.resizing == false && %parent.docked == true)
{
%parent.resizing = true;
%parent.maxSize(%this);
}
}
function DecalPreviewWindow::onMouseDragged(%this)
{
%parent = DecalEditorGui;
if(%parent.panelHidden == true)
{
%parent.showSidePanel();
}
if(%parent.resizing == false && %parent.docked == true)
{
%parent.resizing = true;
%parent.maxSize(%this);
}
}
function DecalEditorGui::onResize(%this, %newPosition, %newExtent)
{
// Window to focus on (mostly the fluid window)
%window = DecalPreviewWindow;
if(%window.panelHidden == true)
{
%window.showSidePanel();
}
if(%this.resizing == false && %this.docked == true)
{
// Only resize once
%this.resizing = true;
%this.maxSize(%window);
}
}
function DecalEditorGui::dockSidePanel()
{
%parent = DecalEditorGui;
%fixedWindow = DecalEditorWindow;
%fluidWindow = DecalPreviewWindow;
if(%parent.docked == true)
return;
// Move and resize the window(s)
%parent.resizing = true;
%parent.maxSize(%fluidWindow);
%parent.docked = true;
%fluidWindow.onMouseDragged();
// Lock the windows in place
%fixedWindow.canCollapse = "0";
%fixedWindow.canMove = "0";
%fluidWindow.canCollapse = "0";
%fluidWindow.canMove = "0";
DecalEditorGui_UnDockBtn.Visible = "1";
DecalEditorGui_DockBtn.Visible = "0";
DecalEditorGui_showBtn.Visible = "0";
DecalEditorGui_hideBtn.Visible = "1";
}
function DecalEditorGui::releaseSidePanel()
{
%parent = DecalEditorGui;
%fixedWindow = DecalEditorWindow;
%fluidWindow = DecalPreviewWindow;
if(%parent.docked == false)
return;
// Unlock the windows so that be moved
%fixedWindow.canCollapse = "1";
%fixedWindow.canMove = "1";
%fluidWindow.canCollapse = "1";
%fluidWindow.canMove = "1";
DecalEditorGui_UnDockBtn.Visible = "0";
DecalEditorGui_DockBtn.Visible = "1";
DecalEditorGui_showBtn.Visible = "0";
DecalEditorGui_hideBtn.Visible = "0";
// Let's do a small resize so it's visually clear we're undocking
%position = %fixedWindow.position.x - 6 SPC %fixedWindow.position.y + 6;
%extent = %fixedWindow.extent.x SPC %fixedWindow.extent.y;
%fixedWindow.resize(%position.x, %position.y, %extent.x, %extent.y);
%position = %fluidWindow.position.x - 6 SPC %fluidWindow.position.y + 6;
%extent = %fluidWindow.extent.x SPC %fluidWindow.extent.y - 12;
%fluidWindow.resize(%position.x, %position.y, %extent.x, %extent.y);
%parent.docked = false;
%parent.resizing = false;
}
function DecalEditorGui::hideSidePanel()
{
%parent = DecalEditorGui;
%fixedWindow = DecalEditorWindow;
%fluidWindow = DecalPreviewWindow;
DecalEditorGui_showBtn.Visible = "1";
DecalEditorGui_hideBtn.Visible = "0";
// hide the content of the panels
%fixedWindow.titleText = %fixedWindow.text;
%fluidWindow.titleText = %fluidWindow.text;
%fixedWindow.text = "";
DecalEditorTabBook.Visible = "0";
%fluidWindow.text = "";
DecalEditorTemplateProperties.Visible = "0";
DecalEditorLibraryProperties.Visible = "0";
// Let's do a resize so that the panel is collapsed to the side
%position = Canvas.extent.x - 24 SPC %fixedWindow.position.y;
%extent = %fixedWindow.extent.x SPC %fixedWindow.extent.y;
%fixedWindow.resize(%position.x, %position.y, %extent.x, %extent.y);
%position = Canvas.extent.x - 24 SPC %fluidWindow.position.y;
%extent = %fluidWindow.extent.x SPC %fluidWindow.extent.y;
%fluidWindow.resize(%position.x, %position.y, %extent.x, %extent.y);
%parent.panelHidden = true;
}
function DecalEditorGui::showSidePanel()
{
%parent = DecalEditorGui;
%fixedWindow = DecalEditorWindow;
%fluidWindow = DecalPreviewWindow;
DecalEditorGui_showBtn.Visible = "0";
DecalEditorGui_hideBtn.Visible = "1";
// show the content of the panels
%fixedWindow.text = %fixedWindow.titleText;
DecalEditorTabBook.Visible = "1";
%fluidWindow.text = %fluidWindow.titleText;
DecalEditorTemplateProperties.Visible = "1";
DecalEditorLibraryProperties.Visible = "1";
%parent.resizing = true;
%parent.maxSize(%fluidWindow);
%parent.panelHidden = false;
}
//-----------------------------------------------------------------------------
function DecalEditorGui::onSelectInstance( %this, %decalId, %lookupName )
{
if( DecalEditorGui.selDecalInstanceId == %decalId )
return;
// Lets remember the new Id
DecalEditorGui.selDecalInstanceId = %decalId;
DecalEditorTreeView.clearSelection();
%name = %decalId SPC %lookupName;
%item = DecalEditorTreeView.findItemByName( %name );
DecalEditorTreeView.selectItem( %item );
DecalEditorGui.syncNodeDetails();
}
function DecalEditorGui::onCreateInstance( %this, %decalId, %lookupName )
{
// Lets remember the new Id
DecalEditorGui.selDecalInstanceId = %decalId;
// Add the new instance to the node tree
DecalEditorTreeView.addNodeTree( %decalId, %lookupName );
DecalEditorTreeView.clearSelection();
%name = %decalId SPC %lookupName;
%item = DecalEditorTreeView.findItemByName( %name );
DecalEditorTreeView.selectItem( %item );
DecalEditorGui.syncNodeDetails();
}
function DecalEditorGui::onDeleteInstance( %this, %decalId, %lookupName )
{
if( %decalId == DecalEditorGui.selDecalInstanceId )
DecalEditorGui.selDecalInstanceId = -1;
%id = DecalEditorTreeView.findItemByName( %decalId SPC %lookupName );
DecalEditorTreeView.removeItem(%id);
}
function DecalEditorGui::editNodeDetails( %this )
{
%decalId = DecalEditorGui.selDecalInstanceId;
if( %decalId == -1 )
return;
%nodeDetails = DecalEditorDetailContainer-->nodePosition.getText();
%nodeDetails = %nodeDetails @ " " @ DecalEditorDetailContainer-->nodeTangent.getText();
%nodeDetails = %nodeDetails @ " " @ DecalEditorDetailContainer-->nodeSize.getText();
if( getWordCount(%nodeDetails) == 7 )
DecalEditorGui.doEditNodeDetails( %decalId, %nodeDetails, false );
}
// Stores the information when the gizmo is first used
function DecalEditorGui::prepGizmoTransform( %this, %decalId, %nodeDetails )
{
DecalEditorGui.gizmoDetails = %nodeDetails;
}
// Activated in onMouseUp while gizmo is dirty
function DecalEditorGui::completeGizmoTransform( %this, %decalId, %nodeDetails )
{
DecalEditorGui.doEditNodeDetails( %decalId, %nodeDetails, true );
}
function DecalEditorGui::onSleep( %this )
{
}
function DecalEditorGui::syncNodeDetails( %this )
{
%decalId = DecalEditorGui.selDecalInstanceId;
if( %decalId == -1 )
return;
%lookupName = DecalEditorGui.getDecalLookupName( %decalId );
DecalEditorGui.updateInstancePreview( %lookupName.materialAsset );
DecalEditorDetailContainer-->instanceId.setText(%decalId @ " " @ %lookupName);
%transformData = DecalEditorGui.getDecalTransform(%decalId);
DecalEditorDetailContainer-->nodePosition.setText(getWords(%transformData, 0, 2));
DecalEditorDetailContainer-->nodeTangent.setText(getWords(%transformData, 3, 5));
DecalEditorDetailContainer-->nodeSize.setText(getWord(%transformData, 6));
}
function DecalEditorGui::paletteSync( %this, %mode )
{
%evalShortcut = "ToolsPaletteArray-->" @ %mode @ ".setStateOn(1);";
eval(%evalShortcut);
}
function DecalDataList::onSelect( %this, %id, %text )
{
%obj = %this.getItemObject( %id );
DecalEditorGui.currentDecalData = %obj;
%itemNum = DecalDataList.getSelectedItem();
if ( %itemNum == -1 )
return;
%data = DecalDataList.getItemObject( %itemNum );
// Update the materialEditorList
$Tools::materialEditorList = %data.getId();
//Canvas.pushDialog( DecalEditDlg );
DecalInspector.inspect( %data );
DecalEditorGui.updateDecalPreview( %data.materialAsset );
}
function RetargetDecalButton::onClick( %this )
{
%id = DecalDataList.getSelectedItem();
%datablock = DecalDataList.getItemText(%id );
if( !isObject(%datablock) )
{
toolsMessageBoxOK("Error", "A valid Decal Template must be selected.");
return;
}
// This is the first place IODropdown is used. The # in the function passed replaced with the output
// of the preset menu.
IODropdown("Retarget Decal Instances",
"Retarget DecalInstances from " @ %datablock.getName() @ " over to....",
"decalDataSet",
"DecalEditorGui.retargetDecalDatablock(" @ %datablock.getName() @ ", #);",
"");
DecalEditorGui.rebuildInstanceTree();
}
function NewDecalButton::onClick( %this )
{
AssetBrowser_SelectModule.showDialog("DecalEditorGui.pickedNewDecalTargetModule");
AssetBrowser_SelectModuleWindow.selectWindow();
}
function DecalEditorGui::pickedNewDecalTargetModule(%this, %module)
{
%moduleDef = ModuleDatabase.findModule(%module);
$decalDataFile = %moduleDef.ModulePath @ "/scripts/managedData/managedDecalData." @ $TorqueScriptFileExtension;
if(!isDirectory(filePath($decalDataFile)))
{
AssetBrowser.dirHandler.createFolder(filePath($decalDataFile));
}
%name = getUniqueName( "NewDecalData" );
%str = "datablock DecalData( " @ %name @ " ) { Material = \"WarningMaterial\"; };";
eval( %str );
DecalPMan.setDirty( %name, $decalDataFile );
if ( strchr(LibraryTabControl.text, "*") $= "" )
LibraryTabControl.text = LibraryTabControl.text @ "*";
DecalDataList.doMirror();
%id = DecalDataList.findItemText( %name );
DecalDataList.setSelected( %id, true );
Canvas.pushDialog( DecalEditDlg );
DecalInspector.inspect( %name );
}
function DeleteDecalButton::onClick( %this )
{
if( DecalEditorTabBook.getSelectedPage() == 0 ) // library
{
%id = DecalDataList.getSelectedItem();
%datablock = DecalDataList.getItemText(%id );
toolsMessageBoxYesNoCancel("Delete Decal Datablock?",
"Are you sure you want to delete
" @ %datablock @ "
Datablock deletion won't take affect until the engine is quit.",
"DecalEditorGui.deleteSelectedDecalDatablock();",
"",
"" );
}
else // instances
{
DecalEditorGui.deleteSelectedDecal();
}
}
// Intended for gui use. The undo/redo functionality for deletion of datablocks
// will enable itself automatically after using this function.
function DecalEditorGui::deleteSelectedDecalDatablock()
{
%id = DecalDataList.getSelectedItem();
%datablock = DecalDataList.getItemText(%id );
DecalEditorGui.deleteDecalDatablock( %datablock );
if( %datablock.getFilename() !$= "" )
{
DecalPMan.removeDirty( %datablock );
DecalPMan.removeObjectFromFile( %datablock );
}
DecalDataList.addFilteredItem( %datablock );
}
function DecalEditorTabBook::onTabSelected( %this, %text, %idx )
{
if( %idx == 0)
{
DecalPreviewWindow.text = ":: Decal Editor - Template Properties";
DecalEditorLibraryProperties.setVisible(true);
DecalEditorTemplateProperties.setVisible(false);
RetargetDecalButton.setVisible( true );
SaveDecalsButton.setVisible( true );
NewDecalButton.setVisible( true );
DeleteDecalButton.tabSelected = %idx;
}
else
{
DecalPreviewWindow.text = ":: Decal Editor - Instance Properties";
RetargetDecalButton.setVisible( false );
NewDecalButton.setVisible( false );
SaveDecalsButton.setVisible( false );
DeleteDecalButton.tabSelected = %idx;
DecalEditorLibraryProperties.setVisible(false);
DecalEditorTemplateProperties.setVisible(true);
}
}
function DecalEditorTreeView::onDefineIcons()
{
%icons = "tools/gui/images/treeview/default:" @
"tools/classIcons/decal:" @
"tools/classIcons/decalNode:";
DecalEditorTreeView.buildIconTable( %icons );
}
function DecalEditorTreeView::onSelect(%this, %id)
{
%instanceTag = getWord( DecalEditorTreeView.getItemText(%id), 1 );
if( !isObject( %instanceTag ) )
return;
if( %instanceTag.getClassName() !$= "DecalData" )
return;
// Grab the id from the tree view
%decalId = getWord( DecalEditorTreeView.getItemText(%id), 0 );
if( DecalEditorGui.selDecalInstanceId == %decalId )
return;
// Set the curent decalinstances id
DecalEditorGui.selDecalInstanceId = %decalId;
DecalEditorGui.selectDecal(%decalId);
DecalEditorGui.syncNodeDetails(%id);
}
// Creating per node in the instance tree
function DecalEditorTreeView::addNodeTree(%this, %nodeName, %parentName)
{
// If my template isnt there...put it there
if ( %this.findItemByName(%parentName) == 0 )
{
%rootId = %this.findItemByName("");
%this.insertItem( %rootId, %parentName, 0, "", 1, 1);
}
%nodeName = %nodeName SPC %parentName;
%parentId = %this.findItemByName(%parentName);
%id = %this.insertItem(%parentId, %nodeName, 0, "", 2);
}
function DecalInspector::onInspectorFieldModified( %this, %object, %fieldName, %arrayIndex, %oldValue, %newValue )
{
if( %fieldName $= "Material" || %fieldName $= "MaterialAsset")
DecalEditorGui.updateDecalPreview( %newValue );
// Same work to do as for the regular WorldEditor Inspector.
Inspector::onInspectorFieldModified( %this, %object, %fieldName, %arrayIndex, %oldValue, %newValue );
if (%oldValue != %newValue || %oldValue !$= %newValue)
%this.setDirty(%object);
}
function DecalInspector::setDirty( %this, %object )
{
DecalPMan.setDirty( %object );
if ( strchr(LibraryTabControl.text, "*") $= "" )
LibraryTabControl.text = LibraryTabControl.text @ "*";
}
function DecalInspector::removeDirty()
{
if ( strchr(LibraryTabControl.text, "*") !$= "" )
LibraryTabControl.text = stripChars(LibraryTabControl.text, "*");
}
function DecalEditorGui::updateDecalPreview( %this, %material )
{
%previewImage = "";
if( isObject( %material ) )
{
%previewImage = %material.getDiffuseMap(0);
}
else
{
if(AssetDatabase.isDeclaredAsset(%material))
{
%previewImage = %material;
}
}
DecalPreviewWindow-->decalPreview.setBitmap( getAssetPreviewImage(%previewImage) );
}
function DecalEditorGui::updateInstancePreview( %this, %material )
{
%previewImage = "";
if( isObject( %material ) )
{
%previewImage = %material.getDiffuseMap(0);
}
else
{
if(AssetDatabase.isDeclaredAsset(%material))
{
%previewImage = %material;
}
}
DecalPreviewWindow-->instancePreview.setBitmap( getAssetPreviewImage(%previewImage) );
}
function DecalEditorGui::rebuildInstanceTree( %this )
{
// Initialize the instance tree when the tab is selected
DecalEditorTreeView.removeItem(0);
%rootId = DecalEditorTreeView.insertItem(0, "", 0, "");
%count = DecalEditorGui.getDecalCount();
for (%i = 0; %i < %count; %i++)
{
%name = DecalEditorGui.getDecalLookupName(%i);
if( %name $= "invalid" )
continue;
DecalEditorTreeView.addNodeTree(%i, %name);
}
}