From 163b14fac1eacc31b0b6863119f78d96dbe08b3e Mon Sep 17 00:00:00 2001 From: Daniel Buckmaster Date: Sat, 29 Nov 2014 00:52:09 +1100 Subject: [PATCH] Added editor. --- .../tools/navEditor/CreateNewNavMeshDlg.gui | 356 ++++++++ .../tools/navEditor/NavEditorConsoleDlg.gui | 169 ++++ .../game/tools/navEditor/NavEditorGui.gui | 851 ++++++++++++++++++ .../tools/navEditor/NavEditorSettingsTab.gui | 506 +++++++++++ .../game/tools/navEditor/NavEditorToolbar.gui | 144 +++ Templates/Empty/game/tools/navEditor/done.wav | Bin 0 -> 36948 bytes .../tools/navEditor/images/nav-cover_d.png | Bin 0 -> 986 bytes .../tools/navEditor/images/nav-cover_h.png | Bin 0 -> 1349 bytes .../tools/navEditor/images/nav-cover_n.png | Bin 0 -> 513 bytes .../tools/navEditor/images/nav-editor_d.png | Bin 0 -> 1457 bytes .../tools/navEditor/images/nav-editor_h.png | Bin 0 -> 1667 bytes .../tools/navEditor/images/nav-editor_n.png | Bin 0 -> 1435 bytes .../tools/navEditor/images/nav-link_d.png | Bin 0 -> 692 bytes .../tools/navEditor/images/nav-link_h.png | Bin 0 -> 894 bytes .../tools/navEditor/images/nav-link_n.png | Bin 0 -> 384 bytes Templates/Empty/game/tools/navEditor/main.cs | 276 ++++++ .../Empty/game/tools/navEditor/navEditor.cs | 37 + .../game/tools/navEditor/navEditorGui.cs | 351 ++++++++ .../NavEditorPalette.ed.gui | 130 +++ .../worldEditor/scripts/editors/creator.ed.cs | 4 +- .../tools/navEditor/CreateNewNavMeshDlg.gui | 356 ++++++++ .../tools/navEditor/NavEditorConsoleDlg.gui | 169 ++++ .../game/tools/navEditor/NavEditorGui.gui | 851 ++++++++++++++++++ .../tools/navEditor/NavEditorSettingsTab.gui | 506 +++++++++++ .../game/tools/navEditor/NavEditorToolbar.gui | 144 +++ Templates/Full/game/tools/navEditor/done.wav | Bin 0 -> 36948 bytes .../tools/navEditor/images/nav-cover_d.png | Bin 0 -> 986 bytes .../tools/navEditor/images/nav-cover_h.png | Bin 0 -> 1349 bytes .../tools/navEditor/images/nav-cover_n.png | Bin 0 -> 513 bytes .../tools/navEditor/images/nav-editor_d.png | Bin 0 -> 1457 bytes .../tools/navEditor/images/nav-editor_h.png | Bin 0 -> 1667 bytes .../tools/navEditor/images/nav-editor_n.png | Bin 0 -> 1435 bytes .../tools/navEditor/images/nav-link_d.png | Bin 0 -> 692 bytes .../tools/navEditor/images/nav-link_h.png | Bin 0 -> 894 bytes .../tools/navEditor/images/nav-link_n.png | Bin 0 -> 384 bytes Templates/Full/game/tools/navEditor/main.cs | 276 ++++++ .../Full/game/tools/navEditor/navEditor.cs | 37 + .../Full/game/tools/navEditor/navEditorGui.cs | 351 ++++++++ .../NavEditorPalette.ed.gui | 130 +++ .../worldEditor/scripts/editors/creator.ed.cs | 4 +- 40 files changed, 5642 insertions(+), 6 deletions(-) create mode 100644 Templates/Empty/game/tools/navEditor/CreateNewNavMeshDlg.gui create mode 100644 Templates/Empty/game/tools/navEditor/NavEditorConsoleDlg.gui create mode 100644 Templates/Empty/game/tools/navEditor/NavEditorGui.gui create mode 100644 Templates/Empty/game/tools/navEditor/NavEditorSettingsTab.gui create mode 100644 Templates/Empty/game/tools/navEditor/NavEditorToolbar.gui create mode 100644 Templates/Empty/game/tools/navEditor/done.wav create mode 100644 Templates/Empty/game/tools/navEditor/images/nav-cover_d.png create mode 100644 Templates/Empty/game/tools/navEditor/images/nav-cover_h.png create mode 100644 Templates/Empty/game/tools/navEditor/images/nav-cover_n.png create mode 100644 Templates/Empty/game/tools/navEditor/images/nav-editor_d.png create mode 100644 Templates/Empty/game/tools/navEditor/images/nav-editor_h.png create mode 100644 Templates/Empty/game/tools/navEditor/images/nav-editor_n.png create mode 100644 Templates/Empty/game/tools/navEditor/images/nav-link_d.png create mode 100644 Templates/Empty/game/tools/navEditor/images/nav-link_h.png create mode 100644 Templates/Empty/game/tools/navEditor/images/nav-link_n.png create mode 100644 Templates/Empty/game/tools/navEditor/main.cs create mode 100644 Templates/Empty/game/tools/navEditor/navEditor.cs create mode 100644 Templates/Empty/game/tools/navEditor/navEditorGui.cs create mode 100644 Templates/Empty/game/tools/worldEditor/gui/ToolsPaletteGroups/NavEditorPalette.ed.gui create mode 100644 Templates/Full/game/tools/navEditor/CreateNewNavMeshDlg.gui create mode 100644 Templates/Full/game/tools/navEditor/NavEditorConsoleDlg.gui create mode 100644 Templates/Full/game/tools/navEditor/NavEditorGui.gui create mode 100644 Templates/Full/game/tools/navEditor/NavEditorSettingsTab.gui create mode 100644 Templates/Full/game/tools/navEditor/NavEditorToolbar.gui create mode 100644 Templates/Full/game/tools/navEditor/done.wav create mode 100644 Templates/Full/game/tools/navEditor/images/nav-cover_d.png create mode 100644 Templates/Full/game/tools/navEditor/images/nav-cover_h.png create mode 100644 Templates/Full/game/tools/navEditor/images/nav-cover_n.png create mode 100644 Templates/Full/game/tools/navEditor/images/nav-editor_d.png create mode 100644 Templates/Full/game/tools/navEditor/images/nav-editor_h.png create mode 100644 Templates/Full/game/tools/navEditor/images/nav-editor_n.png create mode 100644 Templates/Full/game/tools/navEditor/images/nav-link_d.png create mode 100644 Templates/Full/game/tools/navEditor/images/nav-link_h.png create mode 100644 Templates/Full/game/tools/navEditor/images/nav-link_n.png create mode 100644 Templates/Full/game/tools/navEditor/main.cs create mode 100644 Templates/Full/game/tools/navEditor/navEditor.cs create mode 100644 Templates/Full/game/tools/navEditor/navEditorGui.cs create mode 100644 Templates/Full/game/tools/worldEditor/gui/ToolsPaletteGroups/NavEditorPalette.ed.gui diff --git a/Templates/Empty/game/tools/navEditor/CreateNewNavMeshDlg.gui b/Templates/Empty/game/tools/navEditor/CreateNewNavMeshDlg.gui new file mode 100644 index 000000000..0734b4578 --- /dev/null +++ b/Templates/Empty/game/tools/navEditor/CreateNewNavMeshDlg.gui @@ -0,0 +1,356 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiControl(CreateNewNavMeshDlg) { + position = "0 0"; + extent = "1024 768"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + + new GuiWindowCtrl() { + text = "New NavMesh"; + resizeWidth = "0"; + resizeHeight = "0"; + canMove = "1"; + canClose = "1"; + canMinimize = "0"; + canMaximize = "0"; + canCollapse = "0"; + closeCommand = "Canvas.popDialog(CreateNewNavMeshDlg);"; + edgeSnap = "1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "283 240"; + extent = "200 151"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiWindowProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "Name:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "12 29"; + extent = "39 21"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "Nav"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "59 30"; + extent = "129 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "MeshName"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Position:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "12 51"; + extent = "39 21"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "0 0 0"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "59 52"; + extent = "129 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "MeshPosition"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Scale:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "12 73"; + extent = "39 21"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "50 50 20"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "59 74"; + extent = "129 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "MeshScale"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + text = " Fit NavMesh to mission area?"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "22 99"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Positions and scales the NavMesh so it includes all your mission objects."; + hovertime = "1000"; + isContainer = "0"; + internalName = "MeshMissionBounds"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Create!"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "12 121"; + extent = "87 19"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + command = "CreateNewNavMeshDlg.create();"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Cancel"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "104 121"; + extent = "84 19"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + command = "Canvas.popDialog(CreateNewNavMeshDlg);"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; +}; +//--- OBJECT WRITE END --- + +function CreateNewNavMeshDlg::onWake(%this) +{ + %this-->MeshName.setText("Nav"); + %this-->MeshPosition.setText("0 0 0"); + %this-->MeshScale.setText("50 50 20"); +} + +function MissionBoundsExtents(%group) +{ + %box = "0 0 0 0 0 0"; + foreach(%obj in %group) + { + // Skip LevelInfos. Need a way to detect other non-SceneObjects. + // Also skip GroundPlanes. They're too big. + %cls = %obj.getClassName(); + if(%cls $= "LevelInfo" || %cls $= "GroundPlane" || %cls $= "GroundCover") + continue; + + // Get world box - might have to recurse into nested SimGroups. + %wbox = "0 0 0 0 0 0"; + if(%cls $= "SimGroup" || %cls $= "SimSet" || %cls $= "Path") + %wbox = MissionBoundsExtents(%obj); + else if(%obj.getType() & $TypeMasks::StaticObjectType && + !(%obj.getType() & $TypeMasks::EnvironmentObjectType)) + %wbox = %obj.getWorldBox(); + else + continue; + + // Update min point. + for(%j = 0; %j < 3; %j++) + { + if(GetWord(%box, %j) > GetWord(%wbox, %j)) + %box = SetWord(%box, %j, GetWord(%wbox, %j)); + } + // Update max point. + for(%j = 3; %j < 6; %j++) + { + if(GetWord(%box, %j) < GetWord(%wbox, %j)) + %box = SetWord(%box, %j, GetWord(%wbox, %j)); + } + } + return %box; +} + +function CreateNewNavMeshDlg::create(%this) +{ + %name = %this-->MeshName.getText(); + if(%name $= "" || nameToID(%name) != -1) + { + MessageBoxOk("Error", "A NavMesh must have a unique name!"); + return; + } + + %mesh = 0; + + if(%this-->MeshMissionBounds.isStateOn()) + { + if(!isObject(MissionGroup)) + { + MessageBoxOk("Error", "You must have a MissionGroup to use the mission bounds function."); + return; + } + // Get maximum extents of all objects. + %box = MissionBoundsExtents(MissionGroup); + %pos = GetBoxCenter(%box); + %scale = (GetWord(%box, 3) - GetWord(%box, 0)) / 2 + 5 + SPC (GetWord(%box, 4) - GetWord(%box, 1)) / 2 + 5 + SPC (GetWord(%box, 5) - GetWord(%box, 2)) / 2 + 5; + + %mesh = new NavMesh(%name) + { + position = %pos; + scale = %scale; + }; + } + else + { + %mesh = new NavMesh(%name) + { + position = %this-->MeshPosition.getText(); + scale = %this-->MeshScale.getText(); + }; + } + MissionGroup.add(%mesh); + NavEditorGui.selectObject(%mesh); + + Canvas.popDialog(CreateNewNavMeshDlg); +} diff --git a/Templates/Empty/game/tools/navEditor/NavEditorConsoleDlg.gui b/Templates/Empty/game/tools/navEditor/NavEditorConsoleDlg.gui new file mode 100644 index 000000000..401e0e3c7 --- /dev/null +++ b/Templates/Empty/game/tools/navEditor/NavEditorConsoleDlg.gui @@ -0,0 +1,169 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiWindowCtrl(NavEditorConsoleDlg) { + text = "Nav Console"; + resizeWidth = "1"; + resizeHeight = "1"; + canMove = "1"; + canClose = "1"; + canMinimize = "1"; + canMaximize = "1"; + canCollapse = "0"; + closeCommand = "NavEditorConsoleDlg.setVisible(false);"; + edgeSnap = "1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "238 170"; + extent = "320 240"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiWindowProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + + new GuiTextCtrl() { + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "3 222"; + extent = "149 13"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "top"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "StatusLeft"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiScrollCtrl() { + willFirstRespond = "1"; + hScrollBar = "dynamic"; + vScrollBar = "dynamic"; + lockHorizScroll = "1"; + lockVertScroll = "0"; + constantThumbHeight = "0"; + childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + margin = "-14 41 3 3"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "3 23"; + extent = "314 194"; + minExtent = "8 2"; + horizSizing = "relative"; + vertSizing = "relative"; + profile = "GuiEditorScrollProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "OutputScroll"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiListBoxCtrl() { + allowMultipleSelections = "0"; + fitParentWidth = "1"; + colorBullet = "1"; + position = "1 1"; + extent = "312 16"; + minExtent = "8 2"; + horizSizing = "relative"; + vertSizing = "relative"; + profile = "GuiListBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "Output"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; +}; +//--- OBJECT WRITE END --- + +new ScriptMsgListener(NavEditorConsoleListener); +getNavMeshEventManager().subscribe(NavEditorConsoleListener, "NavMeshCreated"); +getNavMeshEventManager().subscribe(NavEditorConsoleListener, "NavMeshRemoved"); +getNavMeshEventManager().subscribe(NavEditorConsoleListener, "NavMeshStartUpdate"); +getNavMeshEventManager().subscribe(NavEditorConsoleListener, "NavMeshUpdate"); +getNavMeshEventManager().subscribe(NavEditorConsoleListener, "NavMeshTileUpdate"); + +function NavEditorConsoleListener::onNavMeshCreated(%this, %data) +{ +} + +function NavEditorConsoleListener::onNavMeshRemoved(%this, %data) +{ +} + +function NavEditorConsoleListener::onNavMeshStartUpdate(%this, %data) +{ + NavEditorConsoleDlg-->Output.clearItems(); + NavEditorConsoleDlg-->Output.addItem("Build starting for NavMesh" SPC %data, "0 0.6 0"); + NavEditorConsoleDlg-->OutputScroll.scrollToBottom(); +} + +function NavEditorConsoleListener::onNavMeshUpdate(%this, %data) +{ + %message = ""; + if(getWordCount(%data) == 2) + { + %seconds = getWord(%data, 1); + %minutes = mFloor(%seconds / 60); + %seconds -= %minutes * 60; + %message = "Built NavMesh" SPC getWord(%data, 0) SPC "in" SPC %minutes @ "m" SPC mRound(%seconds) @ "s"; + if($Nav::Editor::playSoundWhenDone) + { + sfxPlayOnce(Audio2D, "tools/navEditor/done.wav"); + } + } + else + { + %message = "Loaded NavMesh" SPC %data; + } + NavEditorConsoleDlg-->Output.addItem(%message, "0 0.6 0"); + NavEditorConsoleDlg-->OutputScroll.scrollToBottom(); + NavEditorConsoleDlg->StatusLeft.setText(""); +} + +function NavEditorConsoleListener::onNavMeshTileUpdate(%this, %data) +{ + %mesh = getWord(%data, 0); + %index = getWord(%data, 1); + %total = getWord(%data, 2); + %tile = getWords(%data, 3, 4); + %success = getWord(%data, 5) == "1"; + if(!%success) + { + %message = "NavMesh" SPC %mesh SPC "tile" SPC %tile SPC "build failed!"; + NavEditorConsoleDlg-->Output.addItem(%message, "1 0 0"); + NavEditorConsoleDlg-->OutputScroll.scrollToBottom(); + } + %percent = %index / %total * 100; + NavEditorConsoleDlg->StatusLeft.setText("Build progress:" SPC mRound(%percent) @ "%"); +} diff --git a/Templates/Empty/game/tools/navEditor/NavEditorGui.gui b/Templates/Empty/game/tools/navEditor/NavEditorGui.gui new file mode 100644 index 000000000..da2d32e40 --- /dev/null +++ b/Templates/Empty/game/tools/navEditor/NavEditorGui.gui @@ -0,0 +1,851 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiNavEditorCtrl(NavEditorGui, EditorGuiGroup) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "NavEditorProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "0 0"; + Extent = "800 600"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Docking = "None"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "0"; + AnchorBottom = "0"; + AnchorLeft = "0"; + AnchorRight = "0"; + cameraZRot = "0"; + forceFOV = "0"; + renderMissionArea = "0"; + missionAreaFillColor = "255 0 0 20"; + missionAreaFrameColor = "255 0 0 128"; + allowBorderMove = "0"; + borderMovePixelSize = "20"; + borderMoveSpeed = "0.1"; + consoleFrameColor = "255 0 0 255"; + consoleFillColor = "0 0 0 0"; + consoleSphereLevel = "1"; + consoleCircleSegments = "32"; + consoleLineWidth = "1"; + GizmoProfile = "GlobalGizmoProfile"; + + new GuiWindowCollapseCtrl(NavEditorTreeWindow) { + internalName = ""; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiWindowProfile"; + HorizSizing = "windowRelative"; + VertSizing = "windowRelative"; + Position = getWord($pref::Video::mode, 0) - 209 + SPC getWord(EditorGuiToolbar.extent, 1) - 1; + Extent = "210 167"; + MinExtent = "210 100"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + resizeWidth = "1"; + resizeHeight = "1"; + canMove = "1"; + canClose = "0"; + canMinimize = "0"; + canMaximize = "0"; + minSize = "50 50"; + EdgeSnap = "1"; + text = "Navigation"; + + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "115 2"; + extent = "90 18"; + text = "New NavMesh"; + command = "Canvas.pushDialog(CreateNewNavMeshDlg);"; + }; + + new GuiContainer(){ + profile = GuiDefaultProfile; + Position = "5 25"; + Extent = "200 120"; + Docking = "Client"; + Margin = "3 1 3 3 "; + HorizSizing = "width"; + VertSizing = "height"; + isContainer = "1"; + + new GuiScrollCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiEditorScrollProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "0 0"; + Extent = "200 118"; + MinExtent = "8 8"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Docking = "Client"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + willFirstRespond = "1"; + hScrollBar = "alwaysOff"; + vScrollBar = "dynamic"; + lockHorizScroll = "true"; + lockVertScroll = "false"; + constantThumbHeight = "0"; + childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + + new GuiTreeViewCtrl(NavTreeView) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "ToolsGuiTreeViewProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "1 1"; + Extent = "193 21"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + tabSize = "16"; + textOffset = "2"; + fullRowSelect = "0"; + itemHeight = "21"; + destroyTreeOnSleep = "1"; + MouseDragging = "0"; + MultipleSelections = "0"; + DeleteObjectAllowed = "1"; + DragToItemAllowed = "0"; + showRoot = "0"; + internalNamesOnly = "0"; + }; + }; + }; + }; + new GuiWindowCollapseCtrl(NavEditorOptionsWindow) { + internalName = "Window"; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiWindowProfile"; + HorizSizing = "windowRelative"; + VertSizing = "windowRelative"; + Position = getWord($pref::Video::mode, 0) - 209 + SPC getWord(EditorGuiToolbar.extent, 1) + getWord(NavEditorTreeWindow.extent, 1) - 2; + Extent = "210 530"; + MinExtent = "210 300"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "0"; + AnchorBottom = "0"; + AnchorLeft = "0"; + AnchorRight = "0"; + resizeWidth = "1"; + resizeHeight = "1"; + canMove = "1"; + canClose = "0"; + canMinimize = "0"; + canMaximize = "0"; + minSize = "50 50"; + EdgeSnap = "1"; + text = "Properties"; + + new GuiContainer(){ //Actions + isContainer = "1"; + Profile = "inspectorStyleRolloutDarkProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "4 24"; + Extent = "202 85"; + Docking = "Top"; + Margin = "3 3 3 3"; + internalName = "ActionsBox"; + + new GuiTextCtrl(){ + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "5 0"; + Extent = "86 18"; + text = "Actions"; + }; + new GuiFlexibleArrayControl() + { + colSpacing = 2; + rowSpacing = 2; + internalName = "SelectActions"; + position = "7 21"; + extent = "190 64"; + + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "182 18"; + text = "Build NavMesh"; + command = "NavEditorGui.buildSelectedMeshes();"; + }; + new GuiCheckboxCtrl() { + internalName = "BackgroundBuildButton"; + text = "Background"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "75 20"; + minExtent = "8 2"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + variable = "$Nav::Editor::backgroundBuild"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckboxCtrl() { + internalName = "SaveIntermediatesButton"; + text = "Keep intermediates"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "105 20"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + variable = "$Nav::Editor::saveIntermediates"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckboxCtrl() { + internalName = "BuildSoundButton"; + text = "Play sound when done"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "150 20"; + minExtent = "8 2"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + variable = "$Nav::Editor::playSoundWhenDone"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiFlexibleArrayControl() + { + colSpacing = 2; + rowSpacing = 2; + internalName = "LinkActions"; + position = "7 21"; + extent = "190 64"; + + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "182 18"; + text = "Rebuild links"; + command = "NavEditorGui.buildLinks();"; + }; + }; + new GuiFlexibleArrayControl() + { + colSpacing = 2; + rowSpacing = 2; + internalName = "CoverActions"; + position = "7 21"; + extent = "190 64"; + + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "182 18"; + text = "Create Cover"; + command = "NavEditorGui.createCoverPoints();"; + }; + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "182 18"; + text = "Delete Cover"; + command = "NavEditorGui.deleteCoverPoints();"; + }; + }; + new GuiFlexibleArrayControl() + { + colSpacing = 2; + rowSpacing = 2; + internalName = "TileActions"; + position = "7 21"; + extent = "190 64"; + + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "182 18"; + text = "Rebuild tile"; + command = "NavEditorGui.buildTile();"; + }; + }; + new GuiFlexibleArrayControl() + { + colSpacing = 2; + rowSpacing = 2; + internalName = "TestActions"; + position = "7 21"; + extent = "190 64"; + + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "180 18"; + text = "Spawn"; + command = "NavEditorGui.spawnPlayer();"; + }; + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "90 18"; + text = "Delete"; + command = "NavEditorGui.getPlayer().delete();"; + }; + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "90 18"; + text = "Find cover"; + command = "NavEditorGui.findCover();"; + }; + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "90 18"; + text = "Follow"; + command = "NavEditorGui.followObject();"; + }; + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "90 18"; + text = "Stop"; + command = "NavEditorGui.getPlayer().stop();"; + }; + }; + }; + new GuiContainer(){ + isContainer = "1"; + Profile = "inspectorStyleRolloutDarkProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "4 112"; + Extent = "202 31"; + Docking = "Top"; + Margin = "0 0 3 3"; + + new GuiTextCtrl(){ + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "5 0"; + Extent = "121 18"; + text = "Properties"; + }; + }; + + new GuiScrollCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiEditorScrollProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "4 129"; + Extent = "202 357"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Docking = "Client"; + Margin = "-14 41 3 3"; + Padding = "0 0 0 0"; + AnchorTop = "0"; + AnchorBottom = "0"; + AnchorLeft = "0"; + AnchorRight = "0"; + willFirstRespond = "1"; + hScrollBar = "alwaysOff"; + vScrollBar = "dynamic"; + lockHorizScroll = "true"; + lockVertScroll = "false"; + constantThumbHeight = "0"; + childMargin = "0 0"; + internalName = "PropertiesBox"; + + new GuiInspector(NavInspector) { + StackingType = "Vertical"; + HorizStacking = "Left to Right"; + VertStacking = "Top to Bottom"; + Padding = "1"; + name = "NavInspector"; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiTransparentProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "1 1"; + Extent = "178 16"; + MinExtent = "16 16"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + dividerMargin = "5"; + }; + + new GuiFlexibleArrayControl() { + colSpacing = 2; + rowSpacing = 2; + internalName = "LinkProperties"; + position = "7 21"; + extent = "186 64"; + padding = "2 2 2 2"; + + new GuiCheckBoxCtrl() { + internalName = "LinkWalkFlag"; + class = "NavMeshLinkFlagButton"; + text = " Walk"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "This link is just ordinary flat ground."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkJumpFlag"; + class = "NavMeshLinkFlagButton"; + text = " Jump"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Does this link require a jump?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkDropFlag"; + class = "NavMeshLinkFlagButton"; + text = " Drop"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Does this link involve a significant drop?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkLedgeFlag"; + class = "NavMeshLinkFlagButton"; + text = " Ledge"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Should the character jump at the next ledge?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkClimbFlag"; + class = "NavMeshLinkFlagButton"; + text = " Climb"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Does this link involve climbing?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkTeleportFlag"; + class = "NavMeshLinkFlagButton"; + text = " Teleport"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Is this link a teleporter?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiFlexibleArrayControl() { + colSpacing = 2; + rowSpacing = 2; + internalName = "TileProperties"; + position = "7 21"; + extent = "186 64"; + padding = "2 2 2 2"; + + new GuiCheckBoxCtrl() { + text = " Display input geometry"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + variable = "$Nav::Editor::renderInput"; + }; + new GuiCheckBoxCtrl() { + text = " Display voxels"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + variable = "$Nav::Editor::renderVoxels"; + }; + }; + new GuiFlexibleArrayControl() { + colSpacing = 2; + rowSpacing = 2; + internalName = "TestProperties"; + position = "7 21"; + extent = "186 64"; + padding = "2 2 2 2"; + + new GuiTextCtrl() { + text = "Cover"; + profile = "GuiTextProfile"; + extent = "180 20"; + minExtent = "8 2"; + visible = "1"; + }; + new GuiTextEditCtrl() { + internalName = "CoverRadius"; + text = "10"; + profile = "GuiTextEditProfile"; + extent = "40 20"; + minExtent = "8 2"; + visible = "1"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Radius for cover-finding."; + }; + new GuiTextEditCtrl() { + internalName = "CoverPosition"; + text = "LocalClientConnection.getControlObject().getPosition();"; + profile = "GuiTextEditProfile"; + extent = "140 20"; + minExtent = "8 2"; + visible = "1"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Position to find cover from."; + }; + new GuiTextCtrl() { + text = "Follow"; + profile = "GuiTextProfile"; + extent = "180 20"; + minExtent = "8 2"; + visible = "1"; + }; + new GuiTextEditCtrl() { + internalName = "FollowRadius"; + text = "1"; + profile = "GuiTextEditProfile"; + extent = "40 20"; + minExtent = "8 2"; + visible = "1"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Radius for following."; + }; + new GuiTextEditCtrl() { + internalName = "FollowObject"; + text = "LocalClientConnection.player"; + profile = "GuiTextEditProfile"; + extent = "140 20"; + minExtent = "8 2"; + visible = "1"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Object to follow."; + }; + new GuiTextCtrl() { + text = "Movement"; + profile = "GuiTextProfile"; + extent = "180 20"; + minExtent = "8 2"; + visible = "1"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkWalkFlag"; + class = "NavMeshTestFlagButton"; + text = " Walk"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Can this character walk on ground?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkJumpFlag"; + class = "NavMeshTestFlagButton"; + text = " Jump"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Can this character jump?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkDropFlag"; + class = "NavMeshTestFlagButton"; + text = " Drop"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Can this character drop over edges?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkLedgeFlag"; + class = "NavMeshTestFlagButton"; + text = " Ledge"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Can this character jump from ledges?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkClimbFlag"; + class = "NavMeshTestFlagButton"; + text = " Climb"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Can this character climb?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkTeleportFlag"; + class = "NavMeshTestFlagButton"; + text = " Teleport"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Can this character teleport?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + }; + new GuiMLTextCtrl(NavFieldInfoControl) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiInspectorFieldInfoMLTextProfile"; + HorizSizing = "width"; + VertSizing = "top"; + Position = "1 485"; + Extent = "202 42"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + lineSpacing = "2"; + allowColorChars = "0"; + maxChars = "-1"; + useURLMouseCursor = "0"; + }; + }; + +}; + +//--- OBJECT WRITE END --- diff --git a/Templates/Empty/game/tools/navEditor/NavEditorSettingsTab.gui b/Templates/Empty/game/tools/navEditor/NavEditorSettingsTab.gui new file mode 100644 index 000000000..8611ca3d1 --- /dev/null +++ b/Templates/Empty/game/tools/navEditor/NavEditorSettingsTab.gui @@ -0,0 +1,506 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiTabPageCtrl(ENavEditorSettingsPage) { + fitBook = "1"; + text = "Navigation Editor"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 0"; + extent = "208 292"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "height"; + profile = "GuiSolidDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + + new GuiScrollCtrl() { + willFirstRespond = "1"; + hScrollBar = "alwaysOff"; + vScrollBar = "dynamic"; + lockHorizScroll = "1"; + lockVertScroll = "0"; + constantThumbHeight = "0"; + childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 0"; + extent = "208 292"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "height"; + profile = "GuiScrollProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiStackControl() { + stackingType = "Vertical"; + horizStacking = "Left to Right"; + vertStacking = "Top to Bottom"; + padding = "0"; + dynamicSize = "1"; + dynamicNonStackExtent = "0"; + dynamicPos = "0"; + changeChildSizeToFit = "1"; + changeChildPosition = "1"; + position = "1 1"; + extent = "206 124"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiRolloutCtrl() { + caption = "Test spawn"; + margin = "0 3 0 0"; + defaultHeight = "40"; + expanded = "1"; + clickCollapse = "1"; + hideHeader = "0"; + autoCollapseSiblings = "0"; + position = "0 0"; + extent = "206 62"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiRolloutProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiStackControl() { + stackingType = "Vertical"; + horizStacking = "Left to Right"; + vertStacking = "Top to Bottom"; + padding = "3"; + dynamicSize = "1"; + dynamicNonStackExtent = "0"; + dynamicPos = "0"; + changeChildSizeToFit = "1"; + changeChildPosition = "1"; + position = "0 20"; + extent = "206 39"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiControl() { + position = "0 0"; + extent = "206 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "Spawn class:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "5 1"; + extent = "70 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiPopUpMenuCtrlEx() { + maxPopupHeight = "200"; + sbUsesNAColor = "0"; + reverseTextList = "0"; + bitmapBounds = "16 16"; + hotTrackCallback = "0"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "81 0"; + extent = "121 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiPopUpMenuProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "SpawnClassOptions"; + class = "ESettingsWindowPopup"; + canSave = "1"; + canSaveDynamicFields = "1"; + editorSettingsRead = "NavEditorPlugin.readSettings();"; + editorSettingsValue = "NavEditor/SpawnClass"; + editorSettingsWrite = "NavEditorPlugin.writeSettings();"; + }; + }; + new GuiControl() { + position = "0 21"; + extent = "206 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "Datablock:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "5 1"; + extent = "70 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "DefaultPlayerData"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "81 0"; + extent = "121 18"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + class = "ESettingsWindowTextEdit"; + canSave = "1"; + canSaveDynamicFields = "1"; + editorSettingsRead = "NavEditorPlugin.readSettings();"; + editorSettingsValue = "NavEditor/SpawnDatablock"; + editorSettingsWrite = "NavEditorPlugin.writeSettings();"; + }; + }; + }; + }; + new GuiRolloutCtrl() { + caption = "Colors"; + margin = "0 3 0 0"; + defaultHeight = "40"; + expanded = "1"; + clickCollapse = "1"; + hideHeader = "0"; + autoCollapseSiblings = "0"; + position = "0 62"; + extent = "206 62"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiRolloutProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiStackControl() { + stackingType = "Vertical"; + horizStacking = "Left to Right"; + vertStacking = "Top to Bottom"; + padding = "3"; + dynamicSize = "1"; + dynamicNonStackExtent = "0"; + dynamicPos = "0"; + changeChildSizeToFit = "1"; + changeChildPosition = "1"; + position = "0 20"; + extent = "206 39"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiControl() { + position = "0 0"; + extent = "206 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + class = "ESettingsWindowColor"; + canSave = "1"; + canSaveDynamicFields = "1"; + editorSettingsRead = "NavEditorPlugin.readSettings();"; + editorSettingsValue = "NavEditor/HoverSplineColor"; + editorSettingsWrite = "NavEditorPlugin.writeSettings();"; + + new GuiTextCtrl() { + text = "Hover Spline:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 1"; + extent = "70 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "80 0"; + extent = "104 18"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "ColorEdit"; + class = "ESettingsWindowColorEdit"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GuiSwatchButtonCtrl() { + color = "0 0 0 0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "188 2"; + extent = "14 14"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "ColorButton"; + class = "ESettingsWindowColorButton"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + }; + new GuiControl() { + position = "0 21"; + extent = "206 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + class = "ESettingsWindowColor"; + canSave = "1"; + canSaveDynamicFields = "1"; + editorSettingsRead = "NavEditorPlugin.readSettings();"; + editorSettingsValue = "NavEditor/SelectedSplineColor"; + editorSettingsWrite = "NavEditorPlugin.writeSettings();"; + + new GuiTextCtrl() { + text = "Sel. Spline:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 1"; + extent = "70 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "80 0"; + extent = "104 18"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "ColorEdit"; + class = "ESettingsWindowColorEdit"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GuiSwatchButtonCtrl() { + color = "0 0 0 0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "188 2"; + extent = "14 14"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "ColorButton"; + class = "ESettingsWindowColorButton"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + }; + }; + }; + }; + }; +}; +//--- OBJECT WRITE END --- diff --git a/Templates/Empty/game/tools/navEditor/NavEditorToolbar.gui b/Templates/Empty/game/tools/navEditor/NavEditorToolbar.gui new file mode 100644 index 000000000..832324475 --- /dev/null +++ b/Templates/Empty/game/tools/navEditor/NavEditorToolbar.gui @@ -0,0 +1,144 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiControl(NavEditorToolbar,EditorGuiGroup) { + position = "306 0"; + extent = "800 32"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "NavEditorToolbar"; + canSave = "1"; + canSaveDynamicFields = "1"; + enabled = "1"; + + new GuiTextCtrl() { + text = "Navigation Editor"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "6 6"; + extent = "150 20"; + minExtent = "8 8"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapCtrl() { + bitmap = "core/art/gui/images/separator-h.png"; + wrap = "0"; + position = "90 3"; + extent = "2 26"; + minExtent = "1 1"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl(NavEditorAboutBtn) { + text = "Console"; + groupNum = "7"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "100 6"; + extent = "54 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + command = "NavEditorConsoleDlg.setVisible(!NavEditorConsoleDlg.isVisible());"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Show Console"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + text = "Mesh"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "167 1"; + extent = "50 30"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + variable = "$Nav::Editor::renderMesh"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "MeshButton"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + text = "Portals"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "224 1"; + extent = "54 30"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + variable = "$Nav::Editor::renderPortals"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "PortalButton"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + text = "BV tree"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "286 1"; + extent = "140 30"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + variable = "$Nav::Editor::renderBVTree"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "BVTreeButton"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; +}; +//--- OBJECT WRITE END --- diff --git a/Templates/Empty/game/tools/navEditor/done.wav b/Templates/Empty/game/tools/navEditor/done.wav new file mode 100644 index 0000000000000000000000000000000000000000..826250ddd7498b5afba6f79e8c98545772f965bb GIT binary patch literal 36948 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�V75N9_2LsII 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 HdUO8|rKz;W literal 0 HcmV?d00001 diff --git a/Templates/Empty/game/tools/navEditor/images/nav-cover_d.png b/Templates/Empty/game/tools/navEditor/images/nav-cover_d.png new file mode 100644 index 0000000000000000000000000000000000000000..b2f3a49e2076a1df4471cb4a6f8d4b242428bcbc GIT binary patch literal 986 zcmV<0110>4P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyc0 z7cUz~73(kn00UY{L_t(Y$E{U8NNZ^noc!J!!CX>=5JU~;MFjWBD-1$nqorCXq%l^4 zf{-Ryh}c<(LQ=|&A{L_Zw$e_-L{VcAhzRmnNui=bREQegRZR3Ivz1|^uB)!oo%5Z; ze9W2ieJWX&e*jnnV8a(drBXqs(?O@xLeL9GdO_&W0$4N%dYj$;4JMNbYPA|)iR8ja9uwXZfPic)m;JpMN*ih^h~YEuJ%$z*zy1i*{4=kfOT zc2S(q=L>a$AV3WOYPI@Zx4XT)#s2<&QSSKo7;SBB=u{rx=vV0LyE9UUEo8jVJS z4-I5_c^Q7czaU947({)2J=|_Lc6N4PFc=UDg)lTUgt4))Vg)`zw7$NMrluyu<8k!% z_QGPZAQp?kZnpyfMn^|6Jw1(RGzy#TnTcgt<{!U)@jWOjE2G=(rqycY+}vCtpU>wx zFfhQ{+FG8To{}UlFE6Pm3P~~+i}Bskot>Q_nM|UlrUrX^d+6%w0s!Q4IrR1QVPj(h zo12@kTCE@nkH>@g`T37acXD!qXf%q(#>PS}o6VxLvlAB=7YK*LC@n30QVE$%rf``e zqI^CNMNyE=W|2yzkWQyzG#XJ}UJg+d(a_LPM4V2i(caz;v)PQ5l@*Ah2mm-dJjC$u zFt)a~pwVbv5I#j)U=U8H6M;YgDwPTV zKoUJYJs2DuM0Iub+h#~6lT0R)j6@;~1OjwAovf^^q$rB?dc8b9KPO4%a=8~~86O{~ z%jGJV;0duPt))Epcf&}=p{kw{Qc6h1sWe4OYBfk1!` zhl2)#fwC+Y*;|q%S}Yc}w6su?B!gp<6TU%)~8W{?ONRqNF699ca9~TxD zm`bHSC*5naa5x;4B#DVcf_Ha!Z`OZkVgCuA&xeVL3AkJ?c)ecebh`iSQL8@rp*1%* zV`*s#B_$Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyc0 z7ceWMmem3P00hNJL_t(Y$F){pOp{j>KmGbasBNWX#bE~lqO%{tZkbd-CX-|!A_%mjllvup!ja1!xJA2b-}W~MBV8qlyTE)i$;VB-?{FtC#!BqAk5T<>zblJ8jWq^;Er+lEt%i;F%xcC7s)ug}X%M1qdv z9q*Ku?*25+Wr)BLN&%?^k{C;fxc7@Ay5=C6oe>h#*M>WU|C{W(+_k1F+d_IYy&#c5v`#eOFgk zjasb=_VxAtSX5NB3INdDd}O!PYTeP-*V|K2P!J%50Am1%2t1|qr32aRc42OAE^zba z&60+OhTCmzZDRlcv6u)=O-LMad`t=py# z9z0M5gF&?*2oHPvdavsB`lv)C5JgdT=<`F>3kwSw{R90ySy@?;m>7e`#>Tqx@^X7y zd)xizrK3PZvTmTMiK*06U8j0#Yis8L0EkE+7!1k}HXi&W6bfy)YPs5*o}Mlek-*85 zCwEGc#J9GzI*3RBkpfQ$1yK@#5F!&rkqd=F@`Z&3rQh#Q(P%U=K@gs()oQZ0a<2;j zK$M={H@DlJa`^D!dX-8Qwpc8EYPFh(k_h+i-P7Lq^+wsbbLXxwVCAG}4L_kE)YP6zOqZI{%5GdVU`lzn1Zq(=ZN&3xt_r%0R-r(Ti`%0zKl_%t_#yN-x zcDr4B;kyeTpZNAf|EBa!kytdwaU91OB6vJYAg`*bD%0t7fD99&u&{8k^n=p*`T2Ry zfdmyk76K$$*G2J@%`st7m6sW^^knD{l-94VCZOwQJUFHs5b)Y58-l-CCcB2=a=G ziZZQM`%)RjVKSNA3WdVAxVV^VwOZe;si_%}$z&{%z0cBB+ZEvsU zPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyc0 z7cer%{e8j!00DtXL_t(Y$K}*NNR?p}2JoNvdM(97BM4pY#j8n6ff_DO7B~xSVr`MQ znTzcWf};?DwAE4wf(9;u{Ud@v&`BDMB%+pELoI?XNBH{iqTEkiJn+H$KJWR?^PcBD z=Wv#-{*e8tS$}Gu%Mz>^T`8=HC9I<{urVxVA-Www_obV{FHEBl_&C1dY8Ik7JiraC zVFl&H`82+ul=U69@ebcHn!xKYgAKF?b`kknNZPTBd9)_*Jf7fV1m7oqjXSjv4PY>Z zox=j&;6ehQz=vuX<{Efy;N>;%SEXVp*)?ONl>F^u(6VqTf8hQkmj%$EUL}rzcs_7)B^$=d+bJq7b zs=dW}~;(yVqD*Bc6jrqjr(zFaKjPdX#mIm}@XaL+!u`o%zW00000NkvXXu0mjf D?FHa3 literal 0 HcmV?d00001 diff --git a/Templates/Empty/game/tools/navEditor/images/nav-editor_d.png b/Templates/Empty/game/tools/navEditor/images/nav-editor_d.png new file mode 100644 index 0000000000000000000000000000000000000000..06440d0d6e7f6f89c9ffce7b2456ad008fa73e39 GIT binary patch literal 1457 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 N002ovPDHLkV1hi!8+iZ# literal 0 HcmV?d00001 diff --git a/Templates/Empty/game/tools/navEditor/images/nav-editor_n.png b/Templates/Empty/game/tools/navEditor/images/nav-editor_n.png new file mode 100644 index 0000000000000000000000000000000000000000..6da61e45de94ce9efe147bfd4d973d008d46c3b6 GIT binary patch literal 1435 zcmV;M1!Ve(P)Px#24YJ`L;wH)0002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyW1 z78M{sfb0|i00kRKL_t(Y$L&^KXcSiz{_fn_opiHKCO^9gX|Ual))+158j4GdF)4Xy zA}At8Oi)lmN}5Vp1c^#4@zv*6B%vU_n1@6kd?;vxVi2h&Lbj2{U1GxSW|C!hvpd

;0=1Azc?xg439nIXG(??zu=9|S>o^ zZnxvai4&-FGg5MFn(SCk}^$6&DwSARdngj4=d*LB!*6SS%K#(`nqjdl#Z8!tHkB@ZrORQi`goDz2%i3CU!# z!0-2yHA%zaFk4ty$h~;+0)arlv|6p`=;&afPze3~{Wx~)7?zfn004@jps%kF=gytO z#KZ&+9XiD7>gq5)K5i-0QCKXNS1P0whGAfAYz)1uI1ZUihG?1wzu(W&=`=GdR0}G_wwb-_ujhq0zgw!(@&c>Z|-hwZB<<^ z7l}k7V2mLikDH33AR3LD01$~pV6j+8V`HN#%ktM=uXpHQ|EE{3Txp)1oa`4xv1W2| zvOJ&9!)CLA=XvDwd3ZdYMW@sGJEe5M>-FAyZ$QlY_{IGE{FfZZNs=TL*zNYL zD2mH=yZv5EOUth=mrHxEPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyW1 z6%sFNz*h8!@w{E(v-d_Wl;dtxHO$iW{p%Tg|6$&QZFwr&i5Zbs{(K`nKeFdZ15?W zLWM?(hCEDWzz&T8<8oN~K0ZfPdyDf&5-4r9=Sex;~L%7=}DPKJxJJz~bT} zuIsY2v^3T(7K<^_wt^tw`1qJgrNY+M7O$_b)M_gwu9A7dlm>2%oN z-)DJwncLf2DwPW7=jU|0UE1w7hG9@B6zKJOqaAsk7k$0Ij|M3Sf~Z(5M)i9A!+5{n z|I-e`Fe;TwQK?jllu`rz+}zwmBTsa4a>C)^A^CiMXd)Pf!RhHKjYfldy*~Zb`Mysg zk)Tj0j16=$nPhKokBf^7y4~({AYIql+1bIetg*?GNF>N+voxDcI-SmRpmaLT_V)Hf zZ^g1K*4Nhw!;q(^C*I%Rr_Z`c6_3YBr_;Q>z0vRY=L6c^-R0`)3fFZBf`EgAgZY5U z~O{)cqaH2vr29!jaX0KT=`0KWF+@^aIZvT8}ok4cR0000Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyW1 z6%z$tm?4Y+00RC=L_t(Y$F)|^Yg9 zd;k8uAI8SUx~kI}U}pI4ZEoH^pT5vjs9vx8mzI{UE-WlOT3%ju+WW0m%djkq0bqZB zUu3h{s{pXIwe=tn22-lM>$&;4sui?UFTN9@fsmY>oP1fWR?j+5ozPKUsdhz*U>xbu zOd`>oNhF#~1lH){J1unTluArbzm`&p7tfy$wp{nM-|yD|!217+1QA0@dF<4+8~QOG z00NdJ!{KoAz3ZC$2M1<299HdEB8EYvKuST$&Q9Qt#)+&7)E zL<$BGLy`I{tgWs6ST2{(_zWLE{QY4%7!10dJP|_>5u}u#b(f8fjvmg>&;MB{6uu4y zgKzWs{7;=Zi3kQW<0Ozyr(XsF0XG_rHhS?VQV{^e&;rNmZ{Zhef^yL2c~?N UwP{!X(f|Me07*qoM6N<$f_SKzVE_OC literal 0 HcmV?d00001 diff --git a/Templates/Empty/game/tools/navEditor/images/nav-link_n.png b/Templates/Empty/game/tools/navEditor/images/nav-link_n.png new file mode 100644 index 0000000000000000000000000000000000000000..05ef3d74873abba01c7c93ddf90d449179d00ad8 GIT binary patch literal 384 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a@dl*-CY>| zgW!U_%O?XxI14-?iy0WWg+Z8+Vb&Z8pdfpRr>`sf9VTf}Ap+b?*5G+&6y7HE|sDI&$oo)5edSA_v(6 zf?b+AHcGnaJrsHzC;0KeA*1RUn~l@k>i?AS)J}|dWbU4EhK~mO5wgT-B+?LVF(a%(c_Xf6S%*Fmqvq6L>GaWtXjvbX{+^jN`T%y Z#!VUOZhY-l^1$F>@O1TaS?83{1OU~_k)i+q literal 0 HcmV?d00001 diff --git a/Templates/Empty/game/tools/navEditor/main.cs b/Templates/Empty/game/tools/navEditor/main.cs new file mode 100644 index 000000000..b487b2700 --- /dev/null +++ b/Templates/Empty/game/tools/navEditor/main.cs @@ -0,0 +1,276 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 Daniel Buckmaster +// +// 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. +//----------------------------------------------------------------------------- + +// These values should align with enum PolyFlags in walkabout/nav.h +$Nav::WalkFlag = 1 << 0; +$Nav::SwimFlag = 1 << 1; +$Nav::JumpFlag = 1 << 2; +$Nav::LedgeFlag = 1 << 3; +$Nav::DropFlag = 1 << 4; +$Nav::ClimbFlag = 1 << 5; +$Nav::TeleportFlag = 1 << 6; + +function initializeNavEditor() +{ + echo(" % - Initializing Navigation Editor"); + + // Execute all relevant scripts and GUIs. + exec("./NavEditor.cs"); + exec("./NavEditorGui.gui"); + exec("./NavEditorToolbar.gui"); + exec("./NavEditorGui.cs"); + exec("./NavEditorAboutDlg.gui"); + exec("./NavEditorConsoleDlg.gui"); + exec("./CreateNewNavMeshDlg.gui"); + + // Add ourselves to EditorGui, where all the other tools reside + NavEditorGui.setVisible(false); + NavEditorToolbar.setVisible(false); + NavEditorOptionsWindow.setVisible(false); + NavEditorTreeWindow.setVisible(false); + NavEditorConsoleDlg.setVisible(false); + + EditorGui.add(NavEditorGui); + EditorGui.add(NavEditorToolbar); + EditorGui.add(NavEditorOptionsWindow); + EditorGui.add(NavEditorTreeWindow); + EditorGui.add(NavEditorConsoleDlg); + + new ScriptObject(NavEditorPlugin) + { + superClass = "EditorPlugin"; + editorGui = NavEditorGui; + }; + + // Bind shortcuts for the nav editor. + %map = new ActionMap(); + %map.bindCmd(keyboard, "1", "ENavEditorSelectModeBtn.performClick();", ""); + %map.bindCmd(keyboard, "2", "ENavEditorLinkModeBtn.performClick();", ""); + %map.bindCmd(keyboard, "3", "ENavEditorCoverModeBtn.performClick();", ""); + %map.bindCmd(keyboard, "4", "ENavEditorTileModeBtn.performClick();", ""); + %map.bindCmd(keyboard, "5", "ENavEditorTestModeBtn.performClick();", ""); + %map.bindCmd(keyboard, "c", "NavEditorConsoleBtn.performClick();", ""); + NavEditorPlugin.map = %map; + + NavEditorPlugin.initSettings(); +} + +function destroyNavEditor() +{ +} + +function NavEditorPlugin::onWorldEditorStartup(%this) +{ + // Add ourselves to the window menu. + %accel = EditorGui.addToEditorsMenu("Navigation Editor", "", NavEditorPlugin); + + // Add ourselves to the ToolsToolbar. + %tooltip = "Navigation Editor (" @ %accel @ ")"; + EditorGui.addToToolsToolbar("NavEditorPlugin", "NavEditorPalette", expandFilename("tools/navEditor/images/nav-editor"), %tooltip); + + GuiWindowCtrl::attach(NavEditorOptionsWindow, NavEditorTreeWindow); + + // Add ourselves to the Editor Settings window. + exec("./NavEditorSettingsTab.gui"); + ESettingsWindow.addTabPage(ENavEditorSettingsPage); + ENavEditorSettingsPage.init(); + + // Add items to World Editor Creator + EWCreatorWindow.beginGroup("Navigation"); + + EWCreatorWindow.registerMissionObject("NavMesh", "Navigation mesh"); + EWCreatorWindow.registerMissionObject("NavPath", "Path"); + EWCreatorWindow.registerMissionObject("CoverPoint", "Cover point"); + + EWCreatorWindow.endGroup(); +} + +function ENavEditorSettingsPage::init(%this) +{ + // Initialises the settings controls in the settings dialog box. + %this-->SpawnClassOptions.clear(); + %this-->SpawnClassOptions.add("AIPlayer"); + %this-->SpawnClassOptions.setFirstSelected(); +} + +function NavEditorPlugin::onActivated(%this) +{ + %this.readSettings(); + + // Set a global variable so everyone knows we're editing! + $Nav::EditorOpen = true; + + // Start off in Select mode. + ToolsPaletteArray->NavEditorSelectMode.performClick(); + EditorGui.bringToFront(NavEditorGui); + + NavEditorGui.setVisible(true); + NavEditorGui.makeFirstResponder(true); + NavEditorToolbar.setVisible(true); + + NavEditorOptionsWindow.setVisible(true); + NavEditorTreeWindow.setVisible(true); + + // Inspect the ServerNavMeshSet, which contains all the NavMesh objects + // in the mission. + if(!isObject(ServerNavMeshSet)) + new SimSet(ServerNavMeshSet); + if(ServerNavMeshSet.getCount() == 0) + MessageBoxYesNo("No NavMesh", "There is no NavMesh in this level. Would you like to create one?" SPC + "If not, please use the World Editor to create a new NavMesh.", + "Canvas.pushDialog(CreateNewNavMeshDlg);"); + NavTreeView.open(ServerNavMeshSet, true); + + // Push our keybindings to the top. (See initializeNavEditor for where this + // map was created.) + %this.map.push(); + + // Store this on a dynamic field + // in order to restore whatever setting + // the user had before. + %this.prevGizmoAlignment = GlobalGizmoProfile.alignment; + + // Always use Object alignment. + GlobalGizmoProfile.alignment = "Object"; + + // Set the status bar here until all tool have been hooked up + EditorGuiStatusBar.setInfo("Navigation editor."); + EditorGuiStatusBar.setSelection(""); + + // Allow the Gui to setup. + NavEditorGui.onEditorActivated(); + + Parent::onActivated(%this); +} + +function NavEditorPlugin::onDeactivated(%this) +{ + %this.writeSettings(); + + $Nav::EditorOpen = false; + + NavEditorGui.setVisible(false); + NavEditorToolbar.setVisible(false); + NavEditorOptionsWindow.setVisible(false); + NavEditorTreeWindow.setVisible(false); + %this.map.pop(); + + // Restore the previous Gizmo alignment settings. + GlobalGizmoProfile.alignment = %this.prevGizmoAlignment; + + // Allow the Gui to cleanup. + NavEditorGui.onEditorDeactivated(); + + Parent::onDeactivated(%this); +} + +function NavEditorPlugin::onEditMenuSelect(%this, %editMenu) +{ + %hasSelection = false; +} + +function NavEditorPlugin::handleDelete(%this) +{ + // Event happens when the user hits 'delete'. + NavEditorGui.deleteSelected(); +} + +function NavEditorPlugin::handleEscape(%this) +{ + return NavEditorGui.onEscapePressed(); +} + +function NavEditorPlugin::isDirty(%this) +{ + return NavEditorGui.isDirty; +} + +function NavEditorPlugin::onSaveMission(%this, %missionFile) +{ + if(NavEditorGui.isDirty) + { + MissionGroup.save(%missionFile); + NavEditorGui.isDirty = false; + } +} + +//----------------------------------------------------------------------------- +// Settings +//----------------------------------------------------------------------------- + +function NavEditorPlugin::initSettings(%this) +{ + EditorSettings.beginGroup("NavEditor", true); + + EditorSettings.setDefaultValue("SpawnClass", "AIPlayer"); + EditorSettings.setDefaultValue("SpawnDatablock", "DefaultPlayerData"); + + EditorSettings.endGroup(); +} + +function NavEditorPlugin::readSettings(%this) +{ + EditorSettings.beginGroup("NavEditor", true); + + NavEditorGui.spawnClass = EditorSettings.value("SpawnClass"); + NavEditorGui.spawnDatablock = EditorSettings.value("SpawnDatablock"); + + EditorSettings.endGroup(); +} + +function NavEditorPlugin::writeSettings(%this) +{ + EditorSettings.beginGroup("NavEditor", true); + + EditorSettings.setValue("SpawnClass", NavEditorGui.spawnClass); + EditorSettings.setValue("SpawnDatablock", NavEditorGui.spawnDatablock); + + EditorSettings.endGroup(); +} + +function ESettingsWindowPopup::onWake(%this) +{ + %this.setSelected(%this.findText(EditorSettings.value(%this.editorSettingsValue))); +} + +function ESettingsWindowPopup::onSelect(%this) +{ + EditorSettings.setValue(%this.editorSettingsValue, %this.getText()); + eval(%this.editorSettingsRead); +} + +//----------------------------------------------------------------------------- +// Demo +//----------------------------------------------------------------------------- + +function OnWalkaboutDemoLimit() +{ + MessageBoxOK("Walkabout demo", + "This demo only allows two NavMeshes to be created. Sorry!"); +} + +function OnWalkaboutDemoSave() +{ + MessageBoxOK("Walkabout demo", + "This demo doesn't allow you to save NavMeshes. Sorry!" SPC + "The rest of your mission will still be saved."); +} diff --git a/Templates/Empty/game/tools/navEditor/navEditor.cs b/Templates/Empty/game/tools/navEditor/navEditor.cs new file mode 100644 index 000000000..21ea09064 --- /dev/null +++ b/Templates/Empty/game/tools/navEditor/navEditor.cs @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 Daniel Buckmaster +// +// 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. +//----------------------------------------------------------------------------- + +singleton GuiControlProfile(NavEditorProfile) +{ + canKeyFocus = true; + opaque = true; + fillColor = "192 192 192 192"; + category = "Editor"; +}; + +singleton GuiControlProfile(GuiSimpleBorderProfile) +{ + opaque = false; + border = 1; + category = "Editor"; +}; + diff --git a/Templates/Empty/game/tools/navEditor/navEditorGui.cs b/Templates/Empty/game/tools/navEditor/navEditorGui.cs new file mode 100644 index 000000000..4e76abbb2 --- /dev/null +++ b/Templates/Empty/game/tools/navEditor/navEditorGui.cs @@ -0,0 +1,351 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 Daniel Buckmaster +// +// 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. +//----------------------------------------------------------------------------- + +$Nav::EditorOpen = false; +$Nav::Editor::renderMesh = true; +$Nav::Editor::renderPortals = false; +$Nav::Editor::renderBVTree = false; +$Nav::Editor::backgroundBuild = true; +$Nav::Editor::saveIntermediates = false; +$Nav::Editor::playSoundWhenDone = false; + +function NavEditorGui::onEditorActivated(%this) +{ + if(%this.selectedObject) + %this.selectObject(%this.selectedObject); + %this.prepSelectionMode(); +} + +function NavEditorGui::onEditorDeactivated(%this) +{ + if(%this.getMesh()) + %this.deselect(); +} + +function NavEditorGui::onModeSet(%this, %mode) +{ + // Callback when the nav editor changes mode. Set the appropriate dynamic + // GUI contents in the properties/actions boxes. + NavInspector.setVisible(false); + + %actions = NavEditorOptionsWindow->ActionsBox; + %actions->SelectActions.setVisible(false); + %actions->LinkActions.setVisible(false); + %actions->CoverActions.setVisible(false); + %actions->TileActions.setVisible(false); + %actions->TestActions.setVisible(false); + + %properties = NavEditorOptionsWindow->PropertiesBox; + %properties->LinkProperties.setVisible(false); + %properties->TileProperties.setVisible(false); + %properties->TestProperties.setVisible(false); + + switch$(%mode) + { + case "SelectMode": + NavInspector.setVisible(true); + %actions->SelectActions.setVisible(true); + case "LinkMode": + %actions->LinkActions.setVisible(true); + %properties->LinkProperties.setVisible(true); + case "CoverMode": + // + %actions->CoverActions.setVisible(true); + case "TileMode": + %actions->TileActions.setVisible(true); + %properties->TileProperties.setVisible(true); + case "TestMode": + %actions->TestActions.setVisible(true); + %properties->TestProperties.setVisible(true); + } +} + +function NavEditorGui::paletteSync(%this, %mode) +{ + // Synchronise the palette (small buttons on the left) with the actual mode + // the nav editor is in. + %evalShortcut = "ToolsPaletteArray-->" @ %mode @ ".setStateOn(1);"; + eval(%evalShortcut); +} + +function NavEditorGui::onEscapePressed(%this) +{ + return false; +} + +function NavEditorGui::selectObject(%this, %obj) +{ + NavTreeView.clearSelection(); + if(isObject(%obj)) + NavTreeView.selectItem(%obj); + %this.onObjectSelected(%obj); +} + +function NavEditorGui::onObjectSelected(%this, %obj) +{ + if(isObject(%this.selectedObject)) + %this.deselect(); + %this.selectedObject = %obj; + if(isObject(%obj)) + { + %this.selectMesh(%obj); + NavInspector.inspect(%obj); + } +} + +function NavEditorGui::deleteMesh(%this) +{ + if(isObject(%this.selectedObject)) + { + %this.selectedObject.delete(); + %this.selectObject(-1); + } +} + +function NavEditorGui::deleteSelected(%this) +{ + switch$(%this.getMode()) + { + case "SelectMode": + // Try to delete the selected NavMesh. + if(isObject(NavEditorGui.selectedObject)) + MessageBoxYesNo("Warning", + "Are you sure you want to delete" SPC NavEditorGui.selectedObject.getName(), + "NavEditorGui.deleteMesh();"); + case "TestMode": + %this.getPlayer().delete(); + %this.onPlayerDeselected(); + case "LinkMode": + %this.deleteLink(); + %this.isDirty = true; + } +} + +function NavEditorGui::buildSelectedMeshes(%this) +{ + if(isObject(%this.getMesh())) + { + %this.getMesh().build($Nav::Editor::backgroundBuild, $Nav::Editor::saveIntermediates); + %this.isDirty = true; + } +} + +function NavEditorGui::buildLinks(%this) +{ + if(isObject(%this.getMesh())) + { + %this.getMesh().buildLinks(); + %this.isDirty = true; + } +} + +function updateLinkData(%control, %flags) +{ + %control->LinkWalkFlag.setActive(true); + %control->LinkJumpFlag.setActive(true); + %control->LinkDropFlag.setActive(true); + %control->LinkLedgeFlag.setActive(true); + %control->LinkClimbFlag.setActive(true); + %control->LinkTeleportFlag.setActive(true); + + %control->LinkWalkFlag.setStateOn(%flags & $Nav::WalkFlag); + %control->LinkJumpFlag.setStateOn(%flags & $Nav::JumpFlag); + %control->LinkDropFlag.setStateOn(%flags & $Nav::DropFlag); + %control->LinkLedgeFlag.setStateOn(%flags & $Nav::LedgeFlag); + %control->LinkClimbFlag.setStateOn(%flags & $Nav::ClimbFlag); + %control->LinkTeleportFlag.setStateOn(%flags & $Nav::TeleportFlag); +} + +function getLinkFlags(%control) +{ + return (%control->LinkWalkFlag.isStateOn() ? $Nav::WalkFlag : 0) | + (%control->LinkJumpFlag.isStateOn() ? $Nav::JumpFlag : 0) | + (%control->LinkDropFlag.isStateOn() ? $Nav::DropFlag : 0) | + (%control->LinkLedgeFlag.isStateOn() ? $Nav::LedgeFlag : 0) | + (%control->LinkClimbFlag.isStateOn() ? $Nav::ClimbFlag : 0) | + (%control->LinkTeleportFlag.isStateOn() ? $Nav::TeleportFlag : 0); +} + +function disableLinkData(%control) +{ + %control->LinkWalkFlag.setActive(false); + %control->LinkJumpFlag.setActive(false); + %control->LinkDropFlag.setActive(false); + %control->LinkLedgeFlag.setActive(false); + %control->LinkClimbFlag.setActive(false); + %control->LinkTeleportFlag.setActive(false); +} + +function NavEditorGui::onLinkSelected(%this, %flags) +{ + updateLinkData(NavEditorOptionsWindow-->LinkProperties, %flags); +} + +function NavEditorGui::onPlayerSelected(%this, %flags) +{ + updateLinkData(NavEditorOptionsWindow-->TestProperties, %flags); +} + +function NavEditorGui::updateLinkFlags(%this) +{ + if(isObject(%this.getMesh())) + { + %properties = NavEditorOptionsWindow-->LinkProperties; + %this.setLinkFlags(getLinkFlags(%properties)); + %this.isDirty = true; + } +} + +function NavEditorGui::updateTestFlags(%this) +{ + if(isObject(%this.getPlayer())) + { + %properties = NavEditorOptionsWindow-->TestProperties; + %player = %this.getPlayer(); + + %player.allowWwalk = %properties->LinkWalkFlag.isStateOn(); + %player.allowJump = %properties->LinkJumpFlag.isStateOn(); + %player.allowDrop = %properties->LinkDropFlag.isStateOn(); + %player.allowLedge = %properties->LinkLedgeFlag.isStateOn(); + %player.allowClimb = %properties->LinkClimbFlag.isStateOn(); + %player.allowTeleport = %properties->LinkTeleportFlag.isStateOn(); + + %this.isDirty = true; + } +} + +function NavEditorGui::onLinkDeselected(%this) +{ + disableLinkData(NavEditorOptionsWindow-->LinkProperties); +} + +function NavEditorGui::onPlayerDeselected(%this) +{ + disableLinkData(NavEditorOptionsWindow-->TestProperties); +} + +function NavEditorGui::createCoverPoints(%this) +{ + if(isObject(%this.getMesh())) + { + %this.getMesh().createCoverPoints(); + %this.isDirty = true; + } +} + +function NavEditorGui::deleteCoverPoints(%this) +{ + if(isObject(%this.getMesh())) + { + %this.getMesh().deleteCoverPoints(); + %this.isDirty = true; + } +} + +function NavEditorGui::findCover(%this) +{ + if(%this.getMode() $= "TestMode" && isObject(%this.getPlayer())) + { + %pos = LocalClientConnection.getControlObject().getPosition(); + %text = NavEditorOptionsWindow-->TestProperties->CoverPosition.getText(); + if(%text !$= "") + %pos = eval(%text); + %this.getPlayer().findCover(%pos, NavEditorOptionsWindow-->TestProperties->CoverRadius.getText()); + } +} + +function NavEditorGui::followObject(%this) +{ + if(%this.getMode() $= "TestMode" && isObject(%this.getPlayer())) + { + %obj = LocalClientConnection.player; + %text = NavEditorOptionsWindow-->TestProperties->FollowObject.getText(); + if(%text !$= "") + { + eval("%obj = " @ %text); + if(!isObject(%obj)) + MessageBoxOk("Error", "Cannot find object" SPC %text); + } + if(isObject(%obj)) + %this.getPlayer().followObject(%obj, NavEditorOptionsWindow-->TestProperties->FollowRadius.getText()); + } +} + +function NavInspector::inspect(%this, %obj) +{ + %name = ""; + if(isObject(%obj)) + %name = %obj.getName(); + else + NavFieldInfoControl.setText(""); + + Parent::inspect(%this, %obj); +} + +function NavInspector::onInspectorFieldModified(%this, %object, %fieldName, %arrayIndex, %oldValue, %newValue) +{ + // Same work to do as for the regular WorldEditor Inspector. + Inspector::onInspectorFieldModified(%this, %object, %fieldName, %arrayIndex, %oldValue, %newValue); +} + +function NavInspector::onFieldSelected(%this, %fieldName, %fieldTypeStr, %fieldDoc) +{ + NavFieldInfoControl.setText("" @ %fieldName @ " (" @ %fieldTypeStr @ ") " NL "" @ %fieldDoc); +} + +function NavTreeView::onInspect(%this, %obj) +{ + NavInspector.inspect(%obj); +} + +function NavTreeView::onSelect(%this, %obj) +{ + NavInspector.inspect(%obj); + NavEditorGui.onObjectSelected(%obj); +} + +function NavEditorGui::prepSelectionMode(%this) +{ + %this.setMode("SelectMode"); + ToolsPaletteArray-->NavEditorSelectMode.setStateOn(1); +} + +//----------------------------------------------------------------------------- + +function ENavEditorPaletteButton::onClick(%this) +{ + // When clicking on a pelette button, add its description to the bottom of + // the editor window. + EditorGuiStatusBar.setInfo(%this.DetailedDesc); +} + +//----------------------------------------------------------------------------- + +function NavMeshLinkFlagButton::onClick(%this) +{ + NavEditorGui.updateLinkFlags(); +} + +function NavMeshTestFlagButton::onClick(%this) +{ + NavEditorGui.updateTestFlags(); +} diff --git a/Templates/Empty/game/tools/worldEditor/gui/ToolsPaletteGroups/NavEditorPalette.ed.gui b/Templates/Empty/game/tools/worldEditor/gui/ToolsPaletteGroups/NavEditorPalette.ed.gui new file mode 100644 index 000000000..506c525b2 --- /dev/null +++ b/Templates/Empty/game/tools/worldEditor/gui/ToolsPaletteGroups/NavEditorPalette.ed.gui @@ -0,0 +1,130 @@ +%paletteId = new GuiControl(NavEditorPalette,EditorGuiGroup) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "1024 768"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + + new GuiBitmapButtonCtrl(ENavEditorSelectModeBtn) { + canSaveDynamicFields = "1"; + class = ENavEditorPaletteButton; + internalName = "NavEditorSelectMode"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "NavEditorGui.prepSelectionMode();"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "View NavMesh (1)."; + DetailedDesc = ""; + hovertime = "1000"; + bitmap = "tools/gui/images/menubar/visibility-toggle"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; + new GuiBitmapButtonCtrl(ENavEditorLinkModeBtn) { + canSaveDynamicFields = "1"; + class = ENavEditorPaletteButton; + internalName = "NavEditorLinkMode"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "NavEditorGui.setMode(\"LinkMode\");"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "Create off-mesh links (2)."; + DetailedDesc = "Click to select/add. Shift-click to add multiple end points."; + hovertime = "1000"; + bitmap = "tools/navEditor/images/nav-link"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; + new GuiBitmapButtonCtrl(ENavEditorCoverModeBtn) { + canSaveDynamicFields = "1"; + class = ENavEditorPaletteButton; + internalName = "NavEditorCoverMode"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "NavEditorGui.setMode(\"CoverMode\");"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "Edit cover (3)."; + DetailedDesc = ""; + hovertime = "1000"; + bitmap = "tools/navEditor/images/nav-cover"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; + new GuiBitmapButtonCtrl(ENavEditorTileModeBtn) { + canSaveDynamicFields = "1"; + class = ENavEditorPaletteButton; + internalName = "NavEditorTileMode"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "NavEditorGui.setMode(\"TileMode\");"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "View tiles (4)."; + DetailedDesc = "Click to select."; + hovertime = "1000"; + bitmap = "tools/gui/images/menubar/select-bounds"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; + new GuiBitmapButtonCtrl(ENavEditorTestModeBtn) { + canSaveDynamicFields = "1"; + class = ENavEditorPaletteButton; + internalName = "NavEditorTestMode"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "NavEditorGui.setMode(\"TestMode\");"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "Test pathfinding (5)."; + DetailedDesc = "Click to select/move character, CTRL-click to spawn, SHIFT-click to deselect."; + hovertime = "1000"; + bitmap = "tools/worldEditor/images/toolbar/3rd-person-camera"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; +}; \ No newline at end of file diff --git a/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs b/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs index 75d41eb53..3419a5bc0 100644 --- a/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs +++ b/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs @@ -83,8 +83,6 @@ function EWCreatorWindow::init( %this ) %this.registerMissionObject( "SpawnSphere", "Observer Spawn Sphere", "ObserverDropPoint" ); %this.registerMissionObject( "SFXSpace", "Sound Space" ); %this.registerMissionObject( "OcclusionVolume", "Occlusion Volume" ); - %this.registerMissionObject("NavMesh", "Navigation mesh"); - %this.registerMissionObject("NavPath", "Path"); %this.endGroup(); @@ -787,4 +785,4 @@ function genericCreateObject( %class ) // In case the caller wants it. return %obj; -} \ No newline at end of file +} diff --git a/Templates/Full/game/tools/navEditor/CreateNewNavMeshDlg.gui b/Templates/Full/game/tools/navEditor/CreateNewNavMeshDlg.gui new file mode 100644 index 000000000..0734b4578 --- /dev/null +++ b/Templates/Full/game/tools/navEditor/CreateNewNavMeshDlg.gui @@ -0,0 +1,356 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiControl(CreateNewNavMeshDlg) { + position = "0 0"; + extent = "1024 768"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + + new GuiWindowCtrl() { + text = "New NavMesh"; + resizeWidth = "0"; + resizeHeight = "0"; + canMove = "1"; + canClose = "1"; + canMinimize = "0"; + canMaximize = "0"; + canCollapse = "0"; + closeCommand = "Canvas.popDialog(CreateNewNavMeshDlg);"; + edgeSnap = "1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "283 240"; + extent = "200 151"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiWindowProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "Name:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "12 29"; + extent = "39 21"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "Nav"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "59 30"; + extent = "129 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "MeshName"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Position:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "12 51"; + extent = "39 21"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "0 0 0"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "59 52"; + extent = "129 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "MeshPosition"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Scale:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "12 73"; + extent = "39 21"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "50 50 20"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "59 74"; + extent = "129 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "MeshScale"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + text = " Fit NavMesh to mission area?"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "22 99"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Positions and scales the NavMesh so it includes all your mission objects."; + hovertime = "1000"; + isContainer = "0"; + internalName = "MeshMissionBounds"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Create!"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "12 121"; + extent = "87 19"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + command = "CreateNewNavMeshDlg.create();"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Cancel"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "104 121"; + extent = "84 19"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + command = "Canvas.popDialog(CreateNewNavMeshDlg);"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; +}; +//--- OBJECT WRITE END --- + +function CreateNewNavMeshDlg::onWake(%this) +{ + %this-->MeshName.setText("Nav"); + %this-->MeshPosition.setText("0 0 0"); + %this-->MeshScale.setText("50 50 20"); +} + +function MissionBoundsExtents(%group) +{ + %box = "0 0 0 0 0 0"; + foreach(%obj in %group) + { + // Skip LevelInfos. Need a way to detect other non-SceneObjects. + // Also skip GroundPlanes. They're too big. + %cls = %obj.getClassName(); + if(%cls $= "LevelInfo" || %cls $= "GroundPlane" || %cls $= "GroundCover") + continue; + + // Get world box - might have to recurse into nested SimGroups. + %wbox = "0 0 0 0 0 0"; + if(%cls $= "SimGroup" || %cls $= "SimSet" || %cls $= "Path") + %wbox = MissionBoundsExtents(%obj); + else if(%obj.getType() & $TypeMasks::StaticObjectType && + !(%obj.getType() & $TypeMasks::EnvironmentObjectType)) + %wbox = %obj.getWorldBox(); + else + continue; + + // Update min point. + for(%j = 0; %j < 3; %j++) + { + if(GetWord(%box, %j) > GetWord(%wbox, %j)) + %box = SetWord(%box, %j, GetWord(%wbox, %j)); + } + // Update max point. + for(%j = 3; %j < 6; %j++) + { + if(GetWord(%box, %j) < GetWord(%wbox, %j)) + %box = SetWord(%box, %j, GetWord(%wbox, %j)); + } + } + return %box; +} + +function CreateNewNavMeshDlg::create(%this) +{ + %name = %this-->MeshName.getText(); + if(%name $= "" || nameToID(%name) != -1) + { + MessageBoxOk("Error", "A NavMesh must have a unique name!"); + return; + } + + %mesh = 0; + + if(%this-->MeshMissionBounds.isStateOn()) + { + if(!isObject(MissionGroup)) + { + MessageBoxOk("Error", "You must have a MissionGroup to use the mission bounds function."); + return; + } + // Get maximum extents of all objects. + %box = MissionBoundsExtents(MissionGroup); + %pos = GetBoxCenter(%box); + %scale = (GetWord(%box, 3) - GetWord(%box, 0)) / 2 + 5 + SPC (GetWord(%box, 4) - GetWord(%box, 1)) / 2 + 5 + SPC (GetWord(%box, 5) - GetWord(%box, 2)) / 2 + 5; + + %mesh = new NavMesh(%name) + { + position = %pos; + scale = %scale; + }; + } + else + { + %mesh = new NavMesh(%name) + { + position = %this-->MeshPosition.getText(); + scale = %this-->MeshScale.getText(); + }; + } + MissionGroup.add(%mesh); + NavEditorGui.selectObject(%mesh); + + Canvas.popDialog(CreateNewNavMeshDlg); +} diff --git a/Templates/Full/game/tools/navEditor/NavEditorConsoleDlg.gui b/Templates/Full/game/tools/navEditor/NavEditorConsoleDlg.gui new file mode 100644 index 000000000..401e0e3c7 --- /dev/null +++ b/Templates/Full/game/tools/navEditor/NavEditorConsoleDlg.gui @@ -0,0 +1,169 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiWindowCtrl(NavEditorConsoleDlg) { + text = "Nav Console"; + resizeWidth = "1"; + resizeHeight = "1"; + canMove = "1"; + canClose = "1"; + canMinimize = "1"; + canMaximize = "1"; + canCollapse = "0"; + closeCommand = "NavEditorConsoleDlg.setVisible(false);"; + edgeSnap = "1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "238 170"; + extent = "320 240"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiWindowProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + + new GuiTextCtrl() { + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "3 222"; + extent = "149 13"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "top"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "StatusLeft"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiScrollCtrl() { + willFirstRespond = "1"; + hScrollBar = "dynamic"; + vScrollBar = "dynamic"; + lockHorizScroll = "1"; + lockVertScroll = "0"; + constantThumbHeight = "0"; + childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + margin = "-14 41 3 3"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "3 23"; + extent = "314 194"; + minExtent = "8 2"; + horizSizing = "relative"; + vertSizing = "relative"; + profile = "GuiEditorScrollProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "OutputScroll"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiListBoxCtrl() { + allowMultipleSelections = "0"; + fitParentWidth = "1"; + colorBullet = "1"; + position = "1 1"; + extent = "312 16"; + minExtent = "8 2"; + horizSizing = "relative"; + vertSizing = "relative"; + profile = "GuiListBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "Output"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; +}; +//--- OBJECT WRITE END --- + +new ScriptMsgListener(NavEditorConsoleListener); +getNavMeshEventManager().subscribe(NavEditorConsoleListener, "NavMeshCreated"); +getNavMeshEventManager().subscribe(NavEditorConsoleListener, "NavMeshRemoved"); +getNavMeshEventManager().subscribe(NavEditorConsoleListener, "NavMeshStartUpdate"); +getNavMeshEventManager().subscribe(NavEditorConsoleListener, "NavMeshUpdate"); +getNavMeshEventManager().subscribe(NavEditorConsoleListener, "NavMeshTileUpdate"); + +function NavEditorConsoleListener::onNavMeshCreated(%this, %data) +{ +} + +function NavEditorConsoleListener::onNavMeshRemoved(%this, %data) +{ +} + +function NavEditorConsoleListener::onNavMeshStartUpdate(%this, %data) +{ + NavEditorConsoleDlg-->Output.clearItems(); + NavEditorConsoleDlg-->Output.addItem("Build starting for NavMesh" SPC %data, "0 0.6 0"); + NavEditorConsoleDlg-->OutputScroll.scrollToBottom(); +} + +function NavEditorConsoleListener::onNavMeshUpdate(%this, %data) +{ + %message = ""; + if(getWordCount(%data) == 2) + { + %seconds = getWord(%data, 1); + %minutes = mFloor(%seconds / 60); + %seconds -= %minutes * 60; + %message = "Built NavMesh" SPC getWord(%data, 0) SPC "in" SPC %minutes @ "m" SPC mRound(%seconds) @ "s"; + if($Nav::Editor::playSoundWhenDone) + { + sfxPlayOnce(Audio2D, "tools/navEditor/done.wav"); + } + } + else + { + %message = "Loaded NavMesh" SPC %data; + } + NavEditorConsoleDlg-->Output.addItem(%message, "0 0.6 0"); + NavEditorConsoleDlg-->OutputScroll.scrollToBottom(); + NavEditorConsoleDlg->StatusLeft.setText(""); +} + +function NavEditorConsoleListener::onNavMeshTileUpdate(%this, %data) +{ + %mesh = getWord(%data, 0); + %index = getWord(%data, 1); + %total = getWord(%data, 2); + %tile = getWords(%data, 3, 4); + %success = getWord(%data, 5) == "1"; + if(!%success) + { + %message = "NavMesh" SPC %mesh SPC "tile" SPC %tile SPC "build failed!"; + NavEditorConsoleDlg-->Output.addItem(%message, "1 0 0"); + NavEditorConsoleDlg-->OutputScroll.scrollToBottom(); + } + %percent = %index / %total * 100; + NavEditorConsoleDlg->StatusLeft.setText("Build progress:" SPC mRound(%percent) @ "%"); +} diff --git a/Templates/Full/game/tools/navEditor/NavEditorGui.gui b/Templates/Full/game/tools/navEditor/NavEditorGui.gui new file mode 100644 index 000000000..da2d32e40 --- /dev/null +++ b/Templates/Full/game/tools/navEditor/NavEditorGui.gui @@ -0,0 +1,851 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiNavEditorCtrl(NavEditorGui, EditorGuiGroup) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "NavEditorProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "0 0"; + Extent = "800 600"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Docking = "None"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "0"; + AnchorBottom = "0"; + AnchorLeft = "0"; + AnchorRight = "0"; + cameraZRot = "0"; + forceFOV = "0"; + renderMissionArea = "0"; + missionAreaFillColor = "255 0 0 20"; + missionAreaFrameColor = "255 0 0 128"; + allowBorderMove = "0"; + borderMovePixelSize = "20"; + borderMoveSpeed = "0.1"; + consoleFrameColor = "255 0 0 255"; + consoleFillColor = "0 0 0 0"; + consoleSphereLevel = "1"; + consoleCircleSegments = "32"; + consoleLineWidth = "1"; + GizmoProfile = "GlobalGizmoProfile"; + + new GuiWindowCollapseCtrl(NavEditorTreeWindow) { + internalName = ""; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiWindowProfile"; + HorizSizing = "windowRelative"; + VertSizing = "windowRelative"; + Position = getWord($pref::Video::mode, 0) - 209 + SPC getWord(EditorGuiToolbar.extent, 1) - 1; + Extent = "210 167"; + MinExtent = "210 100"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + resizeWidth = "1"; + resizeHeight = "1"; + canMove = "1"; + canClose = "0"; + canMinimize = "0"; + canMaximize = "0"; + minSize = "50 50"; + EdgeSnap = "1"; + text = "Navigation"; + + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "115 2"; + extent = "90 18"; + text = "New NavMesh"; + command = "Canvas.pushDialog(CreateNewNavMeshDlg);"; + }; + + new GuiContainer(){ + profile = GuiDefaultProfile; + Position = "5 25"; + Extent = "200 120"; + Docking = "Client"; + Margin = "3 1 3 3 "; + HorizSizing = "width"; + VertSizing = "height"; + isContainer = "1"; + + new GuiScrollCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiEditorScrollProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "0 0"; + Extent = "200 118"; + MinExtent = "8 8"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Docking = "Client"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + willFirstRespond = "1"; + hScrollBar = "alwaysOff"; + vScrollBar = "dynamic"; + lockHorizScroll = "true"; + lockVertScroll = "false"; + constantThumbHeight = "0"; + childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + + new GuiTreeViewCtrl(NavTreeView) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "ToolsGuiTreeViewProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "1 1"; + Extent = "193 21"; + MinExtent = "8 8"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + tabSize = "16"; + textOffset = "2"; + fullRowSelect = "0"; + itemHeight = "21"; + destroyTreeOnSleep = "1"; + MouseDragging = "0"; + MultipleSelections = "0"; + DeleteObjectAllowed = "1"; + DragToItemAllowed = "0"; + showRoot = "0"; + internalNamesOnly = "0"; + }; + }; + }; + }; + new GuiWindowCollapseCtrl(NavEditorOptionsWindow) { + internalName = "Window"; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiWindowProfile"; + HorizSizing = "windowRelative"; + VertSizing = "windowRelative"; + Position = getWord($pref::Video::mode, 0) - 209 + SPC getWord(EditorGuiToolbar.extent, 1) + getWord(NavEditorTreeWindow.extent, 1) - 2; + Extent = "210 530"; + MinExtent = "210 300"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "0"; + AnchorBottom = "0"; + AnchorLeft = "0"; + AnchorRight = "0"; + resizeWidth = "1"; + resizeHeight = "1"; + canMove = "1"; + canClose = "0"; + canMinimize = "0"; + canMaximize = "0"; + minSize = "50 50"; + EdgeSnap = "1"; + text = "Properties"; + + new GuiContainer(){ //Actions + isContainer = "1"; + Profile = "inspectorStyleRolloutDarkProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "4 24"; + Extent = "202 85"; + Docking = "Top"; + Margin = "3 3 3 3"; + internalName = "ActionsBox"; + + new GuiTextCtrl(){ + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "5 0"; + Extent = "86 18"; + text = "Actions"; + }; + new GuiFlexibleArrayControl() + { + colSpacing = 2; + rowSpacing = 2; + internalName = "SelectActions"; + position = "7 21"; + extent = "190 64"; + + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "182 18"; + text = "Build NavMesh"; + command = "NavEditorGui.buildSelectedMeshes();"; + }; + new GuiCheckboxCtrl() { + internalName = "BackgroundBuildButton"; + text = "Background"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "75 20"; + minExtent = "8 2"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + variable = "$Nav::Editor::backgroundBuild"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckboxCtrl() { + internalName = "SaveIntermediatesButton"; + text = "Keep intermediates"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "105 20"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + variable = "$Nav::Editor::saveIntermediates"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckboxCtrl() { + internalName = "BuildSoundButton"; + text = "Play sound when done"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "150 20"; + minExtent = "8 2"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + variable = "$Nav::Editor::playSoundWhenDone"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiFlexibleArrayControl() + { + colSpacing = 2; + rowSpacing = 2; + internalName = "LinkActions"; + position = "7 21"; + extent = "190 64"; + + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "182 18"; + text = "Rebuild links"; + command = "NavEditorGui.buildLinks();"; + }; + }; + new GuiFlexibleArrayControl() + { + colSpacing = 2; + rowSpacing = 2; + internalName = "CoverActions"; + position = "7 21"; + extent = "190 64"; + + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "182 18"; + text = "Create Cover"; + command = "NavEditorGui.createCoverPoints();"; + }; + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "182 18"; + text = "Delete Cover"; + command = "NavEditorGui.deleteCoverPoints();"; + }; + }; + new GuiFlexibleArrayControl() + { + colSpacing = 2; + rowSpacing = 2; + internalName = "TileActions"; + position = "7 21"; + extent = "190 64"; + + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "182 18"; + text = "Rebuild tile"; + command = "NavEditorGui.buildTile();"; + }; + }; + new GuiFlexibleArrayControl() + { + colSpacing = 2; + rowSpacing = 2; + internalName = "TestActions"; + position = "7 21"; + extent = "190 64"; + + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "180 18"; + text = "Spawn"; + command = "NavEditorGui.spawnPlayer();"; + }; + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "90 18"; + text = "Delete"; + command = "NavEditorGui.getPlayer().delete();"; + }; + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "90 18"; + text = "Find cover"; + command = "NavEditorGui.findCover();"; + }; + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "90 18"; + text = "Follow"; + command = "NavEditorGui.followObject();"; + }; + new GuiButtonCtrl() { + Profile = "GuiButtonProfile"; + buttonType = "PushButton"; + HorizSizing = "right"; + VertSizing = "bottom"; + Extent = "90 18"; + text = "Stop"; + command = "NavEditorGui.getPlayer().stop();"; + }; + }; + }; + new GuiContainer(){ + isContainer = "1"; + Profile = "inspectorStyleRolloutDarkProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "4 112"; + Extent = "202 31"; + Docking = "Top"; + Margin = "0 0 3 3"; + + new GuiTextCtrl(){ + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "5 0"; + Extent = "121 18"; + text = "Properties"; + }; + }; + + new GuiScrollCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiEditorScrollProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "4 129"; + Extent = "202 357"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + Docking = "Client"; + Margin = "-14 41 3 3"; + Padding = "0 0 0 0"; + AnchorTop = "0"; + AnchorBottom = "0"; + AnchorLeft = "0"; + AnchorRight = "0"; + willFirstRespond = "1"; + hScrollBar = "alwaysOff"; + vScrollBar = "dynamic"; + lockHorizScroll = "true"; + lockVertScroll = "false"; + constantThumbHeight = "0"; + childMargin = "0 0"; + internalName = "PropertiesBox"; + + new GuiInspector(NavInspector) { + StackingType = "Vertical"; + HorizStacking = "Left to Right"; + VertStacking = "Top to Bottom"; + Padding = "1"; + name = "NavInspector"; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiTransparentProfile"; + HorizSizing = "width"; + VertSizing = "height"; + Position = "1 1"; + Extent = "178 16"; + MinExtent = "16 16"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + dividerMargin = "5"; + }; + + new GuiFlexibleArrayControl() { + colSpacing = 2; + rowSpacing = 2; + internalName = "LinkProperties"; + position = "7 21"; + extent = "186 64"; + padding = "2 2 2 2"; + + new GuiCheckBoxCtrl() { + internalName = "LinkWalkFlag"; + class = "NavMeshLinkFlagButton"; + text = " Walk"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "This link is just ordinary flat ground."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkJumpFlag"; + class = "NavMeshLinkFlagButton"; + text = " Jump"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Does this link require a jump?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkDropFlag"; + class = "NavMeshLinkFlagButton"; + text = " Drop"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Does this link involve a significant drop?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkLedgeFlag"; + class = "NavMeshLinkFlagButton"; + text = " Ledge"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Should the character jump at the next ledge?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkClimbFlag"; + class = "NavMeshLinkFlagButton"; + text = " Climb"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Does this link involve climbing?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkTeleportFlag"; + class = "NavMeshLinkFlagButton"; + text = " Teleport"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Is this link a teleporter?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiFlexibleArrayControl() { + colSpacing = 2; + rowSpacing = 2; + internalName = "TileProperties"; + position = "7 21"; + extent = "186 64"; + padding = "2 2 2 2"; + + new GuiCheckBoxCtrl() { + text = " Display input geometry"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + variable = "$Nav::Editor::renderInput"; + }; + new GuiCheckBoxCtrl() { + text = " Display voxels"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + variable = "$Nav::Editor::renderVoxels"; + }; + }; + new GuiFlexibleArrayControl() { + colSpacing = 2; + rowSpacing = 2; + internalName = "TestProperties"; + position = "7 21"; + extent = "186 64"; + padding = "2 2 2 2"; + + new GuiTextCtrl() { + text = "Cover"; + profile = "GuiTextProfile"; + extent = "180 20"; + minExtent = "8 2"; + visible = "1"; + }; + new GuiTextEditCtrl() { + internalName = "CoverRadius"; + text = "10"; + profile = "GuiTextEditProfile"; + extent = "40 20"; + minExtent = "8 2"; + visible = "1"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Radius for cover-finding."; + }; + new GuiTextEditCtrl() { + internalName = "CoverPosition"; + text = "LocalClientConnection.getControlObject().getPosition();"; + profile = "GuiTextEditProfile"; + extent = "140 20"; + minExtent = "8 2"; + visible = "1"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Position to find cover from."; + }; + new GuiTextCtrl() { + text = "Follow"; + profile = "GuiTextProfile"; + extent = "180 20"; + minExtent = "8 2"; + visible = "1"; + }; + new GuiTextEditCtrl() { + internalName = "FollowRadius"; + text = "1"; + profile = "GuiTextEditProfile"; + extent = "40 20"; + minExtent = "8 2"; + visible = "1"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Radius for following."; + }; + new GuiTextEditCtrl() { + internalName = "FollowObject"; + text = "LocalClientConnection.player"; + profile = "GuiTextEditProfile"; + extent = "140 20"; + minExtent = "8 2"; + visible = "1"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Object to follow."; + }; + new GuiTextCtrl() { + text = "Movement"; + profile = "GuiTextProfile"; + extent = "180 20"; + minExtent = "8 2"; + visible = "1"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkWalkFlag"; + class = "NavMeshTestFlagButton"; + text = " Walk"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Can this character walk on ground?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkJumpFlag"; + class = "NavMeshTestFlagButton"; + text = " Jump"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Can this character jump?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkDropFlag"; + class = "NavMeshTestFlagButton"; + text = " Drop"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Can this character drop over edges?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkLedgeFlag"; + class = "NavMeshTestFlagButton"; + text = " Ledge"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Can this character jump from ledges?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkClimbFlag"; + class = "NavMeshTestFlagButton"; + text = " Climb"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Can this character climb?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + internalName = "LinkTeleportFlag"; + class = "NavMeshTestFlagButton"; + text = " Teleport"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + extent = "159 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "0"; + tooltipProfile = "GuiToolTipProfile"; + toolTip = "Can this character teleport?"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + }; + new GuiMLTextCtrl(NavFieldInfoControl) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiInspectorFieldInfoMLTextProfile"; + HorizSizing = "width"; + VertSizing = "top"; + Position = "1 485"; + Extent = "202 42"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + lineSpacing = "2"; + allowColorChars = "0"; + maxChars = "-1"; + useURLMouseCursor = "0"; + }; + }; + +}; + +//--- OBJECT WRITE END --- diff --git a/Templates/Full/game/tools/navEditor/NavEditorSettingsTab.gui b/Templates/Full/game/tools/navEditor/NavEditorSettingsTab.gui new file mode 100644 index 000000000..8611ca3d1 --- /dev/null +++ b/Templates/Full/game/tools/navEditor/NavEditorSettingsTab.gui @@ -0,0 +1,506 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiTabPageCtrl(ENavEditorSettingsPage) { + fitBook = "1"; + text = "Navigation Editor"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 0"; + extent = "208 292"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "height"; + profile = "GuiSolidDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + + new GuiScrollCtrl() { + willFirstRespond = "1"; + hScrollBar = "alwaysOff"; + vScrollBar = "dynamic"; + lockHorizScroll = "1"; + lockVertScroll = "0"; + constantThumbHeight = "0"; + childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 0"; + extent = "208 292"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "height"; + profile = "GuiScrollProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiStackControl() { + stackingType = "Vertical"; + horizStacking = "Left to Right"; + vertStacking = "Top to Bottom"; + padding = "0"; + dynamicSize = "1"; + dynamicNonStackExtent = "0"; + dynamicPos = "0"; + changeChildSizeToFit = "1"; + changeChildPosition = "1"; + position = "1 1"; + extent = "206 124"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiRolloutCtrl() { + caption = "Test spawn"; + margin = "0 3 0 0"; + defaultHeight = "40"; + expanded = "1"; + clickCollapse = "1"; + hideHeader = "0"; + autoCollapseSiblings = "0"; + position = "0 0"; + extent = "206 62"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiRolloutProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiStackControl() { + stackingType = "Vertical"; + horizStacking = "Left to Right"; + vertStacking = "Top to Bottom"; + padding = "3"; + dynamicSize = "1"; + dynamicNonStackExtent = "0"; + dynamicPos = "0"; + changeChildSizeToFit = "1"; + changeChildPosition = "1"; + position = "0 20"; + extent = "206 39"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiControl() { + position = "0 0"; + extent = "206 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "Spawn class:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "5 1"; + extent = "70 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiPopUpMenuCtrlEx() { + maxPopupHeight = "200"; + sbUsesNAColor = "0"; + reverseTextList = "0"; + bitmapBounds = "16 16"; + hotTrackCallback = "0"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "81 0"; + extent = "121 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiPopUpMenuProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "SpawnClassOptions"; + class = "ESettingsWindowPopup"; + canSave = "1"; + canSaveDynamicFields = "1"; + editorSettingsRead = "NavEditorPlugin.readSettings();"; + editorSettingsValue = "NavEditor/SpawnClass"; + editorSettingsWrite = "NavEditorPlugin.writeSettings();"; + }; + }; + new GuiControl() { + position = "0 21"; + extent = "206 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "Datablock:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "5 1"; + extent = "70 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "DefaultPlayerData"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "81 0"; + extent = "121 18"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + class = "ESettingsWindowTextEdit"; + canSave = "1"; + canSaveDynamicFields = "1"; + editorSettingsRead = "NavEditorPlugin.readSettings();"; + editorSettingsValue = "NavEditor/SpawnDatablock"; + editorSettingsWrite = "NavEditorPlugin.writeSettings();"; + }; + }; + }; + }; + new GuiRolloutCtrl() { + caption = "Colors"; + margin = "0 3 0 0"; + defaultHeight = "40"; + expanded = "1"; + clickCollapse = "1"; + hideHeader = "0"; + autoCollapseSiblings = "0"; + position = "0 62"; + extent = "206 62"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiRolloutProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiStackControl() { + stackingType = "Vertical"; + horizStacking = "Left to Right"; + vertStacking = "Top to Bottom"; + padding = "3"; + dynamicSize = "1"; + dynamicNonStackExtent = "0"; + dynamicPos = "0"; + changeChildSizeToFit = "1"; + changeChildPosition = "1"; + position = "0 20"; + extent = "206 39"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiControl() { + position = "0 0"; + extent = "206 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + class = "ESettingsWindowColor"; + canSave = "1"; + canSaveDynamicFields = "1"; + editorSettingsRead = "NavEditorPlugin.readSettings();"; + editorSettingsValue = "NavEditor/HoverSplineColor"; + editorSettingsWrite = "NavEditorPlugin.writeSettings();"; + + new GuiTextCtrl() { + text = "Hover Spline:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 1"; + extent = "70 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "80 0"; + extent = "104 18"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "ColorEdit"; + class = "ESettingsWindowColorEdit"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GuiSwatchButtonCtrl() { + color = "0 0 0 0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "188 2"; + extent = "14 14"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "ColorButton"; + class = "ESettingsWindowColorButton"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + }; + new GuiControl() { + position = "0 21"; + extent = "206 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + class = "ESettingsWindowColor"; + canSave = "1"; + canSaveDynamicFields = "1"; + editorSettingsRead = "NavEditorPlugin.readSettings();"; + editorSettingsValue = "NavEditor/SelectedSplineColor"; + editorSettingsWrite = "NavEditorPlugin.writeSettings();"; + + new GuiTextCtrl() { + text = "Sel. Spline:"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 1"; + extent = "70 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextRightProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "80 0"; + extent = "104 18"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "ColorEdit"; + class = "ESettingsWindowColorEdit"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GuiSwatchButtonCtrl() { + color = "0 0 0 0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "188 2"; + extent = "14 14"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "ColorButton"; + class = "ESettingsWindowColorButton"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + }; + }; + }; + }; + }; +}; +//--- OBJECT WRITE END --- diff --git a/Templates/Full/game/tools/navEditor/NavEditorToolbar.gui b/Templates/Full/game/tools/navEditor/NavEditorToolbar.gui new file mode 100644 index 000000000..832324475 --- /dev/null +++ b/Templates/Full/game/tools/navEditor/NavEditorToolbar.gui @@ -0,0 +1,144 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiControl(NavEditorToolbar,EditorGuiGroup) { + position = "306 0"; + extent = "800 32"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "NavEditorToolbar"; + canSave = "1"; + canSaveDynamicFields = "1"; + enabled = "1"; + + new GuiTextCtrl() { + text = "Navigation Editor"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "6 6"; + extent = "150 20"; + minExtent = "8 8"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapCtrl() { + bitmap = "core/art/gui/images/separator-h.png"; + wrap = "0"; + position = "90 3"; + extent = "2 26"; + minExtent = "1 1"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl(NavEditorAboutBtn) { + text = "Console"; + groupNum = "7"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "100 6"; + extent = "54 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiButtonProfile"; + visible = "1"; + active = "1"; + command = "NavEditorConsoleDlg.setVisible(!NavEditorConsoleDlg.isVisible());"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Show Console"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + text = "Mesh"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "167 1"; + extent = "50 30"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + variable = "$Nav::Editor::renderMesh"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "MeshButton"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + text = "Portals"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "224 1"; + extent = "54 30"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + variable = "$Nav::Editor::renderPortals"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "PortalButton"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl() { + text = "BV tree"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "286 1"; + extent = "140 30"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + variable = "$Nav::Editor::renderBVTree"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "BVTreeButton"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; +}; +//--- OBJECT WRITE END --- diff --git a/Templates/Full/game/tools/navEditor/done.wav b/Templates/Full/game/tools/navEditor/done.wav new file mode 100644 index 0000000000000000000000000000000000000000..826250ddd7498b5afba6f79e8c98545772f965bb GIT binary patch literal 36948 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�V75N9_2LsII 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 HdUO8|rKz;W literal 0 HcmV?d00001 diff --git a/Templates/Full/game/tools/navEditor/images/nav-cover_d.png b/Templates/Full/game/tools/navEditor/images/nav-cover_d.png new file mode 100644 index 0000000000000000000000000000000000000000..b2f3a49e2076a1df4471cb4a6f8d4b242428bcbc GIT binary patch literal 986 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 D?FHa3 literal 0 HcmV?d00001 diff --git a/Templates/Full/game/tools/navEditor/images/nav-editor_d.png b/Templates/Full/game/tools/navEditor/images/nav-editor_d.png new file mode 100644 index 0000000000000000000000000000000000000000..06440d0d6e7f6f89c9ffce7b2456ad008fa73e39 GIT binary patch literal 1457 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 N002ovPDHLkV1hi!8+iZ# literal 0 HcmV?d00001 diff --git a/Templates/Full/game/tools/navEditor/images/nav-editor_n.png b/Templates/Full/game/tools/navEditor/images/nav-editor_n.png new file mode 100644 index 0000000000000000000000000000000000000000..6da61e45de94ce9efe147bfd4d973d008d46c3b6 GIT binary patch literal 1435 zcmV;M1!Ve(P)Px#24YJ`L;wH)0002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyW1 z78M{sfb0|i00kRKL_t(Y$L&^KXcSiz{_fn_opiHKCO^9gX|Ual))+158j4GdF)4Xy zA}At8Oi)lmN}5Vp1c^#4@zv*6B%vU_n1@6kd?;vxVi2h&Lbj2{U1GxSW|C!hvpd

;0=1Azc?xg439nIXG(??zu=9|S>o^ zZnxvai4&-FGg5MFn(SCk}^$6&DwSARdngj4=d*LB!*6SS%K#(`nqjdl#Z8!tHkB@ZrORQi`goDz2%i3CU!# z!0-2yHA%zaFk4ty$h~;+0)arlv|6p`=;&afPze3~{Wx~)7?zfn004@jps%kF=gytO z#KZ&+9XiD7>gq5)K5i-0QCKXNS1P0whGAfAYz)1uI1ZUihG?1wzu(W&=`=GdR0}G_wwb-_ujhq0zgw!(@&c>Z|-hwZB<<^ z7l}k7V2mLikDH33AR3LD01$~pV6j+8V`HN#%ktM=uXpHQ|EE{3Txp)1oa`4xv1W2| zvOJ&9!)CLA=XvDwd3ZdYMW@sGJEe5M>-FAyZ$QlY_{IGE{FfZZNs=TL*zNYL zD2mH=yZv5EOUth=mrHxEPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyW1 z6%sFNz*h8!@w{E(v-d_Wl;dtxHO$iW{p%Tg|6$&QZFwr&i5Zbs{(K`nKeFdZ15?W zLWM?(hCEDWzz&T8<8oN~K0ZfPdyDf&5-4r9=Sex;~L%7=}DPKJxJJz~bT} zuIsY2v^3T(7K<^_wt^tw`1qJgrNY+M7O$_b)M_gwu9A7dlm>2%oN z-)DJwncLf2DwPW7=jU|0UE1w7hG9@B6zKJOqaAsk7k$0Ij|M3Sf~Z(5M)i9A!+5{n z|I-e`Fe;TwQK?jllu`rz+}zwmBTsa4a>C)^A^CiMXd)Pf!RhHKjYfldy*~Zb`Mysg zk)Tj0j16=$nPhKokBf^7y4~({AYIql+1bIetg*?GNF>N+voxDcI-SmRpmaLT_V)Hf zZ^g1K*4Nhw!;q(^C*I%Rr_Z`c6_3YBr_;Q>z0vRY=L6c^-R0`)3fFZBf`EgAgZY5U z~O{)cqaH2vr29!jaX0KT=`0KWF+@^aIZvT8}ok4cR0000Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyW1 z6%z$tm?4Y+00RC=L_t(Y$F)|^Yg9 zd;k8uAI8SUx~kI}U}pI4ZEoH^pT5vjs9vx8mzI{UE-WlOT3%ju+WW0m%djkq0bqZB zUu3h{s{pXIwe=tn22-lM>$&;4sui?UFTN9@fsmY>oP1fWR?j+5ozPKUsdhz*U>xbu zOd`>oNhF#~1lH){J1unTluArbzm`&p7tfy$wp{nM-|yD|!217+1QA0@dF<4+8~QOG z00NdJ!{KoAz3ZC$2M1<299HdEB8EYvKuST$&Q9Qt#)+&7)E zL<$BGLy`I{tgWs6ST2{(_zWLE{QY4%7!10dJP|_>5u}u#b(f8fjvmg>&;MB{6uu4y zgKzWs{7;=Zi3kQW<0Ozyr(XsF0XG_rHhS?VQV{^e&;rNmZ{Zhef^yL2c~?N UwP{!X(f|Me07*qoM6N<$f_SKzVE_OC literal 0 HcmV?d00001 diff --git a/Templates/Full/game/tools/navEditor/images/nav-link_n.png b/Templates/Full/game/tools/navEditor/images/nav-link_n.png new file mode 100644 index 0000000000000000000000000000000000000000..05ef3d74873abba01c7c93ddf90d449179d00ad8 GIT binary patch literal 384 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a@dl*-CY>| zgW!U_%O?XxI14-?iy0WWg+Z8+Vb&Z8pdfpRr>`sf9VTf}Ap+b?*5G+&6y7HE|sDI&$oo)5edSA_v(6 zf?b+AHcGnaJrsHzC;0KeA*1RUn~l@k>i?AS)J}|dWbU4EhK~mO5wgT-B+?LVF(a%(c_Xf6S%*Fmqvq6L>GaWtXjvbX{+^jN`T%y Z#!VUOZhY-l^1$F>@O1TaS?83{1OU~_k)i+q literal 0 HcmV?d00001 diff --git a/Templates/Full/game/tools/navEditor/main.cs b/Templates/Full/game/tools/navEditor/main.cs new file mode 100644 index 000000000..b487b2700 --- /dev/null +++ b/Templates/Full/game/tools/navEditor/main.cs @@ -0,0 +1,276 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 Daniel Buckmaster +// +// 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. +//----------------------------------------------------------------------------- + +// These values should align with enum PolyFlags in walkabout/nav.h +$Nav::WalkFlag = 1 << 0; +$Nav::SwimFlag = 1 << 1; +$Nav::JumpFlag = 1 << 2; +$Nav::LedgeFlag = 1 << 3; +$Nav::DropFlag = 1 << 4; +$Nav::ClimbFlag = 1 << 5; +$Nav::TeleportFlag = 1 << 6; + +function initializeNavEditor() +{ + echo(" % - Initializing Navigation Editor"); + + // Execute all relevant scripts and GUIs. + exec("./NavEditor.cs"); + exec("./NavEditorGui.gui"); + exec("./NavEditorToolbar.gui"); + exec("./NavEditorGui.cs"); + exec("./NavEditorAboutDlg.gui"); + exec("./NavEditorConsoleDlg.gui"); + exec("./CreateNewNavMeshDlg.gui"); + + // Add ourselves to EditorGui, where all the other tools reside + NavEditorGui.setVisible(false); + NavEditorToolbar.setVisible(false); + NavEditorOptionsWindow.setVisible(false); + NavEditorTreeWindow.setVisible(false); + NavEditorConsoleDlg.setVisible(false); + + EditorGui.add(NavEditorGui); + EditorGui.add(NavEditorToolbar); + EditorGui.add(NavEditorOptionsWindow); + EditorGui.add(NavEditorTreeWindow); + EditorGui.add(NavEditorConsoleDlg); + + new ScriptObject(NavEditorPlugin) + { + superClass = "EditorPlugin"; + editorGui = NavEditorGui; + }; + + // Bind shortcuts for the nav editor. + %map = new ActionMap(); + %map.bindCmd(keyboard, "1", "ENavEditorSelectModeBtn.performClick();", ""); + %map.bindCmd(keyboard, "2", "ENavEditorLinkModeBtn.performClick();", ""); + %map.bindCmd(keyboard, "3", "ENavEditorCoverModeBtn.performClick();", ""); + %map.bindCmd(keyboard, "4", "ENavEditorTileModeBtn.performClick();", ""); + %map.bindCmd(keyboard, "5", "ENavEditorTestModeBtn.performClick();", ""); + %map.bindCmd(keyboard, "c", "NavEditorConsoleBtn.performClick();", ""); + NavEditorPlugin.map = %map; + + NavEditorPlugin.initSettings(); +} + +function destroyNavEditor() +{ +} + +function NavEditorPlugin::onWorldEditorStartup(%this) +{ + // Add ourselves to the window menu. + %accel = EditorGui.addToEditorsMenu("Navigation Editor", "", NavEditorPlugin); + + // Add ourselves to the ToolsToolbar. + %tooltip = "Navigation Editor (" @ %accel @ ")"; + EditorGui.addToToolsToolbar("NavEditorPlugin", "NavEditorPalette", expandFilename("tools/navEditor/images/nav-editor"), %tooltip); + + GuiWindowCtrl::attach(NavEditorOptionsWindow, NavEditorTreeWindow); + + // Add ourselves to the Editor Settings window. + exec("./NavEditorSettingsTab.gui"); + ESettingsWindow.addTabPage(ENavEditorSettingsPage); + ENavEditorSettingsPage.init(); + + // Add items to World Editor Creator + EWCreatorWindow.beginGroup("Navigation"); + + EWCreatorWindow.registerMissionObject("NavMesh", "Navigation mesh"); + EWCreatorWindow.registerMissionObject("NavPath", "Path"); + EWCreatorWindow.registerMissionObject("CoverPoint", "Cover point"); + + EWCreatorWindow.endGroup(); +} + +function ENavEditorSettingsPage::init(%this) +{ + // Initialises the settings controls in the settings dialog box. + %this-->SpawnClassOptions.clear(); + %this-->SpawnClassOptions.add("AIPlayer"); + %this-->SpawnClassOptions.setFirstSelected(); +} + +function NavEditorPlugin::onActivated(%this) +{ + %this.readSettings(); + + // Set a global variable so everyone knows we're editing! + $Nav::EditorOpen = true; + + // Start off in Select mode. + ToolsPaletteArray->NavEditorSelectMode.performClick(); + EditorGui.bringToFront(NavEditorGui); + + NavEditorGui.setVisible(true); + NavEditorGui.makeFirstResponder(true); + NavEditorToolbar.setVisible(true); + + NavEditorOptionsWindow.setVisible(true); + NavEditorTreeWindow.setVisible(true); + + // Inspect the ServerNavMeshSet, which contains all the NavMesh objects + // in the mission. + if(!isObject(ServerNavMeshSet)) + new SimSet(ServerNavMeshSet); + if(ServerNavMeshSet.getCount() == 0) + MessageBoxYesNo("No NavMesh", "There is no NavMesh in this level. Would you like to create one?" SPC + "If not, please use the World Editor to create a new NavMesh.", + "Canvas.pushDialog(CreateNewNavMeshDlg);"); + NavTreeView.open(ServerNavMeshSet, true); + + // Push our keybindings to the top. (See initializeNavEditor for where this + // map was created.) + %this.map.push(); + + // Store this on a dynamic field + // in order to restore whatever setting + // the user had before. + %this.prevGizmoAlignment = GlobalGizmoProfile.alignment; + + // Always use Object alignment. + GlobalGizmoProfile.alignment = "Object"; + + // Set the status bar here until all tool have been hooked up + EditorGuiStatusBar.setInfo("Navigation editor."); + EditorGuiStatusBar.setSelection(""); + + // Allow the Gui to setup. + NavEditorGui.onEditorActivated(); + + Parent::onActivated(%this); +} + +function NavEditorPlugin::onDeactivated(%this) +{ + %this.writeSettings(); + + $Nav::EditorOpen = false; + + NavEditorGui.setVisible(false); + NavEditorToolbar.setVisible(false); + NavEditorOptionsWindow.setVisible(false); + NavEditorTreeWindow.setVisible(false); + %this.map.pop(); + + // Restore the previous Gizmo alignment settings. + GlobalGizmoProfile.alignment = %this.prevGizmoAlignment; + + // Allow the Gui to cleanup. + NavEditorGui.onEditorDeactivated(); + + Parent::onDeactivated(%this); +} + +function NavEditorPlugin::onEditMenuSelect(%this, %editMenu) +{ + %hasSelection = false; +} + +function NavEditorPlugin::handleDelete(%this) +{ + // Event happens when the user hits 'delete'. + NavEditorGui.deleteSelected(); +} + +function NavEditorPlugin::handleEscape(%this) +{ + return NavEditorGui.onEscapePressed(); +} + +function NavEditorPlugin::isDirty(%this) +{ + return NavEditorGui.isDirty; +} + +function NavEditorPlugin::onSaveMission(%this, %missionFile) +{ + if(NavEditorGui.isDirty) + { + MissionGroup.save(%missionFile); + NavEditorGui.isDirty = false; + } +} + +//----------------------------------------------------------------------------- +// Settings +//----------------------------------------------------------------------------- + +function NavEditorPlugin::initSettings(%this) +{ + EditorSettings.beginGroup("NavEditor", true); + + EditorSettings.setDefaultValue("SpawnClass", "AIPlayer"); + EditorSettings.setDefaultValue("SpawnDatablock", "DefaultPlayerData"); + + EditorSettings.endGroup(); +} + +function NavEditorPlugin::readSettings(%this) +{ + EditorSettings.beginGroup("NavEditor", true); + + NavEditorGui.spawnClass = EditorSettings.value("SpawnClass"); + NavEditorGui.spawnDatablock = EditorSettings.value("SpawnDatablock"); + + EditorSettings.endGroup(); +} + +function NavEditorPlugin::writeSettings(%this) +{ + EditorSettings.beginGroup("NavEditor", true); + + EditorSettings.setValue("SpawnClass", NavEditorGui.spawnClass); + EditorSettings.setValue("SpawnDatablock", NavEditorGui.spawnDatablock); + + EditorSettings.endGroup(); +} + +function ESettingsWindowPopup::onWake(%this) +{ + %this.setSelected(%this.findText(EditorSettings.value(%this.editorSettingsValue))); +} + +function ESettingsWindowPopup::onSelect(%this) +{ + EditorSettings.setValue(%this.editorSettingsValue, %this.getText()); + eval(%this.editorSettingsRead); +} + +//----------------------------------------------------------------------------- +// Demo +//----------------------------------------------------------------------------- + +function OnWalkaboutDemoLimit() +{ + MessageBoxOK("Walkabout demo", + "This demo only allows two NavMeshes to be created. Sorry!"); +} + +function OnWalkaboutDemoSave() +{ + MessageBoxOK("Walkabout demo", + "This demo doesn't allow you to save NavMeshes. Sorry!" SPC + "The rest of your mission will still be saved."); +} diff --git a/Templates/Full/game/tools/navEditor/navEditor.cs b/Templates/Full/game/tools/navEditor/navEditor.cs new file mode 100644 index 000000000..21ea09064 --- /dev/null +++ b/Templates/Full/game/tools/navEditor/navEditor.cs @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 Daniel Buckmaster +// +// 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. +//----------------------------------------------------------------------------- + +singleton GuiControlProfile(NavEditorProfile) +{ + canKeyFocus = true; + opaque = true; + fillColor = "192 192 192 192"; + category = "Editor"; +}; + +singleton GuiControlProfile(GuiSimpleBorderProfile) +{ + opaque = false; + border = 1; + category = "Editor"; +}; + diff --git a/Templates/Full/game/tools/navEditor/navEditorGui.cs b/Templates/Full/game/tools/navEditor/navEditorGui.cs new file mode 100644 index 000000000..4e76abbb2 --- /dev/null +++ b/Templates/Full/game/tools/navEditor/navEditorGui.cs @@ -0,0 +1,351 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 Daniel Buckmaster +// +// 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. +//----------------------------------------------------------------------------- + +$Nav::EditorOpen = false; +$Nav::Editor::renderMesh = true; +$Nav::Editor::renderPortals = false; +$Nav::Editor::renderBVTree = false; +$Nav::Editor::backgroundBuild = true; +$Nav::Editor::saveIntermediates = false; +$Nav::Editor::playSoundWhenDone = false; + +function NavEditorGui::onEditorActivated(%this) +{ + if(%this.selectedObject) + %this.selectObject(%this.selectedObject); + %this.prepSelectionMode(); +} + +function NavEditorGui::onEditorDeactivated(%this) +{ + if(%this.getMesh()) + %this.deselect(); +} + +function NavEditorGui::onModeSet(%this, %mode) +{ + // Callback when the nav editor changes mode. Set the appropriate dynamic + // GUI contents in the properties/actions boxes. + NavInspector.setVisible(false); + + %actions = NavEditorOptionsWindow->ActionsBox; + %actions->SelectActions.setVisible(false); + %actions->LinkActions.setVisible(false); + %actions->CoverActions.setVisible(false); + %actions->TileActions.setVisible(false); + %actions->TestActions.setVisible(false); + + %properties = NavEditorOptionsWindow->PropertiesBox; + %properties->LinkProperties.setVisible(false); + %properties->TileProperties.setVisible(false); + %properties->TestProperties.setVisible(false); + + switch$(%mode) + { + case "SelectMode": + NavInspector.setVisible(true); + %actions->SelectActions.setVisible(true); + case "LinkMode": + %actions->LinkActions.setVisible(true); + %properties->LinkProperties.setVisible(true); + case "CoverMode": + // + %actions->CoverActions.setVisible(true); + case "TileMode": + %actions->TileActions.setVisible(true); + %properties->TileProperties.setVisible(true); + case "TestMode": + %actions->TestActions.setVisible(true); + %properties->TestProperties.setVisible(true); + } +} + +function NavEditorGui::paletteSync(%this, %mode) +{ + // Synchronise the palette (small buttons on the left) with the actual mode + // the nav editor is in. + %evalShortcut = "ToolsPaletteArray-->" @ %mode @ ".setStateOn(1);"; + eval(%evalShortcut); +} + +function NavEditorGui::onEscapePressed(%this) +{ + return false; +} + +function NavEditorGui::selectObject(%this, %obj) +{ + NavTreeView.clearSelection(); + if(isObject(%obj)) + NavTreeView.selectItem(%obj); + %this.onObjectSelected(%obj); +} + +function NavEditorGui::onObjectSelected(%this, %obj) +{ + if(isObject(%this.selectedObject)) + %this.deselect(); + %this.selectedObject = %obj; + if(isObject(%obj)) + { + %this.selectMesh(%obj); + NavInspector.inspect(%obj); + } +} + +function NavEditorGui::deleteMesh(%this) +{ + if(isObject(%this.selectedObject)) + { + %this.selectedObject.delete(); + %this.selectObject(-1); + } +} + +function NavEditorGui::deleteSelected(%this) +{ + switch$(%this.getMode()) + { + case "SelectMode": + // Try to delete the selected NavMesh. + if(isObject(NavEditorGui.selectedObject)) + MessageBoxYesNo("Warning", + "Are you sure you want to delete" SPC NavEditorGui.selectedObject.getName(), + "NavEditorGui.deleteMesh();"); + case "TestMode": + %this.getPlayer().delete(); + %this.onPlayerDeselected(); + case "LinkMode": + %this.deleteLink(); + %this.isDirty = true; + } +} + +function NavEditorGui::buildSelectedMeshes(%this) +{ + if(isObject(%this.getMesh())) + { + %this.getMesh().build($Nav::Editor::backgroundBuild, $Nav::Editor::saveIntermediates); + %this.isDirty = true; + } +} + +function NavEditorGui::buildLinks(%this) +{ + if(isObject(%this.getMesh())) + { + %this.getMesh().buildLinks(); + %this.isDirty = true; + } +} + +function updateLinkData(%control, %flags) +{ + %control->LinkWalkFlag.setActive(true); + %control->LinkJumpFlag.setActive(true); + %control->LinkDropFlag.setActive(true); + %control->LinkLedgeFlag.setActive(true); + %control->LinkClimbFlag.setActive(true); + %control->LinkTeleportFlag.setActive(true); + + %control->LinkWalkFlag.setStateOn(%flags & $Nav::WalkFlag); + %control->LinkJumpFlag.setStateOn(%flags & $Nav::JumpFlag); + %control->LinkDropFlag.setStateOn(%flags & $Nav::DropFlag); + %control->LinkLedgeFlag.setStateOn(%flags & $Nav::LedgeFlag); + %control->LinkClimbFlag.setStateOn(%flags & $Nav::ClimbFlag); + %control->LinkTeleportFlag.setStateOn(%flags & $Nav::TeleportFlag); +} + +function getLinkFlags(%control) +{ + return (%control->LinkWalkFlag.isStateOn() ? $Nav::WalkFlag : 0) | + (%control->LinkJumpFlag.isStateOn() ? $Nav::JumpFlag : 0) | + (%control->LinkDropFlag.isStateOn() ? $Nav::DropFlag : 0) | + (%control->LinkLedgeFlag.isStateOn() ? $Nav::LedgeFlag : 0) | + (%control->LinkClimbFlag.isStateOn() ? $Nav::ClimbFlag : 0) | + (%control->LinkTeleportFlag.isStateOn() ? $Nav::TeleportFlag : 0); +} + +function disableLinkData(%control) +{ + %control->LinkWalkFlag.setActive(false); + %control->LinkJumpFlag.setActive(false); + %control->LinkDropFlag.setActive(false); + %control->LinkLedgeFlag.setActive(false); + %control->LinkClimbFlag.setActive(false); + %control->LinkTeleportFlag.setActive(false); +} + +function NavEditorGui::onLinkSelected(%this, %flags) +{ + updateLinkData(NavEditorOptionsWindow-->LinkProperties, %flags); +} + +function NavEditorGui::onPlayerSelected(%this, %flags) +{ + updateLinkData(NavEditorOptionsWindow-->TestProperties, %flags); +} + +function NavEditorGui::updateLinkFlags(%this) +{ + if(isObject(%this.getMesh())) + { + %properties = NavEditorOptionsWindow-->LinkProperties; + %this.setLinkFlags(getLinkFlags(%properties)); + %this.isDirty = true; + } +} + +function NavEditorGui::updateTestFlags(%this) +{ + if(isObject(%this.getPlayer())) + { + %properties = NavEditorOptionsWindow-->TestProperties; + %player = %this.getPlayer(); + + %player.allowWwalk = %properties->LinkWalkFlag.isStateOn(); + %player.allowJump = %properties->LinkJumpFlag.isStateOn(); + %player.allowDrop = %properties->LinkDropFlag.isStateOn(); + %player.allowLedge = %properties->LinkLedgeFlag.isStateOn(); + %player.allowClimb = %properties->LinkClimbFlag.isStateOn(); + %player.allowTeleport = %properties->LinkTeleportFlag.isStateOn(); + + %this.isDirty = true; + } +} + +function NavEditorGui::onLinkDeselected(%this) +{ + disableLinkData(NavEditorOptionsWindow-->LinkProperties); +} + +function NavEditorGui::onPlayerDeselected(%this) +{ + disableLinkData(NavEditorOptionsWindow-->TestProperties); +} + +function NavEditorGui::createCoverPoints(%this) +{ + if(isObject(%this.getMesh())) + { + %this.getMesh().createCoverPoints(); + %this.isDirty = true; + } +} + +function NavEditorGui::deleteCoverPoints(%this) +{ + if(isObject(%this.getMesh())) + { + %this.getMesh().deleteCoverPoints(); + %this.isDirty = true; + } +} + +function NavEditorGui::findCover(%this) +{ + if(%this.getMode() $= "TestMode" && isObject(%this.getPlayer())) + { + %pos = LocalClientConnection.getControlObject().getPosition(); + %text = NavEditorOptionsWindow-->TestProperties->CoverPosition.getText(); + if(%text !$= "") + %pos = eval(%text); + %this.getPlayer().findCover(%pos, NavEditorOptionsWindow-->TestProperties->CoverRadius.getText()); + } +} + +function NavEditorGui::followObject(%this) +{ + if(%this.getMode() $= "TestMode" && isObject(%this.getPlayer())) + { + %obj = LocalClientConnection.player; + %text = NavEditorOptionsWindow-->TestProperties->FollowObject.getText(); + if(%text !$= "") + { + eval("%obj = " @ %text); + if(!isObject(%obj)) + MessageBoxOk("Error", "Cannot find object" SPC %text); + } + if(isObject(%obj)) + %this.getPlayer().followObject(%obj, NavEditorOptionsWindow-->TestProperties->FollowRadius.getText()); + } +} + +function NavInspector::inspect(%this, %obj) +{ + %name = ""; + if(isObject(%obj)) + %name = %obj.getName(); + else + NavFieldInfoControl.setText(""); + + Parent::inspect(%this, %obj); +} + +function NavInspector::onInspectorFieldModified(%this, %object, %fieldName, %arrayIndex, %oldValue, %newValue) +{ + // Same work to do as for the regular WorldEditor Inspector. + Inspector::onInspectorFieldModified(%this, %object, %fieldName, %arrayIndex, %oldValue, %newValue); +} + +function NavInspector::onFieldSelected(%this, %fieldName, %fieldTypeStr, %fieldDoc) +{ + NavFieldInfoControl.setText("" @ %fieldName @ " (" @ %fieldTypeStr @ ") " NL "" @ %fieldDoc); +} + +function NavTreeView::onInspect(%this, %obj) +{ + NavInspector.inspect(%obj); +} + +function NavTreeView::onSelect(%this, %obj) +{ + NavInspector.inspect(%obj); + NavEditorGui.onObjectSelected(%obj); +} + +function NavEditorGui::prepSelectionMode(%this) +{ + %this.setMode("SelectMode"); + ToolsPaletteArray-->NavEditorSelectMode.setStateOn(1); +} + +//----------------------------------------------------------------------------- + +function ENavEditorPaletteButton::onClick(%this) +{ + // When clicking on a pelette button, add its description to the bottom of + // the editor window. + EditorGuiStatusBar.setInfo(%this.DetailedDesc); +} + +//----------------------------------------------------------------------------- + +function NavMeshLinkFlagButton::onClick(%this) +{ + NavEditorGui.updateLinkFlags(); +} + +function NavMeshTestFlagButton::onClick(%this) +{ + NavEditorGui.updateTestFlags(); +} diff --git a/Templates/Full/game/tools/worldEditor/gui/ToolsPaletteGroups/NavEditorPalette.ed.gui b/Templates/Full/game/tools/worldEditor/gui/ToolsPaletteGroups/NavEditorPalette.ed.gui new file mode 100644 index 000000000..506c525b2 --- /dev/null +++ b/Templates/Full/game/tools/worldEditor/gui/ToolsPaletteGroups/NavEditorPalette.ed.gui @@ -0,0 +1,130 @@ +%paletteId = new GuiControl(NavEditorPalette,EditorGuiGroup) { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiDefaultProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "1024 768"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + + new GuiBitmapButtonCtrl(ENavEditorSelectModeBtn) { + canSaveDynamicFields = "1"; + class = ENavEditorPaletteButton; + internalName = "NavEditorSelectMode"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "NavEditorGui.prepSelectionMode();"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "View NavMesh (1)."; + DetailedDesc = ""; + hovertime = "1000"; + bitmap = "tools/gui/images/menubar/visibility-toggle"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; + new GuiBitmapButtonCtrl(ENavEditorLinkModeBtn) { + canSaveDynamicFields = "1"; + class = ENavEditorPaletteButton; + internalName = "NavEditorLinkMode"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "NavEditorGui.setMode(\"LinkMode\");"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "Create off-mesh links (2)."; + DetailedDesc = "Click to select/add. Shift-click to add multiple end points."; + hovertime = "1000"; + bitmap = "tools/navEditor/images/nav-link"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; + new GuiBitmapButtonCtrl(ENavEditorCoverModeBtn) { + canSaveDynamicFields = "1"; + class = ENavEditorPaletteButton; + internalName = "NavEditorCoverMode"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "NavEditorGui.setMode(\"CoverMode\");"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "Edit cover (3)."; + DetailedDesc = ""; + hovertime = "1000"; + bitmap = "tools/navEditor/images/nav-cover"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; + new GuiBitmapButtonCtrl(ENavEditorTileModeBtn) { + canSaveDynamicFields = "1"; + class = ENavEditorPaletteButton; + internalName = "NavEditorTileMode"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "NavEditorGui.setMode(\"TileMode\");"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "View tiles (4)."; + DetailedDesc = "Click to select."; + hovertime = "1000"; + bitmap = "tools/gui/images/menubar/select-bounds"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; + new GuiBitmapButtonCtrl(ENavEditorTestModeBtn) { + canSaveDynamicFields = "1"; + class = ENavEditorPaletteButton; + internalName = "NavEditorTestMode"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiButtonProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "25 19"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "NavEditorGui.setMode(\"TestMode\");"; + tooltipprofile = "GuiToolTipProfile"; + ToolTip = "Test pathfinding (5)."; + DetailedDesc = "Click to select/move character, CTRL-click to spawn, SHIFT-click to deselect."; + hovertime = "1000"; + bitmap = "tools/worldEditor/images/toolbar/3rd-person-camera"; + buttonType = "RadioButton"; + useMouseEvents = "0"; + }; +}; \ No newline at end of file diff --git a/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs index 75d41eb53..3419a5bc0 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs @@ -83,8 +83,6 @@ function EWCreatorWindow::init( %this ) %this.registerMissionObject( "SpawnSphere", "Observer Spawn Sphere", "ObserverDropPoint" ); %this.registerMissionObject( "SFXSpace", "Sound Space" ); %this.registerMissionObject( "OcclusionVolume", "Occlusion Volume" ); - %this.registerMissionObject("NavMesh", "Navigation mesh"); - %this.registerMissionObject("NavPath", "Path"); %this.endGroup(); @@ -787,4 +785,4 @@ function genericCreateObject( %class ) // In case the caller wants it. return %obj; -} \ No newline at end of file +}