using UnityEngine; using System.Collections.Generic; using System; namespace Obi { public interface IObiConstraints { Oni.ConstraintType? GetConstraintType(); IObiConstraintsBatch GetBatch(int i); int batchCount { get; } void Clear(); bool AddToSolver(ObiSolver solver); bool RemoveFromSolver(); int GetConstraintCount(); int GetActiveConstraintCount(); void ActivateAllConstraints(); void DeactivateAllConstraints(); void Merge(ObiActor actor, IObiConstraints other); } [Serializable] public abstract class ObiConstraints : IObiConstraints where T : class, IObiConstraintsBatch { [NonSerialized] protected ObiSolver m_Solver; [HideInInspector] public List batches = new List(); public int batchCount { get => batches == null ? 0 : batches.Count; } // merges constraints from a given actor with this one. public void Merge(ObiActor actor, IObiConstraints other) { var others = other as ObiConstraints; if (others == null || !other.GetConstraintType().HasValue) return; int constraintType = (int)other.GetConstraintType().Value; // clear batch offsets for this constraint type: actor.solverBatchOffsets[constraintType].Clear(); // create new empty batches if needed: int newBatches = Mathf.Max(0, others.batchCount - batchCount); for (int i = 0; i < newBatches; ++i) AddBatch(CreateBatch()); for (int i = 0; i < other.batchCount; ++i) { // store this batch's offset: actor.solverBatchOffsets[constraintType].Add(batches[i].activeConstraintCount); // merge both batches: batches[i].Merge(actor, others.batches[i]); } } public IObiConstraintsBatch GetBatch(int i) { if (batches != null && i >= 0 && i < batches.Count) return (IObiConstraintsBatch) batches[i]; return null; } public int GetConstraintCount() { int count = 0; if (batches == null) return count; foreach (T batch in batches) if (batch != null) count += batch.constraintCount; return count; } public int GetActiveConstraintCount() { int count = 0; if (batches == null) return count; foreach (T batch in batches) if (batch != null) count += batch.activeConstraintCount; return count; } public void DeactivateAllConstraints() { if (batches != null) foreach (T batch in batches) if (batch != null) batch.DeactivateAllConstraints(); } public void ActivateAllConstraints() { if (batches != null) foreach (T batch in batches) if (batch != null) batch.ActivateAllConstraints(); } public T GetFirstBatch() { return (batches != null && batches.Count > 0) ? batches[0] : null; } public Oni.ConstraintType? GetConstraintType() { if (batches != null && batches.Count > 0) return batches[0].constraintType; else return null; } public void Clear() { RemoveFromSolver(); if (batches != null) batches.Clear(); } public virtual T CreateBatch(T source = null) { return null; } public void AddBatch(T batch) { if (batch != null) batches.Add(batch); } public bool RemoveBatch(T batch) { if (batches == null || batch == null) return false; return batches.Remove(batch); } public bool AddToSolver(ObiSolver solver) { if (this.m_Solver != null || batches == null) return false; this.m_Solver = solver; foreach (T batch in batches) batch.AddToSolver(m_Solver); return true; } public bool RemoveFromSolver() { if (this.m_Solver == null || batches == null) return false; foreach (T batch in batches) batch.RemoveFromSolver(m_Solver); this.m_Solver = null; return true; } } }