108 lines
3.9 KiB
C#
108 lines
3.9 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
|
|
namespace Obi
|
|
{
|
|
/**
|
|
* This component plugs a prefab instance at each cut in the rope. Optionally, it will also place a couple instances at the start/end of an open rope.
|
|
*/
|
|
[RequireComponent(typeof(ObiPathSmoother))]
|
|
public class ObiRopePrefabPlugger : MonoBehaviour
|
|
{
|
|
public GameObject prefab; /**< prefab object being instantiated at the rope cuts.*/
|
|
public Vector3 instanceScale = Vector3.one;
|
|
public bool plugTears = true;
|
|
public bool plugStart = false;
|
|
public bool plugEnd = false;
|
|
|
|
private List<GameObject> instances; /**< instances of the prefab being rendered. */
|
|
private ObiPathSmoother smoother;
|
|
|
|
void OnEnable()
|
|
{
|
|
instances = new List<GameObject>();
|
|
smoother = GetComponent<ObiPathSmoother>();
|
|
GetComponent<ObiActor>().OnInterpolate += UpdatePlugs;
|
|
}
|
|
|
|
void OnDisable()
|
|
{
|
|
GetComponent<ObiActor>().OnInterpolate -= UpdatePlugs;
|
|
ClearPrefabInstances();
|
|
}
|
|
|
|
private GameObject GetOrCreatePrefabInstance(int index)
|
|
{
|
|
if (index < instances.Count)
|
|
return instances[index];
|
|
|
|
GameObject tearPrefabInstance = Instantiate(prefab);
|
|
tearPrefabInstance.hideFlags = HideFlags.HideAndDontSave;
|
|
instances.Add(tearPrefabInstance);
|
|
return tearPrefabInstance;
|
|
}
|
|
|
|
public void ClearPrefabInstances()
|
|
{
|
|
for (int i = 0; i < instances.Count; ++i)
|
|
DestroyImmediate(instances[i]);
|
|
|
|
instances.Clear();
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void UpdatePlugs(ObiActor actor, float simulatedTime, float substepTime)
|
|
{
|
|
if (!actor.isLoaded)
|
|
return;
|
|
|
|
// cache the rope's transform matrix/quaternion:
|
|
Matrix4x4 l2w = smoother.actor.solver.transform.localToWorldMatrix;
|
|
Quaternion l2wRot = l2w.rotation;
|
|
|
|
int instanceIndex = 0;
|
|
|
|
var system = actor.solver.GetRenderSystem<ObiPathSmoother>() as ObiPathSmootherRenderSystem;
|
|
int chunkCount = system.GetChunkCount(smoother.indexInSystem);
|
|
|
|
// place prefabs at the start/end of each curve:
|
|
for (int c = 0; c < chunkCount; ++c)
|
|
{
|
|
if ((plugTears && c > 0) ||
|
|
(plugStart && c == 0))
|
|
{
|
|
var instance = GetOrCreatePrefabInstance(instanceIndex++);
|
|
instance.SetActive(true);
|
|
|
|
ObiPathFrame frame = system.GetFrameAt(smoother.indexInSystem, c, 0);
|
|
instance.transform.position = l2w.MultiplyPoint3x4(frame.position);
|
|
instance.transform.rotation = l2wRot * (Quaternion.LookRotation(-frame.tangent, frame.binormal));
|
|
instance.transform.localScale = instanceScale;
|
|
}
|
|
|
|
|
|
if ((plugTears && c < chunkCount - 1) ||
|
|
(plugEnd && c == chunkCount - 1))
|
|
{
|
|
var instance = GetOrCreatePrefabInstance(instanceIndex++);
|
|
instance.SetActive(true);
|
|
|
|
int frameCount = system.GetSmoothFrameCount(smoother.indexInSystem, c);
|
|
ObiPathFrame frame = system.GetFrameAt(smoother.indexInSystem, c, frameCount-1);
|
|
instance.transform.position = l2w.MultiplyPoint3x4(frame.position);
|
|
instance.transform.rotation = l2wRot * Quaternion.LookRotation(frame.tangent, frame.binormal);
|
|
instance.transform.localScale = instanceScale;
|
|
}
|
|
|
|
}
|
|
|
|
// deactivate remaining instances:
|
|
for (int i = instanceIndex; i < instances.Count; ++i)
|
|
instances[i].SetActive(false);
|
|
|
|
}
|
|
}
|
|
|
|
} |