BITFALL/Assets/GSpawn - Level Designer/Scripts/Level Design/Object Erase/ObjectEraseBrush2D.cs

151 lines
6.4 KiB
C#

#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System;
namespace GSpawn
{
public class ObjectEraseBrush2D : ObjectEraseTool
{
[NonSerialized]
private List<GameObject> _overlappedObjects = new List<GameObject>();
[NonSerialized]
private List<GameObject> _gameObjectBuffer = new List<GameObject>();
[NonSerialized]
private List<Vector2> _vector2Buffer = new List<Vector2>();
[NonSerialized]
private Plane _cullPlane;
[NonSerialized]
private bool _updateCullPlane = true;
[NonSerialized]
private Rect _rect = new Rect();
[NonSerialized]
private SceneRaycastFilter _raycastFilter = new SceneRaycastFilter();
[NonSerialized]
private ObjectBounds.QueryConfig _boundsQConfig = new ObjectBounds.QueryConfig();
public override ObjectEraseToolId toolId { get { return ObjectEraseToolId.Brush2D; } }
public ObjectEraseBrush2D()
{
_raycastFilter.objectTypes = GameObjectType.Mesh | GameObjectType.Sprite;
_raycastFilter.raycastGrid = false;
_boundsQConfig.objectTypes = GameObjectType.Mesh | GameObjectType.Sprite;
}
protected override void doOnSceneGUI()
{
Event e = Event.current;
updateOverlapRect();
if (e.button == 0)
{
switch (e.type)
{
case EventType.MouseDrag:
if (_updateCullPlane) updateCullPlane();
detectOverlappedObjects();
eraseGameObjects(_overlappedObjects);
break;
case EventType.MouseUp:
if (_updateCullPlane) updateCullPlane();
detectOverlappedObjects();
eraseGameObjects(_overlappedObjects);
_updateCullPlane = true;
break;
default:
if (FixedShortcuts.changeRadiusByScrollWheel(e))
{
e.disable();
ObjectErase.instance.eraseBrush2DSettings.radius -= 2.0f * e.getMouseScroll();
EditorUtility.SetDirty(ObjectErase.instance.eraseBrush2DSettings);
}
break;
}
}
}
protected override void draw()
{
Matrix4x4 circleTransform = PluginCamera.camera.calcXYCircleOnNearPlaneTransform(_rect.center, _rect.width * 0.5f, 1e-4f);
Material material = MaterialPool.instance.simpleDiffuse;
material.setCullModeOff();
material.SetColor("_Color", ObjectErasePrefs.instance.brush2DFillColor);
material.SetPass(0);
Graphics.DrawMeshNow(MeshPool.instance.unitCircleXY, circleTransform);
material.SetColor("_Color", ObjectErasePrefs.instance.brush2DBorderColor);
material.SetPass(0);
Graphics.DrawMeshNow(MeshPool.instance.unitWireCircleXY, circleTransform);
}
private void detectOverlappedObjects()
{
_overlappedObjects.Clear();
bool allowPartialOverlap = ObjectErase.instance.eraseBrush2DSettings.allowPartialOverlap;
Rect pickRect = allowPartialOverlap ? PluginCamera.camera.pixelRect : _rect.createInvertedYCoords(PluginCamera.camera);
var pickedObjects = HandleUtility.PickRectObjects(pickRect);
if (pickedObjects.Length == 0) return;
Vector2 circleCenter = _rect.center;
float circleRadius = ObjectErase.instance.eraseBrush2DSettings.radius;
bool eraseCullPlaneToggle = FixedShortcuts.eraseCullPlaneToggle(Event.current);
bool useCullPlane = !_updateCullPlane && ((eraseCullPlaneToggle && !ObjectErase.instance.eraseBrush2DSettings.enableCullPlaneByDefault) ||
(!eraseCullPlaneToggle && ObjectErase.instance.eraseBrush2DSettings.enableCullPlaneByDefault));
// Note: HandleUtility.PickRectObjects seems to pick only parents. We need all objects intersected by the rectangle.
GameObjectEx.getAllObjectsInHierarchies(pickedObjects, false, false, _gameObjectBuffer);
foreach (GameObject go in _gameObjectBuffer)
{
if (ObjectErase.instance.canEraseObject(go))
{
if (useCullPlane)
{
OBB worldOBB = ObjectBounds.calcWorldOBB(go, _boundsQConfig);
if (!worldOBB.isValid || Box3D.classifyAgainstPlane(worldOBB.center, worldOBB.size, worldOBB.rotation, _cullPlane) != PlaneClassifyResult.Spanning)
continue;
}
Rect objectScreenRect = ObjectBounds.calcScreenRect(go, PluginCamera.camera, _boundsQConfig);
if (allowPartialOverlap)
{
if (Circle2D.intersectsRect(circleCenter, circleRadius, objectScreenRect)) _overlappedObjects.Add(go);
}
else
{
objectScreenRect.calcCorners(_vector2Buffer);
if (Circle2D.containsPoints(circleCenter, circleRadius, _vector2Buffer)) _overlappedObjects.Add(go);
}
}
}
}
private void updateOverlapRect()
{
Vector2 mousePos = Event.current.mousePosition;
mousePos.y = PluginCamera.camera.pixelHeight - mousePos.y;
_rect = RectEx.create(mousePos, Vector2.one * ObjectErase.instance.eraseBrush2DSettings.radius * 2.0f);
}
private void updateCullPlane()
{
Ray pickRay = PluginCamera.camera.getCursorRay();
var rayHit = PluginScene.instance.raycastClosest(pickRay, _raycastFilter, ObjectRaycastConfig.defaultConfig);
if (rayHit.wasObjectHit)
{
_cullPlane = new Plane(rayHit.objectHit.hitNormal, rayHit.objectHit.hitPoint - rayHit.objectHit.hitNormal * 1e-3f);
_updateCullPlane = false;
}
}
}
}
#endif