Files
JuegoSim/Assets/_Project/Scripts/Code/ModelCheckingSystem/ModelCheckManager.cs
T
2026-07-21 08:56:10 +03:00

206 lines
6.1 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using NaughtyAttributes;
using UnityEngine.UIElements;
public class ModelCheckManager : MonoBehaviour
{
private static ModelCheckManager instance;
public static ModelCheckManager getInstance() => instance;
private Environment environment;
[SerializeField] private BlocksMap blocksMap;
private BlocksMap currentMap;
private long validNodes;
private long invalidNodes;
private long totalNodes;
public UnityEvent OnAllValidEvent; // help notifing the correctness of all blocks
public UnityEvent OnValidNodeEvent; // add a feedback (materail change, flush light, correct sound, etc)
public UnityEvent OnInvalidNodeEvent; // add a feedback (materail change, flush light, incorrect sound, etc)
[Header("Map Recording")]
public string newMapName = "NewBlocksMap";
[SerializeField] private bool debug = false;
public void setBlockMap(BlocksMap map)
{
blocksMap = map;
totalNodes = blocksMap.calcTotalNodes();
}
void Start()
{
if (debug)
Initialize();
}
// TODO: call this function after selecting the current map and switch to editor scene
public void Initialize()
{
environment = Environment.getInstance();
// get total nodes in the blocksMap
if (blocksMap != null)
totalNodes = blocksMap.calcTotalNodes();
// add listener to env events
environment.onBlockAddedEvent.AddListener(x =>
{
addNode(createBlockNode(x.getBlockData(), x.transform.position, x.transform.rotation));
});
environment.onBlockRemovedEvent.AddListener(x =>
{
removeNode(x.getBlockData().blockName, x.transform.position);
});
environment.onBlockMovedEvt.AddListener((block, pos, rot) =>
{
removeNode(block.getBlockData().blockName, pos);
addNode(createBlockNode(block.getBlockData(), block.transform.position, block.transform.rotation));
});
// initialize the current map
validNodes = 0;
invalidNodes = 0;
currentMap = ScriptableObject.CreateInstance<BlocksMap>();
currentMap.init(blocksMap);
}
private BlockNode createBlockNode(BlockData blockData, Vector3 position, Quaternion rotation)
{
return new BlockNode(blockData, BlocksMap.RoundPosition(position), BlocksMap.RoundRotation(rotation));
}
private void Awake()
{
if (instance == null) instance = this;
else Destroy(gameObject);
}
// handle node addition
public void addNode(BlockNode node)
{
Dictionary<Vector3, BlockNode> map = currentMap.blocks[node.blockData.blockName];
if (map == null)
{
map = new Dictionary<Vector3, BlockNode>();
currentMap.blocks[node.blockData.blockName] = map;
}
map[node.position] = node;
currentMap.allNodes.Add(node);
if (blocksMap == null) return;
if (tryMarkNode(node))
{
validNodes++;
OnValidNodeEvent.Invoke();
if (validNodes == totalNodes && invalidNodes == 0)
OnAllValidEvent.Invoke();
}
else
{
invalidNodes++;
OnInvalidNodeEvent.Invoke();
}
debugisValid(node);
}
// handle updating the node when moving it using the transform
//public void updateNode(BlockNode node)
//{
// // TODO: Update node positions when moved / CTRL + Z if it changed to account for deleting it
//}
// handle node removal
public void removeNode(string blockName, Vector3 position)
{
position = BlocksMap.RoundPosition(position);
BlockNode node = currentMap.blocks[blockName][position];
if (blocksMap == null) return;
currentMap.blocks[blockName].Remove(node.position);
currentMap.allNodes.Remove(node);
if (node.matchedNode != null) // valid node
{
node.matchedNode.matchedNode = null;
node.matchedNode = null;
validNodes--;
}
else // invalid node
{
invalidNodes--;
}
}
private bool tryMarkNode(BlockNode node)
{
Dictionary<Vector3, BlockNode> map = blocksMap.blocks[node.blockData.blockName];
if (map == null) return false;
if (!map.TryGetValue(node.position, out BlockNode target))
return false;
if (!matchRotation(node, target)) return false;
target.matchedNode = node;
node.matchedNode = target;
return true;
}
private bool matchRotation(BlockNode node1, BlockNode node2)
{
float angle = Quaternion.Angle(node1.rotation.normalized, node2.rotation.normalized);
return node1.rotation.normalized.Equals(node2.rotation.normalized) ||
angle == 180;
}
private void debugisValid(BlockNode node)
{
Debug.Log($"Node at {node.position} is " + (node.matchedNode != null ? "valid" : "invalid"));
}
// TODO: seperate this Editor tool
#if UNITY_EDITOR
[Button("Save Current Map as Asset")]
public void saveCurrentMap()
{
if (currentMap == null)
{
Debug.LogWarning("No current map to save.");
return;
}
if (currentMap.allNodes.Count == 0)
{
Debug.LogWarning("Current map is empty. Nothing to save.");
return;
}
currentMap.setRootNode(currentMap.allNodes[0]);
string folder = "Assets/BlocksMaps";
if (!UnityEditor.AssetDatabase.IsValidFolder(folder))
UnityEditor.AssetDatabase.CreateFolder("Assets", "BlocksMaps");
string path = $"{folder}/{newMapName}.asset";
UnityEditor.AssetDatabase.CreateAsset(currentMap, path);
UnityEditor.EditorUtility.SetDirty(currentMap);
UnityEditor.AssetDatabase.SaveAssets();
UnityEditor.AssetDatabase.Refresh();
UnityEditor.EditorGUIUtility.PingObject(currentMap);
Debug.Log($"Saved to {path}");
}
#endif
}