NLDClient-yudde/ProjectNLD/Assets/Editor/Scene/SceneBrush/SceneBrush.Calculator.cs

194 lines
5.4 KiB
C#

using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
using TGS;
using UnityEngine;
public partial class SceneBrush
{
private Vector2 _calculateSize;
private Quaternion _defaultRotation;
protected class SceneObjectLocation
{
public Vector3 position;
public Quaternion rotation = Quaternion.identity;
}
/// <summary>
/// 标准绘制计算器,会根据笔刷配置返回一系列的坐标和朝向
/// </summary>
/// <param name="position"></param>
protected List<SceneObjectLocation> StandardDrawCalculate(Vector3 position)
{
PreCalculate();
var result = CalculateByLayout(position);
if (useTGS && _tgs != null)
{
CullLocationByTGS(result);
}
CullOutsideLocation(result);
if (!canOverlap && _sceneManager != null)
{
CullRepeatLocation(result);
}
return result;
}
protected List<SceneObject> StandardEraseCalculate(Vector3 position)
{
_sceneManager.Refresh();
List<SceneObject> result = new();
var currTypeSObjs = _sceneManager.GetSceneObjectsByType(SceneObjectType);
if (currTypeSObjs != null)
{
foreach (var sObj in currTypeSObjs)
{
if (eraseSameType || sObj.renderInfo == renderInfo)
{
if (IsSceneObjectInBrushArea(position, sObj))
{
result.Add(sObj);
}
}
}
}
return result;
}
private void PreCalculate()
{
_calculateSize = GetGameObjectRectSize(prefab) * scale;
_defaultRotation = Quaternion.Euler(new Vector3(0, yAngle, 0));
}
private Vector2 GetGameObjectRectSize(GameObject go)
{
var bounds = go.GetMaxBounds();
if (bounds == null)
{
return Vector2.zero;
}
var size = ((Bounds)bounds).size;
return new Vector2(size.x, size.z) / 2f;
}
protected List<SceneObjectLocation> CalculateByLayout(Vector3 position)
{
// if (_calculateRadius >= radius)
// {
// return CalculateDirectly(position);
// }
return CalculateDirectly(position);
}
protected void CullLocationByTGS(List<SceneObjectLocation> locations)
{
List<Cell> _usedCell = new();
for (int i = locations.Count - 1; i >= 0; i--)
{
var location = locations[i];
var cell = _tgs.CellGetAtPosition(location.position, true);
if (cell == null || _usedCell.Contains(cell))
{
locations.RemoveAt(i);
continue;
}
else
{
_usedCell.Add(cell);
}
location.position = _tgs.CellGetPosition(cell, true);
}
}
protected void CullOutsideLocation(List<SceneObjectLocation> locations)
{
var groundBounds = _ground.GetComponent<MeshRenderer>().bounds;
for (int i = locations.Count - 1; i >= 0; i--)
{
var location = locations[i];
if (!groundBounds.Contains(location.position))
{
locations.RemoveAt(i);
}
}
}
/// <summary>
/// 场景内类型一致的对象不能有重叠,要尽量剔除,不能保证完全剔除
/// </summary>
/// <param name="locations"></param>
/// <param name="sceneManager"></param>
protected void CullRepeatLocation(List<SceneObjectLocation> locations)
{
_sceneManager.Refresh();
var currTypeSObjs = _sceneManager.GetSceneObjectsByType(SceneObjectType);
if (currTypeSObjs == null)
return;
for (int i = locations.Count - 1; i >= 0; i--)
{
var location = locations[i];
foreach (var savedSObj in currTypeSObjs)
{
if (IsTwoRectInsert(location.position, _calculateSize, savedSObj.transform.position,
GetGameObjectRectSize(savedSObj.gameObject)))
{
locations.RemoveAt(i);
break;
}
}
}
}
//直接返回一个location
protected List<SceneObjectLocation> CalculateDirectly(Vector3 position)
{
List<SceneObjectLocation> result = new()
{
new SceneObjectLocation()
{
position = position,
rotation = _defaultRotation,
}
};
return result;
}
protected List<SceneObjectLocation> CalculateRegularPolygon(Vector3 position, float cRadius)
{
return null;
}
protected List<SceneObjectLocation> CalculateRandom(Vector3 position, float cRadius)
{
return null;
}
private bool IsTwoRectInsert(Vector3 center1, Vector2 size1, Vector3 center2, Vector2 size2)
{
Rect r1 = new Rect();
r1.center = Vector3To2(center1);
r1.size = size1;
Rect r2 = new Rect();
r2.center = Vector3To2(center2);
r2.size = size2;
return r1.Overlaps(r2);
}
private Vector2 Vector3To2(Vector3 vec)
{
return new Vector2(vec.x, vec.z);
}
private bool IsSceneObjectInBrushArea(Vector3 position, SceneObject sObj)
{
var sPosition = sObj.transform.position;
return (position - sPosition).sqrMagnitude <= radius * radius;
}
}