graph chart引入&骑行结果弹窗

This commit is contained in:
lishuo committed 2021-04-22 19:29:59 +08:00
1 parent 40d118cea3
commit 96f3644b5b
2374 files changed
+485161 -2410

No files matched your search

@@ -0,0 +1,19 @@
#define Graph_And_Chart_PRO
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ChartAndGraph.DataSource
{
/// <summary>
/// Collection of columns on a data source
/// </summary>
internal class ChartColumnCollection : ChartDataSourceBaseCollection<ChartDataColumn>
{
protected override string ItemTypeName
{
get { return "category"; }
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b8571a499d9a8704b8a965909e57530a
timeCreated: 1472290467
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,20 @@
#define Graph_And_Chart_PRO
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ChartAndGraph.DataSource
{
/// <summary>
/// a single column in a data source
/// </summary>
internal class ChartDataColumn : ChartDataItemBase
{
public ChartDataColumn(String name)
:base(name)
{
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e2b8dfd01f711d74b8d806da23b40c83
timeCreated: 1472290467
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,47 @@
#define Graph_And_Chart_PRO
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ChartAndGraph.DataSource
{
/// <summary>
/// base class for data items (rows and columns) in a data source
/// </summary>
internal abstract class ChartDataItemBase : IDataItem
{
private string mName;
private string mPrevName;
public string Name
{
get
{
return mName;
}
set
{
mPrevName = mName;
mName = value;
if (NameChanged != null)
NameChanged(mPrevName, this);
}
}
public object UserData { get; set; }
/// <summary>
/// The material for this data source item
/// </summary>
public ChartDynamicMaterial Material { get; set; }
public ChartDataItemBase(String name)
{
mName = name;
}
public event Action<string, IDataItem> NameChanged;
public void CancelNameChange()
{
mName = mPrevName;
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b3aa751507581324b965019d0b8ef3f5
timeCreated: 1472290467
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,20 @@
#define Graph_And_Chart_PRO
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ChartAndGraph.DataSource
{
/// <summary>
/// a single data row in a data source
/// </summary>
internal class ChartDataRow : ChartDataItemBase
{
public ChartDataRow(String name)
:base(name)
{
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e5345015d626d8440b4fcf38ce606f0f
timeCreated: 1472290467
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,56 @@
#define Graph_And_Chart_PRO
using ChartAndGraph.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ChartAndGraph.DataSource
{
/// <summary>
/// base class for all data sources
/// </summary>
internal abstract class ChartDataSourceBase
{
public class DataValueChangedEventArgs : EventArgs
{
public ChartItemIndex ItemIndex { get; private set; }
public double OldValue { get; private set; }
public double NewValue { get; private set; }
public bool MinMaxChanged { get; private set; }
public DataValueChangedEventArgs(int group,int category,double oldValue,double newValue,bool minMaxChanged)
{
ItemIndex = new ChartItemIndex(group, category);
OldValue = oldValue;
NewValue = newValue;
MinMaxChanged = minMaxChanged;
}
}
public event EventHandler DataStructureChanged;
public event Action<string,int,string,int> ItemsReplaced;
public event EventHandler<DataValueChangedEventArgs> DataValueChanged;
protected void OnDataStructureChanged()
{
if (DataStructureChanged != null)
DataStructureChanged(this, EventArgs.Empty);
}
protected void OnItemsReplaced(string first, int firstIndex, string second, int secondIndex)
{
if (ItemsReplaced != null)
ItemsReplaced(first, firstIndex, second, secondIndex);
}
protected void OnDataValueChanged(DataValueChangedEventArgs data)
{
if (DataValueChanged != null)
DataValueChanged(this, data);
}
public abstract double[,] getRawData();
public abstract ChartColumnCollection Columns { get;}
public abstract ChartRowCollection Rows { get; }
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 857078103a3efef4f94798778cf58248
timeCreated: 1473944702
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,215 @@
#define Graph_And_Chart_PRO
using ChartAndGraph.DataSource;
using ChartAndGraph.Exceptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ChartAndGraph
{
/// <summary>
/// base class for all data source collections. (row and column collections)
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class ChartDataSourceBaseCollection<T> : ICollection<T> where T : class,IDataItem
{
Dictionary<string, T> mNameToItem = new Dictionary<string, T>();
List<T> mItems = new List<T>();
/// <summary>
/// Used for messages and exceptions. this can be "column" if the derived class represents a column collestion
/// </summary>
protected abstract string ItemTypeName {get;}
/// <summary>
/// Adds an item to the last index of the collection. throws and exception if an item by that name already exists
/// </summary>
/// <param name="item">the new item to add</param>
public void Add(T item)
{
Insert(mItems.Count, item); // call insert
}
public void SwitchPositions(string first, string second)
{
int firstIndex, secondIndex;
if (TryGetIndexByName(first, out firstIndex) == false)
throw new ChartItemNotExistException(String.Format("A {0} by the name {1} does not exist in the collection", ItemTypeName, first));
if (TryGetIndexByName(second, out secondIndex) == false)
throw new ChartItemNotExistException(String.Format("A {0} by the name {1} does not exist in the collection", ItemTypeName, second));
SwitchPositions(firstIndex, secondIndex);
}
public void SwitchPositions(int first,int second)
{
T tmp = mItems[first];
mItems[first] = mItems[second];
mItems[second] = tmp;
if(ItemsReplaced != null)
ItemsReplaced(mItems[first].Name, first, mItems[second].Name, second);
}
public void Move(string name,int newPosition)
{
if (newPosition >= Count || newPosition<0)
throw new IndexOutOfRangeException();
int currentPosition;
if(TryGetIndexByName(name, out currentPosition) == false)
throw new ChartItemNotExistException(String.Format("A {0} by the name {1} does not exist in the collection", ItemTypeName, name));
int advance = Math.Sign(newPosition - currentPosition);
if (advance == 0) // same position
return;
for(int i=currentPosition; i!=newPosition; i+=advance)
SwitchPositions(i, i + advance);
}
public bool TryGetIndexByName(string name,out int result)
{
for(int i=0; i<mItems.Count; ++i)
{
if (mItems[i].Name == name)
{
result = i;
return true;
}
}
result = -1;
return false;
}
/// <summary>
/// inserts and item at the specified index of the collection. throws and exception if an item by that name already exists
/// </summary>
/// <param name="item">the new item to add</param>
public void Insert(int index, T item)
{
if( item == null)
throw new ArgumentNullException("item argument can't be null");
if (item.Name != null)
{
if (mNameToItem.ContainsKey(item.Name))
throw new ChartDuplicateItemException(String.Format("A {0} by that name already exists in the data source", ItemTypeName));
}
// check if it already contained in the collection
if (mItems.Contains(item) == true)
throw new ChartDuplicateItemException(String.Format("The {0} is already added to the collection", ItemTypeName));
// insert the item
mItems.Insert(index, item);
item.NameChanged += NameChangedHandler;
if (item.Name != null) // make sure the name to index points to it
mNameToItem.Add(item.Name, item);
if (OrderChanged != null)
OrderChanged(this, EventArgs.Empty);
}
#pragma warning disable 0067
public event Action<string, IDataItem> NameChanged;
public event EventHandler OrderChanged;
public event Action<T> ItemRemoved;
public event Action<string, int, string, int> ItemsReplaced;
#pragma warning restore 0067
public T this[int index]
{
get
{
return mItems[index];
}
}
public T this[string name]
{
get
{
T res;
if (mNameToItem.TryGetValue(name, out res) == false)
throw new ChartItemNotExistException(String.Format("A {0} by the name {1} does not exist in the collection", ItemTypeName, name));
return res;
}
}
private void NameChangedHandler(string prevName,IDataItem item)
{
if (prevName == item.Name) // ignore identical names
return;
if (mNameToItem.ContainsKey(item.Name)) // check duplicate names
{
item.CancelNameChange();
throw new ChartDuplicateItemException(String.Format("A {0} by that name already exists in the data source", ItemTypeName));
}
if(prevName != null && mNameToItem.Remove(prevName) == false)
{
item.CancelNameChange();
throw new ChartException(String.Format("Renaming {0} failed", ItemTypeName));
}
if(item.Name != null)
mNameToItem.Add(item.Name, (T)item);
if (NameChanged != null)
NameChanged(prevName, item);
}
/// <summary>
/// clear the collection
/// </summary>
public void Clear()
{
foreach (T item in mItems)
{
item.NameChanged -= NameChangedHandler;
if (ItemRemoved != null)
ItemRemoved(item);
}
mItems.Clear(); // call the corresponding list method
mNameToItem.Clear(); // and clear the name to index dictionary
if (OrderChanged != null)
OrderChanged(this, EventArgs.Empty);
}
public bool Contains(T item)
{
return mItems.Contains(item); // call the corresponding list method
}
public void CopyTo(T[] array, int arrayIndex)
{
mItems.CopyTo(array, arrayIndex); // call the corresponding list method
}
public int Count
{
get { return mItems.Count; } // call the corresponding list method
}
public bool IsReadOnly
{
get { return false;}
}
public bool Remove(T item)
{
if(mItems.Remove(item) == true) // remove the item from the list
{
if(item.Name != null) // remove name to index
mNameToItem.Remove(item.Name);
item.NameChanged -= NameChangedHandler; // remove event handler for name change
if (ItemRemoved != null)
ItemRemoved(item);
if (OrderChanged != null)
OrderChanged(this, EventArgs.Empty);
return true;
}
return false;
}
public IEnumerator<T> GetEnumerator()
{
return mItems.GetEnumerator(); // call the corresponding list method
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return mItems.GetEnumerator(); // call the corresponding list method
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ed5e189ffeb7bab48adaa8a5ce933c7f
timeCreated: 1472290467
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,19 @@
#define Graph_And_Chart_PRO
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ChartAndGraph.DataSource
{
/// <summary>
/// row collection in a data source
/// </summary>
internal class ChartRowCollection : ChartDataSourceBaseCollection<ChartDataRow>
{
protected override string ItemTypeName
{
get { return "group"; }
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a11ef6e4975ad8f4fa64696b57d7a3e6
timeCreated: 1472290466
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,420 @@
#define Graph_And_Chart_PRO
using ChartAndGraph.DataSource;
using ChartAndGraph.Exceptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace ChartAndGraph
{
/// <summary>
/// Holds and manages chart data in a table like fashion, The data in this class can be used with pie and bar chart types.
/// </summary>
internal class ChartSparseDataSource : ChartDataSourceBase
{
struct KeyElement
{
public KeyElement(ChartDataRow row, ChartDataColumn column) : this()
{
Row = row;
Column = column;
}
public bool IsIn(IDataItem item)
{
if (Row == item || Column == item)
return true;
return false;
}
public bool IsInRow(ChartDataRow row)
{
return row == Row;
}
public bool IsInColumn(ChartDataColumn column)
{
return column == Column;
}
static public bool operator == (KeyElement a,KeyElement b)
{
return a.Equals(b);
}
static public bool operator !=(KeyElement a, KeyElement b)
{
return !a.Equals(b);
}
public override bool Equals(object obj)
{
if (obj is KeyElement)
{
KeyElement elem = (KeyElement)obj;
if (elem.Row == Row && elem.Column == Column)
return true;
return false;
}
return base.Equals(obj);
}
public override int GetHashCode()
{
return Column.GetHashCode() ^ Row.GetHashCode();
}
public ChartDataRow Row { get; private set; }
public ChartDataColumn Column { get; private set; }
}
public ChartSparseDataSource()
{
mColumns = new ChartColumnCollection();
mRows = new ChartRowCollection();
mColumns.NameChanged += MColumns_NameChanged;
mRows.NameChanged += MRows_NameChanged;
mColumns.OrderChanged += OrderChanged;
mColumns.ItemsReplaced += MColumns_ItemsReplaced; ;
mRows.OrderChanged += OrderChanged;
mColumns.ItemRemoved += Columns_ItemRemoved;
mRows.ItemRemoved += Rows_ItemRemoved;
}
private void MColumns_ItemsReplaced(string first, int firstIndex, string second, int secondIndex)
{
mRawData = null; // data is invalidated.
mChartDataToIndex.Clear(); // clear the index dictionary
if (mSuspendEvents == false)
OnItemsReplaced(first, firstIndex, second, secondIndex);
else
mFireEvent = true;
}
private void MRows_NameChanged(string arg1, IDataItem arg2)
{
}
private void MColumns_NameChanged(string arg1, IDataItem arg2)
{
}
Dictionary<KeyElement, double> mData = new Dictionary<KeyElement, double>();
Dictionary<ChartDataItemBase, int> mChartDataToIndex = new Dictionary<ChartDataItemBase, int>();
KeyValuePair<KeyElement, double>? mMaxValue = null, mMinValue = null;
bool mFireEvent = false;
bool mSuspendEvents = false;
public bool SuspendEvents
{
get
{
return mSuspendEvents;
}
set
{
if (mSuspendEvents == true && value == false)
{
if (mFireEvent)
{
OnDataStructureChanged();
mFireEvent = false;
}
}
mSuspendEvents = value;
}
}
double[,] mRawData;
public ChartColumnCollection mColumns;
public ChartRowCollection mRows;
public override ChartColumnCollection Columns
{
get
{
return mColumns;
}
}
public override ChartRowCollection Rows
{
get
{
return mRows;
}
}
void OrderChanged(object sender, EventArgs e)
{
// the structer of the table has changed
mRawData = null; // data is invalidated.
mChartDataToIndex.Clear(); // clear the index dictionary
if (mSuspendEvents == false)
OnDataStructureChanged();
else
mFireEvent = true;
}
private void FindMinMaxValue()
{
mMaxValue = null;
mMinValue = null;
KeyValuePair<KeyElement, double>? maxValue = null;
KeyValuePair<KeyElement, double>? minValue = null;
foreach(KeyValuePair<KeyElement,double> pair in mData)
{
if (maxValue.HasValue == false || maxValue.Value.Value < pair.Value)
maxValue = pair;
if (minValue.HasValue == false || minValue.Value.Value > pair.Value)
minValue = pair;
}
if (maxValue.HasValue)
mMaxValue = maxValue.Value;
if (minValue.HasValue)
mMinValue = minValue.Value;
}
public void Clear()
{
Columns.Clear();
Rows.Clear();
}
/// <summary>
/// Raw data is prepared and held as long as the structed or order of the table has not changed
/// </summary>
private void PrepareRawData()
{
mChartDataToIndex.Clear();
for (int i=0; i<mColumns.Count; i++)
{
ChartDataColumn column = mColumns[i];
mChartDataToIndex.Add(column, i);
}
for(int i=0; i<mRows.Count; i++)
{
ChartDataRow row = mRows[i];
mChartDataToIndex.Add(row, i);
}
mRawData = new double[mRows.Count,mColumns.Count];
foreach(KeyValuePair<KeyElement,double> pair in mData)
{
int columnIndex;
int rowIndex;
if (mChartDataToIndex.TryGetValue(pair.Key.Column, out columnIndex) == false)
continue;
if (mChartDataToIndex.TryGetValue(pair.Key.Row, out rowIndex) == false)
continue;
mRawData[rowIndex, columnIndex] = pair.Value;
}
FindMinMaxValue();
}
private bool HasZeroItems()
{
int total = mRows.Count* mColumns.Count;
if (mData.Count < total)
return true;
return false;
}
internal double? getRawMaxValue()
{
EnsureRawData();
if (mMaxValue.HasValue == false)
return null;
double maxValue;
if (mData.TryGetValue(mMaxValue.Value.Key, out maxValue) == false)
return null;
if (HasZeroItems() && maxValue < 0.0)
return 0.0;
return maxValue;
}
internal double? getRawMinValue()
{
EnsureRawData();
if (mMinValue.HasValue == false)
return null;
double minValue;
if (mData.TryGetValue(mMinValue.Value.Key, out minValue) == false)
return null;
if (HasZeroItems() && minValue > 0.0)
return 0.0;
return minValue;
}
private void ItemRemoved(IDataItem item)
{
Dictionary<KeyElement, double> newData = new Dictionary<KeyElement, double>();
foreach(KeyValuePair<KeyElement,double> pair in mData)
{
if (pair.Key.IsIn(item) == false)
newData.Add(pair.Key, pair.Value);
}
mData = newData;
mRawData = null;
if (mSuspendEvents == false)
OnDataStructureChanged();
else
mFireEvent = true;
}
void Rows_ItemRemoved(ChartDataRow obj)
{
ItemRemoved(obj);
}
void Columns_ItemRemoved(ChartDataColumn obj)
{
ItemRemoved(obj);
}
void EnsureRawData()
{
if (mRawData == null) // dynamically check if the raw data should be regenerated
PrepareRawData();
}
public override double[,] getRawData()
{
EnsureRawData();
return mRawData;
}
private bool VerifyMinMaxValue(KeyElement element,double value)
{
bool findMinMax = false;
bool res = false;
if (mMaxValue.HasValue == false || mMaxValue.Value.Value < value)
{
mMaxValue = new KeyValuePair<KeyElement, double>(element, value);
res = true;
}
else
{
if (mMaxValue.Value.Key == element)
findMinMax = true;
}
if (mMinValue.HasValue == false || mMinValue.Value.Value > value)
{
mMinValue = new KeyValuePair<KeyElement, double>(element, value);
res = true;
}
else
{
if (mMinValue.Value.Key == element)
findMinMax = true;
}
if (findMinMax)
{
FindMinMaxValue();
res = true;
}
return res;
}
private void InnerSetValue(ChartDataColumn column, ChartDataRow row, double amount)
{
EnsureRawData();
int columnIndex, rowIndex;
if (mChartDataToIndex.TryGetValue(column, out columnIndex) == false)
throw new ChartException("value cannot be set"); // should never happen
if (mChartDataToIndex.TryGetValue(row, out rowIndex) == false)
throw new ChartException("value cannot be set"); // should never happen
mRawData[rowIndex, columnIndex] = amount;
KeyElement elem = new KeyElement(row, column);
double oldValue;
if (mData.TryGetValue(elem, out oldValue) == false)
oldValue = 0.0;
mData[elem] = amount;
bool minMaxChanged = VerifyMinMaxValue(elem, amount);
if (mSuspendEvents == false)
OnDataValueChanged(new DataValueChangedEventArgs(rowIndex,columnIndex, 0.0,amount, minMaxChanged));
else
mFireEvent = true;
}
private double InnerGetValue(ChartDataColumn column,ChartDataRow row)
{
KeyElement elem = new KeyElement(row, column);
double res;
if (mData.TryGetValue(elem, out res) == false)
return 0.0;
return res;
}
/// <summary>
/// Get the value currently for the specified column and row
/// </summary>
/// <param name="ColumnName">the name of the column</param>
/// <param name="RowName"> the name of the row</param>
/// <returns></returns>
public double GetValue(String ColumnName,String RowName)
{
ChartDataColumn column = mColumns[ColumnName];
ChartDataRow row = mRows[RowName];
return InnerGetValue(column, row);
}
/// <summary>
/// Get the value currently for the specified column and row
/// </summary>
/// <param name="ColumnName">the name of the column</param>
/// <param name="rowIndex"> the index of the row</param>
/// <returns></returns>
public double GetValue(String ColumnName, int rowIndex)
{
ChartDataColumn column = mColumns[ColumnName];
ChartDataRow row = mRows[rowIndex];
return InnerGetValue(column, row);
}
/// <summary>
/// Get the value currently for the specified column and row
/// </summary>
/// <param name="columnIndex">the index of the column</param>
/// <param name="rowIndex"> the index of the row</param>
/// <returns></returns>
public double GetValue(int columnIndex, int rowIndex)
{
ChartDataColumn column = mColumns[columnIndex];
ChartDataRow row = mRows[rowIndex];
return InnerGetValue(column, row);
}
public void AddLabel(string columnName,int rowIndex,string text)
{
}
/// <summary>
/// Sets the value for the specified column and row
/// </summary>
/// <param name="ColumnName">the name of the column</param>
/// <param name="RowName"> the name of the row</param>
/// <param name="amount"> the new value</param>
public void SetValue(string ColumnName, string RowName, double amount)
{
ChartDataColumn column = mColumns[ColumnName];
ChartDataRow row = mRows[RowName];
InnerSetValue(column, row, amount);
}
/// <summary>
/// Sets the value for the specified column and row.
/// </summary>
/// <param name="ColumnName">the name of the column</param>
/// <param name="rowIndex">the index of the row</param>
/// <param name="amount"> the new value</param>
public void SetValue(String ColumnName, int rowIndex, double amount)
{
ChartDataColumn column = mColumns[ColumnName];
ChartDataRow row = mRows[rowIndex];
InnerSetValue(column, row, amount);
}
/// <summary>
/// Sets the value for the specified column and row.
/// </summary>
/// <param name="columnIndex">the index of the column</param>
/// <param name="rowIndex">the index of the row</param>
/// <param name="amount"> the new value</param>
public void SetValue(int columnIndex, int rowIndex, double amount)
{
ChartDataColumn column = mColumns[columnIndex];
ChartDataRow row = mRows[rowIndex];
InnerSetValue(column, row, amount);
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2728fc1cea1366c46bd97ef25c4dfe86
timeCreated: 1472284350
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,22 @@
#define Graph_And_Chart_PRO
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ChartAndGraph.DataSource
{
/// <summary>
/// base interface for data items (columns and charts)
/// </summary>
public interface IDataItem
{
String Name { get; set; }
void CancelNameChange();
/// <summary>
/// the first string argument contains the preivous name used by the item
/// the second object argumnet is the item itself
/// </summary>
event Action<string, IDataItem> NameChanged;
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a071486401c065442936c0584dfff00e
timeCreated: 1472284350
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: