using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace BansheeGz.BGSpline.Curve
|
|
{
|
|
/// <summary>
|
|
/// Abstract superclass for components.
|
|
///
|
|
/// Current Requirements:
|
|
/// 1) editor should be extended from BGCcEditor
|
|
/// 2) Should have a descriptor.
|
|
/// 3) Only one RequireComponent of type BGCc (parent). Parent is another Cc component, this component is totally depends on and can not operate without it.
|
|
///
|
|
/// Cc stands for "Curve's component"
|
|
/// </summary>
|
|
[RequireComponent(typeof (BGCurve))]
|
|
public abstract class BGCc : MonoBehaviour
|
|
{
|
|
/// <summary>if component's parameters changed </summary>
|
|
public event EventHandler ChangedParams;
|
|
|
|
/// <summary>Any information Cc wants to provide (for editor)</summary>
|
|
public virtual string Info
|
|
{
|
|
get { return null; }
|
|
}
|
|
|
|
/// <summary>Warning (for editor)</summary>
|
|
public virtual string Warning
|
|
{
|
|
get { return null; }
|
|
}
|
|
|
|
/// <summary>Error if something is wrong (for editor)</summary>
|
|
public virtual string Error
|
|
{
|
|
get { return null; }
|
|
}
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
// ============================================== !!! This is editor only field
|
|
#pragma warning disable 0414
|
|
//should CC's handles be shown in SceneView
|
|
[SerializeField] private bool showHandles = true;
|
|
#pragma warning restore 0414
|
|
#endif
|
|
|
|
/// <summary>Does this Cc supports handles in SceneView?</summary>
|
|
public virtual bool SupportHandles
|
|
{
|
|
get { return false; }
|
|
}
|
|
|
|
/// <summary>Does this Cc supports some adjustable settings for handles in SceneView?</summary>
|
|
public virtual bool SupportHandlesSettings
|
|
{
|
|
get { return false; }
|
|
}
|
|
|
|
//=============================================== Curve
|
|
private BGCurve curve;
|
|
|
|
public BGCurve Curve
|
|
{
|
|
get
|
|
{
|
|
//do not replace with ??
|
|
if (curve == null) curve = GetComponent<BGCurve>();
|
|
return curve;
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================== Parent
|
|
//parent is another Cc component, this component is totally depends on and can not operate without it
|
|
[SerializeField] private BGCc parent;
|
|
|
|
public void SetParent(BGCc parent)
|
|
{
|
|
this.parent = parent;
|
|
}
|
|
|
|
public T GetParent<T>() where T : BGCc
|
|
{
|
|
return (T) GetParent(typeof (T));
|
|
}
|
|
|
|
public BGCc GetParent(Type type)
|
|
{
|
|
if (parent != null) return parent;
|
|
parent = (BGCc) GetComponent(type);
|
|
return parent;
|
|
}
|
|
|
|
|
|
//=============================================== Name
|
|
//you can name your Cc
|
|
[SerializeField] private string ccName;
|
|
|
|
public string CcName
|
|
{
|
|
get { return string.IsNullOrEmpty(ccName) ? "" + GetInstanceID() : ccName; }
|
|
set { ccName = value; }
|
|
}
|
|
|
|
//=============================================== Transaction
|
|
//transaction is for events grouping only
|
|
private int transactionLevel;
|
|
|
|
//=============================================== Descriptor
|
|
//descriptor is used to add icon, name and description to Cc
|
|
private CcDescriptor descriptor;
|
|
|
|
|
|
public CcDescriptor Descriptor
|
|
{
|
|
get
|
|
{
|
|
//do not replace with ??
|
|
if (descriptor == null) descriptor = GetDescriptor(GetType());
|
|
return descriptor;
|
|
}
|
|
}
|
|
|
|
// www page, containing help info
|
|
public virtual string HelpURL
|
|
{
|
|
get
|
|
{
|
|
var helpUrl = GetHelpUrl(GetType());
|
|
return helpUrl == null ? null : helpUrl.URL;
|
|
}
|
|
}
|
|
|
|
//=================================================== Unity Methods
|
|
public virtual void Start()
|
|
{
|
|
}
|
|
|
|
public virtual void OnDestroy()
|
|
{
|
|
}
|
|
|
|
//=================================================== Methods
|
|
//in case any param changed
|
|
protected bool ParamChanged<T>(ref T oldValue, T newValue)
|
|
{
|
|
var oldValueNull = oldValue == null;
|
|
var newValueNull = newValue == null;
|
|
if (oldValueNull && newValueNull) return false;
|
|
|
|
if (oldValueNull == newValueNull && oldValue.Equals(newValue)) return false;
|
|
|
|
oldValue = newValue;
|
|
FireChangedParams();
|
|
return true;
|
|
}
|
|
|
|
|
|
/// <summary> if component has an error</summary>
|
|
public bool HasError()
|
|
{
|
|
return !string.IsNullOrEmpty(Error);
|
|
}
|
|
|
|
/// <summary> if component has a warning</summary>
|
|
public bool HasWarning()
|
|
{
|
|
return !string.IsNullOrEmpty(Warning);
|
|
}
|
|
|
|
//utility method for chosing error message
|
|
protected string ChoseMessage(string baseError, Func<string> childError)
|
|
{
|
|
return !string.IsNullOrEmpty(baseError) ? baseError : childError();
|
|
}
|
|
|
|
/// <summary> if any parameter changed</summary>
|
|
public void FireChangedParams()
|
|
{
|
|
if (ChangedParams != null && transactionLevel == 0) ChangedParams(this, null);
|
|
}
|
|
|
|
/// <summary> component was added via editor menu</summary>
|
|
public virtual void AddedInEditor()
|
|
{
|
|
}
|
|
|
|
/// <summary> get parent Cc class</summary>
|
|
public Type GetParentClass()
|
|
{
|
|
return GetParentClass(GetType());
|
|
}
|
|
|
|
/// <summary> get parent Cc class</summary>
|
|
public static Type GetParentClass(Type ccType)
|
|
{
|
|
//gather required
|
|
var requiredList = BGReflectionAdapter.GetCustomAttributes(ccType, typeof (RequireComponent), true);
|
|
if (requiredList.Length == 0) return null;
|
|
|
|
var result = new List<Type>();
|
|
foreach (var item in requiredList)
|
|
{
|
|
var requiredComponent = (RequireComponent) item;
|
|
CheckRequired(requiredComponent.m_Type0, result);
|
|
CheckRequired(requiredComponent.m_Type1, result);
|
|
CheckRequired(requiredComponent.m_Type2, result);
|
|
}
|
|
|
|
if (result.Count == 0) return null;
|
|
if (result.Count > 1) throw new CcException(ccType + " has more than one parent (extended from BGCc class), calculated by RequireComponent attribute");
|
|
return result[0];
|
|
}
|
|
|
|
//add class if it's not abstract and a child of BGCc
|
|
private static void CheckRequired(Type type, List<Type> result)
|
|
{
|
|
if (type == null || BGReflectionAdapter.IsAbstract(type) || !BGReflectionAdapter.IsClass(type) || !BGReflectionAdapter.IsSubclassOf(type,typeof (BGCc)))return;
|
|
|
|
result.Add(type);
|
|
}
|
|
|
|
/// <summary> Check standard Unity's DisallowMultipleComponent attribute </summary>
|
|
public static bool IsSingle(Type ccType)
|
|
{
|
|
return BGReflectionAdapter.GetCustomAttributes(ccType, typeof(DisallowMultipleComponent), true).Length > 0;
|
|
}
|
|
|
|
/// <summary> This is used to group events. Use it to change several params and fire one single event</summary>
|
|
public void Transaction(Action action)
|
|
{
|
|
transactionLevel++;
|
|
try
|
|
{
|
|
action();
|
|
}
|
|
finally
|
|
{
|
|
transactionLevel--;
|
|
if (transactionLevel == 0)
|
|
{
|
|
if (ChangedParams != null) ChangedParams(this, null);
|
|
}
|
|
}
|
|
}
|
|
|
|
//======================== descriptor for Editor
|
|
/// <summary>this descriptor is used by editor</summary>
|
|
[AttributeUsage(AttributeTargets.Class)]
|
|
public class CcDescriptor : Attribute
|
|
{
|
|
/// <summary>Component's name</summary>
|
|
public string Name { get; set; }
|
|
/// <summary>Component's desciption</summary>
|
|
public string Description { get; set; }
|
|
/// <summary>Component's icon</summary>
|
|
public string Image { get; set; }
|
|
}
|
|
/// <summary>Retrieves the descriptor from "type"</summary>
|
|
public static CcDescriptor GetDescriptor(Type type)
|
|
{
|
|
var propertyInfos = BGReflectionAdapter.GetCustomAttributes(type, typeof(CcDescriptor), false);
|
|
if (propertyInfos.Length > 0) return (CcDescriptor) propertyInfos[0];
|
|
return null;
|
|
}
|
|
|
|
// get Unity's HelpURLAttribute attrubute
|
|
private static HelpURLAttribute GetHelpUrl(Type type)
|
|
{
|
|
var propertyInfos = BGReflectionAdapter.GetCustomAttributes(type,typeof (HelpURLAttribute), false);
|
|
if (propertyInfos.Length > 0) return (HelpURLAttribute) propertyInfos[0];
|
|
return null;
|
|
}
|
|
|
|
//======================== Exception
|
|
/// <summary>Exception if something is wrong with Cc related stuff</summary>
|
|
public class CcException :Exception
|
|
{
|
|
public CcException(string message) : base(message)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|