提交Unity 联机Pro

This commit is contained in:
PC-20230316NUNE\Administrator
2024-08-17 14:27:18 +08:00
parent f00193b000
commit 894100ae37
7448 changed files with 854473 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 1612d99e81c5543498f1110f9085a789
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -0,0 +1,938 @@

#if !UNITY_5 && !UNITY_5_3_OR_NEWER && UNITY_EDITOR
using System;
using System.Diagnostics;
#pragma warning disable 1591
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedAutoPropertyAccessor.Global
// ReSharper disable IntroduceOptionalParameters.Global
// ReSharper disable MemberCanBeProtected.Global
// ReSharper disable InconsistentNaming
namespace JetBrains.Annotations
{
/// <summary>
/// Indicates that the value of the marked element could be <c>null</c> sometimes,
/// so the check for <c>null</c> is necessary before its usage
/// </summary>
/// <example><code>
/// [CanBeNull] public object Test() { return null; }
/// public void UseTest() {
/// var p = Test();
/// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException'
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class CanBeNullAttribute : Attribute { }
/// <summary>
/// Indicates that the value of the marked element could never be <c>null</c>
/// </summary>
/// <example><code>
/// [NotNull] public object Foo() {
/// return null; // Warning: Possible 'null' assignment
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class NotNullAttribute : Attribute { }
/// <summary>
/// Indicates that collection or enumerable value does not contain null elements
/// </summary>
[AttributeUsage(
AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
AttributeTargets.Delegate | AttributeTargets.Field)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class ItemNotNullAttribute : Attribute { }
/// <summary>
/// Indicates that collection or enumerable value can contain null elements
/// </summary>
[AttributeUsage(
AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
AttributeTargets.Delegate | AttributeTargets.Field)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class ItemCanBeNullAttribute : Attribute { }
/// <summary>
/// Indicates that the marked method builds string by format pattern and (optional) arguments.
/// Parameter, which contains format string, should be given in constructor. The format string
/// should be in <see cref="string.Format(IFormatProvider,string,object[])"/>-like form
/// </summary>
/// <example><code>
/// [StringFormatMethod("message")]
/// public void ShowError(string message, params object[] args) { /* do something */ }
/// public void Foo() {
/// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Delegate)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class StringFormatMethodAttribute : Attribute
{
/// <param name="formatParameterName">
/// Specifies which parameter of an annotated method should be treated as format-string
/// </param>
public StringFormatMethodAttribute(string formatParameterName)
{
FormatParameterName = formatParameterName;
}
public string FormatParameterName { get; private set; }
}
/// <summary>
/// For a parameter that is expected to be one of the limited set of values.
/// Specify fields of which type should be used as values for this parameter.
/// </summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class ValueProviderAttribute : Attribute
{
public ValueProviderAttribute(string name)
{
Name = name;
}
[NotNull]
public string Name { get; private set; }
}
/// <summary>
/// Indicates that the function argument should be string literal and match one
/// of the parameters of the caller function. For example, ReSharper annotates
/// the parameter of <see cref="System.ArgumentNullException"/>
/// </summary>
/// <example><code>
/// public void Foo(string param) {
/// if (param == null)
/// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class InvokerParameterNameAttribute : Attribute { }
/// <summary>
/// Indicates that the method is contained in a type that implements
/// <c>System.ComponentModel.INotifyPropertyChanged</c> interface and this method
/// is used to notify that some property value changed
/// </summary>
/// <remarks>
/// The method should be non-static and conform to one of the supported signatures:
/// <list>
/// <item><c>NotifyChanged(string)</c></item>
/// <item><c>NotifyChanged(params string[])</c></item>
/// <item><c>NotifyChanged{T}(Expression{Func{T}})</c></item>
/// <item><c>NotifyChanged{T,U}(Expression{Func{T,U}})</c></item>
/// <item><c>SetProperty{T}(ref T, T, string)</c></item>
/// </list>
/// </remarks>
/// <example><code>
/// public class Foo : INotifyPropertyChanged {
/// public event PropertyChangedEventHandler PropertyChanged;
/// [NotifyPropertyChangedInvocator]
/// protected virtual void NotifyChanged(string propertyName) { ... }
///
/// private string _name;
/// public string Name {
/// get { return _name; }
/// set { _name = value; NotifyChanged("LastName"); /* Warning */ }
/// }
/// }
/// </code>
/// Examples of generated notifications:
/// <list>
/// <item><c>NotifyChanged("Property")</c></item>
/// <item><c>NotifyChanged(() =&gt; Property)</c></item>
/// <item><c>NotifyChanged((VM x) =&gt; x.Property)</c></item>
/// <item><c>SetProperty(ref myField, value, "Property")</c></item>
/// </list>
/// </example>
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute
{
public NotifyPropertyChangedInvocatorAttribute() { }
public NotifyPropertyChangedInvocatorAttribute(string parameterName)
{
ParameterName = parameterName;
}
public string ParameterName { get; private set; }
}
/// <summary>
/// Describes dependency between method input and output
/// </summary>
/// <syntax>
/// <p>Function Definition Table syntax:</p>
/// <list>
/// <item>FDT ::= FDTRow [;FDTRow]*</item>
/// <item>FDTRow ::= Input =&gt; Output | Output &lt;= Input</item>
/// <item>Input ::= ParameterName: Value [, Input]*</item>
/// <item>Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value}</item>
/// <item>Value ::= true | false | null | notnull | canbenull</item>
/// </list>
/// If method has single input parameter, it's name could be omitted.<br/>
/// Using <c>halt</c> (or <c>void</c>/<c>nothing</c>, which is the same)
/// for method output means that the methos doesn't return normally.<br/>
/// <c>canbenull</c> annotation is only applicable for output parameters.<br/>
/// You can use multiple <c>[ContractAnnotation]</c> for each FDT row,
/// or use single attribute with rows separated by semicolon.<br/>
/// </syntax>
/// <examples><list>
/// <item><code>
/// [ContractAnnotation("=> halt")]
/// public void TerminationMethod()
/// </code></item>
/// <item><code>
/// [ContractAnnotation("halt &lt;= condition: false")]
/// public void Assert(bool condition, string text) // regular assertion method
/// </code></item>
/// <item><code>
/// [ContractAnnotation("s:null => true")]
/// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty()
/// </code></item>
/// <item><code>
/// // A method that returns null if the parameter is null,
/// // and not null if the parameter is not null
/// [ContractAnnotation("null => null; notnull => notnull")]
/// public object Transform(object data)
/// </code></item>
/// <item><code>
/// [ContractAnnotation("s:null=>false; =>true,result:notnull; =>false, result:null")]
/// public bool TryParse(string s, out Person result)
/// </code></item>
/// </list></examples>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class ContractAnnotationAttribute : Attribute
{
public ContractAnnotationAttribute([NotNull] string contract)
: this(contract, false) { }
public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates)
{
Contract = contract;
ForceFullStates = forceFullStates;
}
public string Contract { get; private set; }
public bool ForceFullStates { get; private set; }
}
/// <summary>
/// Indicates that marked element should be localized or not
/// </summary>
/// <example><code>
/// [LocalizationRequiredAttribute(true)]
/// public class Foo {
/// private string str = "my string"; // Warning: Localizable string
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.All)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class LocalizationRequiredAttribute : Attribute
{
public LocalizationRequiredAttribute() : this(true) { }
public LocalizationRequiredAttribute(bool required)
{
Required = required;
}
public bool Required { get; private set; }
}
/// <summary>
/// Indicates that the value of the marked type (or its derivatives)
/// cannot be compared using '==' or '!=' operators and <c>Equals()</c>
/// should be used instead. However, using '==' or '!=' for comparison
/// with <c>null</c> is always permitted.
/// </summary>
/// <example><code>
/// [CannotApplyEqualityOperator]
/// class NoEquality { }
/// class UsesNoEquality {
/// public void Test() {
/// var ca1 = new NoEquality();
/// var ca2 = new NoEquality();
/// if (ca1 != null) { // OK
/// bool condition = ca1 == ca2; // Warning
/// }
/// }
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class CannotApplyEqualityOperatorAttribute : Attribute { }
/// <summary>
/// When applied to a target attribute, specifies a requirement for any type marked
/// with the target attribute to implement or inherit specific type or types.
/// </summary>
/// <example><code>
/// [BaseTypeRequired(typeof(IComponent)] // Specify requirement
/// public class ComponentAttribute : Attribute { }
/// [Component] // ComponentAttribute requires implementing IComponent interface
/// public class MyComponent : IComponent { }
/// </code></example>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
[BaseTypeRequired(typeof(Attribute))]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class BaseTypeRequiredAttribute : Attribute
{
public BaseTypeRequiredAttribute([NotNull] Type baseType)
{
BaseType = baseType;
}
[NotNull]
public Type BaseType { get; private set; }
}
/// <summary>
/// Indicates that the marked symbol is used implicitly
/// (e.g. via reflection, in external library), so this symbol
/// will not be marked as unused (as well as by other usage inspections)
/// </summary>
[AttributeUsage(AttributeTargets.All)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class UsedImplicitlyAttribute : Attribute
{
public UsedImplicitlyAttribute()
: this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { }
public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags)
: this(useKindFlags, ImplicitUseTargetFlags.Default) { }
public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags)
: this(ImplicitUseKindFlags.Default, targetFlags) { }
public UsedImplicitlyAttribute(
ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
{
UseKindFlags = useKindFlags;
TargetFlags = targetFlags;
}
public ImplicitUseKindFlags UseKindFlags { get; private set; }
public ImplicitUseTargetFlags TargetFlags { get; private set; }
}
/// <summary>
/// Should be used on attributes and causes ReSharper
/// to not mark symbols marked with such attributes as unused
/// (as well as by other usage inspections)
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class MeansImplicitUseAttribute : Attribute
{
public MeansImplicitUseAttribute()
: this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { }
public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags)
: this(useKindFlags, ImplicitUseTargetFlags.Default) { }
public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags)
: this(ImplicitUseKindFlags.Default, targetFlags) { }
public MeansImplicitUseAttribute(
ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
{
UseKindFlags = useKindFlags;
TargetFlags = targetFlags;
}
[UsedImplicitly]
public ImplicitUseKindFlags UseKindFlags { get; private set; }
[UsedImplicitly]
public ImplicitUseTargetFlags TargetFlags { get; private set; }
}
[Flags]
public enum ImplicitUseKindFlags
{
Default = Access | Assign | InstantiatedWithFixedConstructorSignature,
/// <summary>Only entity marked with attribute considered used</summary>
Access = 1,
/// <summary>Indicates implicit assignment to a member</summary>
Assign = 2,
/// <summary>
/// Indicates implicit instantiation of a type with fixed constructor signature.
/// That means any unused constructor parameters won't be reported as such.
/// </summary>
InstantiatedWithFixedConstructorSignature = 4,
/// <summary>Indicates implicit instantiation of a type</summary>
InstantiatedNoFixedConstructorSignature = 8,
}
/// <summary>
/// Specify what is considered used implicitly when marked
/// with <see cref="MeansImplicitUseAttribute"/> or <see cref="UsedImplicitlyAttribute"/>
/// </summary>
[Flags]
public enum ImplicitUseTargetFlags
{
Default = Itself,
Itself = 1,
/// <summary>Members of entity marked with attribute are considered used</summary>
Members = 2,
/// <summary>Entity marked with attribute and all its members considered used</summary>
WithMembers = Itself | Members
}
/// <summary>
/// This attribute is intended to mark publicly available API
/// which should not be removed and so is treated as used
/// </summary>
[MeansImplicitUse]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class PublicAPIAttribute : Attribute
{
public PublicAPIAttribute() { }
public PublicAPIAttribute([NotNull] string comment)
{
Comment = comment;
}
public string Comment { get; private set; }
}
/// <summary>
/// Tells code analysis engine if the parameter is completely handled
/// when the invoked method is on stack. If the parameter is a delegate,
/// indicates that delegate is executed while the method is executed.
/// If the parameter is an enumerable, indicates that it is enumerated
/// while the method is executed
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class InstantHandleAttribute : Attribute { }
/// <summary>
/// Indicates that a method does not make any observable state changes.
/// The same as <c>System.Diagnostics.Contracts.PureAttribute</c>
/// </summary>
/// <example><code>
/// [Pure] private int Multiply(int x, int y) { return x * y; }
/// public void Foo() {
/// const int a = 2, b = 2;
/// Multiply(a, b); // Waring: Return value of pure method is not used
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class PureAttribute : Attribute { }
/// <summary>
/// Indicates that a parameter is a path to a file or a folder within a web project.
/// Path can be relative or absolute, starting from web root (~)
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public class PathReferenceAttribute : Attribute
{
public PathReferenceAttribute() { }
public PathReferenceAttribute([PathReference] string basePath)
{
BasePath = basePath;
}
public string BasePath { get; private set; }
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute
{
public AspMvcAreaMasterLocationFormatAttribute(string format)
{
Format = format;
}
public string Format { get; private set; }
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute
{
public AspMvcAreaPartialViewLocationFormatAttribute(string format)
{
Format = format;
}
public string Format { get; private set; }
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute
{
public AspMvcAreaViewLocationFormatAttribute(string format)
{
Format = format;
}
public string Format { get; private set; }
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcMasterLocationFormatAttribute : Attribute
{
public AspMvcMasterLocationFormatAttribute(string format)
{
Format = format;
}
public string Format { get; private set; }
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute
{
public AspMvcPartialViewLocationFormatAttribute(string format)
{
Format = format;
}
public string Format { get; private set; }
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcViewLocationFormatAttribute : Attribute
{
public AspMvcViewLocationFormatAttribute(string format)
{
Format = format;
}
public string Format { get; private set; }
}
/// <summary>
/// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
/// is an MVC action. If applied to a method, the MVC action name is calculated
/// implicitly from the context. Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcActionAttribute : Attribute
{
public AspMvcActionAttribute() { }
public AspMvcActionAttribute(string anonymousProperty)
{
AnonymousProperty = anonymousProperty;
}
public string AnonymousProperty { get; private set; }
}
/// <summary>
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC area.
/// Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcAreaAttribute : PathReferenceAttribute
{
public AspMvcAreaAttribute() { }
public AspMvcAreaAttribute(string anonymousProperty)
{
AnonymousProperty = anonymousProperty;
}
public string AnonymousProperty { get; private set; }
}
/// <summary>
/// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is
/// an MVC controller. If applied to a method, the MVC controller name is calculated
/// implicitly from the context. Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcControllerAttribute : Attribute
{
public AspMvcControllerAttribute() { }
public AspMvcControllerAttribute(string anonymousProperty)
{
AnonymousProperty = anonymousProperty;
}
public string AnonymousProperty { get; private set; }
}
/// <summary>
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC Master. Use this attribute
/// for custom wrappers similar to <c>System.Web.Mvc.Controller.View(String, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcMasterAttribute : Attribute { }
/// <summary>
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC model type. Use this attribute
/// for custom wrappers similar to <c>System.Web.Mvc.Controller.View(String, Object)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcModelTypeAttribute : Attribute { }
/// <summary>
/// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC
/// partial view. If applied to a method, the MVC partial view name is calculated implicitly
/// from the context. Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcPartialViewAttribute : PathReferenceAttribute { }
/// <summary>
/// ASP.NET MVC attribute. Allows disabling inspections for MVC views within a class or a method
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcSupressViewErrorAttribute : Attribute { }
/// <summary>
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template.
/// Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcDisplayTemplateAttribute : Attribute { }
/// <summary>
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC editor template.
/// Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcEditorTemplateAttribute : Attribute { }
/// <summary>
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC template.
/// Use this attribute for custom wrappers similar to
/// <c>System.ComponentModel.DataAnnotations.UIHintAttribute(System.String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcTemplateAttribute : Attribute { }
/// <summary>
/// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
/// is an MVC view. If applied to a method, the MVC view name is calculated implicitly
/// from the context. Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Controller.View(Object)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcViewAttribute : PathReferenceAttribute { }
/// <summary>
/// ASP.NET MVC attribute. When applied to a parameter of an attribute,
/// indicates that this parameter is an MVC action name
/// </summary>
/// <example><code>
/// [ActionName("Foo")]
/// public ActionResult Login(string returnUrl) {
/// ViewBag.ReturnUrl = Url.Action("Foo"); // OK
/// return RedirectToAction("Bar"); // Error: Cannot resolve action
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMvcActionSelectorAttribute : Attribute { }
[AttributeUsage(
AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class HtmlElementAttributesAttribute : Attribute
{
public HtmlElementAttributesAttribute() { }
public HtmlElementAttributesAttribute(string name)
{
Name = name;
}
public string Name { get; private set; }
}
[AttributeUsage(
AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class HtmlAttributeValueAttribute : Attribute
{
public HtmlAttributeValueAttribute([NotNull] string name)
{
Name = name;
}
[NotNull]
public string Name { get; private set; }
}
/// <summary>
/// Razor attribute. Indicates that a parameter or a method is a Razor section.
/// Use this attribute for custom wrappers similar to
/// <c>System.Web.WebPages.WebPageBase.RenderSection(String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class RazorSectionAttribute : Attribute { }
/// <summary>
/// Indicates how method invocation affects content of the collection
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class CollectionAccessAttribute : Attribute
{
public CollectionAccessAttribute(CollectionAccessType collectionAccessType)
{
CollectionAccessType = collectionAccessType;
}
public CollectionAccessType CollectionAccessType { get; private set; }
}
[Flags]
public enum CollectionAccessType
{
/// <summary>Method does not use or modify content of the collection</summary>
None = 0,
/// <summary>Method only reads content of the collection but does not modify it</summary>
Read = 1,
/// <summary>Method can change content of the collection but does not add new elements</summary>
ModifyExistingContent = 2,
/// <summary>Method can add new elements to the collection</summary>
UpdatedContent = ModifyExistingContent | 4
}
/// <summary>
/// Indicates that the marked method is assertion method, i.e. it halts control flow if
/// one of the conditions is satisfied. To set the condition, mark one of the parameters with
/// <see cref="AssertionConditionAttribute"/> attribute
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AssertionMethodAttribute : Attribute { }
/// <summary>
/// Indicates the condition parameter of the assertion method. The method itself should be
/// marked by <see cref="AssertionMethodAttribute"/> attribute. The mandatory argument of
/// the attribute is the assertion type.
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AssertionConditionAttribute : Attribute
{
public AssertionConditionAttribute(AssertionConditionType conditionType)
{
ConditionType = conditionType;
}
public AssertionConditionType ConditionType { get; private set; }
}
/// <summary>
/// Specifies assertion type. If the assertion method argument satisfies the condition,
/// then the execution continues. Otherwise, execution is assumed to be halted
/// </summary>
public enum AssertionConditionType
{
/// <summary>Marked parameter should be evaluated to true</summary>
IS_TRUE = 0,
/// <summary>Marked parameter should be evaluated to false</summary>
IS_FALSE = 1,
/// <summary>Marked parameter should be evaluated to null value</summary>
IS_NULL = 2,
/// <summary>Marked parameter should be evaluated to not null value</summary>
IS_NOT_NULL = 3,
}
/// <summary>
/// Indicates that the marked method unconditionally terminates control flow execution.
/// For example, it could unconditionally throw exception
/// </summary>
[Obsolete("Use [ContractAnnotation('=> halt')] instead")]
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class TerminatesProgramAttribute : Attribute { }
/// <summary>
/// Indicates that method is pure LINQ method, with postponed enumeration (like Enumerable.Select,
/// .Where). This annotation allows inference of [InstantHandle] annotation for parameters
/// of delegate type by analyzing LINQ method chains.
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class LinqTunnelAttribute : Attribute { }
/// <summary>
/// Indicates that IEnumerable, passed as parameter, is not enumerated.
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class NoEnumerationAttribute : Attribute { }
/// <summary>
/// Indicates that parameter is regular expression pattern.
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class RegexPatternAttribute : Attribute { }
/// <summary>
/// XAML attribute. Indicates the type that has <c>ItemsSource</c> property and should be
/// treated as <c>ItemsControl</c>-derived type, to enable inner items <c>DataContext</c>
/// type resolve.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class XamlItemsControlAttribute : Attribute { }
/// <summary>
/// XAML attibute. Indicates the property of some <c>BindingBase</c>-derived type, that
/// is used to bind some item of <c>ItemsControl</c>-derived type. This annotation will
/// enable the <c>DataContext</c> type resolve for XAML bindings for such properties.
/// </summary>
/// <remarks>
/// Property should have the tree ancestor of the <c>ItemsControl</c> type or
/// marked with the <see cref="XamlItemsControlAttribute"/> attribute.
/// </remarks>
[AttributeUsage(AttributeTargets.Property)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class XamlItemBindingOfItemsControlAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspChildControlTypeAttribute : Attribute
{
public AspChildControlTypeAttribute(string tagName, Type controlType)
{
TagName = tagName;
ControlType = controlType;
}
public string TagName { get; private set; }
public Type ControlType { get; private set; }
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspDataFieldAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspDataFieldsAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Property)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspMethodPropertyAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspRequiredAttributeAttribute : Attribute
{
public AspRequiredAttributeAttribute([NotNull] string attribute)
{
Attribute = attribute;
}
public string Attribute { get; private set; }
}
[AttributeUsage(AttributeTargets.Property)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class AspTypePropertyAttribute : Attribute
{
public bool CreateConstructorReferences { get; private set; }
public AspTypePropertyAttribute(bool createConstructorReferences)
{
CreateConstructorReferences = createConstructorReferences;
}
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class RazorImportNamespaceAttribute : Attribute
{
public RazorImportNamespaceAttribute(string name)
{
Name = name;
}
public string Name { get; private set; }
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class RazorInjectionAttribute : Attribute
{
public RazorInjectionAttribute(string type, string fieldName)
{
Type = type;
FieldName = fieldName;
}
public string Type { get; private set; }
public string FieldName { get; private set; }
}
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class RazorHelperCommonAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Property)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class RazorLayoutAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class RazorWriteLiteralMethodAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Method)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class RazorWriteMethodAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Parameter)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class RazorWriteMethodParameterAttribute : Attribute { }
/// <summary>
/// Prevents the Member Reordering feature from tossing members of the marked class.
/// </summary>
/// <remarks>
/// The attribute must be mentioned in your member reordering patterns.
/// </remarks>
[AttributeUsage(AttributeTargets.All)]
[Conditional("JETBRAINS_ANNOTATIONS")]
public sealed class NoReorder : Attribute { }
}
#endif

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 643a949c9c71dd94a970b2573c29fe67
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,626 @@
/*
* Copyright (c) 2013 Calvin Rien
*
* Based on the JSON parser by Patrick van Bergen
* http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html
*
* Simplified it so that it doesn't throw exceptions
* and can be used in Unity iPhone with maximum code stripping.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System.Globalization;
namespace SRF
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
// Example usage:
//
// using UnityEngine;
// using System.Collections;
// using System.Collections.Generic;
// using MiniJSON;
//
// public class MiniJSONTest : MonoBehaviour {
// void Start () {
// var jsonString = "{ \"array\": [1.44,2,3], " +
// "\"object\": {\"key1\":\"value1\", \"key2\":256}, " +
// "\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " +
// "\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " +
// "\"int\": 65536, " +
// "\"float\": 3.1415926, " +
// "\"bool\": true, " +
// "\"null\": null }";
//
// var dict = Json.Deserialize(jsonString) as Dictionary<string,object>;
//
// Debug.Log("deserialized: " + dict.GetType());
// Debug.Log("dict['array'][0]: " + ((List<object>) dict["array"])[0]);
// Debug.Log("dict['string']: " + (string) dict["string"]);
// Debug.Log("dict['float']: " + (double) dict["float"]); // floats come out as doubles
// Debug.Log("dict['int']: " + (long) dict["int"]); // ints come out as longs
// Debug.Log("dict['unicode']: " + (string) dict["unicode"]);
//
// var str = Json.Serialize(dict);
//
// Debug.Log("serialized: " + str);
// }
// }
/// <summary>
/// This class encodes and decodes JSON strings.
/// Spec. details, see http://www.json.org/
/// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary.
/// All numbers are parsed to doubles.
/// </summary>
public static class Json
{
/// <summary>
/// Parses the string json into a value
/// </summary>
/// <param name="json">A JSON string.</param>
/// <returns>An List&lt;object&gt;, a Dictionary&lt;string, object&gt;, a double, an integer,a string, null, true, or false</returns>
public static object Deserialize(string json)
{
// save the string for debug information
if (json == null)
{
return null;
}
return Parser.Parse(json);
}
/// <summary>
/// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string
/// </summary>
/// <param name="json">A Dictionary&lt;string, object&gt; / List&lt;object&gt;</param>
/// <returns>A JSON encoded string, or null if object 'json' is not serializable</returns>
public static string Serialize(object obj)
{
return Serializer.Serialize(obj);
}
private sealed class Parser : IDisposable
{
private const string WORD_BREAK = "{}[],:\"";
private StringReader json;
private Parser(string jsonString)
{
json = new StringReader(jsonString);
}
private char PeekChar
{
get { return Convert.ToChar(json.Peek()); }
}
private char NextChar
{
get { return Convert.ToChar(json.Read()); }
}
private string NextWord
{
get
{
var word = new StringBuilder();
while (!IsWordBreak(PeekChar))
{
word.Append(NextChar);
if (json.Peek() == -1)
{
break;
}
}
return word.ToString();
}
}
private TOKEN NextToken
{
get
{
EatWhitespace();
if (json.Peek() == -1)
{
return TOKEN.NONE;
}
switch (PeekChar)
{
case '{':
return TOKEN.CURLY_OPEN;
case '}':
json.Read();
return TOKEN.CURLY_CLOSE;
case '[':
return TOKEN.SQUARED_OPEN;
case ']':
json.Read();
return TOKEN.SQUARED_CLOSE;
case ',':
json.Read();
return TOKEN.COMMA;
case '"':
return TOKEN.STRING;
case ':':
return TOKEN.COLON;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
return TOKEN.NUMBER;
}
switch (NextWord)
{
case "false":
return TOKEN.FALSE;
case "true":
return TOKEN.TRUE;
case "null":
return TOKEN.NULL;
}
return TOKEN.NONE;
}
}
public void Dispose()
{
json.Dispose();
json = null;
}
public static bool IsWordBreak(char c)
{
return char.IsWhiteSpace(c) || WORD_BREAK.IndexOf(c) != -1;
}
public static object Parse(string jsonString)
{
using (var instance = new Parser(jsonString))
{
return instance.ParseValue();
}
}
private Dictionary<string, object> ParseObject()
{
var table = new Dictionary<string, object>();
// ditch opening brace
json.Read();
// {
while (true)
{
switch (NextToken)
{
case TOKEN.NONE:
return null;
case TOKEN.COMMA:
continue;
case TOKEN.CURLY_CLOSE:
return table;
default:
// name
var name = ParseString();
if (name == null)
{
return null;
}
// :
if (NextToken != TOKEN.COLON)
{
return null;
}
// ditch the colon
json.Read();
// value
table[name] = ParseValue();
break;
}
}
}
private List<object> ParseArray()
{
var array = new List<object>();
// ditch opening bracket
json.Read();
// [
var parsing = true;
while (parsing)
{
var nextToken = NextToken;
switch (nextToken)
{
case TOKEN.NONE:
return null;
case TOKEN.COMMA:
continue;
case TOKEN.SQUARED_CLOSE:
parsing = false;
break;
default:
var value = ParseByToken(nextToken);
array.Add(value);
break;
}
}
return array;
}
private object ParseValue()
{
var nextToken = NextToken;
return ParseByToken(nextToken);
}
private object ParseByToken(TOKEN token)
{
switch (token)
{
case TOKEN.STRING:
return ParseString();
case TOKEN.NUMBER:
return ParseNumber();
case TOKEN.CURLY_OPEN:
return ParseObject();
case TOKEN.SQUARED_OPEN:
return ParseArray();
case TOKEN.TRUE:
return true;
case TOKEN.FALSE:
return false;
case TOKEN.NULL:
return null;
default:
return null;
}
}
private string ParseString()
{
var s = new StringBuilder();
char c;
// ditch opening quote
json.Read();
var parsing = true;
while (parsing)
{
if (json.Peek() == -1)
{
parsing = false;
break;
}
c = NextChar;
switch (c)
{
case '"':
parsing = false;
break;
case '\\':
if (json.Peek() == -1)
{
parsing = false;
break;
}
c = NextChar;
switch (c)
{
case '"':
case '\\':
case '/':
s.Append(c);
break;
case 'b':
s.Append('\b');
break;
case 'f':
s.Append('\f');
break;
case 'n':
s.Append('\n');
break;
case 'r':
s.Append('\r');
break;
case 't':
s.Append('\t');
break;
case 'u':
var hex = new char[4];
for (var i = 0; i < 4; i++)
{
hex[i] = NextChar;
}
s.Append((char) Convert.ToInt32(new string(hex), 16));
break;
}
break;
default:
s.Append(c);
break;
}
}
return s.ToString();
}
private object ParseNumber()
{
var number = NextWord;
if (number.IndexOf('.') == -1)
{
long parsedInt;
long.TryParse(number, out parsedInt);
return parsedInt;
}
double parsedDouble;
double.TryParse(number, out parsedDouble);
return parsedDouble;
}
private void EatWhitespace()
{
while (char.IsWhiteSpace(PeekChar))
{
json.Read();
if (json.Peek() == -1)
{
break;
}
}
}
private enum TOKEN
{
NONE,
CURLY_OPEN,
CURLY_CLOSE,
SQUARED_OPEN,
SQUARED_CLOSE,
COLON,
COMMA,
STRING,
NUMBER,
TRUE,
FALSE,
NULL
};
}
private sealed class Serializer
{
private StringBuilder builder;
private Serializer()
{
builder = new StringBuilder();
}
public static string Serialize(object obj)
{
var instance = new Serializer();
instance.SerializeValue(obj);
return instance.builder.ToString();
}
private void SerializeValue(object value)
{
IList asList;
IDictionary asDict;
string asStr;
if (value == null)
{
builder.Append("null");
}
else if ((asStr = value as string) != null)
{
SerializeString(asStr);
}
else if (value is bool)
{
builder.Append((bool) value ? "true" : "false");
}
else if ((asList = value as IList) != null)
{
SerializeArray(asList);
}
else if ((asDict = value as IDictionary) != null)
{
SerializeObject(asDict);
}
else if (value is char)
{
SerializeString(new string((char) value, 1));
}
else
{
SerializeOther(value);
}
}
private void SerializeObject(IDictionary obj)
{
var first = true;
builder.Append('{');
foreach (var e in obj.Keys)
{
if (!first)
{
builder.Append(',');
}
SerializeString(e.ToString());
builder.Append(':');
SerializeValue(obj[e]);
first = false;
}
builder.Append('}');
}
private void SerializeArray(IList anArray)
{
builder.Append('[');
var first = true;
foreach (var obj in anArray)
{
if (!first)
{
builder.Append(',');
}
SerializeValue(obj);
first = false;
}
builder.Append(']');
}
private void SerializeString(string str)
{
builder.Append('\"');
var charArray = str.ToCharArray();
foreach (var c in charArray)
{
switch (c)
{
case '"':
builder.Append("\\\"");
break;
case '\\':
builder.Append("\\\\");
break;
case '\b':
builder.Append("\\b");
break;
case '\f':
builder.Append("\\f");
break;
case '\n':
builder.Append("\\n");
break;
case '\r':
builder.Append("\\r");
break;
case '\t':
builder.Append("\\t");
break;
default:
var codepoint = Convert.ToInt32(c);
if ((codepoint >= 32) && (codepoint <= 126))
{
builder.Append(c);
}
else
{
builder.Append("\\u");
builder.Append(codepoint.ToString("x4"));
}
break;
}
}
builder.Append('\"');
}
private void SerializeOther(object value)
{
// NOTE: decimals lose precision during serialization.
// They always have, I'm just letting you know.
// Previously floats and doubles lost precision too.
if (value is float)
{
builder.Append(((float) value).ToString("R", CultureInfo.InvariantCulture));
}
else if (value is int
|| value is uint
|| value is long
|| value is sbyte
|| value is byte
|| value is short
|| value is ushort
|| value is ulong)
{
builder.Append(value);
}
else if (value is double
|| value is decimal)
{
builder.Append(Convert.ToDouble(value).ToString("R", CultureInfo.InvariantCulture));
}
else
{
SerializeString(value.ToString());
}
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ac9ef7034b8966443b1c264ec9cf4cdd
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: c843948cd30ff504ca75040138c14ed9
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -0,0 +1,81 @@
namespace SRF.Internal
{
internal static class ComponentMenuPaths
{
public const string PathRoot = "SRF";
public const string SRServiceManager = PathRoot + "/Service/Service Manager";
#region Behaviours
public const string BehavioursRoot = PathRoot + "/Behaviours";
public const string DestroyOnDisable = BehavioursRoot + "/Destroy On Disable";
public const string DontDestroyOnLoad = BehavioursRoot + "/Don't Destroy On Load";
public const string MatchTransform = BehavioursRoot + "/Match Transform";
public const string LookAt = BehavioursRoot + "/LookAt";
public const string MatchForwardDirection = BehavioursRoot + "/Match Forward Direction";
public const string MatchMainCameraForwardDirection = BehavioursRoot + "/Match Forward Direction (Main Camera)";
public const string RuntimePosition = BehavioursRoot + "/Runtime Position";
public const string ScrollTexture = BehavioursRoot + "/Scroll Texture";
public const string SmoothFloatBehaviour = BehavioursRoot + "/Smooth Float";
public const string SmoothFollow2D = BehavioursRoot + "/Smooth Follow (2D)";
public const string SpringFollow = BehavioursRoot + "/Spring Follow";
public const string SmoothMatchTransform = BehavioursRoot + "/Match Transform (Smooth)";
public const string SpawnPrefab = BehavioursRoot + "/Spawn Prefab";
public const string Velocity = BehavioursRoot + "/Velocity";
public const string SmoothOscillate = BehavioursRoot + "/Smooth Oscillate";
public const string SRDebugCamera = BehavioursRoot + "/Camera/SRDebugCamera";
#endregion
#region Components
public const string ComponentsRoot = PathRoot + "/Components";
public const string SRLineRenderer = ComponentsRoot + "/SRLineRenderer";
public const string SelectionRoot = ComponentsRoot + "/Selection Root";
public const string SRSpriteFadeRenderer = ComponentsRoot + "/Fade Renderer (Sprite)";
public const string SRMaterialFadeRenderer = ComponentsRoot + "/Fade Renderer (Material)";
public const string SRCompositeFadeRenderer = ComponentsRoot + "/Fade Renderer (Composite)";
#endregion
#region UI
public const string UIRoot = PathRoot + "/UI";
public const string TiltOnTouch = UIRoot + "/Tilt On Touch";
public const string ScaleOnTouch = UIRoot + "/Scale On Touch";
public const string InheritColour = UIRoot + "/Inherit Colour";
public const string FlashGraphic = UIRoot + "/Flash Graphic";
public const string CopyPreferredSize = UIRoot + "/Copy Preferred Size";
public const string CopyPreferredSizes = UIRoot + "/Copy Preferred Size (Multiple)";
public const string CopyLayoutElement = UIRoot + "/Copy Layout Element";
public const string CopySizeIntoLayoutElement = UIRoot + "/Copy Size Into Layout Element";
public const string SRText = UIRoot + "/SRText";
public const string Unselectable = UIRoot + "/Unselectable";
public const string LongPressButton = UIRoot + "/Long Press Button";
public const string ScrollToBottom = UIRoot + "/Scroll To Bottom Behaviour";
public const string FlowLayoutGroup = UIRoot + "/Layout/Flow Layout Group";
public const string VirtualVerticalLayoutGroup = UIRoot + "/Layout/VerticalLayoutGroup (Virtualizing)";
public const string StyleRoot = UIRoot + "/Style Root";
public const string StyleComponent = UIRoot + "/Style Component";
public const string ResponsiveEnable = UIRoot + "/Responsive (Enable)";
public const string ResponsiveResize = UIRoot + "/Responsive (Resize)";
public const string RetinaScaler = UIRoot + "/Retina Scaler";
public const string NumberButton = UIRoot + "/SRNumberButton";
public const string NumberSpinner = UIRoot + "/SRNumberSpinner";
public const string SRSpinner = UIRoot + "/Spinner";
public const string ContentFitText = UIRoot + "/Content Fit Text";
#endregion
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5483729387663d0428dfecd534652360
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,19 @@
Copyright (c) 2014 Stompy Robot LTD
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,4 @@
fileFormatVersion: 2
guid: 8bd9e7d9842a77042bf5a124af70a142
DefaultImporter:
userData:

View File

@@ -0,0 +1,12 @@
SRF (Stompy Robot Framework)
===
This is a stripped-down LITE version of SRF, containing the minimal necessary scripts for SRDebugger. Visit http://github.com/StompyRobot/SRF for the full version.
SRF contains numerious helpful behaviours and components for the Unity3D game engine that we use internally at Stompy Robot. We have made it available for anyone to use in their own games.
Dependencies
==
SRF depends on the following libraries, which are included in the External folder
* MiniJSON

View File

@@ -0,0 +1,4 @@
fileFormatVersion: 2
guid: 5c4f30500bf5ea74da5892d0e5a19f55
DefaultImporter:
userData:

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: d6dccedcbd04a634ba6919a7a6a53912
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 713ffa030c417a84190555e6aef2e0b2
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -0,0 +1,346 @@
namespace SRF
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using UnityEngine;
/// <summary>
/// IList implementation which does not release the buffer when clearing/removing elements. Based on the NGUI BetterList
/// </summary>
[Serializable]
public class SRList<T> : IList<T>, ISerializationCallbackReceiver
{
[SerializeField] private T[] _buffer;
[SerializeField] private int _count;
private EqualityComparer<T> _equalityComparer;
private ReadOnlyCollection<T> _readOnlyWrapper;
public SRList() {}
public SRList(int capacity)
{
Buffer = new T[capacity];
}
/// <summary>
/// Create a new list with the range of values. Contains a foreach loop, which will allocate garbage when used with most
/// generic collection types.
/// </summary>
public SRList(IEnumerable<T> source)
{
AddRange(source);
}
public T[] Buffer
{
get { return _buffer; }
private set { _buffer = value; }
}
private EqualityComparer<T> EqualityComparer
{
get
{
if (_equalityComparer == null)
{
_equalityComparer = EqualityComparer<T>.Default;
}
return _equalityComparer;
}
}
public int Count
{
get { return _count; }
private set { _count = value; }
}
public IEnumerator<T> GetEnumerator()
{
if (Buffer != null)
{
for (var i = 0; i < Count; ++i)
{
yield return Buffer[i];
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
if (Buffer == null || Count == Buffer.Length)
{
Expand();
}
Buffer[Count++] = item;
}
public void Clear()
{
Count = 0;
}
public bool Contains(T item)
{
if (Buffer == null)
{
return false;
}
for (var i = 0; i < Count; ++i)
{
if (EqualityComparer.Equals(Buffer[i], item))
{
return true;
}
}
return false;
}
public void CopyTo(T[] array, int arrayIndex)
{
Trim();
Buffer.CopyTo(array, arrayIndex);
}
public bool Remove(T item)
{
if (Buffer == null)
{
return false;
}
var index = IndexOf(item);
if (index < 0)
{
return false;
}
RemoveAt(index);
return true;
}
public bool IsReadOnly
{
get { return false; }
}
public int IndexOf(T item)
{
if (Buffer == null)
{
return -1;
}
for (var i = 0; i < Count; ++i)
{
if (EqualityComparer.Equals(Buffer[i], item))
{
return i;
}
}
return -1;
}
public void Insert(int index, T item)
{
if (Buffer == null || Count == Buffer.Length)
{
Expand();
}
if (index < Count)
{
for (var i = Count; i > index; --i)
{
Buffer[i] = Buffer[i - 1];
}
Buffer[index] = item;
++Count;
}
else
{
Add(item);
}
}
public void RemoveAt(int index)
{
if (Buffer != null && index < Count)
{
--Count;
Buffer[index] = default(T);
for (var b = index; b < Count; ++b)
{
Buffer[b] = Buffer[b + 1];
}
}
}
public T this[int index]
{
get
{
if (Buffer == null)
{
throw new IndexOutOfRangeException();
}
return Buffer[index];
}
set
{
if (Buffer == null)
{
throw new IndexOutOfRangeException();
}
Buffer[index] = value;
}
}
public void OnBeforeSerialize()
{
// Clean buffer of unused elements before serializing
Clean();
}
public void OnAfterDeserialize()
{
}
/// <summary>
/// Add range of values to the list. Contains a foreach loop, which will allocate garbage when used with most
/// generic collection types.
/// </summary>
/// <param name="range"></param>
public void AddRange(IEnumerable<T> range)
{
foreach (var item in range)
{
Add(item);
}
}
/// <summary>
/// Clear the list, optionally setting each element to default(T)
/// </summary>
public void Clear(bool clean)
{
Clear();
if (!clean)
{
return;
}
Clean();
}
public void Clean()
{
if (Buffer == null)
{
return;
}
for (var i = Count; i < _buffer.Length; i++)
{
_buffer[i] = default(T);
}
}
/// <summary>
/// Get a read-only wrapper of this list. This is cached, so very little cost after first called.
/// </summary>
/// <returns></returns>
public ReadOnlyCollection<T> AsReadOnly()
{
if (_readOnlyWrapper == null)
{
_readOnlyWrapper = new ReadOnlyCollection<T>(this);
}
return _readOnlyWrapper;
}
/// <summary>
/// Helper function that expands the size of the array, maintaining the content.
/// </summary>
private void Expand()
{
var newList = (Buffer != null) ? new T[Mathf.Max(Buffer.Length << 1, 32)] : new T[32];
if (Buffer != null && Count > 0)
{
Buffer.CopyTo(newList, 0);
}
Buffer = newList;
}
/// <summary>
/// Trim the unnecessary memory, resizing the buffer to be of 'Length' size.
/// Call this function only if you are sure that the buffer won't need to resize anytime soon.
/// </summary>
public void Trim()
{
if (Count > 0)
{
if (Count >= Buffer.Length)
{
return;
}
var newList = new T[Count];
for (var i = 0; i < Count; ++i)
{
newList[i] = Buffer[i];
}
Buffer = newList;
}
else
{
Buffer = new T[0];
}
}
/// <summary>
/// List.Sort equivalent.
/// </summary>
public void Sort(Comparison<T> comparer)
{
var changed = true;
while (changed)
{
changed = false;
for (var i = 1; i < Count; ++i)
{
if (comparer.Invoke(Buffer[i - 1], Buffer[i]) > 0)
{
var temp = Buffer[i];
Buffer[i] = Buffer[i - 1];
Buffer[i - 1] = temp;
changed = true;
}
}
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5201015973137a64986d1c3a21aa95bd
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: b492ab4aeb29c06468a92411414d3647
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -0,0 +1,74 @@
namespace SRF.Components
{
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;
/// <summary>
/// Singleton MonoBehaviour class which automatically creates an instance if one does not already exist.
/// </summary>
public abstract class SRAutoSingleton<T> : SRMonoBehaviour where T : SRAutoSingleton<T>
{
private static T _instance;
/// <summary>
/// Get (or create) the instance of this Singleton
/// </summary>
public static T Instance
{
[DebuggerStepThrough]
get
{
// Instance required for the first time, we look for it
if (_instance == null && Application.isPlaying)
{
#if UNITY_EDITOR
// Support reloading scripts after a recompile - static reference will be cleared, but we can find it again.
T autoSingleton = FindObjectOfType<T>();
if (autoSingleton != null)
{
_instance = autoSingleton;
return _instance;
}
#endif
var go = new GameObject("_" + typeof (T).Name);
go.AddComponent<T>(); // _instance set by Awake() constructor
}
return _instance;
}
}
public static bool HasInstance
{
get { return _instance != null; }
}
// If no other monobehaviour request the instance in an awake function
// executing before this one, no need to search the object.
protected virtual void Awake()
{
if (_instance != null)
{
Debug.LogWarning("More than one singleton object of type {0} exists.".Fmt(typeof (T).Name));
return;
}
_instance = (T) this;
}
protected virtual void OnEnable()
{
#if UNITY_EDITOR
// Restore reference after C# recompile.
_instance = (T) this;
#endif
}
// Make sure the instance isn't referenced anymore when the user quit, just in case.
private void OnApplicationQuit()
{
_instance = null;
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 73f72db4fa1856540bbe92740280c8e2
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,202 @@
namespace SRF
{
using System.Diagnostics;
using UnityEngine;
/// <summary>
/// Base MonoBehaviour which provides useful common functionality
/// </summary>
public abstract class SRMonoBehaviour : MonoBehaviour
{
/// <summary>
/// Get the Transform component, using a cached reference if possible.
/// </summary>
public Transform CachedTransform
{
[DebuggerStepThrough]
[DebuggerNonUserCode]
get
{
if (_transform == null)
{
_transform = base.transform;
}
return _transform;
}
}
/// <summary>
/// Get the Collider component, using a cached reference if possible.
/// </summary>
public Collider CachedCollider
{
[DebuggerStepThrough]
[DebuggerNonUserCode]
get
{
if (_collider == null)
{
_collider = GetComponent<Collider>();
}
return _collider;
}
}
/// <summary>
/// Get the Collider component, using a cached reference if possible.
/// </summary>
public Collider2D CachedCollider2D
{
[DebuggerStepThrough]
[DebuggerNonUserCode]
get
{
if (_collider2D == null)
{
_collider2D = GetComponent<Collider2D>();
}
return _collider2D;
}
}
/// <summary>
/// Get the Rigidbody component, using a cached reference if possible.
/// </summary>
public Rigidbody CachedRigidBody
{
[DebuggerStepThrough]
[DebuggerNonUserCode]
get
{
if (_rigidBody == null)
{
_rigidBody = GetComponent<Rigidbody>();
}
return _rigidBody;
}
}
/// <summary>
/// Get the Rigidbody2D component, using a cached reference if possible.
/// </summary>
public Rigidbody2D CachedRigidBody2D
{
[DebuggerStepThrough]
[DebuggerNonUserCode]
get
{
if (_rigidbody2D == null)
{
_rigidbody2D = GetComponent<Rigidbody2D>();
}
return _rigidbody2D;
}
}
/// <summary>
/// Get the GameObject this behaviour is attached to, using a cached reference if possible.
/// </summary>
public GameObject CachedGameObject
{
[DebuggerStepThrough]
[DebuggerNonUserCode]
get
{
if (_gameObject == null)
{
_gameObject = base.gameObject;
}
return _gameObject;
}
}
// Override existing getters for legacy usage
// ReSharper disable InconsistentNaming
public new Transform transform
{
get { return CachedTransform; }
}
#if !UNITY_5 && !UNITY_2017_1_OR_NEWER
public new Collider collider
{
get { return CachedCollider; }
}
public new Collider2D collider2D
{
get { return CachedCollider2D; }
}
public new Rigidbody rigidbody
{
get { return CachedRigidBody; }
}
public new Rigidbody2D rigidbody2D
{
get { return CachedRigidBody2D; }
}
public new GameObject gameObject
{
get { return CachedGameObject; }
}
#endif
// ReSharper restore InconsistentNaming
private Collider _collider;
private Transform _transform;
private Rigidbody _rigidBody;
private GameObject _gameObject;
private Rigidbody2D _rigidbody2D;
private Collider2D _collider2D;
/// <summary>
/// Assert that the value is not null, disable the object and print a debug error message if it is.
/// </summary>
/// <param name="value">Object to check</param>
/// <param name="fieldName">Debug name to pass in</param>
[DebuggerNonUserCode]
[DebuggerStepThrough]
protected void AssertNotNull(object value, string fieldName = null)
{
SRDebugUtil.AssertNotNull(value, fieldName, this);
}
[DebuggerNonUserCode]
[DebuggerStepThrough]
protected void Assert(bool condition, string message = null)
{
SRDebugUtil.Assert(condition, message, this);
}
/// <summary>
/// Assert that the value is not null, disable the object and print a debug error message if it is.
/// </summary>
/// <param name="value">Object to check</param>
/// <param name="fieldName">Debug name to pass in</param>
/// <returns>True if object is not null</returns>
[Conditional("UNITY_EDITOR")]
[DebuggerNonUserCode]
[DebuggerStepThrough]
protected void EditorAssertNotNull(object value, string fieldName = null)
{
AssertNotNull(value, fieldName);
}
[Conditional("UNITY_EDITOR")]
[DebuggerNonUserCode]
[DebuggerStepThrough]
protected void EditorAssert(bool condition, string message = null)
{
Assert(condition, message);
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a97a8611d5d683b4aa89a5054bc3774e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,215 @@
// ReSharper disable once RedundantUsingDirective
using System.Linq;
namespace SRF
{
using System;
using System.Collections.Generic;
using System.Reflection;
using Helpers;
using Service;
using UnityEngine;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field)]
public sealed class RequiredFieldAttribute : Attribute
{
private bool _autoCreate;
private bool _autoSearch;
private bool _editorOnly = true;
public RequiredFieldAttribute(bool autoSearch)
{
AutoSearch = autoSearch;
}
public RequiredFieldAttribute() {}
public bool AutoSearch
{
get { return _autoSearch; }
set { _autoSearch = value; }
}
public bool AutoCreate
{
get { return _autoCreate; }
set { _autoCreate = value; }
}
[Obsolete]
public bool EditorOnly
{
get { return _editorOnly; }
set { _editorOnly = value; }
}
}
/// <summary>
/// Add to a field to attempt to use SRServiceManager to get an instance of the field type
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
public class ImportAttribute : Attribute
{
public readonly Type Service;
public ImportAttribute() {}
public ImportAttribute(Type serviceType)
{
Service = serviceType;
}
}
public abstract class SRMonoBehaviourEx : SRMonoBehaviour
{
private static Dictionary<Type, IList<FieldInfo>> _checkedFields;
private static void CheckFields(SRMonoBehaviourEx instance, bool justSet = false)
{
if (_checkedFields == null)
{
_checkedFields = new Dictionary<Type, IList<FieldInfo>>();
}
var t = instance.GetType();
IList<FieldInfo> cache;
if (!_checkedFields.TryGetValue(instance.GetType(), out cache))
{
cache = ScanType(t);
_checkedFields.Add(t, cache);
}
PopulateObject(cache, instance, justSet);
}
private static void PopulateObject(IList<FieldInfo> cache, SRMonoBehaviourEx instance, bool justSet)
{
for (var i = 0; i < cache.Count; i++)
{
var f = cache[i];
if (!EqualityComparer<object>.Default.Equals(f.Field.GetValue(instance), null))
{
continue;
}
// If import is enabled, use SRServiceManager to import the reference
if (f.Import)
{
var t = f.ImportType ?? f.Field.FieldType;
var service = SRServiceManager.GetService(t);
if (service == null)
{
Debug.LogWarning("Field {0} import failed (Type {1})".Fmt(f.Field.Name, t));
continue;
}
f.Field.SetValue(instance, service);
continue;
}
// If autoset is enabled on field, try and find the component on the GameObject
if (f.AutoSet)
{
var newValue = instance.GetComponent(f.Field.FieldType);
if (!EqualityComparer<object>.Default.Equals(newValue, null))
{
f.Field.SetValue(instance, newValue);
continue;
}
}
if (justSet)
{
continue;
}
if (f.AutoCreate)
{
var newValue = instance.CachedGameObject.AddComponent(f.Field.FieldType);
f.Field.SetValue(instance, newValue);
}
throw new UnassignedReferenceException(
"Field {0} is unassigned, but marked with RequiredFieldAttribute".Fmt(f.Field.Name));
}
}
private static List<FieldInfo> ScanType(Type t)
{
var cache = new List<FieldInfo>();
// Check for attribute added to the class
var globalAttr = SRReflection.GetAttribute<RequiredFieldAttribute>(t);
#if NETFX_CORE
var fields = t.GetTypeInfo().DeclaredFields.Where(f => !f.IsStatic);
#else
// Check each field for the attribute
var fields = t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
#endif
foreach (var f in fields)
{
var requiredFieldAttribute = SRReflection.GetAttribute<RequiredFieldAttribute>(f);
var importAttribute = SRReflection.GetAttribute<ImportAttribute>(f);
if (globalAttr == null && requiredFieldAttribute == null && importAttribute == null)
{
continue; // Early out if no attributes found.
}
var info = new FieldInfo();
info.Field = f;
if (importAttribute != null)
{
info.Import = true;
info.ImportType = importAttribute.Service;
}
else if (requiredFieldAttribute != null)
{
info.AutoSet = requiredFieldAttribute.AutoSearch;
info.AutoCreate = requiredFieldAttribute.AutoCreate;
}
else
{
info.AutoSet = globalAttr.AutoSearch;
info.AutoCreate = globalAttr.AutoCreate;
}
cache.Add(info);
}
return cache;
}
protected virtual void Awake()
{
CheckFields(this);
}
protected virtual void Start() {}
protected virtual void Update() {}
protected virtual void FixedUpdate() {}
protected virtual void OnEnable() {}
protected virtual void OnDisable() {}
protected virtual void OnDestroy() {}
private struct FieldInfo
{
public bool AutoCreate;
public bool AutoSet;
public System.Reflection.FieldInfo Field;
public bool Import;
public Type ImportType;
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 82088ea802108344da1e919daa6881fd
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,82 @@
namespace SRF.Components
{
using System;
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;
/// <summary>
/// Inherit from this component to easily create a singleton gameobject.
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class SRSingleton<T> : SRMonoBehaviour where T : SRSingleton<T>
{
private static T _instance;
/// <summary>
/// Get the instance of this singleton.
/// </summary
public static T Instance
{
[DebuggerStepThrough]
get
{
// Instance requiered for the first time, we look for it
if (_instance == null)
{
throw new InvalidOperationException("No instance of {0} present in scene".Fmt(typeof (T).Name));
}
return _instance;
}
}
public static bool HasInstance
{
[DebuggerStepThrough] get { return _instance != null; }
}
private void Register()
{
if (_instance != null)
{
Debug.LogWarning("More than one singleton object of type {0} exists.".Fmt(typeof (T).Name));
// Check if gameobject only contains Transform and this component
if (GetComponents<Component>().Length == 2)
{
Destroy(gameObject);
}
else
{
Destroy(this);
}
return;
}
_instance = (T) this;
}
// If no other monobehaviour request the instance in an awake function
// executing before this one, no need to search the object.
protected virtual void Awake()
{
Register();
}
protected virtual void OnEnable()
{
// In case of code-reload, this should restore the single instance
if (_instance == null)
{
Register();
}
}
// Make sure the instance isn't referenced anymore when the user quit, just in case.
private void OnApplicationQuit()
{
_instance = null;
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ca9e6e61f807f3442b520b02db3a48c7
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,18 @@
namespace SRF
{
using System.Collections;
using UnityEngine;
public static class Coroutines
{
public static IEnumerator WaitForSecondsRealTime(float time)
{
var endTime = Time.realtimeSinceStartup + time;
while (Time.realtimeSinceStartup < endTime)
{
yield return null;
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 83ca528cafb0d2e40866729c49dc2d76
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 5a242390cef216543a4fa08843e88004
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -0,0 +1,27 @@
namespace SRF
{
using UnityEngine;
public static class SRFFloatExtensions
{
public static float Sqr(this float f)
{
return f*f;
}
public static float SqrRt(this float f)
{
return Mathf.Sqrt(f);
}
public static bool ApproxZero(this float f)
{
return Mathf.Approximately(0, f);
}
public static bool Approx(this float f, float f2)
{
return Mathf.Approximately(f, f2);
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bb221a6020786a841a6f7f1ea19a7eb7
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,100 @@
namespace SRF
{
using UnityEngine;
public static class SRFGameObjectExtensions
{
public static T GetIComponent<T>(this GameObject t) where T : class
{
return t.GetComponent(typeof (T)) as T;
}
/// <summary>
/// Get the component T, or add it to the GameObject if none exists
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T GetComponentOrAdd<T>(this GameObject obj) where T : Component
{
var t = obj.GetComponent<T>();
if (t == null)
{
t = obj.AddComponent<T>();
}
return t;
}
/// <summary>
/// Removed component of type T if it exists on the GameObject
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
public static void RemoveComponentIfExists<T>(this GameObject obj) where T : Component
{
var t = obj.GetComponent<T>();
if (t != null)
{
Object.Destroy(t);
}
}
/// <summary>
/// Removed components of type T if it exists on the GameObject
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
public static void RemoveComponentsIfExists<T>(this GameObject obj) where T : Component
{
var t = obj.GetComponents<T>();
for (var i = 0; i < t.Length; i++)
{
Object.Destroy(t[i]);
}
}
/// <summary>
/// Set enabled property MonoBehaviour of type T if it exists
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <param name="enable"></param>
/// <returns>True if the component exists</returns>
public static bool EnableComponentIfExists<T>(this GameObject obj, bool enable = true) where T : MonoBehaviour
{
var t = obj.GetComponent<T>();
if (t == null)
{
return false;
}
t.enabled = enable;
return true;
}
/// <summary>
/// Set the layer of a gameobject and all child objects
/// </summary>
/// <param name="o"></param>
/// <param name="layer"></param>
public static void SetLayerRecursive(this GameObject o, int layer)
{
SetLayerInternal(o.transform, layer);
}
private static void SetLayerInternal(Transform t, int layer)
{
t.gameObject.layer = layer;
foreach (Transform o in t)
{
SetLayerInternal(o, layer);
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 57a08f4d800e4384fac80b0ecf63a7a0
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,47 @@
namespace SRF
{
using System;
using System.Collections.Generic;
public static class SRFIListExtensions
{
public static T Random<T>(this IList<T> list)
{
if (list.Count == 0)
{
throw new IndexOutOfRangeException("List needs at least one entry to call Random()");
}
if (list.Count == 1)
{
return list[0];
}
return list[UnityEngine.Random.Range(0, list.Count)];
}
public static T RandomOrDefault<T>(this IList<T> list)
{
if (list.Count == 0)
{
return default(T);
}
return list.Random();
}
public static T PopLast<T>(this IList<T> list)
{
if (list.Count == 0)
{
throw new InvalidOperationException();
}
var t = list[list.Count - 1];
list.RemoveAt(list.Count - 1);
return t;
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c196b9d1bba9e9e44939cf8776545577
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,32 @@

#if NETFX_CORE
using System;
using System.Reflection;
namespace SRF
{
public static class NetFxExtensions
{
public static bool IsAssignableFrom(this Type @this, Type t)
{
return @this.GetTypeInfo().IsAssignableFrom(t.GetTypeInfo());
}
public static bool IsInstanceOfType(this Type @this, object obj)
{
return @this.IsAssignableFrom(obj.GetType());
}
}
}
#endif

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f503b1a2564101f4f96417c97debaaf5
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,13 @@
namespace SRF
{
public static class SRFStringExtensions
{
#if UNITY_EDITOR
[JetBrains.Annotations.StringFormatMethod("formatString")]
#endif
public static string Fmt(this string formatString, params object[] args)
{
return string.Format(formatString, args);
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 71e45638ff7335744a6554752b778f39
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,91 @@
namespace SRF
{
using System.Collections.Generic;
using UnityEngine;
public static class SRFTransformExtensions
{
public static IEnumerable<Transform> GetChildren(this Transform t)
{
var i = 0;
while (i < t.childCount)
{
yield return t.GetChild(i);
++i;
}
}
/// <summary>
/// Reset all local values on a transform to identity
/// </summary>
/// <param name="t"></param>
public static void ResetLocal(this Transform t)
{
t.localPosition = Vector3.zero;
t.localRotation = Quaternion.identity;
t.localScale = Vector3.one;
}
/// <summary>
/// Create an empty child object of this transform
/// </summary>
/// <param name="t"></param>
/// <param name="name"></param>
/// <returns></returns>
public static GameObject CreateChild(this Transform t, string name)
{
var go = new GameObject(name);
go.transform.parent = t;
go.transform.ResetLocal();
go.gameObject.layer = t.gameObject.layer;
return go;
}
/// <summary>
/// Set the parent of this transform, but maintain the localScale, localPosition, localRotation values.
/// </summary>
/// <param name="t"></param>
/// <param name="parent"></param>
public static void SetParentMaintainLocals(this Transform t, Transform parent)
{
t.SetParent(parent, false);
}
/// <summary>
/// Copy local position,rotation,scale from other transform
/// </summary>
/// <param name="t"></param>
/// <param name="from"></param>
public static void SetLocals(this Transform t, Transform from)
{
t.localPosition = from.localPosition;
t.localRotation = from.localRotation;
t.localScale = from.localScale;
}
/// <summary>
/// Set position/rotation to from. Scale is unchanged
/// </summary>
/// <param name="t"></param>
/// <param name="from"></param>
public static void Match(this Transform t, Transform from)
{
t.position = from.position;
t.rotation = from.rotation;
}
/// <summary>
/// Destroy all child game objects
/// </summary>
/// <param name="t"></param>
public static void DestroyChildren(this Transform t)
{
foreach (var child in t)
{
Object.Destroy(((Transform) child).gameObject);
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 891f8206d8bca304fbbf298c6a37648e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 5354a62e7d1e47949b07ff9e9b123080
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -0,0 +1,63 @@
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace SRF.Helpers
{
using System.IO;
using UnityEngine;
public static class AssetUtil
{
#if UNITY_EDITOR
// This makes it easy to create, name and place unique new ScriptableObject asset files.
/// <summary>
/// </summary>
public static T CreateAsset<T>() where T : ScriptableObject
{
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
if (path == "")
{
path = "Assets";
}
else if (Path.GetExtension(path) != "")
{
path = path.Replace(Path.GetFileName(path), "");
}
return CreateAsset<T>(path, "New " + typeof (T).Name);
}
public static T CreateAsset<T>(string path, string name) where T : ScriptableObject
{
if (string.IsNullOrEmpty(path))
{
path = "Assets";
}
if (!name.EndsWith(".asset"))
{
name += ".asset";
}
var assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(path + "/" + name);
var asset = ScriptableObject.CreateInstance<T>();
AssetDatabase.CreateAsset(asset, assetPathAndName);
AssetDatabase.SaveAssets();
return asset;
}
public static void SelectAssetInProjectView(Object asset)
{
EditorUtility.FocusProjectWindow();
Selection.activeObject = asset;
}
#endif
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: de28cc9633260c54a9ba062b7ad82e63
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,73 @@
namespace SRF
{
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class Hierarchy
{
private static readonly char[] Seperator = {'/'};
private static readonly Dictionary<string, Transform> Cache = new Dictionary<string, Transform>();
[Obsolete("Use static Get() instead")]
public Transform this[string key]
{
get { return Get(key); }
}
/// <summary>
/// Pass in a path (e.g. /Test/Me/One) and get a transform with the hierarchy Test->Me->One.
/// Any Transforms required below this path will be auto-created.
/// This is a very slow method, so use only on initialisation.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static Transform Get(string key)
{
Transform t;
// Check cache
if (Cache.TryGetValue(key, out t))
{
return t;
}
var find = GameObject.Find(key);
if (find)
{
t = find.transform;
Cache.Add(key, t);
return t;
}
// Find container parent
var elements = key.Split(Seperator, StringSplitOptions.RemoveEmptyEntries);
// Create new container
t = new GameObject(elements.Last()).transform;
Cache.Add(key, t);
// If root
if (elements.Length == 1)
{
return t;
}
t.parent = Get(string.Join("/", elements, 0, elements.Length - 1));
return t;
}
#if (!UNITY_2017 && !UNITY_2018 && !UNITY_2019) || UNITY_2019_3_OR_NEWER
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
public static void RuntimeInitialize()
{
// To handle entering play mode without a domain reload, need to reset the state of the service manager.
Cache.Clear();
}
#endif
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ecf392c4c08d14543b90300c27422d60
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,37 @@
using System;
namespace SRF.Helpers
{
using System.Reflection;
public sealed class MethodReference
{
private readonly Func<object[], object> _method;
public MethodReference(object target, MethodInfo method)
{
SRDebugUtil.AssertNotNull(target);
_method = o => method.Invoke(target, o);
}
public MethodReference(Func<object[], object> method)
{
_method = method;
}
public object Invoke(object[] parameters)
{
return _method.Invoke(parameters);
}
public static implicit operator MethodReference(Action action)
{
return new MethodReference(args =>
{
action();
return null;
});
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3ed7f46979ff4b3418a838a6b940a9ab
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,208 @@
using System.Collections.Generic;
using System.ComponentModel;
using JetBrains.Annotations;
using UnityEngine;
namespace SRF.Helpers
{
using System;
using System.Linq;
using System.Reflection;
public delegate void PropertyValueChangedHandler(PropertyReference property);
public sealed class PropertyReference
{
public event PropertyValueChangedHandler ValueChanged
{
add
{
if (_valueChangedListeners == null)
{
_valueChangedListeners = new List<PropertyValueChangedHandler>();
}
_valueChangedListeners.Add(value);
if (_valueChangedListeners.Count == 1 && _target is INotifyPropertyChanged)
{
// Subscribe to value changed event on target.
((INotifyPropertyChanged)_target).PropertyChanged += OnTargetPropertyChanged;
}
}
remove
{
if (_valueChangedListeners == null)
{
return;
}
if (_valueChangedListeners.Remove(value) && _valueChangedListeners.Count == 0 &&
_target is INotifyPropertyChanged)
{
// Unsubscribe from value changed event on target.
((INotifyPropertyChanged) _target).PropertyChanged -= OnTargetPropertyChanged;
}
}
}
[CanBeNull] private readonly PropertyInfo _property;
[CanBeNull] private readonly object _target;
[CanBeNull] private readonly Attribute[] _attributes;
[CanBeNull] private readonly Func<object> _getter;
[CanBeNull] private readonly Action<object> _setter;
[CanBeNull] private List<PropertyValueChangedHandler> _valueChangedListeners;
public static PropertyReference FromLambda<T>(Func<T> getter, Action<T> setter = null, params Attribute[] attributes)
{
Action<object> internalSetter = null;
if (setter != null)
{
internalSetter = o => setter((T)o);
}
return new PropertyReference(typeof(T), () => getter(), internalSetter, attributes);
}
/// <summary>
/// Create a property reference from an object target and reflection PropertyInfo.
/// This represents a property on an object.
/// </summary>
public PropertyReference(object target, PropertyInfo property)
{
SRDebugUtil.AssertNotNull(target);
SRDebugUtil.AssertNotNull(property);
PropertyType = property.PropertyType;
_property = property;
_target = target;
#if NETFX_CORE
if(_property.GetMethod != null && _property.GetMethod.IsPublic)
#else
if (property.GetGetMethod() != null)
#endif
{
_getter = () => SRReflection.GetPropertyValue(target, property);
}
#if NETFX_CORE
if(_property.SetMethod != null && _property.SetMethod.IsPublic)
#else
if (property.GetSetMethod() != null)
#endif
{
_setter = (v) => SRReflection.SetPropertyValue(target, property, v);
}
}
/// <summary>
/// Create a property reference from lambdas. This has no underlying reflection or object associated with it.
/// </summary>
public PropertyReference(Type type, Func<object> getter = null, Action<object> setter = null, Attribute[] attributes = null)
{
SRDebugUtil.AssertNotNull(type);
PropertyType = type;
_attributes = attributes;
_getter = getter;
_setter = setter;
}
public Type PropertyType { get; private set; }
public bool CanRead
{
get
{
return _getter != null;
}
}
public bool CanWrite
{
get
{
return _setter != null;
}
}
/// <summary>
/// Notify any listeners to <see cref="ValueChanged"/> that the value has been updated.
/// </summary>
public void NotifyValueChanged()
{
if (_valueChangedListeners == null)
{
return;
}
foreach (var handler in _valueChangedListeners)
{
handler(this);
}
}
public object GetValue()
{
if (_getter != null)
{
return _getter();
}
return null;
}
public void SetValue(object value)
{
if (_setter != null)
{
_setter(value);
}
else
{
throw new InvalidOperationException("Can not write to property");
}
}
public T GetAttribute<T>() where T : Attribute
{
if (_attributes != null)
{
return _attributes.FirstOrDefault(p => p is T) as T;
}
if (_property != null)
{
return _property.GetCustomAttributes(typeof(T), true).FirstOrDefault() as T;
}
return null;
}
private void OnTargetPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (_valueChangedListeners == null || _valueChangedListeners.Count == 0)
{
Debug.LogWarning("[PropertyReference] Received property value changed event when there are no listeners. Did the event not get unsubscribed correctly?");
return;
}
NotifyValueChanged();
}
public override string ToString()
{
if (_property != null)
{
return "{0}.{1}".Fmt(_property.DeclaringType.Name, _property.Name);
}
return "<delegate>";
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dedbd84f93f7d4c4e86f2d3a238916c4
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using SRF;
using UnityEngine;
using Debug = UnityEngine.Debug;
public static class SRDebugUtil
{
public const int LineBufferCount = 512;
public static bool IsFixedUpdate { get; set; }
[DebuggerNonUserCode]
[DebuggerStepThrough]
public static void AssertNotNull(object value, string message = null, MonoBehaviour instance = null)
{
if (!EqualityComparer<object>.Default.Equals(value, null))
{
return;
}
message = message != null ? "NotNullAssert Failed: {0}".Fmt(message) : "Assert Failed";
Debug.LogError(message, instance);
if (instance != null)
{
instance.enabled = false;
}
throw new NullReferenceException(message);
}
[DebuggerNonUserCode]
[DebuggerStepThrough]
public static void Assert(bool condition, string message = null, MonoBehaviour instance = null)
{
if (condition)
{
return;
}
message = message != null ? "Assert Failed: {0}".Fmt(message) : "Assert Failed";
Debug.LogError(message, instance);
throw new Exception(message);
}
[Conditional("UNITY_EDITOR")]
[DebuggerNonUserCode]
[DebuggerStepThrough]
public static void EditorAssertNotNull(object value, string message = null, MonoBehaviour instance = null)
{
AssertNotNull(value, message, instance);
}
[Conditional("UNITY_EDITOR")]
[DebuggerNonUserCode]
[DebuggerStepThrough]
public static void EditorAssert(bool condition, string message = null, MonoBehaviour instance = null)
{
Assert(condition, message, instance);
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f74f500c46d2b60419e95b8bd0cb87b6
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,73 @@
using System.IO;
using System.Threading;
public static class SRFileUtil
{
#if !UNITY_WEBPLAYER && !NETFX_CORE
public static void DeleteDirectory(string path)
{
try
{
Directory.Delete(path, true);
}
catch (IOException)
{
Thread.Sleep(0);
Directory.Delete(path, true);
}
}
#endif
/// <summary>
/// Returns the human-readable file size for an arbitrary, 64-bit file size
/// The default format is "0.### XB", e.g. "4.2 KB" or "1.434 GB"
/// </summary>
/// <param name="i"></param>
/// <remarks>http://stackoverflow.com/a/281684/147003</remarks>
/// <returns></returns>
public static string GetBytesReadable(long i)
{
var sign = (i < 0 ? "-" : "");
double readable = (i < 0 ? -i : i);
string suffix;
if (i >= 0x1000000000000000) // Exabyte
{
suffix = "EB";
readable = i >> 50;
}
else if (i >= 0x4000000000000) // Petabyte
{
suffix = "PB";
readable = i >> 40;
}
else if (i >= 0x10000000000) // Terabyte
{
suffix = "TB";
readable = i >> 30;
}
else if (i >= 0x40000000) // Gigabyte
{
suffix = "GB";
readable = i >> 20;
}
else if (i >= 0x100000) // Megabyte
{
suffix = "MB";
readable = i >> 10;
}
else if (i >= 0x400) // Kilobyte
{
suffix = "KB";
readable = i;
}
else
{
return i.ToString(sign + "0 B"); // Byte
}
readable /= 1024;
return sign + readable.ToString("0.### ") + suffix;
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8c5dd64a3a7854e4f948daaec7d318fa
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,19 @@
using UnityEngine;
public static class SRInstantiate
{
public static T Instantiate<T>(T prefab) where T : Component
{
return (T) Object.Instantiate(prefab);
}
public static GameObject Instantiate(GameObject prefab)
{
return (GameObject) Object.Instantiate(prefab);
}
public static T Instantiate<T>(T prefab, Vector3 position, Quaternion rotation) where T : Component
{
return (T) Object.Instantiate(prefab, position, rotation);
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2b2502558f76a9a4b9d3fd4d26d4d2a6
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,788 @@
using UnityEngine;
public static partial class SRMath
{
/**
*
* These tweening functions taken from https://wpf-animation.googlecode.com/svn/trunk/src/WPF/Animation/PennerDoubleAnimation.cs
* Licensed under the new BSD License
*
* @author Darren David darren-code@lookorfeel.com
* @version 1.0
*
* Credit/Thanks:
* Robert Penner - The easing equations we all know and love
* (http://robertpenner.com/easing/) [See License.txt for license info]
*
* Lee Brimelow - initial port of Penner's equations to WPF
* (http://thewpfblog.com/?p=12)
*
* Zeh Fernando - additional equations (out/in) from
* caurina.transitions.Tweener (http://code.google.com/p/tweener/)
* [See License.txt for license info]
*
*/
private static class TweenFunctions
{
#region Equations
#region Linear
/// <summary>
/// Easing equation function for a simple linear tweening, with no easing.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float Linear(float t, float b, float c, float d)
{
return c*t/d + b;
}
#endregion
#region Expo
/// <summary>
/// Easing equation function for an exponential (2^t) easing out:
/// decelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float ExpoEaseOut(float t, float b, float c, float d)
{
return (t == d) ? b + c : c*(-Mathf.Pow(2, -10*t/d) + 1) + b;
}
/// <summary>
/// Easing equation function for an exponential (2^t) easing in:
/// accelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float ExpoEaseIn(float t, float b, float c, float d)
{
return (t == 0) ? b : c*Mathf.Pow(2, 10*(t/d - 1)) + b;
}
/// <summary>
/// Easing equation function for an exponential (2^t) easing in/out:
/// acceleration until halfway, then deceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float ExpoEaseInOut(float t, float b, float c, float d)
{
if (t == 0)
{
return b;
}
if (t == d)
{
return b + c;
}
if ((t /= d/2) < 1)
{
return c/2*Mathf.Pow(2, 10*(t - 1)) + b;
}
return c/2*(-Mathf.Pow(2, -10*--t) + 2) + b;
}
/// <summary>
/// Easing equation function for an exponential (2^t) easing out/in:
/// deceleration until halfway, then acceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float ExpoEaseOutIn(float t, float b, float c, float d)
{
if (t < d/2)
{
return ExpoEaseOut(t*2, b, c/2, d);
}
return ExpoEaseIn((t*2) - d, b + c/2, c/2, d);
}
#endregion
#region Circular
/// <summary>
/// Easing equation function for a circular (sqrt(1-t^2)) easing out:
/// decelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float CircEaseOut(float t, float b, float c, float d)
{
return c*Mathf.Sqrt(1 - (t = t/d - 1)*t) + b;
}
/// <summary>
/// Easing equation function for a circular (sqrt(1-t^2)) easing in:
/// accelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float CircEaseIn(float t, float b, float c, float d)
{
return -c*(Mathf.Sqrt(1 - (t /= d)*t) - 1) + b;
}
/// <summary>
/// Easing equation function for a circular (sqrt(1-t^2)) easing in/out:
/// acceleration until halfway, then deceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float CircEaseInOut(float t, float b, float c, float d)
{
if ((t /= d/2) < 1)
{
return -c/2*(Mathf.Sqrt(1 - t*t) - 1) + b;
}
return c/2*(Mathf.Sqrt(1 - (t -= 2)*t) + 1) + b;
}
/// <summary>
/// Easing equation function for a circular (sqrt(1-t^2)) easing in/out:
/// acceleration until halfway, then deceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float CircEaseOutIn(float t, float b, float c, float d)
{
if (t < d/2)
{
return CircEaseOut(t*2, b, c/2, d);
}
return CircEaseIn((t*2) - d, b + c/2, c/2, d);
}
#endregion
#region Quad
/// <summary>
/// Easing equation function for a quadratic (t^2) easing out:
/// decelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float QuadEaseOut(float t, float b, float c, float d)
{
return -c*(t /= d)*(t - 2) + b;
}
/// <summary>
/// Easing equation function for a quadratic (t^2) easing in:
/// accelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float QuadEaseIn(float t, float b, float c, float d)
{
return c*(t /= d)*t + b;
}
/// <summary>
/// Easing equation function for a quadratic (t^2) easing in/out:
/// acceleration until halfway, then deceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float QuadEaseInOut(float t, float b, float c, float d)
{
if ((t /= d/2) < 1)
{
return c/2*t*t + b;
}
return -c/2*((--t)*(t - 2) - 1) + b;
}
/// <summary>
/// Easing equation function for a quadratic (t^2) easing out/in:
/// deceleration until halfway, then acceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float QuadEaseOutIn(float t, float b, float c, float d)
{
if (t < d/2)
{
return QuadEaseOut(t*2, b, c/2, d);
}
return QuadEaseIn((t*2) - d, b + c/2, c/2, d);
}
#endregion
#region Sine
/// <summary>
/// Easing equation function for a sinusoidal (sin(t)) easing out:
/// decelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float SineEaseOut(float t, float b, float c, float d)
{
return c*Mathf.Sin(t/d*(Mathf.PI/2)) + b;
}
/// <summary>
/// Easing equation function for a sinusoidal (sin(t)) easing in:
/// accelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float SineEaseIn(float t, float b, float c, float d)
{
return -c*Mathf.Cos(t/d*(Mathf.PI/2)) + c + b;
}
/// <summary>
/// Easing equation function for a sinusoidal (sin(t)) easing in/out:
/// acceleration until halfway, then deceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float SineEaseInOut(float t, float b, float c, float d)
{
if ((t /= d/2) < 1)
{
return c/2*(Mathf.Sin(Mathf.PI*t/2)) + b;
}
return -c/2*(Mathf.Cos(Mathf.PI*--t/2) - 2) + b;
}
/// <summary>
/// Easing equation function for a sinusoidal (sin(t)) easing in/out:
/// deceleration until halfway, then acceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float SineEaseOutIn(float t, float b, float c, float d)
{
if (t < d/2)
{
return SineEaseOut(t*2, b, c/2, d);
}
return SineEaseIn((t*2) - d, b + c/2, c/2, d);
}
#endregion
#region Cubic
/// <summary>
/// Easing equation function for a cubic (t^3) easing out:
/// decelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float CubicEaseOut(float t, float b, float c, float d)
{
return c*((t = t/d - 1)*t*t + 1) + b;
}
/// <summary>
/// Easing equation function for a cubic (t^3) easing in:
/// accelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float CubicEaseIn(float t, float b, float c, float d)
{
return c*(t /= d)*t*t + b;
}
/// <summary>
/// Easing equation function for a cubic (t^3) easing in/out:
/// acceleration until halfway, then deceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float CubicEaseInOut(float t, float b, float c, float d)
{
if ((t /= d/2) < 1)
{
return c/2*t*t*t + b;
}
return c/2*((t -= 2)*t*t + 2) + b;
}
/// <summary>
/// Easing equation function for a cubic (t^3) easing out/in:
/// deceleration until halfway, then acceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float CubicEaseOutIn(float t, float b, float c, float d)
{
if (t < d/2)
{
return CubicEaseOut(t*2, b, c/2, d);
}
return CubicEaseIn((t*2) - d, b + c/2, c/2, d);
}
#endregion
#region Quartic
/// <summary>
/// Easing equation function for a quartic (t^4) easing out:
/// decelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float QuartEaseOut(float t, float b, float c, float d)
{
return -c*((t = t/d - 1)*t*t*t - 1) + b;
}
/// <summary>
/// Easing equation function for a quartic (t^4) easing in:
/// accelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float QuartEaseIn(float t, float b, float c, float d)
{
return c*(t /= d)*t*t*t + b;
}
/// <summary>
/// Easing equation function for a quartic (t^4) easing in/out:
/// acceleration until halfway, then deceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float QuartEaseInOut(float t, float b, float c, float d)
{
if ((t /= d/2) < 1)
{
return c/2*t*t*t*t + b;
}
return -c/2*((t -= 2)*t*t*t - 2) + b;
}
/// <summary>
/// Easing equation function for a quartic (t^4) easing out/in:
/// deceleration until halfway, then acceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float QuartEaseOutIn(float t, float b, float c, float d)
{
if (t < d/2)
{
return QuartEaseOut(t*2, b, c/2, d);
}
return QuartEaseIn((t*2) - d, b + c/2, c/2, d);
}
#endregion
#region Quintic
/// <summary>
/// Easing equation function for a quintic (t^5) easing out:
/// decelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float QuintEaseOut(float t, float b, float c, float d)
{
return c*((t = t/d - 1)*t*t*t*t + 1) + b;
}
/// <summary>
/// Easing equation function for a quintic (t^5) easing in:
/// accelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float QuintEaseIn(float t, float b, float c, float d)
{
return c*(t /= d)*t*t*t*t + b;
}
/// <summary>
/// Easing equation function for a quintic (t^5) easing in/out:
/// acceleration until halfway, then deceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float QuintEaseInOut(float t, float b, float c, float d)
{
if ((t /= d/2) < 1)
{
return c/2*t*t*t*t*t + b;
}
return c/2*((t -= 2)*t*t*t*t + 2) + b;
}
/// <summary>
/// Easing equation function for a quintic (t^5) easing in/out:
/// acceleration until halfway, then deceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float QuintEaseOutIn(float t, float b, float c, float d)
{
if (t < d/2)
{
return QuintEaseOut(t*2, b, c/2, d);
}
return QuintEaseIn((t*2) - d, b + c/2, c/2, d);
}
#endregion
#region Elastic
/// <summary>
/// Easing equation function for an elastic (exponentially decaying sine wave) easing out:
/// decelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float ElasticEaseOut(float t, float b, float c, float d)
{
if ((t /= d) == 1)
{
return b + c;
}
var p = d*.3f;
var s = p/4;
return (c*Mathf.Pow(2, -10*t)*Mathf.Sin((t*d - s)*(2*Mathf.PI)/p) + c + b);
}
/// <summary>
/// Easing equation function for an elastic (exponentially decaying sine wave) easing in:
/// accelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float ElasticEaseIn(float t, float b, float c, float d)
{
if ((t /= d) == 1)
{
return b + c;
}
var p = d*.3f;
var s = p/4;
return -(c*Mathf.Pow(2, 10*(t -= 1))*Mathf.Sin((t*d - s)*(2*Mathf.PI)/p)) + b;
}
/// <summary>
/// Easing equation function for an elastic (exponentially decaying sine wave) easing in/out:
/// acceleration until halfway, then deceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float ElasticEaseInOut(float t, float b, float c, float d)
{
if ((t /= d/2) == 2)
{
return b + c;
}
var p = d*(.3f*1.5f);
var s = p/4;
if (t < 1)
{
return -.5f*(c*Mathf.Pow(2, 10*(t -= 1))*Mathf.Sin((t*d - s)*(2*Mathf.PI)/p)) + b;
}
return c*Mathf.Pow(2, -10*(t -= 1))*Mathf.Sin((t*d - s)*(2*Mathf.PI)/p)*.5f + c + b;
}
/// <summary>
/// Easing equation function for an elastic (exponentially decaying sine wave) easing out/in:
/// deceleration until halfway, then acceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float ElasticEaseOutIn(float t, float b, float c, float d)
{
if (t < d/2)
{
return ElasticEaseOut(t*2, b, c/2, d);
}
return ElasticEaseIn((t*2) - d, b + c/2, c/2, d);
}
#endregion
#region Bounce
/// <summary>
/// Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out:
/// decelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float BounceEaseOut(float t, float b, float c, float d)
{
if ((t /= d) < (1/2.75f))
{
return c*(7.5625f*t*t) + b;
}
if (t < (2/2.75))
{
return c*(7.5625f*(t -= (1.5f/2.75f))*t + .75f) + b;
}
if (t < (2.5/2.75))
{
return c*(7.5625f*(t -= (2.25f/2.75f))*t + .9375f) + b;
}
return c*(7.5625f*(t -= (2.625f/2.75f))*t + .984375f) + b;
}
/// <summary>
/// Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in:
/// accelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float BounceEaseIn(float t, float b, float c, float d)
{
return c - BounceEaseOut(d - t, 0, c, d) + b;
}
/// <summary>
/// Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in/out:
/// acceleration until halfway, then deceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float BounceEaseInOut(float t, float b, float c, float d)
{
if (t < d/2)
{
return BounceEaseIn(t*2, 0, c, d)*.5f + b;
}
return BounceEaseOut(t*2 - d, 0, c, d)*.5f + c*.5f + b;
}
/// <summary>
/// Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out/in:
/// deceleration until halfway, then acceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float BounceEaseOutIn(float t, float b, float c, float d)
{
if (t < d/2)
{
return BounceEaseOut(t*2, b, c/2, d);
}
return BounceEaseIn((t*2) - d, b + c/2, c/2, d);
}
#endregion
#region Back
/// <summary>
/// Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out:
/// decelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float BackEaseOut(float t, float b, float c, float d)
{
return c*((t = t/d - 1)*t*((1.70158f + 1)*t + 1.70158f) + 1) + b;
}
/// <summary>
/// Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in:
/// accelerating from zero velocity.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float BackEaseIn(float t, float b, float c, float d)
{
return c*(t /= d)*t*((1.70158f + 1)*t - 1.70158f) + b;
}
/// <summary>
/// Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in/out:
/// acceleration until halfway, then deceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float BackEaseInOut(float t, float b, float c, float d)
{
var s = 1.70158f;
if ((t /= d/2) < 1)
{
return c/2*(t*t*(((s *= (1.525f)) + 1)*t - s)) + b;
}
return c/2*((t -= 2)*t*(((s *= (1.525f)) + 1)*t + s) + 2) + b;
}
/// <summary>
/// Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in:
/// deceleration until halfway, then acceleration.
/// </summary>
/// <param name="t">Current time in seconds.</param>
/// <param name="b">Starting value.</param>
/// <param name="c">Final value.</param>
/// <param name="d">Duration of animation.</param>
/// <returns>The correct value.</returns>
public static float BackEaseOutIn(float t, float b, float c, float d)
{
if (t < d/2)
{
return BackEaseOut(t*2, b, c/2, d);
}
return BackEaseIn((t*2) - d, b + c/2, c/2, d);
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c0be6d36a29af844fa2d7584d66b374c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,209 @@
using System;
using UnityEngine;
public static partial class SRMath
{
public enum EaseType
{
Linear,
QuadEaseOut,
QuadEaseIn,
QuadEaseInOut,
QuadEaseOutIn,
ExpoEaseOut,
ExpoEaseIn,
ExpoEaseInOut,
ExpoEaseOutIn,
CubicEaseOut,
CubicEaseIn,
CubicEaseInOut,
CubicEaseOutIn,
QuartEaseOut,
QuartEaseIn,
QuartEaseInOut,
QuartEaseOutIn,
QuintEaseOut,
QuintEaseIn,
QuintEaseInOut,
QuintEaseOutIn,
CircEaseOut,
CircEaseIn,
CircEaseInOut,
CircEaseOutIn,
SineEaseOut,
SineEaseIn,
SineEaseInOut,
SineEaseOutIn,
ElasticEaseOut,
ElasticEaseIn,
ElasticEaseInOut,
ElasticEaseOutIn,
BounceEaseOut,
BounceEaseIn,
BounceEaseInOut,
BounceEaseOutIn,
BackEaseOut,
BackEaseIn,
BackEaseInOut,
BackEaseOutIn
}
public static float Ease(float from, float to, float t, EaseType type)
{
switch (type)
{
case EaseType.Linear:
return TweenFunctions.Linear(t, from, to, 1f);
case EaseType.QuadEaseOut:
return TweenFunctions.QuadEaseOut(t, from, to, 1f);
case EaseType.QuadEaseIn:
return TweenFunctions.QuadEaseIn(t, from, to, 1f);
case EaseType.QuadEaseInOut:
return TweenFunctions.QuadEaseInOut(t, from, to, 1f);
case EaseType.QuadEaseOutIn:
return TweenFunctions.QuadEaseOutIn(t, from, to, 1f);
case EaseType.ExpoEaseOut:
return TweenFunctions.ExpoEaseOut(t, from, to, 1f);
case EaseType.ExpoEaseIn:
return TweenFunctions.ExpoEaseIn(t, from, to, 1f);
case EaseType.ExpoEaseInOut:
return TweenFunctions.ExpoEaseInOut(t, from, to, 1f);
case EaseType.ExpoEaseOutIn:
return TweenFunctions.ExpoEaseOutIn(t, from, to, 1f);
case EaseType.CubicEaseOut:
return TweenFunctions.CubicEaseOut(t, from, to, 1f);
case EaseType.CubicEaseIn:
return TweenFunctions.CubicEaseIn(t, from, to, 1f);
case EaseType.CubicEaseInOut:
return TweenFunctions.CubicEaseInOut(t, from, to, 1f);
case EaseType.CubicEaseOutIn:
return TweenFunctions.CubicEaseOutIn(t, from, to, 1f);
case EaseType.QuartEaseOut:
return TweenFunctions.QuartEaseOut(t, from, to, 1f);
case EaseType.QuartEaseIn:
return TweenFunctions.QuartEaseIn(t, from, to, 1f);
case EaseType.QuartEaseInOut:
return TweenFunctions.QuartEaseInOut(t, from, to, 1f);
case EaseType.QuartEaseOutIn:
return TweenFunctions.QuartEaseOutIn(t, from, to, 1f);
case EaseType.QuintEaseOut:
return TweenFunctions.QuintEaseOut(t, from, to, 1f);
case EaseType.QuintEaseIn:
return TweenFunctions.QuintEaseIn(t, from, to, 1f);
case EaseType.QuintEaseInOut:
return TweenFunctions.QuintEaseInOut(t, from, to, 1f);
case EaseType.QuintEaseOutIn:
return TweenFunctions.QuintEaseOutIn(t, from, to, 1f);
case EaseType.CircEaseOut:
return TweenFunctions.CircEaseOut(t, from, to, 1f);
case EaseType.CircEaseIn:
return TweenFunctions.CircEaseIn(t, from, to, 1f);
case EaseType.CircEaseInOut:
return TweenFunctions.CircEaseInOut(t, from, to, 1f);
case EaseType.CircEaseOutIn:
return TweenFunctions.CircEaseOutIn(t, from, to, 1f);
case EaseType.SineEaseOut:
return TweenFunctions.SineEaseOut(t, from, to, 1f);
case EaseType.SineEaseIn:
return TweenFunctions.SineEaseIn(t, from, to, 1f);
case EaseType.SineEaseInOut:
return TweenFunctions.SineEaseInOut(t, from, to, 1f);
case EaseType.SineEaseOutIn:
return TweenFunctions.SineEaseOutIn(t, from, to, 1f);
case EaseType.ElasticEaseOut:
return TweenFunctions.ElasticEaseOut(t, from, to, 1f);
case EaseType.ElasticEaseIn:
return TweenFunctions.ElasticEaseIn(t, from, to, 1f);
case EaseType.ElasticEaseInOut:
return TweenFunctions.ElasticEaseInOut(t, from, to, 1f);
case EaseType.ElasticEaseOutIn:
return TweenFunctions.ElasticEaseOutIn(t, from, to, 1f);
case EaseType.BounceEaseOut:
return TweenFunctions.BounceEaseOut(t, from, to, 1f);
case EaseType.BounceEaseIn:
return TweenFunctions.BounceEaseIn(t, from, to, 1f);
case EaseType.BounceEaseInOut:
return TweenFunctions.BounceEaseInOut(t, from, to, 1f);
case EaseType.BounceEaseOutIn:
return TweenFunctions.BounceEaseOutIn(t, from, to, 1f);
case EaseType.BackEaseOut:
return TweenFunctions.BackEaseOut(t, from, to, 1f);
case EaseType.BackEaseIn:
return TweenFunctions.BackEaseIn(t, from, to, 1f);
case EaseType.BackEaseInOut:
return TweenFunctions.BackEaseInOut(t, from, to, 1f);
case EaseType.BackEaseOutIn:
return TweenFunctions.BackEaseOutIn(t, from, to, 1f);
default:
throw new ArgumentOutOfRangeException("type");
}
}
/// <summary>
/// Calculate a framerate-independent value to lerp by
/// </summary>
/// <param name="strength"></param>
/// <param name="deltaTime"></param>
/// <returns></returns>
public static float SpringLerp(float strength, float deltaTime)
{
var ms = Mathf.RoundToInt(deltaTime*1000f);
var step = 0.001f*strength;
var from = 0f;
var to = 1f;
for (var i = 0; i < ms; i++)
{
from = Mathf.Lerp(from, to, step);
}
return from;
}
/// <summary>
/// A frame-rate independent way of doing Mathf.Lerp(from, to, Time.deltaTime * strength). Based on NGUIMath.SpringLerp
/// </summary>
/// <param name="from">Starting Value</param>
/// <param name="to">End Value</param>
/// <param name="strength">How fast the spring will complete</param>
/// <param name="deltaTime">Pass in Time.deltaTime or RealTime.deltaTime</param>
/// <returns>Interpolated value</returns>
public static float SpringLerp(float from, float to, float strength, float deltaTime)
{
return Mathf.Lerp(from, to, SpringLerp(strength, deltaTime));
}
public static Vector3 SpringLerp(Vector3 from, Vector3 to, float strength, float deltaTime)
{
return Vector3.Lerp(from, to, SpringLerp(strength, deltaTime));
}
public static Quaternion SpringLerp(Quaternion from, Quaternion to, float strength, float deltaTime)
{
return Quaternion.Slerp(from, to, SpringLerp(strength, deltaTime));
}
/// <summary>
/// Smoothly clamp value between 0 and max, smoothing between min and max
/// </summary>
/// <param name="value"></param>
/// <param name="min"></param>
/// <param name="max"></param>
/// <param name="easeType"></param>
/// <returns></returns>
public static float SmoothClamp(float value, float min, float max, float scrollMax,
EaseType easeType = EaseType.ExpoEaseOut)
{
if (value < min)
{
return value;
}
var p = Mathf.Clamp01((value - min)/(scrollMax - min));
Debug.Log(p);
return Mathf.Clamp(min + Mathf.Lerp(value - min, max, Ease(0, 1f, p, easeType)), 0, max);
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 810c2c875ec6af345a04174ff5828880
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,151 @@
using System;
using UnityEngine;
public static partial class SRMath
{
/// <summary>
/// Lerp from one value to another, without clamping t to 0-1.
/// </summary>
/// <param name="from"></param>
/// <param name="to"></param>
/// <param name="t"></param>
/// <returns></returns>
public static float LerpUnclamped(float from, float to, float t)
{
return (1.0f - t)*from + t*to;
}
/// <summary>
/// Lerp from one vector to another, without clamping t
/// </summary>
/// <param name="from"></param>
/// <param name="to"></param>
/// <param name="t"></param>
/// <returns></returns>
public static Vector3 LerpUnclamped(Vector3 from, Vector3 to, float t)
{
return new Vector3(
LerpUnclamped(from.x, to.x, t),
LerpUnclamped(from.y, to.y, t),
LerpUnclamped(from.z, to.z, t)
);
}
/// <summary>
/// Value from 0.0f-1.0f, 0 when facing fully away and 1.0f when facing fully towards
/// </summary>
public static float FacingNormalized(Vector3 dir1, Vector3 dir2)
{
dir1.Normalize();
dir2.Normalize();
return Mathf.InverseLerp(-1, 1, Vector3.Dot(dir1, dir2));
}
/// <summary>
/// Reduces a given angle to a value between 180 and -180.
/// </summary>
/// <param name="angle">The angle to reduce, in radians.</param>
/// <returns>The new angle, in radians.</returns>
/// https://github.com/mono/MonoGame/blob/develop/MonoGame.Framework/MathHelper.cs
public static float WrapAngle(float angle)
{
if (angle <= -180f)
{
angle += 360f;
}
else
{
if (angle > 180f)
{
angle -= 360f;
}
}
return angle;
}
/// <summary>
/// Return the angle closest to 'to'
/// </summary>
/// <param name="to"></param>
/// <param name="angle1"></param>
/// <param name="angle2"></param>
/// <returns></returns>
public static float NearestAngle(float to, float angle1, float angle2)
{
if (Mathf.Abs(Mathf.DeltaAngle(to, angle1)) > Mathf.Abs(Mathf.DeltaAngle(to, angle2)))
{
return angle2;
}
return angle1;
}
/// <summary>
/// Wrap value to 0-max (non-inclusive)
/// </summary>
/// <param name="max">Max value (non-inclusive)</param>
/// <param name="value"></param>
/// <returns>Value wrapped from 0-max</returns>
public static int Wrap(int max, int value)
{
if (max < 0)
{
throw new ArgumentOutOfRangeException("max", "max must be greater than 0");
}
while (value < 0)
{
value += max;
}
while (value >= max)
{
value -= max;
}
return value;
}
/// <summary>
/// Wrap value to 0-max (non-inclusive)
/// </summary>
/// <param name="max">Max value (non-inclusive)</param>
/// <param name="value"></param>
/// <returns>Value wrapped from 0-max</returns>
public static float Wrap(float max, float value)
{
while (value < 0)
{
value += max;
}
while (value >= max)
{
value -= max;
}
return value;
}
public static float Average(float v1, float v2)
{
return (v1 + v2)*0.5f;
}
/// <summary>
/// Return an angle in range -180, 180 based on direction vector
/// </summary>
/// <param name="direction"></param>
/// <returns></returns>
public static float Angle(Vector2 direction)
{
var angle = Vector3.Angle(Vector3.up, direction);
if (Vector3.Cross(direction, Vector3.up).z > 0f)
{
angle *= -1;
}
return angle;
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dc751da3d31975645847e0e4088ff560
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,46 @@
namespace SRF.Helpers
{
using System;
using System.Reflection;
public static class SRReflection
{
public static void SetPropertyValue(object obj, PropertyInfo p, object value)
{
#if NETFX_CORE
p.SetValue(obj, value, null);
#else
p.GetSetMethod().Invoke(obj, new[] {value});
#endif
}
public static object GetPropertyValue(object obj, PropertyInfo p)
{
#if NETFX_CORE
return p.GetValue(obj, null);
#else
return p.GetGetMethod().Invoke(obj, null);
#endif
}
public static T GetAttribute<T>(MemberInfo t) where T : Attribute
{
#if !NETFX_CORE
return Attribute.GetCustomAttribute(t, typeof (T)) as T;
#else
return t.GetCustomAttribute(typeof (T), true) as T;
#endif
}
#if NETFX_CORE
public static T GetAttribute<T>(Type t) where T : Attribute
{
return GetAttribute<T>(t.GetTypeInfo());
}
#endif
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6aaf1b857713dd44a955633b6458f1c2
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 9107076f77b9a344d8c00028a350b6fb
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -0,0 +1,39 @@
using UnityEngine.Scripting;
namespace SRF.Service
{
using System;
[AttributeUsage(AttributeTargets.Class)]
public sealed class ServiceAttribute : PreserveAttribute
{
public ServiceAttribute(Type serviceType)
{
ServiceType = serviceType;
}
public Type ServiceType { get; private set; }
}
[AttributeUsage(AttributeTargets.Method)]
public sealed class ServiceSelectorAttribute : PreserveAttribute
{
public ServiceSelectorAttribute(Type serviceType)
{
ServiceType = serviceType;
}
public Type ServiceType { get; private set; }
}
[AttributeUsage(AttributeTargets.Method)]
public sealed class ServiceConstructorAttribute : PreserveAttribute
{
public ServiceConstructorAttribute(Type serviceType)
{
ServiceType = serviceType;
}
public Type ServiceType { get; private set; }
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 901f51b194db73d479d84ae26519fc20
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,7 @@
namespace SRF.Service
{
public interface IAsyncService
{
bool IsLoaded { get; }
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 08e9b59ff0ffb22488411ef5134ee325
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,91 @@
//#define ENABLE_LOGGING
namespace SRF.Service
{
using System;
using System.Collections;
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;
using Object = UnityEngine.Object;
/// <summary>
/// A service which has async-loading dependencies
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class SRDependencyServiceBase<T> : SRServiceBase<T>, IAsyncService where T : class
{
private bool _isLoaded;
protected abstract Type[] Dependencies { get; }
public bool IsLoaded
{
get { return _isLoaded; }
}
[Conditional("ENABLE_LOGGING")]
private void Log(string msg, Object target)
{
//#if ENABLE_LOGGING
Debug.Log(msg, target);
//#endif
}
protected override void Start()
{
base.Start();
StartCoroutine(LoadDependencies());
}
/// <summary>
/// Invoked once all dependencies are loaded
/// </summary>
protected virtual void OnLoaded() {}
private IEnumerator LoadDependencies()
{
SRServiceManager.LoadingCount++;
Log("[Service] Loading service ({0})".Fmt(GetType().Name), this);
foreach (var d in Dependencies)
{
var hasService = SRServiceManager.HasService(d);
Log("[Service] Resolving Service ({0}) HasService: {1}".Fmt(d.Name, hasService), this);
if (hasService)
{
continue;
}
var service = SRServiceManager.GetService(d);
if (service == null)
{
Debug.LogError("[Service] Could not resolve dependency ({0})".Fmt(d.Name));
enabled = false;
yield break;
}
var a = service as IAsyncService;
if (a != null)
{
while (!a.IsLoaded)
{
yield return new WaitForEndOfFrame();
}
}
}
Log("[Service] Loading service ({0}) complete.".Fmt(GetType().Name), this);
_isLoaded = true;
SRServiceManager.LoadingCount--;
OnLoaded();
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8c5aaa1711d009f48a19f2db87d71b82
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,128 @@
//#define ENABLE_LOGGING
namespace SRF.Service
{
using System.Collections;
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;
public abstract class SRSceneServiceBase<T, TImpl> : SRServiceBase<T>, IAsyncService
where T : class
where TImpl : Component
{
private TImpl _rootObject;
/// <summary>
/// Name of the scene this service's contents are within
/// </summary>
protected abstract string SceneName { get; }
/// <summary>
/// Scene contents root object
/// </summary>
protected TImpl RootObject
{
get { return _rootObject; }
}
public bool IsLoaded
{
get { return _rootObject != null; }
}
[Conditional("ENABLE_LOGGING")]
private void Log(string msg, Object target)
{
//#if ENABLE_LOGGING
Debug.Log(msg, target);
//#endif
}
protected override void Start()
{
base.Start();
StartCoroutine(LoadCoroutine());
}
protected override void OnDestroy()
{
if (IsLoaded)
{
Destroy(_rootObject.gameObject);
}
base.OnDestroy();
}
protected virtual void OnLoaded() {}
private IEnumerator LoadCoroutine()
{
if (_rootObject != null)
{
yield break;
}
SRServiceManager.LoadingCount++;
#if UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
if (Application.loadedLevelName == SceneName)
#else
if (UnityEngine.SceneManagement.SceneManager.GetSceneByName(SceneName).isLoaded)
#endif
{
Log("[Service] Already in service scene {0}. Searching for root object...".Fmt(SceneName), this);
}
else
{
Log("[Service] Loading scene ({0})".Fmt(SceneName), this);
#if UNITY_PRO_LICENSE || UNITY_5 || UNITY_5_3_OR_NEWER
#if UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
yield return Application.LoadLevelAdditiveAsync(SceneName);
#else
yield return UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(SceneName, UnityEngine.SceneManagement.LoadSceneMode.Additive);
#endif
#else
Application.LoadLevelAdditive(SceneName);
yield return new WaitForEndOfFrame();
#endif
Log("[Service] Scene loaded. Searching for root object...", this);
}
var go = GameObject.Find(SceneName);
if (go == null)
{
goto Error;
}
var timpl = go.GetComponent<TImpl>();
if (timpl == null)
{
goto Error;
}
_rootObject = timpl;
_rootObject.transform.parent = CachedTransform;
DontDestroyOnLoad(go);
Debug.Log("[Service] Loading {0} complete. (Scene: {1})".Fmt(GetType().Name, SceneName), this);
SRServiceManager.LoadingCount--;
OnLoaded();
yield break;
Error:
SRServiceManager.LoadingCount--;
Debug.LogError("[Service] Root object ({0}) not found".Fmt(SceneName), this);
enabled = false;
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ff0dcbb555990d24e9e3055e77395656
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,17 @@
namespace SRF.Service
{
public abstract class SRServiceBase<T> : SRMonoBehaviourEx where T : class
{
protected override void Awake()
{
base.Awake();
SRServiceManager.RegisterService<T>(this);
}
protected override void OnDestroy()
{
base.OnDestroy();
SRServiceManager.UnRegisterService<T>();
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c4f48d5ad0a809349bd5e46160a824d3
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,530 @@
// Disable unreachable code warning caused by DEBUG
#pragma warning disable 0162
namespace SRF.Service
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Components;
using Helpers;
using Internal;
using UnityEngine;
using Object = UnityEngine.Object;
[AddComponentMenu(ComponentMenuPaths.SRServiceManager)]
public class SRServiceManager : SRAutoSingleton<SRServiceManager>
{
#if SRDEBUG
public const bool EnableLogging = true;
#else
public const bool EnableLogging = false;
#endif
#if UNITY_EDITOR && ((!UNITY_2017 && !UNITY_2018 && !UNITY_2019) || UNITY_2019_3_OR_NEWER)
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
public static void RuntimeInitialize()
{
// To handle entering play mode without a domain reload, need to reset the state of the service manager.
_hasQuit = false;
}
#endif
/// <summary>
/// Register the assembly that contains type <typeparamref name="TType"/> with the service manager.
/// </summary>
/// <typeparam name="TType"></typeparam>
public static void RegisterAssembly<TType>()
{
#if NETFX_CORE
var assembly = typeof(TType).GetTypeInfo().Assembly;
#else
var assembly = typeof(TType).Assembly;
#endif
if (_assemblies.Contains(assembly))
{
return;
}
_assemblies.Add(assembly);
}
/// <summary>
/// Is there a service loading?
/// </summary>
public static bool IsLoading
{
get { return LoadingCount > 0; }
}
public static int LoadingCount = 0;
public static T GetService<T>() where T : class
{
var s = GetServiceInternal(typeof(T)) as T;
if (s == null && (!_hasQuit || EnableLogging))
{
Debug.LogWarning("Service {0} not found. (HasQuit: {1})".Fmt(typeof(T).Name, _hasQuit));
}
return s;
}
public static object GetService(Type t)
{
var s = GetServiceInternal(t);
if (s == null && (!_hasQuit || EnableLogging))
{
Debug.LogWarning("Service {0} not found. (HasQuit: {1})".Fmt(t.Name, _hasQuit));
}
return s;
}
private static object GetServiceInternal(Type t)
{
if (_hasQuit || !Application.isPlaying)
{
return null;
}
var services = Instance._services;
for (var i = 0; i < services.Count; i++)
{
var s = services[i];
if (t.IsAssignableFrom(s.Type))
{
if (s.Object == null)
{
UnRegisterService(t);
break;
}
return s.Object;
}
}
return Instance.AutoCreateService(t);
}
public static bool HasService<T>() where T : class
{
return HasService(typeof(T));
}
public static bool HasService(Type t)
{
if (_hasQuit || !Application.isPlaying)
{
return false;
}
var services = Instance._services;
for (var i = 0; i < services.Count; i++)
{
var s = services[i];
if (t.IsAssignableFrom(s.Type))
{
return s.Object != null;
}
}
return false;
}
public static void RegisterService<T>(object service) where T : class
{
RegisterService(typeof(T), service);
}
private static void RegisterService(Type t, object service)
{
if (_hasQuit)
{
return;
}
if (HasService(t))
{
if (GetServiceInternal(t) == service)
{
return;
}
throw new Exception("Service already registered for type " + t.Name);
}
UnRegisterService(t);
if (!t.IsInstanceOfType(service))
{
throw new ArgumentException("service {0} must be assignable from type {1}".Fmt(service.GetType(), t));
}
Instance._services.Add(new Service {
Object = service,
Type = t
});
}
public static void UnRegisterService<T>() where T : class
{
UnRegisterService(typeof(T));
}
private static void UnRegisterService(Type t)
{
if (_hasQuit || !HasInstance)
{
return;
}
if (!HasService(t))
{
return;
}
var services = Instance._services;
for (var i = services.Count - 1; i >= 0; i--)
{
var s = services[i];
if (s.Type == t)
{
services.RemoveAt(i);
}
}
}
private class Service
{
public object Object;
public Type Type;
}
private class ServiceStub
{
public Func<object> Constructor;
public Type InterfaceType;
public Func<Type> Selector;
public Type Type;
public override string ToString()
{
var s = InterfaceType.Name + " (";
if (Type != null)
{
s += "Type: " + Type;
}
else if (Selector != null)
{
s += "Selector: " + Selector;
}
else if (Constructor != null)
{
s += "Constructor: " + Constructor;
}
s += ")";
return s;
}
}
private static readonly List<Assembly> _assemblies = new List<Assembly>(2);
private readonly SRList<Service> _services = new SRList<Service>();
private List<ServiceStub> _serviceStubs;
private static bool _hasQuit;
protected override void Awake()
{
_hasQuit = false;
base.Awake();
DontDestroyOnLoad(CachedGameObject);
CachedGameObject.hideFlags = HideFlags.NotEditable;
}
protected void UpdateStubs()
{
if (_serviceStubs != null)
{
return;
}
RegisterAssembly<SRServiceManager>();
_serviceStubs = new List<ServiceStub>();
var types = new List<Type>();
foreach (var assembly in _assemblies)
{
try
{
#if NETFX_CORE
types.AddRange(assembly.Types);
#else
types.AddRange(assembly.GetTypes());
#endif
}
catch (Exception e)
{
Debug.LogError("[SRServiceManager] Error loading assembly {0}".Fmt(assembly.FullName), this);
Debug.LogException(e);
}
}
foreach (var type in types)
{
ScanType(type);
}
if (EnableLogging)
{
var serviceStrings =
_serviceStubs.Select(p => " {0}".Fmt(p)).ToArray();
Debug.Log("[SRServiceManager] Services Discovered: {0} \n {1}".Fmt(serviceStrings.Length,
string.Join("\n ", serviceStrings)));
}
}
protected object AutoCreateService(Type t)
{
UpdateStubs();
foreach (var stub in _serviceStubs)
{
if (stub.InterfaceType != t)
{
continue;
}
object service = null;
if (stub.Constructor != null)
{
service = stub.Constructor();
}
else
{
var serviceType = stub.Type;
if (serviceType == null)
{
serviceType = stub.Selector();
}
service = DefaultServiceConstructor(t, serviceType);
}
if (!HasService(t))
{
RegisterService(t, service);
}
if (EnableLogging)
{
Debug.Log("[SRServiceManager] Auto-created service: {0} ({1})".Fmt(stub.Type, stub.InterfaceType),
service as Object);
}
return service;
}
return null;
}
protected void OnApplicationQuit()
{
_hasQuit = true;
_assemblies.Clear();
}
#if UNITY_EDITOR
protected void OnDisable()
{
if (EnableLogging)
{
Debug.Log("[SRServiceManager] Cleaning up services");
}
// Script recompile is likely in progress - clear up everything.
foreach (Service s in _services)
{
IDisposable disposable = s.Object as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
Behaviour behaviour = s.Object as Behaviour;
if (behaviour != null)
{
DestroyImmediate(behaviour.gameObject);
} else if (s.Object is Object)
{
DestroyImmediate(s.Object as Object);
}
}
_services.Clear(clean: true);
}
#endif
private static object DefaultServiceConstructor(Type serviceIntType, Type implType)
{
// If mono-behaviour based, create a gameobject for this service
if (typeof(MonoBehaviour).IsAssignableFrom(implType))
{
var go = new GameObject("_S_" + serviceIntType.Name);
return go.AddComponent(implType);
}
// If ScriptableObject based, create an instance
if (typeof(ScriptableObject).IsAssignableFrom(implType))
{
var obj = ScriptableObject.CreateInstance(implType);
return obj;
}
// If just a standard C# object, just create an instance
return Activator.CreateInstance(implType);
}
#region Type Scanning
private void ScanType(Type type)
{
var attribute = SRReflection.GetAttribute<ServiceAttribute>(type);
if (attribute != null)
{
_serviceStubs.Add(new ServiceStub {
Type = type,
InterfaceType = attribute.ServiceType
});
}
ScanTypeForConstructors(type, _serviceStubs);
ScanTypeForSelectors(type, _serviceStubs);
}
private static void ScanTypeForSelectors(Type t, List<ServiceStub> stubs)
{
var methods = GetStaticMethods(t);
foreach (var method in methods)
{
var attrib = SRReflection.GetAttribute<ServiceSelectorAttribute>(method);
if (attrib == null)
{
continue;
}
if (method.ReturnType != typeof(Type))
{
Debug.LogError("ServiceSelector must have return type of Type ({0}.{1}())".Fmt(t.Name, method.Name));
continue;
}
if (method.GetParameters().Length > 0)
{
Debug.LogError("ServiceSelector must have no parameters ({0}.{1}())".Fmt(t.Name, method.Name));
continue;
}
var stub = stubs.FirstOrDefault(p => p.InterfaceType == attrib.ServiceType);
if (stub == null)
{
stub = new ServiceStub {
InterfaceType = attrib.ServiceType
};
stubs.Add(stub);
}
#if NETFX_CORE
stub.Selector = (Func<Type>)method.CreateDelegate(typeof(Func<Type>));
#else
stub.Selector = (Func<Type>)Delegate.CreateDelegate(typeof(Func<Type>), method);
#endif
}
}
private static void ScanTypeForConstructors(Type t, List<ServiceStub> stubs)
{
var methods = GetStaticMethods(t);
foreach (var method in methods)
{
var attrib = SRReflection.GetAttribute<ServiceConstructorAttribute>(method);
if (attrib == null)
{
continue;
}
if (method.ReturnType != attrib.ServiceType)
{
Debug.LogError("ServiceConstructor must have return type of {2} ({0}.{1}())".Fmt(t.Name, method.Name,
attrib.ServiceType));
continue;
}
if (method.GetParameters().Length > 0)
{
Debug.LogError("ServiceConstructor must have no parameters ({0}.{1}())".Fmt(t.Name, method.Name));
continue;
}
var stub = stubs.FirstOrDefault(p => p.InterfaceType == attrib.ServiceType);
if (stub == null)
{
stub = new ServiceStub {
InterfaceType = attrib.ServiceType
};
stubs.Add(stub);
}
var m = method;
stub.Constructor = () => m.Invoke(null, null);
}
}
#endregion
#region Reflection
private static MethodInfo[] GetStaticMethods(Type t)
{
#if !NETFX_CORE
return t.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
#else
return t.GetTypeInfo().DeclaredMethods.Where(p => p.IsStatic).ToArray();
#endif
}
#endregion
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 83920a42d6e0f814bacbc701ae8636a5
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 16100
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: ed6eb48a67380fe40a3864e012ce762d
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -0,0 +1,145 @@
namespace SRF.UI
{
using Internal;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[RequireComponent(typeof (RectTransform))]
[ExecuteInEditMode]
[AddComponentMenu(ComponentMenuPaths.ContentFitText)]
public class ContentFitText : UIBehaviour, ILayoutElement
{
public SRText CopySource;
public Vector2 Padding;
public float minWidth
{
get
{
if (CopySource == null)
{
return -1f;
}
return LayoutUtility.GetMinWidth(CopySource.rectTransform) + Padding.x;
}
}
public float preferredWidth
{
get
{
if (CopySource == null)
{
return -1f;
}
return LayoutUtility.GetPreferredWidth(CopySource.rectTransform) + Padding.x;
}
}
public float flexibleWidth
{
get
{
if (CopySource == null)
{
return -1f;
}
return LayoutUtility.GetFlexibleWidth(CopySource.rectTransform);
}
}
public float minHeight
{
get
{
if (CopySource == null)
{
return -1f;
}
return LayoutUtility.GetFlexibleHeight(CopySource.rectTransform) + Padding.y;
}
}
public float preferredHeight
{
get
{
if (CopySource == null)
{
return -1f;
}
return LayoutUtility.GetPreferredHeight(CopySource.rectTransform) + Padding.y;
}
}
public float flexibleHeight
{
get
{
if (CopySource == null)
{
return -1f;
}
return LayoutUtility.GetFlexibleHeight(CopySource.rectTransform);
}
}
public int layoutPriority
{
get { return 0; }
}
public void CalculateLayoutInputHorizontal()
{
CopySource.CalculateLayoutInputHorizontal();
}
public void CalculateLayoutInputVertical()
{
CopySource.CalculateLayoutInputVertical();
}
protected override void OnEnable()
{
SetDirty();
CopySource.LayoutDirty += CopySourceOnLayoutDirty;
}
private void CopySourceOnLayoutDirty(SRText srText)
{
SetDirty();
}
protected override void OnTransformParentChanged()
{
SetDirty();
}
protected override void OnDisable()
{
CopySource.LayoutDirty -= CopySourceOnLayoutDirty;
SetDirty();
}
protected override void OnDidApplyAnimationProperties()
{
SetDirty();
}
protected override void OnBeforeTransformParentChanged()
{
SetDirty();
}
protected void SetDirty()
{
if (!IsActive())
{
return;
}
LayoutRebuilder.MarkLayoutForRebuild(transform as RectTransform);
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dced79525dbfa2b44b8d52b2cca6d745
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,95 @@
namespace SRF.UI
{
using Internal;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
/// <summary>
/// Copies the preferred size of another layout element (useful for a parent object basing its sizing from a child
/// element).
/// This does have very quirky behaviour, though.
/// TODO: Write custom editor for this to match layout element editor
/// </summary>
[RequireComponent(typeof (RectTransform))]
[ExecuteInEditMode]
[AddComponentMenu(ComponentMenuPaths.CopyLayoutElement)]
public class CopyLayoutElement : UIBehaviour, ILayoutElement
{
public bool CopyMinHeight;
public bool CopyMinWidth;
public bool CopyPreferredHeight;
public bool CopyPreferredWidth;
public RectTransform CopySource;
public float PaddingMinHeight;
public float PaddingMinWidth;
public float PaddingPreferredHeight;
public float PaddingPreferredWidth;
public float preferredWidth
{
get
{
if (!CopyPreferredWidth || CopySource == null || !IsActive())
{
return -1f;
}
return LayoutUtility.GetPreferredWidth(CopySource) + PaddingPreferredWidth;
}
}
public float preferredHeight
{
get
{
if (!CopyPreferredHeight || CopySource == null || !IsActive())
{
return -1f;
}
return LayoutUtility.GetPreferredHeight(CopySource) + PaddingPreferredHeight;
}
}
public float minWidth
{
get
{
if (!CopyMinWidth || CopySource == null || !IsActive())
{
return -1f;
}
return LayoutUtility.GetMinWidth(CopySource) + PaddingMinWidth;
}
}
public float minHeight
{
get
{
if (!CopyMinHeight || CopySource == null || !IsActive())
{
return -1f;
}
return LayoutUtility.GetMinHeight(CopySource) + PaddingMinHeight;
}
}
public int layoutPriority
{
get { return 2; }
}
public float flexibleHeight
{
get { return -1; }
}
public float flexibleWidth
{
get { return -1; }
}
public void CalculateLayoutInputHorizontal() {}
public void CalculateLayoutInputVertical() {}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 525a40520606ceb469b7494cb8ddef87
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,50 @@
namespace SRF.UI
{
using Internal;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// Copies the preferred size of another layout element (useful for a parent object basing its sizing from a child
/// element).
/// This does have very quirky behaviour, though.
/// </summary>
[RequireComponent(typeof (RectTransform))]
[ExecuteInEditMode]
[AddComponentMenu(ComponentMenuPaths.CopyPreferredSize)]
public class CopyPreferredSize : LayoutElement
{
public RectTransform CopySource;
public float PaddingHeight;
public float PaddingWidth;
public override float preferredWidth
{
get
{
if (CopySource == null || !IsActive())
{
return -1f;
}
return LayoutUtility.GetPreferredWidth(CopySource) + PaddingWidth;
}
}
public override float preferredHeight
{
get
{
if (CopySource == null || !IsActive())
{
return -1f;
}
return LayoutUtility.GetPreferredHeight(CopySource) + PaddingHeight;
}
}
public override int layoutPriority
{
get { return 2; }
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 32609112f4257a740aa4b920a8556d24
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,107 @@
using System;
namespace SRF.UI
{
using Internal;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// Copies the preferred size of another layout element (useful for a parent object basing its sizing from a child
/// element).
/// This does have very quirky behaviour, though.
/// </summary>
[RequireComponent(typeof(RectTransform))]
[ExecuteInEditMode]
[AddComponentMenu(ComponentMenuPaths.CopyPreferredSizes)]
public class CopyPreferredSizes : LayoutElement
{
public enum Operations
{
Max,
Min
}
[Serializable]
public class CopySource
{
public RectTransform Rect;
public float PaddingHeight;
public float PaddingWidth;
}
public CopySource[] CopySources;
public Operations Operation;
public override float preferredWidth
{
get
{
if (CopySources == null || CopySources.Length == 0 || !IsActive())
{
return -1f;
}
float current = Operation == Operations.Max ? float.MinValue : float.MaxValue;
for (var i = 0; i < CopySources.Length; i++)
{
if (CopySources[i].Rect == null)
continue;
float width = LayoutUtility.GetPreferredWidth(CopySources[i].Rect) + CopySources[i].PaddingWidth;
if (Operation == Operations.Max && width > current)
current = width;
else if (Operation == Operations.Min && width < current)
current = width;
}
// ReSharper disable CompareOfFloatsByEqualityOperator
if (Operation == Operations.Max && current == float.MinValue) return -1;
if (Operation == Operations.Min && current == float.MaxValue) return -1;
// ReSharper restore CompareOfFloatsByEqualityOperator
return current;
}
}
public override float preferredHeight
{
get
{
if (CopySources == null || CopySources.Length == 0 || !IsActive())
{
return -1f;
}
float current = Operation == Operations.Max ? float.MinValue : float.MaxValue;
for (var i = 0; i < CopySources.Length; i++)
{
if (CopySources[i].Rect == null)
continue;
float height = LayoutUtility.GetPreferredHeight(CopySources[i].Rect) + CopySources[i].PaddingHeight;
if (Operation == Operations.Max && height > current)
current = height;
else if (Operation == Operations.Min && height < current)
current = height;
}
// ReSharper disable CompareOfFloatsByEqualityOperator
if (Operation == Operations.Max && current == float.MinValue) return -1;
if (Operation == Operations.Min && current == float.MaxValue) return -1;
// ReSharper restore CompareOfFloatsByEqualityOperator
return current;
}
}
public override int layoutPriority
{
get { return 2; }
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d5c292f06a2fb3644aac9698b40bd348
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,76 @@
namespace SRF.UI
{
using Internal;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// Copies the preferred size of another layout element (useful for a parent object basing its sizing from a child
/// element).
/// This does have very quirky behaviour, though.
/// </summary>
[RequireComponent(typeof(RectTransform))]
[ExecuteInEditMode]
[AddComponentMenu(ComponentMenuPaths.CopySizeIntoLayoutElement)]
public class CopySizeIntoLayoutElement : LayoutElement
{
public RectTransform CopySource;
public float PaddingHeight;
public float PaddingWidth;
public bool SetPreferredSize = false;
public bool SetMinimumSize = false;
public override float preferredWidth
{
get
{
if (!SetPreferredSize || CopySource == null || !IsActive())
{
return -1f;
}
return CopySource.rect.width + PaddingWidth;
}
}
public override float preferredHeight
{
get
{
if (!SetPreferredSize || CopySource == null || !IsActive())
{
return -1f;
}
return CopySource.rect.height + PaddingHeight;
}
}
public override float minWidth
{
get
{
if (!SetMinimumSize || CopySource == null || !IsActive())
{
return -1f;
}
return CopySource.rect.width + PaddingWidth;
}
}
public override float minHeight
{
get
{
if (!SetMinimumSize || CopySource == null || !IsActive())
{
return -1f;
}
return CopySource.rect.height + PaddingHeight;
}
}
public override int layoutPriority
{
get { return 2; }
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 65f264d1c98f61c4f9143ddeb0e74ff5
timeCreated: 1476961746
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,190 @@
namespace SRF.UI
{
using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class DragHandle : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
{
private CanvasScaler _canvasScaler;
private float _delta;
private float _startValue;
public RectTransform.Axis Axis = RectTransform.Axis.Horizontal;
public bool Invert = false;
public float MaxSize = -1;
public LayoutElement TargetLayoutElement;
public RectTransform TargetRectTransform;
private float Mult
{
get { return Invert ? -1 : 1; }
}
public void OnBeginDrag(PointerEventData eventData)
{
if (!Verify())
{
return;
}
//Debug.Log("OnBeginDrag");
_startValue = GetCurrentValue();
_delta = 0;
}
public void OnDrag(PointerEventData eventData)
{
if (!Verify())
{
return;
}
//Debug.Log("OnDrag");
var delta = 0f;
if (Axis == RectTransform.Axis.Horizontal)
{
delta += eventData.delta.x;
}
else
{
delta += eventData.delta.y;
}
if (_canvasScaler != null)
{
delta /= _canvasScaler.scaleFactor;
}
delta *= Mult;
_delta += delta;
SetCurrentValue(Mathf.Clamp(_startValue + _delta, GetMinSize(), GetMaxSize()));
}
public void OnEndDrag(PointerEventData eventData)
{
if (!Verify())
{
return;
}
//Debug.Log("OnEndDrag");
SetCurrentValue(Mathf.Max(_startValue + _delta, GetMinSize()));
_delta = 0;
CommitCurrentValue();
}
private void Start()
{
Verify();
_canvasScaler = GetComponentInParent<CanvasScaler>();
}
private bool Verify()
{
if (TargetLayoutElement == null && TargetRectTransform == null)
{
Debug.LogWarning(
"DragHandle: TargetLayoutElement and TargetRectTransform are both null. Disabling behaviour.");
enabled = false;
return false;
}
return true;
}
private float GetCurrentValue()
{
if (TargetLayoutElement != null)
{
return Axis == RectTransform.Axis.Horizontal
? TargetLayoutElement.preferredWidth
: TargetLayoutElement.preferredHeight;
}
if (TargetRectTransform != null)
{
return Axis == RectTransform.Axis.Horizontal
? TargetRectTransform.sizeDelta.x
: TargetRectTransform.sizeDelta.y;
}
throw new InvalidOperationException();
}
private void SetCurrentValue(float value)
{
if (TargetLayoutElement != null)
{
if (Axis == RectTransform.Axis.Horizontal)
{
TargetLayoutElement.preferredWidth = value;
}
else
{
TargetLayoutElement.preferredHeight = value;
}
return;
}
if (TargetRectTransform != null)
{
var d = TargetRectTransform.sizeDelta;
if (Axis == RectTransform.Axis.Horizontal)
{
d.x = value;
}
else
{
d.y = value;
}
TargetRectTransform.sizeDelta = d;
return;
}
throw new InvalidOperationException();
}
private void CommitCurrentValue()
{
if (TargetLayoutElement != null)
{
if (Axis == RectTransform.Axis.Horizontal)
{
TargetLayoutElement.preferredWidth = ((RectTransform) TargetLayoutElement.transform).sizeDelta.x;
}
else
{
TargetLayoutElement.preferredHeight = ((RectTransform) TargetLayoutElement.transform).sizeDelta.y;
}
}
}
private float GetMinSize()
{
if (TargetLayoutElement == null)
{
return 0;
}
return Axis == RectTransform.Axis.Horizontal ? TargetLayoutElement.minWidth : TargetLayoutElement.minHeight;
}
private float GetMaxSize()
{
if (MaxSize > 0)
{
return MaxSize;
}
return float.MaxValue;
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8faed27c04557e24e8aecd35f2b4d9d3
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: fee397aaceb8d684a94ce2bae9b71aa1
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -0,0 +1,39 @@
namespace SRF.UI.Editor
{
/*[CustomEditor(typeof(CopyLayoutElement))]
[CanEditMultipleObjects]
public class CopyLayoutElementEditor : UnityEditor.Editor
{
private SerializedProperty _copySourceProperty;
private SerializedProperty _paddingWidthProperty;
private SerializedProperty _paddingHeightProperty;
protected void OnEnable()
{
_paddingWidthProperty = serializedObject.FindProperty("PaddingWidth");
_paddingHeightProperty = serializedObject.FindProperty("PaddingHeight");
_copySourceProperty = serializedObject.FindProperty("CopySource");
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
EditorGUILayout.Space();
EditorGUILayout.PropertyField(_copySourceProperty);
EditorGUILayout.PropertyField(_paddingWidthProperty);
EditorGUILayout.PropertyField(_paddingHeightProperty);
serializedObject.ApplyModifiedProperties();
serializedObject.Update();
}
}*/
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 44df26ca5be5b5c468b5090cbe3df8ab
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,34 @@
using UnityEditor;
namespace SRF.UI.Editor
{
[CustomEditor(typeof (CopyPreferredSize))]
[CanEditMultipleObjects]
public class CopyPreferredSizeEditor : UnityEditor.Editor
{
private SerializedProperty _copySourceProperty;
private SerializedProperty _paddingHeightProperty;
private SerializedProperty _paddingWidthProperty;
protected void OnEnable()
{
_paddingWidthProperty = serializedObject.FindProperty("PaddingWidth");
_paddingHeightProperty = serializedObject.FindProperty("PaddingHeight");
_copySourceProperty = serializedObject.FindProperty("CopySource");
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
EditorGUILayout.Space();
EditorGUILayout.PropertyField(_copySourceProperty);
EditorGUILayout.PropertyField(_paddingWidthProperty);
EditorGUILayout.PropertyField(_paddingHeightProperty);
serializedObject.ApplyModifiedProperties();
serializedObject.Update();
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 776c60ba14d0d0242968c3258a3ba16c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,31 @@
using UnityEditor;
namespace SRF.UI.Editor
{
[CustomEditor(typeof(CopyPreferredSizes))]
[CanEditMultipleObjects]
public class CopyPreferredSizesEditor : UnityEditor.Editor
{
private SerializedProperty _copySourcesProperty;
private SerializedProperty _operationProperty;
protected void OnEnable()
{
_copySourcesProperty = serializedObject.FindProperty("CopySources");
_operationProperty = serializedObject.FindProperty("Operation");
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
EditorGUILayout.Space();
EditorGUILayout.PropertyField(_operationProperty);
EditorGUILayout.PropertyField(_copySourcesProperty);
serializedObject.ApplyModifiedProperties();
serializedObject.Update();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 393fb435a5c8c8043a1cbc34b977e315
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
using UnityEditor;
using UnityEditor.UI;
namespace SRF.UI.Editor
{
[CustomEditor(typeof (LongPressButton), true)]
[CanEditMultipleObjects]
public class LongPressButtonEditor : ButtonEditor
{
private SerializedProperty _onLongPressProperty;
protected override void OnEnable()
{
base.OnEnable();
_onLongPressProperty = serializedObject.FindProperty("_onLongPress");
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
EditorGUILayout.Space();
serializedObject.Update();
EditorGUILayout.PropertyField(_onLongPressProperty);
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1d57f229ac662764aa4508a0d42ddede
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,32 @@
using UnityEditor;
using UnityEditor.UI;
namespace SRF.UI.Editor
{
[CustomEditor(typeof (SRNumberButton))]
[CanEditMultipleObjects]
public class SRNumberButtonEditor : ButtonEditor
{
private SerializedProperty _amountProperty;
private SerializedProperty _targetFieldProperty;
protected override void OnEnable()
{
base.OnEnable();
_targetFieldProperty = serializedObject.FindProperty("TargetField");
_amountProperty = serializedObject.FindProperty("Amount");
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
EditorGUILayout.Space();
serializedObject.Update();
EditorGUILayout.PropertyField(_targetFieldProperty);
EditorGUILayout.PropertyField(_amountProperty);
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0d1845f798a1b5a47af337e37e463641
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

Some files were not shown because too many files have changed in this diff Show More