2024-05-17 14:08:19 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2024-05-15 13:52:07 +00:00
|
|
|
|
using System.IO;
|
2024-05-14 14:26:33 +00:00
|
|
|
|
using ColdMint.scripts.levelGraphEditor;
|
2024-05-18 15:35:12 +00:00
|
|
|
|
using ColdMint.scripts.nodeBinding;
|
2024-05-14 14:26:33 +00:00
|
|
|
|
using ColdMint.scripts.serialization;
|
|
|
|
|
using ColdMint.scripts.utils;
|
2024-05-12 10:00:47 +00:00
|
|
|
|
using Godot;
|
2024-05-14 14:26:33 +00:00
|
|
|
|
using Godot.Collections;
|
2024-05-15 13:52:07 +00:00
|
|
|
|
using FileAccess = Godot.FileAccess;
|
2024-05-12 10:00:47 +00:00
|
|
|
|
|
|
|
|
|
namespace ColdMint.scripts.loader.uiLoader;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Level graph editor</para>
|
|
|
|
|
/// <para>关卡图编辑器</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
public partial class LevelGraphEditorLoader : UiLoaderTemplate
|
|
|
|
|
{
|
2024-05-12 15:06:07 +00:00
|
|
|
|
private string? _defaultRoomName;
|
2024-05-16 14:46:03 +00:00
|
|
|
|
|
2024-06-10 13:05:18 +00:00
|
|
|
|
private readonly LevelGraphEditorBinding _nodeBinding = new();
|
2024-05-18 15:35:12 +00:00
|
|
|
|
|
2024-05-16 14:46:03 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Index of the room</para>
|
|
|
|
|
/// <para>房间的索引</para>
|
|
|
|
|
/// </summary>
|
2024-05-12 15:06:07 +00:00
|
|
|
|
private int _roomIndex = 1;
|
2024-05-16 14:46:03 +00:00
|
|
|
|
|
2024-05-27 14:10:05 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Is there a start node?</para>
|
|
|
|
|
/// <para>是否有开始节点了?</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
private bool _hasStartNode;
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
private PackedScene? _roomNodeScene;
|
|
|
|
|
|
2024-06-10 13:05:18 +00:00
|
|
|
|
private readonly List<Node> _selectedNodes = new();
|
2024-06-14 16:14:17 +00:00
|
|
|
|
private PackedScene? _mainMenu;
|
2024-05-17 14:08:19 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Displays the time to enter the suggestion</para>
|
|
|
|
|
/// <para>显示输入建议的时刻</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
private DateTime? _displaysTheSuggestedInputTime;
|
2024-05-16 14:46:03 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Offset to append when a new node is created.</para>
|
|
|
|
|
/// <para>创建新节点时追加的偏移量。</para>
|
|
|
|
|
/// </summary>
|
2024-06-10 13:05:18 +00:00
|
|
|
|
private Vector2 _positionOffset = new(100, 100);
|
2024-05-16 14:46:03 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Is the press event of an active button saved?</para>
|
|
|
|
|
/// <para>活动按钮的按下事件是否为保存?</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
private bool _saveMode;
|
|
|
|
|
|
2024-05-12 10:00:47 +00:00
|
|
|
|
|
|
|
|
|
public override void InitializeData()
|
|
|
|
|
{
|
|
|
|
|
base.InitializeData();
|
2024-06-14 16:14:17 +00:00
|
|
|
|
_mainMenu = GD.Load<PackedScene>("res://scenes/mainMenu.tscn");
|
|
|
|
|
_roomNodeScene = GD.Load<PackedScene>("res://prefab/ui/RoomNode.tscn");
|
2024-06-13 16:43:31 +00:00
|
|
|
|
_defaultRoomName = TranslationServerUtils.Translate("ui_default_room_name");
|
2024-05-15 13:52:07 +00:00
|
|
|
|
var folder = Config.GetLevelGraphExportDirectory();
|
|
|
|
|
if (!Directory.Exists(folder))
|
|
|
|
|
{
|
|
|
|
|
Directory.CreateDirectory(folder);
|
|
|
|
|
}
|
2024-05-12 10:00:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override void InitializeUi()
|
|
|
|
|
{
|
|
|
|
|
base.InitializeUi();
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.Binding(this);
|
|
|
|
|
if (_nodeBinding.OpenExportFolderButton != null)
|
2024-05-14 14:26:33 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
//If open directories are supported, a button is displayed.
|
|
|
|
|
//若支持打开目录,那么显示按钮。
|
|
|
|
|
_nodeBinding.OpenExportFolderButton.Visible = ExplorerUtils.SupportOpenDirectory();
|
2024-05-14 14:26:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.RoomTemplateTipsLabel != null)
|
2024-05-15 13:52:07 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.RoomTemplateTipsLabel.Text = string.Empty;
|
|
|
|
|
}
|
2024-05-12 10:00:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Creating room node</para>
|
|
|
|
|
/// <para>创建房间节点</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="roomNodeData"></param>
|
|
|
|
|
/// <returns></returns>
|
2024-05-16 14:46:03 +00:00
|
|
|
|
private RoomNode? CreateRoomNode(RoomNodeData roomNodeData)
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_roomNodeScene == null || _nodeBinding.GraphEdit == null)
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
2024-05-16 14:46:03 +00:00
|
|
|
|
return null;
|
2024-05-12 10:00:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-10 13:05:18 +00:00
|
|
|
|
var node = NodeUtils.InstantiatePackedScene<Node>(_roomNodeScene);
|
2024-05-12 10:00:47 +00:00
|
|
|
|
if (node == null)
|
|
|
|
|
{
|
2024-05-16 14:46:03 +00:00
|
|
|
|
return null;
|
2024-05-12 10:00:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.GraphEdit?.AddChild(node);
|
2024-05-12 10:00:47 +00:00
|
|
|
|
if (node is not RoomNode roomNode)
|
|
|
|
|
{
|
2024-05-16 14:46:03 +00:00
|
|
|
|
return null;
|
2024-05-12 10:00:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-12 15:06:07 +00:00
|
|
|
|
roomNode.RoomNodeData = roomNodeData;
|
2024-05-16 14:46:03 +00:00
|
|
|
|
roomNode.PositionOffset = _positionOffset * _roomIndex;
|
2024-05-12 15:06:07 +00:00
|
|
|
|
_roomIndex++;
|
2024-05-16 14:46:03 +00:00
|
|
|
|
return roomNode;
|
2024-05-12 10:00:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-17 14:08:19 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Displays input suggestions for room templates</para>
|
|
|
|
|
/// <para>显示房间模板的输入建议</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void DisplayInputPrompt()
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.RoomTemplateTipsLabel == null || _nodeBinding.RoomTemplateCollectionTextEdit == null)
|
2024-05-14 14:26:33 +00:00
|
|
|
|
{
|
2024-05-17 14:08:19 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
var text = _nodeBinding.RoomTemplateCollectionTextEdit.Text;
|
2024-05-17 14:08:19 +00:00
|
|
|
|
if (string.IsNullOrEmpty(text))
|
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.RoomTemplateTipsLabel.Text = string.Empty;
|
2024-05-17 14:08:19 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var lastLine = StrUtils.GetLastLine(text);
|
|
|
|
|
if (string.IsNullOrEmpty(lastLine))
|
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.RoomTemplateTipsLabel.Text = string.Empty;
|
2024-05-17 14:08:19 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Parse the last line
|
|
|
|
|
//解析最后一行
|
|
|
|
|
if (lastLine.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
if (!lastLine.StartsWith("res://"))
|
2024-05-14 14:26:33 +00:00
|
|
|
|
{
|
2024-06-13 16:43:31 +00:00
|
|
|
|
var lineError = TranslationServer.Translate("ui_line_errors_must_start_with_res");
|
2024-05-17 14:08:19 +00:00
|
|
|
|
if (lineError == null)
|
2024-05-14 14:26:33 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.RoomTemplateTipsLabel.Text = string.Format(lineError, lastLine);
|
2024-05-17 14:08:19 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2024-05-14 14:26:33 +00:00
|
|
|
|
|
2024-05-17 14:08:19 +00:00
|
|
|
|
var fileExists = FileAccess.FileExists(lastLine);
|
|
|
|
|
var dirExists = DirAccess.DirExistsAbsolute(lastLine);
|
|
|
|
|
if (!fileExists && !dirExists)
|
|
|
|
|
{
|
2024-06-13 16:43:31 +00:00
|
|
|
|
var lineError = TranslationServerUtils.Translate("ui_error_specifying_room_template_line");
|
2024-05-17 14:08:19 +00:00
|
|
|
|
if (lineError == null)
|
2024-05-14 14:26:33 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.RoomTemplateTipsLabel.Text = string.Format(lineError, lastLine);
|
2024-05-17 14:08:19 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2024-05-14 14:26:33 +00:00
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.RoomTemplateTipsLabel.Text = string.Empty;
|
2024-05-17 14:08:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-05-14 14:26:33 +00:00
|
|
|
|
|
2024-05-17 14:08:19 +00:00
|
|
|
|
public override void _Process(double delta)
|
|
|
|
|
{
|
|
|
|
|
base._Process(delta);
|
|
|
|
|
if (_displaysTheSuggestedInputTime != null && DateTime.Now > _displaysTheSuggestedInputTime)
|
|
|
|
|
{
|
|
|
|
|
//Performs the actual input field text change event.
|
|
|
|
|
//执行实际的输入框文本改变事件。
|
|
|
|
|
DisplayInputPrompt();
|
|
|
|
|
_displaysTheSuggestedInputTime = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void LoadUiActions()
|
|
|
|
|
{
|
|
|
|
|
base.LoadUiActions();
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.RoomTemplateCollectionTextEdit != null)
|
2024-05-17 14:08:19 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.RoomTemplateCollectionTextEdit.TextChanged += () =>
|
2024-05-17 14:08:19 +00:00
|
|
|
|
{
|
|
|
|
|
//Add anti-shake treatment.
|
|
|
|
|
//添加防抖处理。
|
|
|
|
|
//Higher frequency events are executed last time.
|
|
|
|
|
//频率较高的事件中,执行最后一次。
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_displaysTheSuggestedInputTime =
|
|
|
|
|
DateTime.Now.Add(TimeSpan.FromMilliseconds(Config.TextChangesBuffetingDuration));
|
2024-05-14 14:26:33 +00:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.GraphEdit != null)
|
2024-05-12 15:06:07 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.GraphEdit.NodeSelected += node => { _selectedNodes.Add(node); };
|
|
|
|
|
_nodeBinding.GraphEdit.NodeDeselected += node => { _selectedNodes.Remove(node); };
|
|
|
|
|
_nodeBinding.GraphEdit.ConnectionRequest += (fromNode, fromPort, toNode, toPort) =>
|
2024-05-12 15:06:07 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.GraphEdit.ConnectNode(fromNode, (int)fromPort, toNode, (int)toPort);
|
2024-05-12 15:06:07 +00:00
|
|
|
|
};
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.GraphEdit.DisconnectionRequest += (fromNode, fromPort, toNode, toPort) =>
|
2024-05-12 15:06:07 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.GraphEdit.DisconnectNode(fromNode, (int)fromPort, toNode, (int)toPort);
|
2024-05-12 15:06:07 +00:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.OpenExportFolderButton != null)
|
2024-05-15 13:52:07 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.OpenExportFolderButton.Pressed += () =>
|
2024-05-15 13:52:07 +00:00
|
|
|
|
{
|
|
|
|
|
ExplorerUtils.OpenFolder(Config.GetLevelGraphExportDirectory());
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.DeleteSelectedNodeButton != null)
|
2024-05-17 14:08:19 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.DeleteSelectedNodeButton.Pressed += () =>
|
2024-05-17 14:08:19 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.GraphEdit == null)
|
2024-05-17 14:08:19 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_selectedNodes.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var nodes = _selectedNodes.ToArray();
|
2024-05-27 14:10:05 +00:00
|
|
|
|
_roomIndex -= _selectedNodes.Count;
|
2024-05-17 14:08:19 +00:00
|
|
|
|
foreach (var node in nodes)
|
|
|
|
|
{
|
|
|
|
|
if (node is not RoomNode roomNode)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 14:10:05 +00:00
|
|
|
|
if (roomNode.RoomNodeData != null && roomNode.RoomNodeData.HasTag(Config.RoomDataTag.StartingRoom))
|
|
|
|
|
{
|
|
|
|
|
//The node with the start room label was deleted.
|
|
|
|
|
//删除了带有起始房间标签的节点。
|
|
|
|
|
_hasStartNode = false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.GraphEdit.RemoveChild(node);
|
2024-05-17 14:08:19 +00:00
|
|
|
|
roomNode.QueueFree();
|
|
|
|
|
_selectedNodes.Remove(node);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.ShowCreateRoomPanelButton != null)
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.ShowCreateRoomPanelButton.Pressed += () =>
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.GraphEdit != null)
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
2024-06-08 15:59:24 +00:00
|
|
|
|
_nodeBinding.GraphEdit.Hide();
|
2024-05-12 10:00:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.CreateOrEditorPanel != null)
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
2024-06-08 15:59:24 +00:00
|
|
|
|
_nodeBinding.CreateOrEditorPanel.Show();
|
2024-05-12 10:00:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.RoomNameLineEdit != null && _defaultRoomName != null)
|
2024-05-12 15:06:07 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.RoomNameLineEdit.Text = string.Format(_defaultRoomName, _roomIndex);
|
2024-05-12 15:06:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 14:10:05 +00:00
|
|
|
|
if (_nodeBinding.RoomDescriptionLineEdit != null)
|
|
|
|
|
{
|
|
|
|
|
_nodeBinding.RoomDescriptionLineEdit.Text = string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_nodeBinding.TagLineEdit != null)
|
|
|
|
|
{
|
|
|
|
|
if (_hasStartNode)
|
|
|
|
|
{
|
|
|
|
|
_nodeBinding.TagLineEdit.Text = string.Empty;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_nodeBinding.TagLineEdit.Text = Config.RoomDataTag.StartingRoom;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.HBoxContainer != null)
|
2024-05-12 15:06:07 +00:00
|
|
|
|
{
|
2024-06-08 15:59:24 +00:00
|
|
|
|
_nodeBinding.HBoxContainer.Hide();
|
2024-05-12 15:06:07 +00:00
|
|
|
|
}
|
2024-05-12 10:00:47 +00:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-16 12:18:44 +00:00
|
|
|
|
if (_nodeBinding.ExitButton != null)
|
2024-05-12 15:06:07 +00:00
|
|
|
|
{
|
2024-06-16 12:18:44 +00:00
|
|
|
|
_nodeBinding.ExitButton.Pressed += () =>
|
2024-05-12 15:06:07 +00:00
|
|
|
|
{
|
2024-06-14 16:14:17 +00:00
|
|
|
|
if (_mainMenu == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
GetTree().ChangeSceneToPacked(_mainMenu);
|
2024-05-12 15:06:07 +00:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.HideCreateRoomPanelButton != null)
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.HideCreateRoomPanelButton.Pressed += HideCreateRoomPanel;
|
2024-05-12 10:00:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.CreateRoomButton != null)
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.CreateRoomButton.Pressed += () =>
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.RoomNameLineEdit == null || _nodeBinding.RoomDescriptionLineEdit == null ||
|
2024-05-27 14:10:05 +00:00
|
|
|
|
_nodeBinding.RoomTemplateCollectionTextEdit == null || _nodeBinding.TagLineEdit == null)
|
2024-05-17 14:08:19 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
var roomTemplateData = _nodeBinding.RoomTemplateCollectionTextEdit.Text;
|
2024-05-17 14:08:19 +00:00
|
|
|
|
if (string.IsNullOrEmpty(roomTemplateData))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var roomTemplateArray = roomTemplateData.Split('\n');
|
|
|
|
|
if (roomTemplateArray.Length == 0)
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 14:10:05 +00:00
|
|
|
|
string[]? tagArray = null;
|
|
|
|
|
var tagData = _nodeBinding.TagLineEdit.Text;
|
|
|
|
|
if (!string.IsNullOrEmpty(tagData))
|
|
|
|
|
{
|
|
|
|
|
tagArray = tagData.Split(',');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-05-12 10:00:47 +00:00
|
|
|
|
var roomNodeData = new RoomNodeData
|
|
|
|
|
{
|
2024-05-15 13:52:07 +00:00
|
|
|
|
Id = GuidUtils.GetGuid(),
|
2024-05-18 15:35:12 +00:00
|
|
|
|
Title = _nodeBinding.RoomNameLineEdit.Text,
|
|
|
|
|
Description = _nodeBinding.RoomDescriptionLineEdit.Text,
|
2024-05-27 14:10:05 +00:00
|
|
|
|
RoomTemplateSet = roomTemplateArray,
|
2024-05-30 14:49:54 +00:00
|
|
|
|
Tags = tagArray,
|
|
|
|
|
RoomInjectionProcessorData = _nodeBinding.RoomInjectionProcessorDataTextEdit?.Text
|
2024-05-12 10:00:47 +00:00
|
|
|
|
};
|
2024-05-27 14:10:05 +00:00
|
|
|
|
if (!_hasStartNode && roomNodeData.HasTag(Config.RoomDataTag.StartingRoom))
|
|
|
|
|
{
|
|
|
|
|
_hasStartNode = true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-16 14:46:03 +00:00
|
|
|
|
var roomNode = CreateRoomNode(roomNodeData);
|
|
|
|
|
if (roomNode != null)
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
|
|
|
|
HideCreateRoomPanel();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
2024-05-14 14:26:33 +00:00
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.CancelButton != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.CancelButton.Pressed += () =>
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.SaveOrLoadPanel != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-06-08 15:59:24 +00:00
|
|
|
|
_nodeBinding.SaveOrLoadPanel.Hide();
|
2024-05-16 14:46:03 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.ActionButton != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.ActionButton.Pressed += () =>
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.SaveOrLoadPanel != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-06-08 15:59:24 +00:00
|
|
|
|
_nodeBinding.SaveOrLoadPanel.Hide();
|
2024-05-16 14:46:03 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.ShowLoadPanelButton != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.ShowLoadPanelButton.Pressed += () =>
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.SaveOrLoadPanel != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-06-08 15:59:24 +00:00
|
|
|
|
_nodeBinding.SaveOrLoadPanel.Show();
|
2024-05-16 14:46:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.ActionButton != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-06-13 16:43:31 +00:00
|
|
|
|
_nodeBinding.ActionButton.Text = TranslationServerUtils.Translate("ui_load");
|
2024-05-16 14:46:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.FileNameLineEdit != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.FileNameLineEdit.Text = string.Empty;
|
2024-05-16 14:46:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.SaveOrLoadPanelTitleLabel != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-06-13 16:43:31 +00:00
|
|
|
|
_nodeBinding.SaveOrLoadPanelTitleLabel.Text = TranslationServerUtils.Translate("ui_load");
|
2024-05-16 14:46:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_saveMode = false;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.ShowSavePanelButton != null)
|
2024-05-14 14:26:33 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.ShowSavePanelButton.Pressed += () =>
|
2024-05-14 14:26:33 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.SaveOrLoadPanel != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-06-08 15:59:24 +00:00
|
|
|
|
_nodeBinding.SaveOrLoadPanel.Show();
|
2024-05-16 14:46:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.ActionButton != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-06-13 16:43:31 +00:00
|
|
|
|
_nodeBinding.ActionButton.Text = TranslationServerUtils.Translate("ui_save");
|
2024-05-16 14:46:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.FileNameLineEdit != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.FileNameLineEdit.Text = string.Empty;
|
2024-05-16 14:46:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.SaveOrLoadPanelTitleLabel != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-06-13 16:43:31 +00:00
|
|
|
|
_nodeBinding.SaveOrLoadPanelTitleLabel.Text = TranslationServerUtils.Translate("ui_save");
|
2024-05-16 14:46:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_saveMode = true;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.ActionButton != null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.ActionButton.Pressed += () =>
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.FileNameLineEdit == null)
|
2024-05-14 14:26:33 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
var fileName = _nodeBinding.FileNameLineEdit.Text;
|
2024-05-16 14:46:03 +00:00
|
|
|
|
if (string.IsNullOrEmpty(fileName))
|
2024-05-14 14:26:33 +00:00
|
|
|
|
{
|
2024-05-15 13:52:07 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2024-05-14 14:26:33 +00:00
|
|
|
|
|
2024-05-16 14:46:03 +00:00
|
|
|
|
if (_saveMode)
|
2024-05-15 13:52:07 +00:00
|
|
|
|
{
|
2024-05-16 14:46:03 +00:00
|
|
|
|
SaveFile(fileName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LoadFile(fileName);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>save file</para>
|
|
|
|
|
/// <para>保存文件</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="fileName">
|
|
|
|
|
///<para>filename</para>
|
|
|
|
|
///<para>文件名</para>
|
|
|
|
|
/// </param>
|
|
|
|
|
private async void SaveFile(string fileName)
|
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.GraphEdit == null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-05-14 14:26:33 +00:00
|
|
|
|
|
2024-05-16 14:46:03 +00:00
|
|
|
|
var levelGraphEditorSaveData = new LevelGraphEditorSaveData();
|
|
|
|
|
//Serialize room node information
|
|
|
|
|
//序列化房间节点信息
|
2024-05-18 15:35:12 +00:00
|
|
|
|
var length = _nodeBinding.GraphEdit.GetChildCount();
|
2024-05-16 14:46:03 +00:00
|
|
|
|
if (length <= 0)
|
|
|
|
|
{
|
|
|
|
|
//no room
|
|
|
|
|
//没有房间
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var roomNodeDataList = new List<RoomNodeData>();
|
|
|
|
|
levelGraphEditorSaveData.RoomNodeDataList = roomNodeDataList;
|
|
|
|
|
for (var i = 0; i < length; i++)
|
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
var node = _nodeBinding.GraphEdit.GetChild(i);
|
2024-05-16 14:46:03 +00:00
|
|
|
|
if (node is not RoomNode roomNode) continue;
|
|
|
|
|
var data = roomNode.RoomNodeData;
|
|
|
|
|
if (data == null)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
roomNodeDataList.Add(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Serialized connection information
|
|
|
|
|
//序列化连接信息
|
2024-05-18 15:35:12 +00:00
|
|
|
|
Array<Dictionary> connectionList = _nodeBinding.GraphEdit.GetConnectionList();
|
2024-05-16 14:46:03 +00:00
|
|
|
|
var connectionDataList = new List<ConnectionData>();
|
|
|
|
|
levelGraphEditorSaveData.ConnectionDataList = connectionDataList;
|
|
|
|
|
if (connectionList.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
foreach (var dictionary in connectionList)
|
|
|
|
|
{
|
|
|
|
|
if (dictionary == null)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
2024-05-15 13:52:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-16 14:46:03 +00:00
|
|
|
|
var keys = dictionary.Keys;
|
|
|
|
|
if (keys.Count == 0)
|
2024-05-15 13:52:07 +00:00
|
|
|
|
{
|
2024-05-16 14:46:03 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-05-15 13:52:07 +00:00
|
|
|
|
|
2024-05-16 14:46:03 +00:00
|
|
|
|
var connectionData = new ConnectionData();
|
|
|
|
|
foreach (var variant in keys)
|
|
|
|
|
{
|
|
|
|
|
var typeStr = variant.ToString();
|
|
|
|
|
switch (typeStr)
|
|
|
|
|
{
|
|
|
|
|
case "from_node":
|
|
|
|
|
var fromRoomNodeData = GetRoomNodeData(dictionary[variant].AsString());
|
|
|
|
|
if (fromRoomNodeData == null)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-05-15 13:52:07 +00:00
|
|
|
|
|
2024-05-16 14:46:03 +00:00
|
|
|
|
connectionData.FromId = fromRoomNodeData.Id;
|
|
|
|
|
break;
|
|
|
|
|
case "from_port":
|
|
|
|
|
connectionData.FromPort = dictionary[variant].AsInt32();
|
|
|
|
|
break;
|
|
|
|
|
case "to_node":
|
|
|
|
|
var toRoomNodeData = GetRoomNodeData(dictionary[variant].AsString());
|
|
|
|
|
if (toRoomNodeData == null)
|
2024-05-15 13:52:07 +00:00
|
|
|
|
{
|
2024-05-16 14:46:03 +00:00
|
|
|
|
continue;
|
2024-05-15 13:52:07 +00:00
|
|
|
|
}
|
2024-05-14 14:26:33 +00:00
|
|
|
|
|
2024-05-16 14:46:03 +00:00
|
|
|
|
connectionData.ToId = toRoomNodeData.Id;
|
|
|
|
|
break;
|
|
|
|
|
case "to_port":
|
|
|
|
|
connectionData.ToPort = dictionary[variant].AsInt32();
|
|
|
|
|
break;
|
2024-05-14 14:26:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-16 14:46:03 +00:00
|
|
|
|
connectionDataList.Add(connectionData);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var filePath = Path.Join(Config.GetLevelGraphExportDirectory(), FileNameToActualName(fileName));
|
|
|
|
|
await File.WriteAllTextAsync(filePath, JsonSerialization.Serialize(levelGraphEditorSaveData));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Filename to real name</para>
|
|
|
|
|
/// <para>文件名到真实名称</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="fileName">
|
|
|
|
|
///<para>If the filename does not have a file format, add the file format.</para>
|
|
|
|
|
///<para>若文件名没有文件格式,那么加上文件格式。</para>
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private string FileNameToActualName(string fileName)
|
|
|
|
|
{
|
|
|
|
|
string actualName;
|
|
|
|
|
if (fileName.EndsWith(".json"))
|
|
|
|
|
{
|
|
|
|
|
actualName = fileName;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
actualName = fileName + ".json";
|
2024-05-14 14:26:33 +00:00
|
|
|
|
}
|
2024-05-16 14:46:03 +00:00
|
|
|
|
|
|
|
|
|
return actualName;
|
2024-05-12 10:00:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-05-16 14:46:03 +00:00
|
|
|
|
private async void LoadFile(string fileName)
|
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.GraphEdit == null)
|
2024-05-16 14:46:03 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var filePath = Path.Join(Config.GetLevelGraphExportDirectory(), FileNameToActualName(fileName));
|
|
|
|
|
if (!File.Exists(filePath))
|
|
|
|
|
{
|
|
|
|
|
//file does not exist
|
|
|
|
|
//文件不存在。
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var levelGraphEditorSaveData =
|
|
|
|
|
await JsonSerialization.ReadJsonFileToObj<LevelGraphEditorSaveData>(filePath);
|
|
|
|
|
if (levelGraphEditorSaveData == null)
|
|
|
|
|
{
|
|
|
|
|
//Deserialization failed.
|
|
|
|
|
//反序列化失败。
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Do not call DeleteAllChildAsync; this will raise "ERROR: Caller thread can't call this function in this node."
|
|
|
|
|
//不要调用DeleteAllChildAsync方法,这会引发“ERROR: Caller thread can't call this function in this node”。
|
2024-05-18 15:35:12 +00:00
|
|
|
|
NodeUtils.DeleteAllChild(_nodeBinding.GraphEdit);
|
2024-05-16 14:46:03 +00:00
|
|
|
|
_roomIndex = 1;
|
2024-05-27 14:10:05 +00:00
|
|
|
|
_hasStartNode = false;
|
2024-05-16 14:46:03 +00:00
|
|
|
|
var roomNodeDataList = levelGraphEditorSaveData.RoomNodeDataList;
|
|
|
|
|
if (roomNodeDataList != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (var roomNodeData in roomNodeDataList)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(roomNodeData.Id))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 14:10:05 +00:00
|
|
|
|
if (!_hasStartNode && roomNodeData.HasTag(Config.RoomDataTag.StartingRoom))
|
|
|
|
|
{
|
|
|
|
|
_hasStartNode = true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-16 14:46:03 +00:00
|
|
|
|
//Instantiate the room node.
|
|
|
|
|
//实例化房间节点。
|
|
|
|
|
var roomNode = CreateRoomNode(roomNodeData);
|
|
|
|
|
if (roomNode != null)
|
|
|
|
|
{
|
|
|
|
|
roomNode.Name = roomNodeData.Id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var connectionDataList = levelGraphEditorSaveData.ConnectionDataList;
|
|
|
|
|
if (connectionDataList != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (var connectionData in connectionDataList)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(connectionData.FromId))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(connectionData.ToId))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Connecting rooms
|
|
|
|
|
//连接房间
|
2024-05-18 15:35:12 +00:00
|
|
|
|
_nodeBinding.GraphEdit?.ConnectNode(connectionData.FromId, connectionData.FromPort, connectionData.ToId,
|
2024-05-16 14:46:03 +00:00
|
|
|
|
connectionData.ToPort);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-15 13:52:07 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Get node data by name</para>
|
|
|
|
|
/// <para>根据名称获取节点数据</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">
|
|
|
|
|
///<para>name</para>
|
|
|
|
|
///<para>名称</para>
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <returns></returns>
|
2024-05-16 14:46:03 +00:00
|
|
|
|
private RoomNodeData? GetRoomNodeData(string name)
|
2024-05-15 13:52:07 +00:00
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.GraphEdit == null)
|
2024-05-15 13:52:07 +00:00
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
var roomNode = _nodeBinding.GraphEdit.GetNodeOrNull<RoomNode>(name);
|
2024-05-15 13:52:07 +00:00
|
|
|
|
if (roomNode == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return roomNode.RoomNodeData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-05-12 10:00:47 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>Hide the Create Room panel</para>
|
|
|
|
|
/// <para>隐藏创建房间面板</para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void HideCreateRoomPanel()
|
|
|
|
|
{
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.GraphEdit != null)
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
2024-06-08 15:59:24 +00:00
|
|
|
|
_nodeBinding.GraphEdit.Show();
|
2024-05-12 10:00:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.CreateOrEditorPanel != null)
|
2024-05-12 10:00:47 +00:00
|
|
|
|
{
|
2024-06-08 15:59:24 +00:00
|
|
|
|
_nodeBinding.CreateOrEditorPanel.Hide();
|
2024-05-12 10:00:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-18 15:35:12 +00:00
|
|
|
|
if (_nodeBinding.HBoxContainer != null)
|
2024-05-12 15:06:07 +00:00
|
|
|
|
{
|
2024-06-08 15:59:24 +00:00
|
|
|
|
_nodeBinding.HBoxContainer.Show();
|
2024-05-12 15:06:07 +00:00
|
|
|
|
}
|
2024-05-12 10:00:47 +00:00
|
|
|
|
}
|
|
|
|
|
}
|