Replicated the weapon flying tick setup using resources
This commit is contained in:
@@ -0,0 +1,328 @@
|
||||
// Copyright © Gamesmiths Guild.
|
||||
|
||||
#if TOOLS
|
||||
using Gamesmiths.Forge.Godot.Resources.Statescript;
|
||||
using Godot;
|
||||
|
||||
namespace Gamesmiths.Forge.Godot.Editor.Statescript;
|
||||
|
||||
public partial class StatescriptGraphEditorDock
|
||||
{
|
||||
private void OnFileMenuIdPressed(long id)
|
||||
{
|
||||
switch ((int)id)
|
||||
{
|
||||
case 0:
|
||||
ShowNewStatescriptDialog();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ShowLoadStatescriptDialog();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
OnSavePressed();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ShowSaveAsDialog();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
CloseCurrentTab();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowNewStatescriptDialog()
|
||||
{
|
||||
_newStatescriptDialog?.QueueFree();
|
||||
|
||||
_newStatescriptDialog = new AcceptDialog
|
||||
{
|
||||
Title = "Create Statescript",
|
||||
Size = new Vector2I(400, 140),
|
||||
Exclusive = true,
|
||||
};
|
||||
|
||||
var vBox = new VBoxContainer { SizeFlagsHorizontal = SizeFlags.ExpandFill };
|
||||
var pathRow = new HBoxContainer { SizeFlagsHorizontal = SizeFlags.ExpandFill };
|
||||
vBox.AddChild(pathRow);
|
||||
|
||||
pathRow.AddChild(new Label { Text = "Path:", CustomMinimumSize = new Vector2(50, 0) });
|
||||
|
||||
_newStatescriptPathEdit = new LineEdit
|
||||
{
|
||||
Text = "res://new_statescript.tres",
|
||||
SizeFlagsHorizontal = SizeFlags.ExpandFill,
|
||||
};
|
||||
|
||||
pathRow.AddChild(_newStatescriptPathEdit);
|
||||
|
||||
_newStatescriptDialog.AddChild(vBox);
|
||||
_newStatescriptDialog.Confirmed += OnNewStatescriptConfirmed;
|
||||
|
||||
AddChild(_newStatescriptDialog);
|
||||
_newStatescriptDialog.PopupCentered();
|
||||
}
|
||||
|
||||
private void OnNewStatescriptConfirmed()
|
||||
{
|
||||
if (_newStatescriptPathEdit is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var path = _newStatescriptPathEdit.Text.Trim();
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!path.EndsWith(".tres", System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
path += ".tres";
|
||||
}
|
||||
|
||||
var graph = new StatescriptGraph();
|
||||
graph.EnsureEntryNode();
|
||||
|
||||
graph.StatescriptName = path.GetFile().GetBaseName();
|
||||
|
||||
ResourceSaver.Save(graph, path);
|
||||
EditorInterface.Singleton.GetResourceFilesystem().Scan();
|
||||
|
||||
graph = ResourceLoader.Load<StatescriptGraph>(path);
|
||||
if (graph is not null)
|
||||
{
|
||||
OpenGraph(graph);
|
||||
}
|
||||
|
||||
_newStatescriptDialog?.QueueFree();
|
||||
_newStatescriptDialog = null;
|
||||
}
|
||||
|
||||
private void ShowLoadStatescriptDialog()
|
||||
{
|
||||
var dialog = new EditorFileDialog
|
||||
{
|
||||
FileMode = FileDialog.FileModeEnum.OpenFile,
|
||||
Title = "Load Statescript File",
|
||||
Access = FileDialog.AccessEnum.Resources,
|
||||
};
|
||||
|
||||
dialog.AddFilter("*.tres;StatescriptGraph");
|
||||
dialog.FileSelected += path =>
|
||||
{
|
||||
Resource? graph = ResourceLoader.Load(path);
|
||||
if (graph is StatescriptGraph statescriptGraph)
|
||||
{
|
||||
OpenGraph(statescriptGraph);
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.PushWarning($"Failed to load StatescriptGraph from: {path}");
|
||||
}
|
||||
|
||||
dialog.QueueFree();
|
||||
};
|
||||
|
||||
dialog.Canceled += dialog.QueueFree;
|
||||
|
||||
AddChild(dialog);
|
||||
dialog.PopupCentered(new Vector2I(700, 500));
|
||||
}
|
||||
|
||||
private void ShowSaveAsDialog()
|
||||
{
|
||||
StatescriptGraph? graph = CurrentGraph;
|
||||
if (graph is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var dialog = new EditorFileDialog
|
||||
{
|
||||
FileMode = FileDialog.FileModeEnum.SaveFile,
|
||||
Title = "Save Statescript As",
|
||||
Access = FileDialog.AccessEnum.Resources,
|
||||
};
|
||||
|
||||
dialog.AddFilter("*.tres", "Godot Resource");
|
||||
dialog.FileSelected += path =>
|
||||
{
|
||||
if (_graphEdit is not null)
|
||||
{
|
||||
graph.ScrollOffset = _graphEdit.ScrollOffset;
|
||||
graph.Zoom = _graphEdit.Zoom;
|
||||
SyncVisualNodePositionsToGraph();
|
||||
SyncConnectionsToCurrentGraph();
|
||||
}
|
||||
|
||||
ResourceSaver.Save(graph, path);
|
||||
EditorInterface.Singleton.GetResourceFilesystem().Scan();
|
||||
GD.Print($"Statescript graph saved as: {path}");
|
||||
|
||||
StatescriptGraph? savedGraph = ResourceLoader.Load<StatescriptGraph>(path);
|
||||
if (savedGraph is not null)
|
||||
{
|
||||
OpenGraph(savedGraph);
|
||||
}
|
||||
|
||||
dialog.QueueFree();
|
||||
};
|
||||
|
||||
dialog.Canceled += dialog.QueueFree;
|
||||
|
||||
AddChild(dialog);
|
||||
dialog.PopupCentered(new Vector2I(700, 500));
|
||||
}
|
||||
|
||||
private void OnSavePressed()
|
||||
{
|
||||
StatescriptGraph? graph = CurrentGraph;
|
||||
if (graph is null || _graphEdit is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
graph.ScrollOffset = _graphEdit.ScrollOffset;
|
||||
graph.Zoom = _graphEdit.Zoom;
|
||||
SyncVisualNodePositionsToGraph();
|
||||
SyncConnectionsToCurrentGraph();
|
||||
|
||||
if (string.IsNullOrEmpty(graph.ResourcePath))
|
||||
{
|
||||
ShowSaveAsDialog();
|
||||
return;
|
||||
}
|
||||
|
||||
SaveGraphResource(graph);
|
||||
GD.Print($"Statescript graph saved: {graph.ResourcePath}");
|
||||
}
|
||||
|
||||
private void OnGraphEditPopupRequest(Vector2 atPosition)
|
||||
{
|
||||
if (CurrentGraph is null || _graphEdit is null || _addNodeDialog is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClearPendingConnection();
|
||||
|
||||
Vector2 graphPosition = (_graphEdit.ScrollOffset + atPosition) / _graphEdit.Zoom;
|
||||
var screenPosition = (Vector2I)(_graphEdit.GetScreenPosition() + atPosition);
|
||||
|
||||
_addNodeDialog.ShowAtPosition(graphPosition, screenPosition);
|
||||
}
|
||||
|
||||
private void OnConnectionToEmpty(StringName fromNode, long fromPort, Vector2 releasePosition)
|
||||
{
|
||||
if (CurrentGraph is null || _graphEdit is null || _addNodeDialog is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_pendingConnectionNode = fromNode;
|
||||
_pendingConnectionPort = (int)fromPort;
|
||||
_pendingConnectionIsOutput = true;
|
||||
|
||||
Vector2 graphPosition = (_graphEdit.ScrollOffset + releasePosition) / _graphEdit.Zoom;
|
||||
var screenPosition = (Vector2I)(_graphEdit.GetScreenPosition() + releasePosition);
|
||||
|
||||
_addNodeDialog.ShowAtPosition(graphPosition, screenPosition);
|
||||
}
|
||||
|
||||
private void OnConnectionFromEmpty(StringName toNode, long toPort, Vector2 releasePosition)
|
||||
{
|
||||
if (CurrentGraph is null || _graphEdit is null || _addNodeDialog is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_pendingConnectionNode = toNode;
|
||||
_pendingConnectionPort = (int)toPort;
|
||||
_pendingConnectionIsOutput = false;
|
||||
|
||||
Vector2 graphPosition = (_graphEdit.ScrollOffset + releasePosition) / _graphEdit.Zoom;
|
||||
var screenPosition = (Vector2I)(_graphEdit.GetScreenPosition() + releasePosition);
|
||||
|
||||
_addNodeDialog.ShowAtPosition(graphPosition, screenPosition);
|
||||
}
|
||||
|
||||
private void OnDialogNodeCreationRequested(
|
||||
StatescriptNodeDiscovery.NodeTypeInfo? typeInfo,
|
||||
StatescriptNodeType nodeType,
|
||||
Vector2 position)
|
||||
{
|
||||
string newNodeId;
|
||||
|
||||
if (typeInfo is not null)
|
||||
{
|
||||
newNodeId = AddNodeAtPosition(nodeType, typeInfo.DisplayName, typeInfo.RuntimeTypeName, position);
|
||||
}
|
||||
else
|
||||
{
|
||||
newNodeId = AddNodeAtPosition(StatescriptNodeType.Exit, "Exit", string.Empty, position);
|
||||
}
|
||||
|
||||
if (_pendingConnectionNode is not null && _graphEdit is not null)
|
||||
{
|
||||
if (_pendingConnectionIsOutput)
|
||||
{
|
||||
var inputPort = FindFirstEnabledInputPort(newNodeId);
|
||||
if (inputPort >= 0)
|
||||
{
|
||||
OnConnectionRequest(
|
||||
_pendingConnectionNode,
|
||||
_pendingConnectionPort,
|
||||
newNodeId,
|
||||
inputPort);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var outputPort = FindFirstEnabledOutputPort(newNodeId);
|
||||
if (outputPort >= 0)
|
||||
{
|
||||
OnConnectionRequest(
|
||||
newNodeId,
|
||||
outputPort,
|
||||
_pendingConnectionNode,
|
||||
_pendingConnectionPort);
|
||||
}
|
||||
}
|
||||
|
||||
ClearPendingConnection();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDialogCanceled()
|
||||
{
|
||||
ClearPendingConnection();
|
||||
}
|
||||
|
||||
private void ClearPendingConnection()
|
||||
{
|
||||
_pendingConnectionNode = null;
|
||||
_pendingConnectionPort = 0;
|
||||
_pendingConnectionIsOutput = false;
|
||||
}
|
||||
|
||||
private void OnAddNodeButtonPressed()
|
||||
{
|
||||
if (CurrentGraph is null || _graphEdit is null || _addNodeDialog is null || _addNodeButton is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClearPendingConnection();
|
||||
|
||||
var screenPosition = (Vector2I)(_addNodeButton.GetScreenPosition() + new Vector2(0, _addNodeButton.Size.Y));
|
||||
|
||||
Vector2 centerPosition = (_graphEdit.ScrollOffset + (_graphEdit.Size / 2)) / _graphEdit.Zoom;
|
||||
|
||||
_addNodeDialog.ShowAtPosition(centerPosition, screenPosition);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user