Files
2025-05-29 22:31:40 +03:00

126 lines
4.8 KiB
C#

using UnityEngine;
using UnityEditor;
using System;
using System.Collections;
using System.Collections.Generic;
namespace Obi
{
public class ObiRaycastBrush : ObiBrushBase
{
public Matrix4x4 raycastTransform = Matrix4x4.identity;
public Mesh raycastTarget = null;
public bool drawVolume = false;
private List<Ray> rays = new List<Ray>();
private List<ObiRaycastHit> hits = new List<ObiRaycastHit>();
public ObiBrushMirrorSettings mirror;
public ObiRaycastBrush(Mesh raycastTarget, Action onStrokeStart, Action onStrokeUpdate, Action onStrokeEnd) : base(onStrokeStart, onStrokeUpdate, onStrokeEnd)
{
radius = 0.1f;
this.raycastTarget = raycastTarget;
rays = new List<Ray>();
}
protected override void GenerateWeights(Vector3[] positions)
{
if (raycastTarget != null)
{
rays.Clear();
hits.Clear();
for (int i = 0; i < positions.Length; i++)
weights[i] = 0;
var vertices = raycastTarget.vertices;
var triangles = raycastTarget.triangles;
Ray mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
rays.Add(mouseRay);
ObiBrushMirrorSettings currentAxis = mirror;
if (mirror.axis != ObiBrushMirrorSettings.MirrorAxis.None)
{
for (int i = 0; i < 3; i++)
{
currentAxis.axis = (ObiBrushMirrorSettings.MirrorAxis)(1u << i);
if (((uint)mirror.axis & (1u << i)) < 1)
continue;
Vector3 mirrorVector = currentAxis.ToAxis();
if (currentAxis.space == ObiBrushMirrorSettings.MirrorSpace.World)
{
Vector3 center = raycastTarget.bounds.center;
rays.Add(new Ray(Vector3.Scale(mouseRay.origin - center, mirrorVector) + center,
Vector3.Scale(mouseRay.direction, mirrorVector)));
}
else
{
Transform t = SceneView.lastActiveSceneView.camera.transform;
Vector3 o = t.InverseTransformPoint(mouseRay.origin);
Vector3 d = t.InverseTransformDirection(mouseRay.direction);
rays.Add(new Ray(t.TransformPoint(Vector3.Scale(o, mirrorVector)),
t.TransformDirection(Vector3.Scale(d, mirrorVector))));
}
}
}
foreach (var ray in rays)
{
if (ObiMeshUtils.WorldRaycast(ray, raycastTransform, vertices, triangles, out ObiRaycastHit hit))
{
hit.position = raycastTransform.MultiplyPoint3x4(hit.position);
hit.normal = raycastTransform.MultiplyVector(hit.normal);
hits.Add(hit);
for (int i = 0; i < positions.Length; i++)
{
// get distance from hit position to particle position:
float weight = WeightFromDistance(Vector3.Distance(hit.position, positions[i]));
weights[i] = Mathf.Max(weights[i], weight);
}
}
}
}
}
protected override void OnMouseMove(Vector3[] positions)
{
base.OnMouseMove(positions);
GenerateWeights(positions);
}
protected override void OnRepaint()
{
base.OnRepaint();
if (raycastTarget != null)
{
Color brushColor = ObiEditorSettings.GetOrCreateSettings().brushColor;
foreach (var hit in hits)
{
if (hit != null && hit.triangle >= 0)
{
Handles.color = brushColor;
Handles.DrawLine(hit.position, hit.position + hit.normal.normalized * radius);
Handles.DrawWireDisc(hit.position, hit.normal, radius);
Handles.DrawWireDisc(hit.position, hit.normal, innerRadius * radius);
if (drawVolume)
{
Handles.color = new Color(brushColor.r, brushColor.g, brushColor.b, 0.2f);
Handles.SphereHandleCap(0, hit.position, Quaternion.identity, radius * 2, EventType.Repaint);
}
}
}
}
}
}
}