Files
FlaxEngine/Source/Editor/Tools/Terrain/CarveTab.cs

229 lines
7.2 KiB
C#

// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.GUI.Tabs;
using FlaxEditor.Modules;
using FlaxEditor.SceneGraph.Actors;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Tools.Terrain
{
/// <summary>
/// Terrain carving tab. Supports different modes for terrain editing including: carving, painting and managing tools.
/// </summary>
/// <seealso cref="Tab" />
[HideInEditor]
public class CarveTab : Tab
{
private readonly Tabs _modes;
private readonly ContainerControl _noTerrainPanel;
private readonly Button _createTerrainButton;
/// <summary>
/// The editor instance.
/// </summary>
public readonly Editor Editor;
/// <summary>
/// The cached selected terrain. It's synchronized with <see cref="SceneEditingModule.Selection"/>.
/// </summary>
public FlaxEngine.Terrain SelectedTerrain;
/// <summary>
/// Occurs when selected terrain gets changed (to a different value).
/// </summary>
public event Action SelectedTerrainChanged;
/// <summary>
/// The sculpt tab;
/// </summary>
public SculptTab Sculpt;
/// <summary>
/// The paint tab;
/// </summary>
public PaintTab Paint;
/// <summary>
/// The edit tab;
/// </summary>
public EditTab Edit;
/// <summary>
/// Initializes a new instance of the <see cref="CarveTab"/> class.
/// </summary>
/// <param name="icon">The icon.</param>
/// <param name="editor">The editor instance.</param>
public CarveTab(SpriteHandle icon, Editor editor)
: base(string.Empty, icon)
{
Level.SceneLoaded += OnSceneLoaded;
Editor = editor;
Editor.SceneEditing.SelectionChanged += OnSelectionChanged;
Selected += OnSelected;
_modes = new Tabs
{
Orientation = Orientation.Vertical,
UseScroll = true,
Offsets = Margin.Zero,
AnchorPreset = AnchorPresets.StretchAll,
TabsSize = new Float2(50, 32),
Parent = this
};
// Init tool modes
InitSculptMode();
InitPaintMode();
InitEditMode();
_modes.SelectedTabIndex = 0;
_noTerrainPanel = new ContainerControl
{
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
BackgroundColor = Style.Current.Background,
Parent = this
};
var noTerrainLabel = new Label
{
Text = "Select terrain to edit\nor\n\n\n\n",
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
Parent = _noTerrainPanel
};
var buttonText = "Create new terrain";
_createTerrainButton = new Button
{
Text = buttonText,
AnchorPreset = AnchorPresets.MiddleCenter,
Offsets = new Margin(-60, 120, -12, 24),
Parent = _noTerrainPanel,
Enabled = false
};
var textSize = Style.Current.FontMedium.MeasureText(buttonText);
if (_createTerrainButton.Width < textSize.X)
{
_createTerrainButton.LocalX -= (textSize.X - _createTerrainButton.Width) / 2;
_createTerrainButton.Width = textSize.X + 6;
}
_createTerrainButton.Clicked += OnCreateNewTerrainClicked;
OnSelectionChanged();
}
private void OnSceneLoaded(Scene arg1, Guid arg2)
{
_createTerrainButton.Enabled = true;
Level.SceneUnloaded += OnSceneUnloaded;
Level.SceneLoaded -= OnSceneLoaded;
}
private void OnSceneUnloaded(Scene arg1, Guid arg2)
{
_createTerrainButton.Enabled = false;
Level.SceneLoaded += OnSceneLoaded;
Level.SceneUnloaded -= OnSceneUnloaded;
}
private void OnSelected(Tab tab)
{
// Auto select first terrain actor to make usage easier
if (Editor.SceneEditing.SelectionCount == 1 && Editor.SceneEditing.Selection[0] is SceneGraph.ActorNode actorNode && actorNode.Actor is FlaxEngine.Terrain)
return;
var actor = Level.FindActor<FlaxEngine.Terrain>();
if (actor)
{
Editor.SceneEditing.Select(actor);
}
}
private void OnCreateNewTerrainClicked()
{
Editor.UI.CreateTerrain();
}
private void OnSelectionChanged()
{
var terrainNode = Editor.SceneEditing.SelectionCount > 0 ? Editor.SceneEditing.Selection[0] as TerrainNode : null;
var terrain = terrainNode?.Actor as FlaxEngine.Terrain;
if (terrain != SelectedTerrain)
{
SelectedTerrain = terrain;
SelectedTerrainChanged?.Invoke();
}
_noTerrainPanel.Visible = terrain == null;
_modes.Visible = !_noTerrainPanel.Visible;
}
private void InitSculptMode()
{
var tab = _modes.AddTab(Sculpt = new SculptTab(this, Editor.Windows.EditWin.Viewport.SculptTerrainGizmo));
tab.Selected += OnTabSelected;
}
private void InitPaintMode()
{
var tab = _modes.AddTab(Paint = new PaintTab(this, Editor.Windows.EditWin.Viewport.PaintTerrainGizmo));
tab.Selected += OnTabSelected;
}
private void InitEditMode()
{
var tab = _modes.AddTab(Edit = new EditTab(this, Editor.Windows.EditWin.Viewport.EditTerrainGizmo));
tab.Selected += OnTabSelected;
}
/// <inheritdoc />
public override void OnSelected()
{
base.OnSelected();
UpdateGizmoMode();
}
private void OnTabSelected(Tab tab)
{
UpdateGizmoMode();
}
/// <summary>
/// Updates the active viewport gizmo mode based on the current mode.
/// </summary>
private void UpdateGizmoMode()
{
switch (_modes.SelectedTabIndex)
{
case 0:
Editor.Windows.EditWin.Viewport.Gizmos.SetActiveMode<SculptTerrainGizmoMode>();
break;
case 1:
Editor.Windows.EditWin.Viewport.Gizmos.SetActiveMode<PaintTerrainGizmoMode>();
break;
case 2:
Editor.Windows.EditWin.Viewport.Gizmos.SetActiveMode<EditTerrainGizmoMode>();
break;
default: throw new IndexOutOfRangeException("Invalid carve tab mode.");
}
}
/// <inheritdoc />
public override void OnDestroy()
{
if (_createTerrainButton.Enabled)
Level.SceneUnloaded -= OnSceneUnloaded;
else
Level.SceneLoaded -= OnSceneLoaded;
base.OnDestroy();
}
}
}