194 lines
5.4 KiB
C#
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;
|
|
}
|
|
} |