Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save DirtyHarryE/d387cfcb052b9d468bb337c1d2868450 to your computer and use it in GitHub Desktop.
Save DirtyHarryE/d387cfcb052b9d468bb337c1d2868450 to your computer and use it in GitHub Desktop.
Plant Data
using ItalicPig.PaleoPines.Loading;
using UnityEngine;
using UnityEngine.Serialization;
/*
* Copyright © 2020, Italic Pig, All Rights Reserved
*
* Author: Harry Evans
* Date: 25/02/2020
*/
namespace ItalicPig.PaleoPines.Inventories
{
/// <summary>
/// Abstract superclass for parent object holding Additional Item Information Data.
/// </summary>
/// <typeparam name="TItemInformationData">Type of additional data to store.</typeparam>
public abstract class AdditionalInventoryInformationData<TItemInformationData> : ScriptableObject, ILoadable<AdditionalInventoryInformationData<TItemInformationData>>
where TItemInformationData : AdditionalItemInformationData
{
public const string MenuPrefix = "Italic Pig/Paleo/Inventory/Additional Info/";
#pragma warning disable CS0414, IDE0052, IDE0051, IDE0169, IDE0649 // Remove unread private members warning - they are used in Unity editor
[SerializeField, HideInInspector, FormerlySerializedAs("importerMode")]
private int _ImporterMode = 0;
[SerializeField, HideInInspector, FormerlySerializedAs("csvPath")]
private string _CsvPath = string.Empty;
[SerializeField, HideInInspector, FormerlySerializedAs("csvStartRow")]
private int _CsvStartRow = 0;
#pragma warning restore CS0414, IDE0052, IDE0051, IDE0169, IDE0649 // Remove unread private members warning - they are used in Unity editor
/// <summary>
/// Array of Additional Item Information Data
/// </summary>
[SerializeField]
private TItemInformationData[] _infoData;
int ILoadable.Priority => 25;
protected virtual void OnValidate() { }
public virtual void Load() { }
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using ItalicPig.PaleoPines.Importing;
using ItalicPig.PaleoPines.Inventories;
using ItalicPig.PaleoPines.LinqExtensions;
using ItalicPig.PaleoPines.Misc;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using Object = UnityEngine.Object;
namespace ItalicPig.PaleoPines.Editor.Inventory
{
public abstract class AdditionalInventoryInformationDataEditor<TItemInformationData> : UnityEditor.Editor
where TItemInformationData : AdditionalItemInformationData
{
public enum VariableType
{
AutoDetect = 0,
Bool = 1,
Integer = 2,
Float = 3,
String = 4,
Enum = 5,
EnumFlags = 6,
ItemID = 7
}
protected struct SerializationNameInfo
{
public string SerializedPropertyName;
public StringPlayerPref NameInCSVPref;
public EnumPlayerPref<VariableType> VariableTypePref;
public SerializationNameInfo(string serializedPropertyName, StringPlayerPref nameInCSVPref, EnumPlayerPref<VariableType> variableTypePref)
{
SerializedPropertyName = serializedPropertyName;
NameInCSVPref = nameInCSVPref;
VariableTypePref = variableTypePref;
}
}
private struct ColToPropertyNameInfo
{
public readonly string PropertyName;
public readonly EnumPlayerPref<VariableType> VariableTypePref;
public readonly bool IsCSVItem;
public readonly int Width;
public readonly int Height;
public readonly bool IsItemID;
public readonly string[] Headers;
public ColToPropertyNameInfo(string propertyName, EnumPlayerPref<VariableType> variableTypePref)
{
PropertyName = propertyName;
VariableTypePref = variableTypePref;
Width = 1;
Height = 1;
IsCSVItem = false;
Headers = Array.Empty<string>();
IsItemID = false;
}
public ColToPropertyNameInfo(string propertyName)
{
PropertyName = propertyName;
VariableTypePref = default;
Width = 1;
Height = 1;
IsCSVItem = false;
Headers = Array.Empty<string>();
IsItemID = false;
}
public ColToPropertyNameInfo(string propertyName,
EnumPlayerPref<VariableType> variableTypePref,
int width,
int height,
bool isCSVItem,
string[] headers,
bool isItemID)
: this(propertyName, variableTypePref)
{
Width = width;
Height = height;
IsCSVItem = isCSVItem;
Headers = headers;
IsItemID = isItemID;
}
}
private struct PropertyToValueInfo
{
public string SerializedPropertyName;
public string PropertyValue;
public readonly EnumPlayerPref<VariableType> VariableTypePref;
public readonly int X;
public readonly int Y;
public readonly bool IsSubtable;
public readonly int Width;
public readonly int Height;
public readonly bool IsItemID;
public readonly string[] Headers;
public PropertyToValueInfo(string serializedPropertyName,
string propertyValue,
EnumPlayerPref<VariableType> variableTypePref,
int x, int y)
{
SerializedPropertyName = serializedPropertyName;
PropertyValue = propertyValue;
VariableTypePref = variableTypePref;
X = x;
Y = y;
Width = 1;
Height = 1;
Headers = Array.Empty<string>();
IsSubtable = false;
IsItemID = false;
}
public PropertyToValueInfo(string serializedPropertyName,
string propertyValue,
EnumPlayerPref<VariableType> variableTypePref,
int x, int y,
int width,
int height,
bool isCSVItem,
string[] headers,
bool isItemID)
: this(serializedPropertyName, propertyValue, variableTypePref, x, y)
{
Width = width;
Height = height;
IsSubtable = isCSVItem;
IsItemID = isItemID;
Headers = headers;
}
}
private enum FindElementMethod
{
ByUniqueID,
ByName
}
private ReorderableList reorderableList;
private CSVImporterWidget csvImporterWidget;
protected SerializationNameInfo[] SerializedPropertyToCSVName;
protected virtual int HeaderRow => 0;
private StringPlayerPref uniqueID;
private StringPlayerPref itemName;
private string guid;
private bool debugOptions = false;
private string assetName = string.Empty;
protected virtual void OnEnable()
{
assetName = target.name;
guid = AssetDatabase.GUIDToAssetPath(AssetDatabase.GetAssetPath(target));
uniqueID = new StringPlayerPref(guid + "_uniqueID", "itemID");
itemName = new StringPlayerPref(guid + "_name", "name");
SerializedPropertyToCSVName = GetSerializationNameInfos();
}
protected virtual SerializationNameInfo[] GetSerializationNameInfos()
{
string[] serializableNames = EditorHelper.GetSerializablePropertyNames(typeof(TItemInformationData), true).DistinctBy(s => s).ToArray();
var names = new SerializationNameInfo[serializableNames.Length];
for (int i = 0; i < serializableNames.Length; i++)
{
string n = serializableNames[i];
names[i] = new SerializationNameInfo(
n,
new StringPlayerPref(guid + "_" + n, GetDefaultCSVHeader(n)),
new EnumPlayerPref<VariableType>(
guid + "_" + n + "_" + "VariableType",
VariableType.AutoDetect
));
}
return names;
}
public override void OnInspectorGUI()
{
if (DrawRenamePanel())
{
return;
}
var infoDataSerializedProperty = serializedObject.FindProperty("_infoData");
reorderableList = reorderableList ?? GetReorderableList(serializedObject, infoDataSerializedProperty);
if (csvImporterWidget == null)
{
string dataName = typeof(TItemInformationData).Name;
csvImporterWidget = new CSVImporterWidget(dataName, OnCSVImported, ExportCSV)
{
GetPathname = delegate ()
{
using (SerializedProperty csvPathProperty = serializedObject.FindProperty("_CsvPath"))
{
return csvPathProperty.stringValue;
}
},
SetPathname = delegate (string pathname)
{
using (SerializedProperty csvPathProperty = serializedObject.FindProperty("_CsvPath"))
{
if (csvPathProperty.stringValue != pathname)
{
csvPathProperty.stringValue = pathname;
serializedObject.ApplyModifiedProperties();
}
}
},
GetStartRow = delegate ()
{
using (SerializedProperty rowProperty = serializedObject.FindProperty("_CsvStartRow"))
{
return rowProperty.intValue;
}
},
SetStartRow = delegate (int row)
{
using (SerializedProperty rowProperty = serializedObject.FindProperty("_CsvStartRow"))
{
if (rowProperty.intValue != row)
{
rowProperty.intValue = row;
serializedObject.ApplyModifiedProperties();
}
}
},
GetImporterMode = delegate ()
{
using (var rowProperty = serializedObject.FindProperty("_ImporterMode"))
{
return (CSVImporterWidget.ImporterMode)rowProperty.intValue;
}
},
SetImporterMode = delegate (CSVImporterWidget.ImporterMode mode)
{
int m = (int)mode;
using (var rowProperty = serializedObject.FindProperty("_ImporterMode"))
{
if (rowProperty.intValue != m)
{
rowProperty.intValue = m;
serializedObject.ApplyModifiedProperties();
}
}
}
};
csvImporterWidget.ExtraOptions = ExtraOptions;
csvImporterWidget.IsReadyToExport = true;
}
csvImporterWidget.DrawLayout();
EditorGUI.BeginChangeCheck();
DrawRemainingProperties();
reorderableList.DoLayoutList();
GUILayout.Space(50);
DrawFixButtonsArea();
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
}
}
protected virtual void DrawRemainingProperties()
{
DrawPropertiesExcluding(serializedObject, "m_Script", "_infoData");
}
private bool DrawRenamePanel()
{
using (new EditorGUILayout.HorizontalScope())
{
assetName = EditorGUILayout.TextField(assetName);
if (GUILayout.Button("Rename", EditorStyles.miniButton, GUILayout.Width(70)))
{
if (string.CompareOrdinal(assetName, target.name) != 0)
{
var oldPath = AssetDatabase.GetAssetPath(target);
var list = AssetDatabase.LoadAllAssetsAtPath(oldPath).Where(a => a != target).ToList();
var ext = Path.GetExtension(oldPath);
var newPath = oldPath.Substring(0, oldPath.Length - Path.GetFileName(oldPath).Length);
newPath = Path.Combine(newPath, assetName + ext);
var newAsset = Object.Instantiate(target);
newAsset.name = assetName;
AssetDatabase.CreateAsset(newAsset, newPath);
foreach (var subAsset in list)
{
AssetDatabase.RemoveObjectFromAsset(subAsset);
AssetDatabase.AddObjectToAsset(subAsset, newAsset);
}
AssetDatabase.ImportAsset(newPath);
AssetDatabase.DeleteAsset(oldPath);
AssetDatabase.Refresh();
Selection.objects = new[] { newAsset };
return true;
}
}
}
return false;
}
protected virtual void ExtraOptions()
{
var label = new GUIContent("CSV Headers");
if (EditorHelper.DrawHelpButton(() => EditorGUILayout.LabelField(label, EditorStyles.boldLabel),
label,
EditorStyles.boldLabel))
{
CustomWindow.ShowHelpWindow(GUILayoutUtility.GetLastRect(), label, delegate (GUIStyle style)
{
EditorGUILayout.LabelField("Here is where you assign the header name for the program to look for in the CSV.", style);
EditorGUILayout.LabelField("In the left hand column you will see a description of what data the program expects.", style);
EditorGUILayout.LabelField("In the right hand column is the corresponding column header in the CSV that contains that data. Write the header of the info there", style);
}
);
}
var types = Enum.GetNames(typeof(VariableType)).Select(ObjectNames.NicifyVariableName).ToArray();
var variableTypeLabel = new GUIContent("Type");
var varLabelW = EditorStyles.label.CalcSize(variableTypeLabel).x;
GUILayoutOption nameGUIOptions = GUILayout.Width(100);
GUILayoutOption typeLabelGUIOptions = GUILayout.Width(varLabelW);
uniqueID.Value = EditorGUILayout.TextField("Unique ID", uniqueID.Value);
itemName.Value = EditorGUILayout.TextField("Name", itemName.Value);
GUILayout.Space(EditorGUIUtility.singleLineHeight * 0.5f);
for (var i = 0; i < SerializedPropertyToCSVName.Length; i++)
{
SerializationNameInfo info = SerializedPropertyToCSVName[i];
StringPlayerPref nameInCSVPref = info.NameInCSVPref;
EnumPlayerPref<VariableType> variableTypePref = info.VariableTypePref;
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.PrefixLabel(ObjectNames.NicifyVariableName(info.SerializedPropertyName));
var nameVal = EditorGUILayout.TextField(nameInCSVPref.Value, nameGUIOptions);
EditorGUILayout.LabelField(variableTypeLabel, typeLabelGUIOptions);
nameInCSVPref.Value = nameVal;
var isSubtable = typeof(TItemInformationData).GetField(info.SerializedPropertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.GetCustomAttributes<CSVItemAttribute>()
.Any();
using (new EditorGUI.DisabledScope(isSubtable))
{
int pre = (int)variableTypePref.Value;
int typeVal = EditorGUILayout.Popup(
isSubtable
? 0 : pre,
isSubtable
? new[] { "Subtable" } : types);
if (!isSubtable && pre != typeVal)
{
variableTypePref.Value = (VariableType)typeVal;
}
}
}
}
}
protected virtual void OnCSVImported(string[][] output)
{
EditorCoroutiner.StartCoroutine(ImportCSVCoroutine(output));
}
protected virtual IEnumerator ImportCSVCoroutine(string[][] output)
{
var debugSubtable = false;
var progressBarTitle = "Importing " + typeof(TItemInformationData).Name;
const string errorTitle = "Error on Import!";
const char delimiter = ',';
var tableRead = new StringBuilder();
var report = new StringBuilder();
var parseErrors = new List<string>();
var generics = new List<string>();
var csvNotImplemented = new List<string>();
var unExpectedProperties = new List<string>();
var cannotFindProperties = new List<string>();
var couldNotFindItemID = new List<string>();
var cannotFindAssignableProperties = new List<string>();
var itemType = typeof(TItemInformationData);
EditorUtility.DisplayProgressBar(progressBarTitle, "Starting", 0);
const string UniqueIDPropertyName = "_Uid";
var elements = serializedObject.FindProperty("_infoData");
var data = new List<SerializedObject>();
var uniqueIDcolumn = 0;
var nameIDcolumn = 0;
var additionalDataPropertyPathInItem = string.Empty;
var colToPropertyNameDict = new Dictionary<int, ColToPropertyNameInfo>();
int x, y;
var uniqueIDFound = false;
var headerIncr = 1;
float GetProgress(int index, int total, int stage)
{
const float totalStages = 3;
var thisProgress = index / ((float)total);
thisProgress = thisProgress / totalStages;
var incr = Mathf.Clamp(stage, 1f, totalStages) / totalStages;
return Mathf.Clamp01(thisProgress + incr);
}
for (x = 0; x < output[HeaderRow].Length; x += headerIncr)
{
EditorUtility.DisplayProgressBar(progressBarTitle, "Reading headers... " + output[HeaderRow][x], GetProgress(x, output[HeaderRow].Length, 1));
headerIncr = 1;
var header = output[HeaderRow][x];
report.Append("Reading: ").Append(header).AppendLine();
tableRead.Append(header).Append(delimiter);
if (ComparePossibleNames(header, uniqueID))
{
uniqueIDcolumn = x;
uniqueIDFound = true;
}
else if (ComparePossibleNames(header, itemName))
{
nameIDcolumn = x;
}
else
{
bool found = false;
for (var k = 0; k < SerializedPropertyToCSVName.Length; k++)
{
if (ComparePossibleNames(header, SerializedPropertyToCSVName[k].NameInCSVPref))
{
var serializedPropName = SerializedPropertyToCSVName[k].SerializedPropertyName;
var fieldinfo = itemType.GetField(serializedPropName,
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
int height = 1, width = 1;
var isCSVItem = false;
var headers = new[] { header };
var isItemID = false;
report.Append("Finding: ")
.Append(serializedPropName)
.Append(" in ")
.Append(itemType.Name).Append(" = ").Append(fieldinfo != null).AppendLine();
if (fieldinfo != null)
{
var csvAtts = fieldinfo.GetCustomAttributes<CSVItemAttribute>(true);
var hasCSVAtts = csvAtts.Any();
report.Append("Detecting CSV attributes ").Append(hasCSVAtts).AppendLine();
if (hasCSVAtts)
{
CSVItemAttribute csvAtt = csvAtts.First();
headerIncr = csvAtt.Width;
headers = new string[csvAtt.Width];
for (var i = 0; i < csvAtt.Width; i++)
{
headers[i] = output[HeaderRow][x + i];
}
width = csvAtt.Width;
height = csvAtt.Height;
isCSVItem = true;
report.Append("Adding CSV : ").Append(csvAtt.Width).Append("|").Append(csvAtt.Height).AppendLine();
}
isItemID = fieldinfo.GetCustomAttributes<ItemIDAttribute>(true).Any();
report.Append("Detecting Item ID attributes ").Append(isItemID).AppendLine();
}
colToPropertyNameDict.Add(x,
new ColToPropertyNameInfo(
SerializedPropertyToCSVName[k].SerializedPropertyName,
SerializedPropertyToCSVName[k].VariableTypePref,
width, height, isCSVItem, headers, isItemID
));
report.Append("Adding to dict : ").Append(x).Append(" :: ").Append(SerializedPropertyToCSVName[k].SerializedPropertyName).AppendLine();
found = true;
break;
}
}
if (!found)
{
unExpectedProperties.Add(header);
}
}
}
report.Append('-', 50).AppendLine().Append("Headers Completed").AppendLine();
if (!uniqueIDFound)
{
EditorUtility.DisplayDialog(errorTitle, "Could not find the column for the unique ID\n\nAre you sure \"" + uniqueID + "\" is correct?", "Cancel");
yield break;
}
int xIncr = 1, yIncr = 1;
for (y = HeaderRow + 1; y < output.Length; y += yIncr)
{
xIncr = 1;
report.Append("Reading row [").Append(y).Append("] \"");
for (int i = 0; i < output[y].Length; i++)
{
if (i != 0)
{
report.Append(delimiter).Append(' ');
}
var cell = output[y][i];
if (cell.Contains(delimiter))
{
report.Append('"').Append(cell).Append('"');
}
else
{
report.Append(cell);
}
}
report.AppendLine();
tableRead.AppendLine();
yIncr = 1;
ItemData item = null;
var itemName = string.Empty;
var propertyToValueList = new List<PropertyToValueInfo>();
if (Helper.GetVariableName(System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(output[y][nameIDcolumn]), out string variableName))
{
itemName = char.ToUpper(variableName[0]) + variableName.Substring(1);
}
else
{
itemName = typeof(TItemInformationData).Name;
}
report.Append("ITEMID: [").Append(uniqueIDcolumn).Append(", ").Append(y).Append("] ").Append(output[y][uniqueIDcolumn]).AppendLine();
var itemID = output[y][uniqueIDcolumn];
yield return ItemExists(itemID, delegate (string newItemID, ItemData foundItem)
{
var propertyInfo = new PropertyToValueInfo(
UniqueIDPropertyName,
newItemID,
default,
uniqueIDcolumn, y,
1, 1, false, new[] { UniqueIDPropertyName },
false
);
propertyToValueList.Add(propertyInfo);
item = foundItem;
itemID = foundItem.Uid;
});
for (x = 0; x < output[y].Length; x += xIncr)
{
if (x == nameIDcolumn || x == uniqueIDcolumn)
{
continue;
}
report.Append("CELL: [").Append(x).Append(", ").Append(y).Append("] ").Append(output[y][x]).AppendLine();
tableRead.Append(output[y][x]).Append(delimiter);
xIncr = 1;
if (!colToPropertyNameDict.TryGetValue(x, out ColToPropertyNameInfo info))
{
continue;
}
EditorUtility.DisplayProgressBar(progressBarTitle, "Reading cell... " + itemName, GetProgress(y, output[y].Length, 2));
var propName = info.PropertyName;
var propertyInfo = new PropertyToValueInfo(
propName,
output[y][x],
info.VariableTypePref,
x, y,
info.Width, info.Height, info.IsCSVItem, info.Headers,
info.IsItemID);
propertyToValueList.Add(propertyInfo);
xIncr = info.Width;
yIncr = info.Height;
report.Append("Increasing: ").Append(xIncr).Append(", ").Append(yIncr).AppendLine();
}
report.Append("ASSIGNING VALUES").AppendLine();
var hasID = !string.IsNullOrEmpty(itemID);
var newData = CreateOrFindNewInfo(
elements,
hasID ? FindElementMethod.ByUniqueID : FindElementMethod.ByName,
hasID ? itemID : itemName,
elements.arraySize,
itemName);
using (var newSerializedObject = new SerializedObject(newData))
{
for (int p = 0; p < propertyToValueList.Count; p++)
{
var propertyInfo = propertyToValueList[p];
var key = propertyInfo.SerializedPropertyName;
var value = propertyInfo.PropertyValue;
var variableTypePref = propertyToValueList[p].VariableTypePref;
var variableType = string.IsNullOrEmpty(variableTypePref.Key) ? variableTypePref.Value : VariableType.AutoDetect;
using (var newProperty = newSerializedObject.FindProperty(key))
{
if (newProperty == null)
{
cannotFindProperties.Add(key);
}
else
{
if (debugSubtable)
{
report
.Append("Is \"")
.Append(newProperty.name)
.Append("\" a CSV item? ")
.Append(propertyInfo.IsSubtable)
.AppendLine();
}
if (propertyInfo.IsSubtable)
{
if (debugSubtable)
{
report.Append('-', 50).AppendLine()
.Append("BEGIN MAKING SUBTABLE").AppendLine();
}
var subtable = new string[propertyInfo.Height][];
var propX = propertyInfo.X;
var propY = propertyInfo.Y;
for (int h = 0; h < propertyInfo.Height; h++)
{
subtable[h] = new string[propertyInfo.Width];
for (int w = 0; w < propertyInfo.Width; w++)
{
try
{
if (debugSubtable)
{
report.Append(h).Append(", ").Append(w).Append("; ");
report.Append(h + propY).Append(", ").Append(w + propX).Append("; ");
report.AppendLine();
}
var cell = output[h + propY][w + propX];
if (debugSubtable)
{
report.Append(cell);
report.AppendLine();
}
subtable[h][w] = cell;
}
catch
{
if (debugSubtable)
{
report.Append("Out of Bounds");
report.AppendLine();
}
}
}
}
try
{
ProcessSubtable(itemID, newSerializedObject, newProperty, subtable, propertyInfo.Headers);
}
catch (NotImplementedException)
{
csvNotImplemented.Add(propertyInfo.SerializedPropertyName);
}
if (debugSubtable)
{
report
.Append("END SUBTABLE").AppendLine()
.Append('-', 50);
}
}
else
{
report.Append("Begin Assignment \"")
.Append(newProperty.name)
.Append("\" :: ")
.Append(variableType)
.AppendLine();
switch (variableType)
{
case VariableType.AutoDetect:
{
report.Append("Is \"")
.Append(newProperty.name)
.Append("\" an ItemID item? ")
.Append(propertyInfo.IsItemID)
.AppendLine();
bool foundItem = false;
if (propertyInfo.IsItemID)
{
yield return ItemExists(value, delegate (string newItemID, ItemData valueItem)
{
report.Append("Trying to find: ").Append(value).AppendLine();
newProperty.stringValue = valueItem.Uid;
foundItem = true;
});
}
if (!foundItem)
{
try
{
switch (newProperty.propertyType)
{
case SerializedPropertyType.Generic:
if (newProperty.hasVisibleChildren && value.Contains(delimiter))
{
var split = value.Split(delimiter);
SerializedProperty[] children = newProperty.GetVisibleChildren().ToArray();
if (children.Length <= split.Length)
{
for (int i = 0; i < children.Length; i++)
{
report.Append("Assigning \"").Append(newProperty.name).Append('.').Append(children[i].name).Append("\" to ")
.Append("\"").Append(split[i]).Append("\"").AppendLine();
children[i].SetValueString(split[i]);
}
}
}
break;
case SerializedPropertyType.Boolean:
newProperty.boolValue = Helper.StringToBoolFuzzy(value);
break;
default:
newProperty.SetValueString(value, delimiter);
break;
}
}
catch (ParseException e)
{
var errBuilder = new StringBuilder();
errBuilder.AppendMany("Could not parse \"", value, "\" to \"", newProperty.name, "\" (", newProperty.propertyType, ")")
.ToString();
if (newProperty.propertyType == SerializedPropertyType.Generic)
{
//errBuilder.AppendMany(" Make sure that \"", newProperty.GetPropertyType().Name, " \"can be converted to from a string!");
generics.Add(newProperty.GetPropertyType().Name);
}
var err = errBuilder.ToString();
parseErrors.Add(err);
report.Append(err).AppendLine().Append(e).AppendLine();
}
catch (ArgumentException e) when (newProperty.propertyType == SerializedPropertyType.Enum)
{
Debug.LogWarning(e.ToString());
}
}
}
break;
case VariableType.Bool:
newProperty.boolValue = Helper.StringToBoolFuzzy(value);
break;
case VariableType.Integer:
newProperty.intValue = int.Parse(value);
break;
case VariableType.Float:
newProperty.floatValue = float.Parse(value);
break;
case VariableType.String:
newProperty.stringValue = value;
break;
case VariableType.Enum:
try
{
newProperty.SetEnumValue(value);
}
catch (ArgumentException argumentException)
{
Debug.LogWarning(argumentException.ToString());
}
break;
case VariableType.EnumFlags:
newProperty.AssignEnumValueFlags(value, delimiter);
break;
case VariableType.ItemID:
{
var assignString = false;
yield return ItemExists(value, delegate (string newItemID, ItemData valueItem)
{
newProperty.stringValue = valueItem.Uid;
assignString = true;
});
if (assignString)
{
newProperty.stringValue = value;
}
}
break;
default:
break;
}
//Overriding autodetect
if (variableType == VariableType.AutoDetect)
{
switch (newProperty.propertyType)
{
case SerializedPropertyType.Integer:
variableTypePref.Value = VariableType.Integer;
break;
case SerializedPropertyType.Boolean:
variableTypePref.Value = VariableType.Bool;
break;
case SerializedPropertyType.Float:
variableTypePref.Value = VariableType.Float;
break;
case SerializedPropertyType.String:
report.Append("Overriding : ").Append(propertyInfo.SerializedPropertyName).Append("(").Append(propertyInfo.IsItemID).Append(")").AppendLine();
if (propertyInfo.IsItemID)
{
variableTypePref.Value = VariableType.ItemID;
}
else
{
variableTypePref.Value = VariableType.String;
}
break;
case SerializedPropertyType.Enum:
variableTypePref.Value = value.Contains(delimiter) ? VariableType.EnumFlags : VariableType.Enum;
break;
case SerializedPropertyType.Character:
variableTypePref.Value = VariableType.String;
break;
}
}
}
}
}
}
if (item != null)
{
var type = typeof(TItemInformationData);
using (var itemSerializedObject = new SerializedObject(item))
{
using (var target = string.IsNullOrEmpty(additionalDataPropertyPathInItem)
? itemSerializedObject.FindPropertyOfType(type, true)
: itemSerializedObject.FindProperty(additionalDataPropertyPathInItem))
{
if (target == null)
{
cannotFindAssignableProperties.Add(newSerializedObject.targetObject.name + "(" + type + ")");
}
else
{
target.objectReferenceValue = newData;
target.serializedObject.ApplyModifiedProperties();
additionalDataPropertyPathInItem = target.propertyPath;
}
}
}
}
else
{
couldNotFindItemID.Add(itemID);
}
OnApplyChanges(newData, newSerializedObject);
data.Add(newSerializedObject);
}
OnImported(newData);
}
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
AssetDatabase.Refresh();
EditorUtility.ClearProgressBar();
}
private IEnumerator ItemExists(string givenID, Action<string, ItemData> onFoundItem)
{
foreach (var item in ItemDatabase.Items.Values)
{
foreach (var term in ItemSearchTerms(item))
{
if (ComparePossibleNames(givenID, term))
{
onFoundItem(givenID, item);
yield break;
}
}
}
var layout = -1;
var options = new GUIContent[] {
new GUIContent("Create New Item"),
new GUIContent("Choose Item"),
new GUIContent("Cancel") };
var newItemID = givenID;
var newItemName = Helper.CamelCaseToTitle(givenID);
var newPath = string.Empty;
var customWindow = CustomWindow.Show(delegate (CustomWindow window)
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
using (new EditorGUILayout.VerticalScope())
{
GUILayout.FlexibleSpace();
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Box(EditorGUIUtility.FindTexture("d_console.erroricon"), GUIStyle.none);
using (new EditorGUILayout.VerticalScope())
{
EditorGUILayout.LabelField("Could not find the following Item ID:");
EditorGUILayout.LabelField(givenID);
EditorGUILayout.LabelField("What would you like to do?");
}
}
GUILayout.FlexibleSpace();
layout = GUILayout.Toolbar(layout, options);
switch (layout)
{
case 0:
GUILayout.FlexibleSpace();
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
{
newItemID = EditorGUILayout.TextField("New Item ID", newItemID);
newItemName = EditorGUILayout.TextField("New Item Name", newItemName);
var rect = EditorGUILayout.GetControlRect();
if (EditorGUI.DropdownButton(rect, new GUIContent(string.IsNullOrEmpty(newPath) ? "Choose..." : newPath), FocusType.Keyboard))
{
var menu = new GenericMenu();
var databases = AssetDatabase.FindAssets("t:ItemDataGroup")
.Select(AssetDatabase.GUIDToAssetPath);
foreach (var path in databases)
{
menu.AddItem(new GUIContent(Path.GetFileNameWithoutExtension(path)),
string.CompareOrdinal(newPath, path) == 0,
delegate
{
newPath = path;
});
}
menu.DropDown(rect);
}
using (new EditorGUI.DisabledGroupScope(string.IsNullOrEmpty(newPath)))
{
if (GUILayout.Button("OK"))
{
var database = AssetDatabase.LoadAssetAtPath<ItemDataGroup>(newPath);
if (database != null)
{
using (var databaseSerializedObject = new SerializedObject(database))
{
using (var arraySerializedProperty = databaseSerializedObject.FindProperty("_Items"))
{
int size = arraySerializedProperty.arraySize;
arraySerializedProperty.arraySize = size + 1;
using (var newElementProperty = arraySerializedProperty.GetArrayElementAtIndex(size))
{
var inventoryItemData = CreateInstance<ItemData>();
inventoryItemData.name = newItemName;
using (var itemSerializedObject = new SerializedObject(inventoryItemData))
{
using (var idElementProperty = itemSerializedObject.FindProperty("_Uid"))
{
idElementProperty.stringValue = newItemID;
}
itemSerializedObject.ApplyModifiedProperties();
}
AssetDatabase.AddObjectToAsset(inventoryItemData, database);
inventoryItemData.name = newItemName;
newElementProperty.objectReferenceValue = inventoryItemData;
serializedObject.ApplyModifiedProperties();
onFoundItem(newItemID, inventoryItemData);
}
}
databaseSerializedObject.ApplyModifiedProperties();
}
}
AssetDatabase.ImportAsset(newPath);
AssetDatabase.Refresh();
window.Close();
}
}
}
break;
case 1:
GUILayout.FlexibleSpace();
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
{
var rect = EditorGUILayout.GetControlRect();
if (EditorGUI.DropdownButton(rect, new GUIContent(string.CompareOrdinal(newItemID, givenID) == 0 ? "Choose..." : newItemID), FocusType.Keyboard))
{
var menu = new GenericMenu();
foreach (var item in ItemDatabase.Items.Values
.WhereNotNull()
.Select((i, n) => new
{
Index = n,
ID = i.Uid,
Item = i,
Menu = Path.GetFileNameWithoutExtension(AssetDatabase.GetAssetPath(i)) + Path.AltDirectorySeparatorChar + ItemName.GetWithQuality(i)
})
.OrderBy(i => i.Menu)
)
{
menu.AddItem(new GUIContent(item.Menu),
string.CompareOrdinal(item.ID, newItemID) == 0,
delegate
{
newItemID = item.ID;
});
}
menu.DropDown(rect);
}
using (new EditorGUI.DisabledGroupScope(!ItemDatabase.Items.ContainsKey(newItemID)))
{
if (GUILayout.Button("OK"))
{
onFoundItem(newItemID, ItemDatabase.Items[newItemID]);
window.Close();
}
}
}
break;
case 2:
window.Close();
break;
}
GUILayout.FlexibleSpace();
}
GUILayout.FlexibleSpace();
}
}, CustomWindow.WindowType.Utility);
EditorUtility.ClearProgressBar();
while (customWindow.IsOpen)
{
yield return null;
}
}
private IEnumerable<string> ItemSearchTerms(ItemData item)
{
yield return item.Uid;
yield return item.Class.ToString();
foreach (var tag in item.Tags)
{
yield return tag;
}
}
private bool ComparePossibleNames(string a, string b)
{
var comparison = StringComparison.OrdinalIgnoreCase;
foreach (var ai in GetOtherPossibleNamesForValue(a))
{
foreach (var bi in GetOtherPossibleNamesForValue(b))
{
if (string.Equals(ai, bi, comparison))
{
return true;
}
}
}
return false;
}
private IEnumerable<string> GetOtherPossibleNamesForValue(string str)
{
yield return str;
string trimmed = str.Trim().ToLower();
yield return trimmed;
yield return trimmed.Replace(" ", "");
yield return trimmed.Replace(" ", "_");
yield return trimmed.Replace("_", "");
yield return trimmed.Replace("_", " ");
var noNumbers = new string(str.Where(c => char.IsLetter(c)).ToArray());
if (str != noNumbers)
{
foreach (string otherNoNumbers in GetOtherPossibleNamesForValue(noNumbers))
{
yield return otherNoNumbers;
}
}
}
protected virtual string[][] ExportCSV()
{
var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
SerializedProperty elements = serializedObject.FindProperty("_infoData");
var colNum = SerializedPropertyToCSVName.Length + 2;
var rowNum = elements.arraySize + 1;
var rows = new string[rowNum][];
rows[0] = new string[colNum];
int i, j;
int ii = 0;
const int idCol = 1;
const int nameCol = 0;
rows[0][idCol] = uniqueID.Value;
rows[0][nameCol] = itemName.Value;
for (j = 0; j < SerializedPropertyToCSVName.Length; j++)
{
rows[0][j + 2] = SerializedPropertyToCSVName[j].NameInCSVPref.Value;
}
for (i = 0; i < elements.arraySize; i++)
{
var elementProp = elements.GetArrayElementAtIndex(i);
var elementObj = elementProp.objectReferenceValue;
if (elementObj == null)
{
Debug.LogError("Element " + elements.name + "[" + i + "] is null.");
continue;
}
var elementSerializedObject = new SerializedObject(elementObj);
var idProperty = elementSerializedObject.FindProperty("_Uid");
if (idProperty == null)
{
Debug.LogError("Cannot find ID on" + elements.name + "[" + i + "].");
continue;
}
ii = i;
var row = ii + 1;
rows[row] = new string[colNum];
rows[row][idCol] = idProperty.stringValue;
var suffix = "_" + typeof(TItemInformationData).Name;
var rowName = elementSerializedObject.targetObject.name;
if (rowName.EndsWith(suffix))
{
rowName = rowName.Substring(0, rowName.Length - suffix.Length);
}
rows[row][nameCol] = rowName;
for (j = 0; j < SerializedPropertyToCSVName.Length; j++)
{
var t = elementObj.GetType();
var propName = SerializedPropertyToCSVName[j].SerializedPropertyName;
var fieldInfo = t.GetField(propName, bindingFlags);
var obj = fieldInfo.GetValue(elementObj);
var val = GetObjectString(delegate
{
return elementSerializedObject.FindProperty(propName);
}, propName, obj);
rows[row][j + 2] = val;
}
}
return rows;
}
protected virtual void ProcessSubtable(string uniqueID, SerializedObject serializedObject, SerializedProperty property, string[][] subtable, string[] headers)
{
throw new NotImplementedException("If you have CSVItems, please override the ProcessCSVItem method to process them");
}
protected virtual void OnApplyChanges(Object target, SerializedObject serializedObject)
{
serializedObject.ApplyModifiedProperties();
}
protected virtual void OnImported(TItemInformationData data)
{
}
private string GetObjectString(Func<SerializedProperty> getProperty, string varName, object obj)
{
if (obj == null)
{
return string.Empty;
}
if (getProperty != null)
{
var property = getProperty();
try
{
switch (property.propertyType)
{
case SerializedPropertyType.Integer:
return property.intValue.ToString();
case SerializedPropertyType.Boolean:
return property.boolValue.ToString();
case SerializedPropertyType.Float:
return property.floatValue.ToString();
case SerializedPropertyType.String:
return property.stringValue;
case SerializedPropertyType.Color:
return property.colorValue.ToString();
case SerializedPropertyType.ObjectReference:
return AssetDatabase.GetAssetPath(property.objectReferenceValue);
case SerializedPropertyType.Vector2:
return property.vector2Value.ToString();
case SerializedPropertyType.Vector3:
return property.vector3Value.ToString();
case SerializedPropertyType.Vector4:
return property.vector4Value.ToString();
case SerializedPropertyType.Rect:
return property.rectValue.ToString();
case SerializedPropertyType.Character:
return new string((char)property.intValue, 1);
case SerializedPropertyType.Bounds:
return property.boundsValue.ToString();
case SerializedPropertyType.Quaternion:
return property.quaternionValue.ToString();
case SerializedPropertyType.Vector2Int:
return property.vector2IntValue.ToString();
case SerializedPropertyType.Vector3Int:
return property.vector3IntValue.ToString();
case SerializedPropertyType.RectInt:
return property.rectIntValue.ToString();
}
}
catch (NullReferenceException) when (property == null)
{
}
}
var type = obj.GetType();
if (obj is string || type == typeof(string) || type == typeof(string))
{
return obj.ToString();
}
if (type.IsArray)
{
var builder = new StringBuilder();
var addComma = false;
var index = 0;
foreach (object entry in (IEnumerable)obj)
{
var i = index;
index += 1;
if (entry == null)
{
continue;
}
if (addComma)
{
builder.Append(',');
}
builder.Append(GetObjectString(delegate
{
var prop = getProperty();
var arrProp = prop.GetArrayElementAtIndex(i);
return arrProp;
}, varName, entry));
addComma = true;
}
return builder.ToString();
}
return obj.ToString()
.Replace("\n", string.Empty)
.Replace("\r", string.Empty)
.Trim();
}
private ReorderableList GetReorderableList(SerializedObject serializedObject, SerializedProperty elements)
{
var italicLabelStyle = new GUIStyle(EditorStyles.label)
{
fontStyle = FontStyle.Italic
};
var list = new ReorderableList(serializedObject, elements)
{
drawHeaderCallback = GetElementHeader,
drawElementCallback = GetElement,
onAddDropdownCallback = delegate (Rect buttonRect, ReorderableList l)
{
var window = CreateInstance<ItemSelectorWindow>();
window.Instantiate(delegate (ItemData item)
{
var infoData = CreateNewInfo(elements, l);
var infoSerializedObject = new SerializedObject(infoData);
infoSerializedObject.FindProperty("_Uid").stringValue = item.Uid;
var itemObj = item as Object;
if (itemObj != null)
{
infoData.name = itemObj.name;// + "_" + typeof(TItemInformationData).Name;
var itemSerializedObject = new SerializedObject(itemObj);
var itm = itemSerializedObject.FindPropertyOfType<TItemInformationData>();
if (itm != null)
{
itm.objectReferenceValue = infoData;
}
itemSerializedObject.ApplyModifiedProperties();
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
}
infoSerializedObject.ApplyModifiedProperties();
}, elements);
if (window == null)
{
throw new NullReferenceException("Window was null");
}
if (buttonRect == null)
{
throw new NullReferenceException("buttonRect was null");
}
window.ShowAsDropDown(GUIUtility.GUIToScreenRect(buttonRect), new Vector2(300, 200));
},
onRemoveCallback = delegate (ReorderableList l)
{
ReorderableList.defaultBehaviours.DoRemoveButton(l);
serializedObject.ApplyModifiedProperties();
bool deletedAsset = false;
foreach (var i in AssetDatabase.LoadAllAssetRepresentationsAtPath(AssetDatabase.GetAssetPath(target))
.Select(o => o as TItemInformationData)
.WhereNotNull()
.Except(elements
.GetPropertiesInArray()
.Select(p => p.objectReferenceValue as TItemInformationData)
.WhereNotNull()
))
{
DestroyImmediate(i, true);
deletedAsset = true;
}
if (deletedAsset)
{
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
AssetDatabase.Refresh();
}
for (int i = elements.arraySize - 1; i >= 0; i--)
{
if (elements.GetArrayElementAtIndex(i).objectReferenceValue == null)
{
elements.DeleteArrayElementAtIndex(i);
}
}
serializedObject.ApplyModifiedProperties();
}
};
return list;
}
protected virtual void GetElementHeader(Rect rect)
{
const float buttonW = 70f;
using (var elements = serializedObject.FindProperty("_infoData"))
{
var clearContent = new GUIContent("Clear");
var clearStyle = new GUIStyle(EditorStyles.miniButton)
{
fixedHeight = 0
};
float height = EditorGUIUtility.singleLineHeight;
float diff = 1;
var lRect = new Rect(rect.x,
rect.y + diff,
rect.width - buttonW,
rect.height - diff - diff);
var rRect = new Rect(rect.x + rect.width - buttonW,
rect.y + diff,
buttonW,
rect.height - diff - diff);
EditorGUI.LabelField(lRect, ObjectNames.NicifyVariableName(typeof(TItemInformationData).Name));
if (GUI.Button(rRect, clearContent, clearStyle))
{
elements.arraySize = 0;
serializedObject.ApplyModifiedProperties();
bool deletedAsset = false;
foreach (var i in AssetDatabase.LoadAllAssetRepresentationsAtPath(AssetDatabase.GetAssetPath(target))
.Select(o => o as TItemInformationData)
.WhereNotNull()
.Except(elements
.GetPropertiesInArray()
.Select(p => p.objectReferenceValue as TItemInformationData)
.WhereNotNull()
))
{
DestroyImmediate(i, true);
deletedAsset = true;
}
if (deletedAsset)
{
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
AssetDatabase.Refresh();
}
serializedObject.ApplyModifiedProperties();
}
}
}
protected virtual void GetElement(Rect rect, int index, bool isActive, bool isFocused)
{
var labelStyle = new GUIStyle(EditorStyles.label);
const float buttonW = 70f;
using (var elements = serializedObject.FindProperty("_infoData"))
{
if (0 > index || index >= elements.arraySize)
{
EditorGUI.LabelField(rect, "Error");
return;
}
using (var property = elements.GetArrayElementAtIndex(index))
{
if (property == null || property.objectReferenceValue == null)
{
EditorGUI.LabelField(rect, "Error");
return;
}
string itemName;
using (var objectSO = new SerializedObject(property.objectReferenceValue))
using (var uniqueID = objectSO.FindProperty("_Uid"))
{
if (string.IsNullOrEmpty(uniqueID.stringValue))
{
itemName = ObjectNames.NicifyVariableName(property.objectReferenceValue.name);
}
else
{
if (ItemDatabase.Items.TryGetValue(uniqueID.stringValue, out var item))
{
var casted = property.objectReferenceValue as TItemInformationData;
if (casted == null)
{
itemName = "Item " + index;
}
else
{
itemName = GetItemName(casted);
}
}
else
{
itemName = "Item " + index;
}
}
}
var openContent = new GUIContent("Open");
var openStyle = EditorStyles.miniButton;
var height = EditorGUIUtility.singleLineHeight;
var diff = 2;
var lRect = new Rect(rect.x,
rect.y + diff,
rect.width - buttonW,
height);
var rRect = new Rect(rect.x + rect.width - buttonW,
rect.y + diff,
buttonW,
height);
EditorGUI.LabelField(lRect, itemName, labelStyle);
if (GUI.Button(rRect, openContent, openStyle))
{
Selection.objects = new[] { elements.GetArrayElementAtIndex(index).objectReferenceValue };
}
}
}
}
protected virtual string GetItemName(TItemInformationData objectReferenceValue)
{
return ObjectNames.NicifyVariableName(objectReferenceValue.name);
}
private TItemInformationData CreateNewInfo(SerializedProperty elements, ReorderableList list)
{
int index = list.index + 1;
if (0 > index || index >= elements.arraySize)
{
index = elements.arraySize;
}
var infoData = CreateNewInfo(elements, index);
list.index = index;
return infoData;
}
private TItemInformationData CreateOrFindNewInfo(SerializedProperty elements, FindElementMethod findMethod, string uniqueID, int index, string itemName = "")
{
if (TryFindElement(elements, findMethod, uniqueID, out var item))
{
return item;
}
return CreateNewInfo(elements, index, itemName);
}
private bool TryFindElement(SerializedProperty elements, FindElementMethod findMethod, string uniqueID, out TItemInformationData item)
{
if (elements == null || !elements.isArray)
{
item = default;
return false;
}
for (int i = 0; i < elements.arraySize; i++)
{
using (var elementProperty = elements.GetArrayElementAtIndex(i))
{
if (elementProperty == null
|| elementProperty.propertyType != SerializedPropertyType.ObjectReference
)
{
continue;
}
var obj = elementProperty.objectReferenceValue;
if (obj == null)
{
continue;
}
var data = obj as TItemInformationData;
if (data == null)
{
continue;
}
using (var elementObject = new SerializedObject(obj))
{
switch (findMethod)
{
case FindElementMethod.ByUniqueID:
using (SerializedProperty uniqueIDProperty = elementObject.FindProperty("_Uid"))
{
if (uniqueIDProperty == null || uniqueIDProperty.propertyType != SerializedPropertyType.String)
{
continue;
}
if (string.CompareOrdinal(uniqueIDProperty.stringValue, uniqueID) == 0)
{
item = data;
return true;
}
}
break;
case FindElementMethod.ByName:
if (string.CompareOrdinal(data.name, uniqueID) == 0)
{
item = data;
return true;
}
break;
}
}
}
}
item = default;
return false;
}
private TItemInformationData CreateNewInfo(SerializedProperty elements, int index, string itemName = "")
{
var infoData = ScriptableObject.CreateInstance<TItemInformationData>();
if (string.IsNullOrEmpty(itemName))
{
infoData.name = typeof(TItemInformationData).Name + "_" + elements.arraySize;
}
else
{
infoData.name = itemName;
}
AssetDatabase.AddObjectToAsset(infoData, target);
elements.InsertArrayElementAtIndex(index);
elements.GetArrayElementAtIndex(index).objectReferenceValue = infoData;
serializedObject.ApplyModifiedProperties();
return infoData;
}
private string GetDefaultCSVHeader(string variableName)
{
var s = variableName;
var builder = new StringBuilder();
for (int i = 0; i < s.Length; i++)
{
char c = s[i];
if (builder.Length == 0)
{
if (char.IsLetter(c))
{
builder.Append(char.ToUpper(c));
}
}
else
{
builder.Append(c);
}
}
return builder.ToString();
}
private void DrawFixButtonsArea()
{
debugOptions = EditorGUILayout.Foldout(debugOptions, "Debug Options", true);
if (!debugOptions)
{
return;
}
using (new EditorGUILayout.VerticalScope(GUI.skin.box))
{
EditorGUILayout.Space();
DrawFixButtons();
}
}
protected virtual void DrawFixButtons()
{
EditorGUILayout.LabelField("Array", EditorStyles.boldLabel);
if (DoFixButton("Adds items to the array that are present in the asset", "Add missing"))
{
DoAddMissing();
}
if (DoFixButton("Removes null entries in the array", "Remove Null"))
{
DoRemoveNulls();
}
EditorGUILayout.LabelField("Asset", EditorStyles.boldLabel);
if (DoFixButton("Renames the sub-assets to have the correct names", "Fix Names"))
{
DoFixNames();
}
if (DoFixButton("Adds all " + ObjectNames.NicifyVariableName(typeof(TItemInformationData).Name) + " to this asset", "Adopt All"))
{
MakeMeMaster();
}
EditorGUILayout.LabelField("Items", EditorStyles.boldLabel);
if (DoFixButton("Fixes references items to sub assets", "Fix Item to Asset References"))
{
DoFixItemToAssetReferences();
}
}
protected bool DoFixButton(string label, string buttonContent)
{
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.LabelField(label, new GUIStyle(EditorStyles.label) { wordWrap = true });
return GUILayout.Button(buttonContent, EditorStyles.miniButton, GUILayout.Width(120));
}
}
private void DoRemoveNulls()
{
var array = serializedObject.FindProperty("_infoData");
for (int i = array.arraySize - 1; i >= 0; i--)
{
var element = array.GetArrayElementAtIndex(i);
if (element == null || element.objectReferenceValue == null)
{
array.DeleteArrayElementAtIndex(i);
}
}
serializedObject.ApplyModifiedProperties();
}
private void DoAddMissing()
{
var array = serializedObject.FindProperty("_infoData");
var assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(target))
.Where(a => a is TItemInformationData)
.Except(array.GetPropertiesInArray().Select(p => p.objectReferenceValue));
foreach (var asset in assets)
{
int size = array.arraySize;
array.arraySize = size + 1;
array.GetArrayElementAtIndex(size).objectReferenceValue = asset;
}
serializedObject.ApplyModifiedProperties();
}
private void DoFixItemToAssetReferences()
{
var typeName = typeof(TItemInformationData).Name.ToLower().Trim();
var infoDataSerializedProperty = serializedObject.FindProperty("_infoData");
var builder = new StringBuilder();
builder.AppendManyLine("Begin : ", serializedObject.targetObject.name, " (", infoDataSerializedProperty.arraySize, ")");
var paths = new List<string>();
for (int i = 0; i < infoDataSerializedProperty.arraySize; i++)
{
builder.AppendManyLine("Checking Item _infoData[", i, "]");
builder.Append(" ");
var infoDataProperty = infoDataSerializedProperty.GetArrayElementAtIndex(i);
var infoDataPropertyContents = infoDataProperty.objectReferenceValue;
if (infoDataPropertyContents == null)
{
builder.AppendManyLine("FAILURE: [", i, "] is null");
continue;
}
var infoDataSerializedObject = new SerializedObject(infoDataPropertyContents);
var idProperty = infoDataSerializedObject.FindProperty("_Uid");
var uniqueID = idProperty.stringValue;
ItemDatabase.Items.TryGetValue(uniqueID, out var item);
if (item == null)
{
builder.AppendManyLine("FAILURE: Cannot find:- ", uniqueID);
continue;
}
var itemSerializedObject = new SerializedObject(item);
var iterator = itemSerializedObject.GetIterator();
iterator.Next(true);
var changed = false;
do
{
if (iterator.propertyType != SerializedPropertyType.ObjectReference)
{
continue;
}
var t = iterator.GetPropertyType();
if (t == null)
{
builder.AppendManyLine("Could not find type for: ", iterator.name, " => ", iterator.type);
builder.Append(" ");
continue;
}
var thisTypeName = t.Name;
var iteratorTypeName = thisTypeName.ToLower().Trim();
if (iteratorTypeName == typeName)
{
builder.AppendManyLine("SUCCESS: ", item.name, " :: ", iterator.name, " => ", infoDataPropertyContents.name, " (", thisTypeName, ")");
iterator.objectReferenceValue = infoDataPropertyContents;
changed = true;
string path = AssetDatabase.GetAssetPath(item);
if (!paths.Contains(path))
{
paths.Add(path);
}
}
}
while (iterator.Next(true));
if (changed)
{
itemSerializedObject.ApplyModifiedProperties();
builder.AppendManyLine("Apply Changes: ", itemSerializedObject.targetObject.name);
}
else
{
builder.AppendManyLine("FAILURE: Cannot find: ", typeof(TItemInformationData).Name, " on ", item.name);
}
}
if (paths.Count > 0)
{
for (int i = 0; i < paths.Count; i++)
{
AssetDatabase.ImportAsset(paths[i]);
}
AssetDatabase.Refresh();
}
Debug.Log(builder.ToString());
}
private void DoFixNames()
{
var builder = new StringBuilder();
bool reimportNeeded = false;
var items = AssetDatabase.FindAssets("t:InventoryItemData")
.Select(AssetDatabase.GUIDToAssetPath)
.Distinct()
.SelectMany(AssetDatabase.LoadAllAssetsAtPath)
.Select(o => o as ItemData)
.Where(d => d != null);
var infoDataArraySerializedProperty = serializedObject.FindProperty("_infoData");
for (int i = 0; i < infoDataArraySerializedProperty.arraySize; i++)
{
builder.AppendManyLine("Checking[", i, "]");
var infoSerialializedProperty = infoDataArraySerializedProperty.GetArrayElementAtIndex(i);
if (infoSerialializedProperty == null)
{
continue;
}
var targetObject = infoSerialializedProperty.objectReferenceValue;
if (targetObject == null)
{
continue;
}
var dataSerializedObject = new SerializedObject(infoSerialializedProperty.objectReferenceValue);
var serializedProperty = dataSerializedObject.FindProperty("_Uid");
if (serializedProperty == null)
{
continue;
}
string uniqueID = serializedProperty.stringValue;
if (string.IsNullOrEmpty(uniqueID))
{
continue;
}
var itemData = items.FirstOrDefault(d => d.Uid == uniqueID);
if (itemData != null)
{
builder.AppendManyLine("Changing ", targetObject.name, " to ", itemData.name);
targetObject.name = itemData.name;
reimportNeeded = true;
}
else
{
}
}
if (reimportNeeded)
{
AssetDatabase.Refresh();
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
}
Debug.Log(builder.ToString());
}
private void MakeMeMaster()
{
var builder = new StringBuilder();
try
{
builder.Append("ADOPTING " + target.name).AppendLine();
var assets = AssetDatabase.FindAssets("t:" + typeof(TItemInformationData).Name)
.Select(AssetDatabase.GUIDToAssetPath)
.SelectMany(AssetDatabase.LoadAllAssetsAtPath)
.Where(a => a is TItemInformationData)
.Where(a => AssetDatabase.LoadMainAssetAtPath(AssetDatabase.GetAssetPath(a)) != target);
foreach (var asset in assets.Where(a => !AssetDatabase.IsMainAsset(a)))
{
builder.Append("Removing : ").Append(asset.name).AppendLine();
try
{
AssetDatabase.RemoveObjectFromAsset(asset);
}
catch
{
builder.Append("ERROR REMOVING : ").Append(asset.name).AppendLine();
}
try
{
AssetDatabase.AddObjectToAsset(asset, target);
}
catch
{
builder.Append("ERROR ADDING : ").Append(asset.name).AppendLine();
}
EditorUtility.SetDirty(asset);
}
foreach (var asset in assets.Where(a => AssetDatabase.IsMainAsset(a)))
{
builder.Append("Adding : ").Append(asset.name).AppendLine();
try
{
AssetDatabase.AddObjectToAsset(asset, target);
}
catch
{
builder.Append("ERROR ADDING : ").Append(asset.name).AppendLine();
}
}
EditorUtility.SetDirty(target);
AssetDatabase.SaveAssets();
}
finally
{
Debug.Log(builder);
}
}
}
}
using ItalicPig.PaleoPines.Loading;
using UnityEngine;
using UnityEngine.Serialization;
/*
* Copyright © 2020, Italic Pig, All Rights Reserved
*
* Author: Harry Evans
* Date: 26/02/2020
*/
namespace ItalicPig.PaleoPines.Inventories
{
/// <summary>
/// Abstract superclass for additional item information data to be associated with individual ItemData.
/// </summary>
public abstract class AdditionalItemInformationData : ScriptableObject, ILoadable<AdditionalItemInformationData>
{
/// <summary>
/// Unique ID of the ItemData this Additional Data is associated with.
/// </summary>
[SerializeField, FormerlySerializedAs("_uniqueID"), ItemID(updateTargetItem: true)]
private string _Uid = string.Empty;
/// <summary>
/// Unique ID of the ItemData this Additional Data is associated with.
/// </summary>
public string UniqueID => _Uid;
public virtual int Priority => 100;
public virtual void Load() { }
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using ItalicPig.PaleoPines.Inventories;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace ItalicPig.PaleoPines.Editor.Inventory
{
[CustomEditor(typeof(AdditionalItemInformationData), true), CanEditMultipleObjects]
public class AdditionalItemInformationDataEditor : UnityEditor.Editor
{
public static int BackInstanceID = 0;
private string objectName = string.Empty;
private GUIContent[] otherObjectContent = null;
private bool otherNamesSet = false;
protected virtual void OnEnable()
{
otherNamesSet = false;
objectName = target.name;
}
protected virtual void OnDisable()
{
BackInstanceID = 0;
}
public override void OnInspectorGUI()
{
EditorGUI.BeginChangeCheck();
Object obj = EditorUtility.InstanceIDToObject(BackInstanceID);
if (obj != null)
{
DrawBackButton(obj.name, () => obj);
}
else if (!AssetDatabase.IsMainAsset(this))
{
string path = AssetDatabase.GetAssetPath(target);
DrawBackButton(Path.GetFileNameWithoutExtension(path), () => AssetDatabase.LoadMainAssetAtPath(path));
}
DrawInspector();
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
}
}
private void DrawBackButton(string label, Func<Object> getObj)
{
var buttonContent = new GUIContent(ObjectNames.NicifyVariableName(label), EditorGUIUtility.FindTexture("tab_prev"));
var buttonStyle = new GUIStyle("IN BigTitle")
{
alignment = TextAnchor.MiddleLeft,
fontStyle = FontStyle.Bold
};
buttonStyle.padding = new RectOffset(buttonStyle.padding.left + 5, buttonStyle.padding.right, buttonStyle.padding.top, buttonStyle.padding.bottom);
Vector2 size = buttonStyle.CalcSize(buttonContent);
float h = size.y * 1.25f;
if (GUI.Button(new Rect(0, -1, Screen.width, h), buttonContent, buttonStyle))
{
Selection.objects = new Object[] { getObj() };
}
GUILayout.Space(h + 5f);
}
protected virtual void DrawInspector()
{
if (!serializedObject.isEditingMultipleObjects)
{
const string nameField = "NameField";
GUI.SetNextControlName(nameField);
objectName = EditorGUILayout.TextField("Asset Name", objectName);
if (objectName != target.name && GUI.GetNameOfFocusedControl() != nameField)
{
target.name = objectName;
AssetDatabase.Refresh();
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
}
}
using (var UniqueIDProperty = serializedObject.FindProperty("_Uid"))
{
string OldVal = UniqueIDProperty.stringValue;
EditorGUILayout.PropertyField(UniqueIDProperty);
if (!otherNamesSet || OldVal != UniqueIDProperty.stringValue)
{
otherNamesSet = true;
var TargetType = target.GetType();
otherObjectContent = ItemDatabase.Items.Values.Where(item =>
{
if (item.Uid == UniqueIDProperty.stringValue)
{
return false;
}
var ItemType = item.GetType();
var Properties = ItemType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var propertyInfo in Properties)
{
if (propertyInfo.PropertyType == TargetType)
{
var value = propertyInfo.GetValue(item) as Object;
return target == value;
}
}
return false;
})
.Select(i => new GUIContent(ItemName.GetWithQuality(i), i.Icon.texture)).ToArray();
}
if (otherObjectContent != null && otherObjectContent.Length > 0)
{
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.PrefixLabel("Also attached to");
GUILayout.Space(3);
using (new EditorGUILayout.VerticalScope())
{
for (int i = 0; i < otherObjectContent.Length; i++)
{
GUILayout.Label(otherObjectContent[i], GUILayout.Height(EditorGUIUtility.singleLineHeight));
}
}
}
}
EditorGUILayout.Space();
EditorHelper.GuiLine();
EditorGUILayout.Space();
}
DrawProperties();
}
protected virtual void DrawProperties()
{
DrawPropertiesExcluding(serializedObject, GetExcludedProperties().ToArray());
}
protected virtual IEnumerable<string> GetExcludedProperties()
{
yield return "m_Script";
yield return "_Uid";
}
}
}
using UnityEngine;
namespace ItalicPig.PaleoPines.Inventories
{
public enum CropType
{
Ground,
Tree,
Bush
}
[CreateAssetMenu(menuName = MenuPrefix + "Garden Inventory Information Data", fileName = "GardenInformationData")]
public class GardenInventoryInformationData : AdditionalInventoryInformationData<GardenItemInformationData>
{
[SerializeField]
private GardenGlobalData _GardenGlobalData;
}
}
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using ItalicPig.PaleoPines.Inventories;
using UnityEditor;
using UnityEngine;
namespace ItalicPig.PaleoPines.Editor.Inventory
{
[CustomEditor(typeof(GardenInventoryInformationData))]
public class GardenInventoryInformationDataEditor
: AdditionalInventoryInformationDataEditor<GardenItemInformationData>
{
private const float ONE_HUNDRED_PERCENT = 100f;
private List<PlantStageData> existingStages = null;
protected override void DrawRemainingProperties()
{
DrawPropertiesExcluding(serializedObject, "m_Script", "_infoData", "_GardenGlobalData");
using (new EditorGUILayout.HorizontalScope())
{
using (var gardenGlobalDataProperty = serializedObject.FindProperty("_GardenGlobalData"))
{
EditorGUI.BeginChangeCheck();
gardenGlobalDataProperty.objectReferenceValue = EditorGUILayout.ObjectField(gardenGlobalDataProperty.objectReferenceValue,
typeof(GardenGlobalData),
false);
if (gardenGlobalDataProperty.objectReferenceValue == null)
{
if (GUILayout.Button("Create Global Data"))
{
string oldPath = AssetDatabase.GetAssetPath(target);
string newPath = oldPath.Substring(0, oldPath.Length - Path.GetFileName(oldPath).Length);
newPath = Path.Combine(newPath, "GlobalGardenData.asset");
var instance = ScriptableObject.CreateInstance<GardenGlobalData>();
AssetDatabase.CreateAsset(instance, newPath);
gardenGlobalDataProperty.objectReferenceValue = AssetDatabase.LoadAssetAtPath<GardenGlobalData>(newPath);
}
}
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
}
}
}
}
protected override void OnCSVImported(string[][] output)
{
existingStages = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(target))
.Select(a => a as PlantStageData)
.Where(s => s != null)
.Distinct()
.ToList();
base.OnCSVImported(output);
for (int i = existingStages.Count - 1; i >= 0; i--)
{
DestroyImmediate(existingStages[i], true);
}
existingStages = null;
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
AssetDatabase.Refresh();
}
protected override void ProcessSubtable(string uniqueID, SerializedObject serializedObject, SerializedProperty property, string[][] subtable, string[] headers)
{
if (property == null)
{
return;
}
if (property.name == "_Stages")
{
ProcessStages(uniqueID, serializedObject, property, subtable, headers);
}
}
protected void ProcessItemQualities(string uniqueID, SerializedObject serializedObject, SerializedProperty property, string[][] subtable, string[] headers)
{
Debug.Log(uniqueID
+ "\n" + serializedObject.targetObject.name
+ "\n" + property.name
+ "\n" + string.Join("\n", subtable.Select(s => string.Join(", ", s)).ToArray())
+ "\n" + string.Join(", ", headers)
);
}
protected void ProcessStages(string uniqueID, SerializedObject serializedObject, SerializedProperty property, string[][] subtable, string[] headers)
{
if (!property.isArray)
{
return;
}
try
{
property.arraySize = 0;
int c, r;
var lists = new List<List<string>>();
for (r = 0; r < subtable.Length; r++)
{
string[] row = subtable[r];
for (c = 0; c < row.Length; c++)
{
if (c >= lists.Count)
{
lists.Add(new List<string>());
}
if (lists[c] == null)
{
lists[c] = new List<string>();
}
lists[c].Add(row[c]);
}
}
int index = 0;
var allInfo = lists.Skip(1).Select((l, i) => (
Stage: l[0],
Length: l[1],
WiltingChance: l[2],
InTimeline: l[3],
WithersMature: l[4],
ChanceOfWeeds: l[5],
NumberOfHarvests: l[6],
StageAfterHarvest: l[7],
HarvestMinimum: l[8],
HarvestMaximum: l[9],
CropBumper: l[10],
SeedBumper: l[11],
QualityBase: l[12],
QualitySoilBoost: l[13],
QualitySeasonBoost: l[14],
QualityMusicBoost: l[15],
BumperWateringStreak: l[16],
BumperMusicBoost: l[17],
BumperSoilBoost: l[18],
SeasonBumperBoost: l[19]
));
string family = serializedObject.FindProperty("_Family").stringValue;
bool isCrop = false, isTree = false, isBush = false;
if (family.ToLower().Contains("tree"))
{
isTree = true;
}
else if (family.ToLower().Contains("bush"))
{
isBush = true;
}
else
{
int cropCount = allInfo.Count(i => ConvertCropGrowthStage(i.Stage).IsCrop());
int treeCount = allInfo.Count(i => ConvertTreeGrowthStage(i.Stage).IsTree());
int bushCount = allInfo.Count(i => ConvertBushGrowthStage(i.Stage).IsBush());
isCrop = cropCount > treeCount && cropCount > bushCount;
isTree = treeCount > bushCount && treeCount > cropCount;
isBush = bushCount > treeCount && bushCount > cropCount;
}
foreach (var info in allInfo)
{
PlantGrowthStage stage =
isCrop ? ConvertCropGrowthStage(info.Stage) :
isTree ? ConvertTreeGrowthStage(info.Stage) :
isBush ? ConvertBushGrowthStage(info.Stage) :
PlantGrowthStage.none;
if (stage == PlantGrowthStage.none || stage == PlantGrowthStage.count)
{
continue;
}
int i = index++;
PlantStageData stageData = null;
int numberOfHarvests = ConvertInt(info.NumberOfHarvests, 0);
int harvestMin = ConvertInt(info.HarvestMinimum, 0);
int harvestMax = ConvertInt(info.HarvestMaximum, 0);
Type typeOfStage = GetTypeOfStage(stage, harvestMin, harvestMax);
if (existingStages.Any())
{
stageData = existingStages
.FirstOrDefault(delegate (PlantStageData plant)
{
using (var existingStageObject = new SerializedObject(plant))
{
using (SerializedProperty stageProperty = existingStageObject.FindProperty("stage"))
{
return existingStageObject.FindProperty("uniqueID").stringValue == uniqueID
&& stageProperty.enumNames[stageProperty.enumValueIndex] == stage.ToString()
&& plant.GetType() == typeOfStage;
}
}
});
existingStages.Remove(stageData);
}
if (stageData == null)
{
stageData = (PlantStageData)CreateInstance(typeOfStage);
AssetDatabase.AddObjectToAsset(stageData, target);
serializedObject.ApplyModifiedProperties();
}
stageData.name = property.serializedObject.targetObject.name + " (" + i + ": " + stage + ")";
property.InsertArrayElementAtIndex(i);
property.GetArrayElementAtIndex(i).objectReferenceValue = stageData;
var stageObject = new SerializedObject(stageData);
stageObject.FindProperty("uniqueID").stringValue = uniqueID;
stageObject.FindProperty("index").intValue = i;
ApplyGrowthStage(stageObject.FindProperty("stage"), stage);
if (stageData is GrowingStageData)
{
stageObject.FindProperty("maturesOld").boolValue = ConvertBool(info.WithersMature);
stageObject.FindProperty("stageLength").intValue = ConvertInt(info.Length);
ConvertWiltingData(stageObject.FindProperty("wiltingInfo"), info.WiltingChance);
stageObject.FindProperty("enterableViaTimeline").boolValue = ConvertBool(info.InTimeline);
}
if (stageData is HarvestStageData)
{
stageObject.FindProperty("numberOfHarvest").intValue = numberOfHarvests;
SerializedProperty stageToGoToOnHarvestProperty = stageObject.FindProperty("stageToGoToOnHarvest");
if (numberOfHarvests <= 1)
{
ApplyGrowthStage(stageToGoToOnHarvestProperty, PlantGrowthStage.none);
}
else if (isCrop)
{
ApplyGrowthStage(stageToGoToOnHarvestProperty, ConvertCropGrowthStage(info.StageAfterHarvest, PlantGrowthStage.CROP_Mature));
}
else if (isTree)
{
ApplyGrowthStage(stageToGoToOnHarvestProperty, ConvertTreeGrowthStage(info.StageAfterHarvest, PlantGrowthStage.TREE_Mature));
}
else if (isBush)
{
ApplyGrowthStage(stageToGoToOnHarvestProperty, ConvertBushGrowthStage(info.StageAfterHarvest, PlantGrowthStage.BUSH_Mature));
}
stageObject.FindProperty("infiniteHarvest").boolValue = false;//todo fix
stageObject.FindProperty("cropYieldMin").intValue = harvestMin;
stageObject.FindProperty("cropYieldMax").intValue = harvestMax;
stageObject.FindProperty("cropBumper").intValue = ConvertInt(info.CropBumper);
stageObject.FindProperty("seedBumper").intValue = ConvertInt(info.SeedBumper);
SerializedProperty bumperProperty = stageObject.FindProperty("bumper");
bumperProperty.FindPropertyRelative("WateringStreakRequiredForBumper").intValue = ConvertInt(info.BumperWateringStreak);
bumperProperty.FindPropertyRelative("BumperIsSeed").boolValue = harvestMin <= 1 && harvestMax <= 1;
bumperProperty.FindPropertyRelative("HeardMusicBumperIncr").floatValue = ConvertFloat(info.BumperMusicBoost);
bumperProperty.FindPropertyRelative("CorrectSoilBumperIncr").floatValue = ConvertFloat(info.BumperSoilBoost);
bumperProperty.FindPropertyRelative("SeasonBumperIncr").floatValue = ConvertFloat(info.SeasonBumperBoost);
}
if (stageData is WitherStageData)
{
stageObject.FindProperty("seedYieldMin").intValue = ConvertInt(info.HarvestMinimum);
stageObject.FindProperty("seedYieldMax").intValue = ConvertInt(info.HarvestMaximum);
}
stageObject.ApplyModifiedProperties();
}
}
catch (System.Exception e)
{
Debug.LogError(e);
}
}
protected override string GetItemName(GardenItemInformationData objectReferenceValue)
{
using (var serializedObject = new SerializedObject(objectReferenceValue))
using (var serializedProperty = serializedObject.FindProperty("_Season"))
{
return $"{ base.GetItemName(objectReferenceValue) } ({serializedProperty.enumDisplayNames[serializedProperty.enumValueIndex]})";
}
}
private Type GetTypeOfStage(PlantGrowthStage stage, int harvestMin, int harvestMax)
{
if (harvestMin > 0 && harvestMax > 0)
{
return stage == PlantGrowthStage.BUSH_Ripe_Full || stage == PlantGrowthStage.BUSH_Ripe_Partial ? typeof(BushHarvestStageData) : typeof(HarvestStageData);
}
else if (stage == PlantGrowthStage.CROP_WitheredYoung)
{
return typeof(WitherYoungStageData);
}
else if (stage == PlantGrowthStage.CROP_WitheredMature)
{
return typeof(WitherStageData);
}
return typeof(GrowingStageData);
}
private void ApplyGrowthStage(SerializedProperty property, PlantGrowthStage stage)
{
string[] enumNames = property.enumNames;
for (int i = 0; i < enumNames.Length; i++)
{
if (enumNames[i].Trim().Equals(stage.ToString()))
{
property.enumValueIndex = i;
}
}
}
private PlantGrowthStage ConvertGrowthStage(string value, PlantGrowthStage defaultStage = PlantGrowthStage.none)
{
if (string.IsNullOrEmpty(value) || value.Equals("-"))
{
return defaultStage;
}
if (Enum.TryParse(value, true, out PlantGrowthStage enumStage))
{
return enumStage;
}
return ConvertCropGrowthStage(value);
}
private PlantGrowthStage ConvertCropGrowthStage(string value, PlantGrowthStage defaultStage = PlantGrowthStage.none)
{
if (string.IsNullOrEmpty(value) || value.Equals("-"))
{
return defaultStage;
}
if (Enum.TryParse(value, true, out PlantGrowthStage enumStage))
{
return enumStage;
}
string trimmed = value.Trim().ToLower().Replace(" ", string.Empty).Replace("_", string.Empty);
switch (trimmed)
{
case "seed": return PlantGrowthStage.CROP_Seed;
case "seedling": return PlantGrowthStage.CROP_Seedling;
case "sprout": return PlantGrowthStage.CROP_Sprout;
case "flowering": return PlantGrowthStage.CROP_Flowering;
case "ripening": return PlantGrowthStage.CROP_Ripening;
case "ripe": return PlantGrowthStage.CROP_Ripe;
case "mature": return PlantGrowthStage.CROP_Mature;
case "witheredyoung": return PlantGrowthStage.CROP_WitheredYoung;
case "withered":
case "wither":
case "witheredmature": return PlantGrowthStage.CROP_WitheredMature;
default:
if (trimmed.Contains("wither"))
{
return trimmed.Contains("young")
? PlantGrowthStage.CROP_WitheredYoung
: PlantGrowthStage.CROP_WitheredMature;
}
return PlantGrowthStage.none;
}
}
private PlantGrowthStage ConvertTreeGrowthStage(string value, PlantGrowthStage defaultStage = PlantGrowthStage.none)
{
if (string.IsNullOrEmpty(value) || value.Equals("-"))
{
return defaultStage;
}
if (Enum.TryParse(value, true, out PlantGrowthStage enumStage))
{
return enumStage;
}
string trimmed = value.Trim().ToLower().Replace(" ", string.Empty).Replace("_", string.Empty);
switch (trimmed)
{
case "sprout": return PlantGrowthStage.TREE_Sprout;
case "sapling": return PlantGrowthStage.TREE_Sapling;
case "mature": return PlantGrowthStage.TREE_Mature;
case "flowering": return PlantGrowthStage.TREE_Flowering;
case "ripe": return PlantGrowthStage.TREE_Ripe;
default: return PlantGrowthStage.none;
}
}
private PlantGrowthStage ConvertBushGrowthStage(string value, PlantGrowthStage defaultStage = PlantGrowthStage.none)
{
if (string.IsNullOrEmpty(value) || value.Equals("-"))
{
return defaultStage;
}
if (Enum.TryParse(value, true, out PlantGrowthStage enumStage))
{
return enumStage;
}
string trimmed = value.Trim().ToLower().Replace(" ", string.Empty).Replace("_", string.Empty);
switch (trimmed)
{
case "seeded": return PlantGrowthStage.BUSH_Seeded;
case "sprout": return PlantGrowthStage.BUSH_Sprout;
case "seeding": return PlantGrowthStage.BUSH_Sapling;
case "flowering": return PlantGrowthStage.BUSH_Flowering;
case "ripe": return PlantGrowthStage.BUSH_Ripe_Full;
case "mature": return PlantGrowthStage.BUSH_Mature;
case "sparse": return PlantGrowthStage.BUSH_Sparse;
default: return PlantGrowthStage.none;
}
}
private bool ConvertBool(string value, bool onNull = false)
{
if (string.IsNullOrEmpty(value))
{
return onNull;
}
string trimmed = value.Trim().ToLower();
if (trimmed.Equals("y") || trimmed.StartsWith("y") || trimmed.Equals("true"))
{
return true;
}
return false;
}
private int ConvertInt(string value, int onNull = 0)
{
return int.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out int Result) ? Result : onNull;
}
private float ConvertFloat(string value, float onNull = 0)
{
return float.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out float Result) ? Result : onNull;
}
private void ConvertWiltingData(SerializedProperty property, string value)
{
if (string.IsNullOrEmpty(value))
{
return;
}
void Apply(int initial, int cumulative, float weed, bool percent = true)
{
property.FindPropertyRelative("initialWiltChance").floatValue = percent ? Mathf.Clamp01(initial / ONE_HUNDRED_PERCENT) : initial;
property.FindPropertyRelative("cumulativeChanceIncrease").floatValue = percent ? Mathf.Clamp01(cumulative / ONE_HUNDRED_PERCENT) : cumulative;
property.FindPropertyRelative("weedMultiplier").floatValue = Mathf.Max(1, weed);
}
if (int.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out int integer))
{
if (integer <= 0)
{
Apply(0, 0, 0, false);
}
else
{
Apply(integer, 0, 2f, false);
}
}
else
{
const char plus = '+';
const string n = "n";
const string w = "w";
int initial = 5;
int cumulative = 0;
float weed = 2f;
string[] split = value.Split(plus);
for (int i = 0; i < split.Length; i++)
{
string str = split[i].Trim().ToLower();
bool foundcumulative = false;
bool foundweed = false;
if (split[i].Contains(n))
{
if (int.TryParse(str.Replace(n, string.Empty).Trim(), NumberStyles.Number, CultureInfo.InvariantCulture, out int nVal))
{
cumulative = nVal;
foundcumulative = true;
}
}
if (split[i].Contains(w))
{
if (int.TryParse(str.Replace(w, string.Empty).Trim(), NumberStyles.Number, CultureInfo.InvariantCulture, out int nVal))
{
weed = nVal;
foundweed = true;
}
}
if (!foundweed && !foundcumulative)
{
if (int.TryParse(str, NumberStyles.Number, CultureInfo.InvariantCulture, out int initVal))
{
initial = initVal;
}
}
}
Apply(initial, cumulative, weed);
}
}
[MenuItem("CONTEXT/GardenInventoryInformationData/Fix Assets")]
private static void FixSubAssets(MenuCommand command)
{
var assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(command.context))
.Select(o => o as GardenItemInformationData)
.Where(o => o != null)
.SelectMany(GetStages);
foreach (var item in assets)
{
Debug.Log(item.name);
}
}
private static IEnumerable<PlantStageData> GetStages(GardenItemInformationData data)
{
using (var serializedObject = new SerializedObject(data))
{
using (var stagesProperty = serializedObject.FindProperty("_Stages"))
{
for (int i = 0; i < stagesProperty.arraySize; i++)
{
using (var element = stagesProperty.GetArrayElementAtIndex(i))
{
var stage = element.objectReferenceValue as PlantStageData;
if (stage != null)
{
yield return stage;
}
}
}
}
}
}
[MenuItem("CONTEXT/GardenInventoryInformationData/Fix Seed Bumper Yields")]
private static void FixSeedBumoerYields(MenuCommand command)
{
var Assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(command.context))
.Select(o => o as GardenItemInformationData)
.Where(o => o != null)
.SelectMany(GetStages)
.Select(s => s as HarvestStageData)
.Where(s => s != null);
foreach (var Stage in Assets)
{
using var SerializedObject = new SerializedObject(Stage);
#pragma warning disable CS0618 // Type or member is obsolete
if (Stage.BumperData.BumperIsSeed)
#pragma warning restore CS0618 // Type or member is obsolete
{
using var CropBumperProperty = SerializedObject.FindProperty("cropBumper");
using var SeedBumperProperty = SerializedObject.FindProperty("seedBumper");
SeedBumperProperty.intValue = CropBumperProperty.intValue;
}
else
{
using var SeedBumperProperty = SerializedObject.FindProperty("seedBumper");
SeedBumperProperty.intValue = 0;
}
using (var BumperDataProperty = SerializedObject.FindProperty("_CropBumper"))
using (var IsSeedProperty = BumperDataProperty.FindPropertyRelative("BumperIsSeed"))
{
IsSeedProperty.boolValue = false;
}
SerializedObject.ApplyModifiedProperties();
}
}
}
}
#if UNITY_EDITOR
using UnityEditor;
#endif
using System;
using System.Collections.Generic;
using ItalicPig.PaleoPines.Importing;
using UnityEngine;
using UnityEngine.Serialization;
using Season = ItalicPig.PaleoPines.Global.Season;
using System.Linq;
using System.Text;
using ItalicPig.PaleoPines.UI;
namespace ItalicPig.PaleoPines.Inventories
{
public enum PlantGrowthStage
{
none = -1,
CROP_Seed,
CROP_Seedling,
CROP_Sprout,
CROP_Flowering,
CROP_Ripening,
CROP_Ripe,
CROP_Mature,
CROP_WitheredYoung,
CROP_WitheredMature,
TREE_Sprout,
TREE_Sapling,
TREE_Mature,
TREE_Flowering,
TREE_Picked,
TREE_Ripe,
BUSH_Seeded,
BUSH_Sprout,
BUSH_Sapling,
BUSH_Mature,
BUSH_Flowering,
BUSH_Picked,
BUSH_Ripe_Partial,
BUSH_Ripe_Full,
BUSH_Sparse,
BOTH_Dead,
count
}
public enum SoilType
{
Soft = 0,
Firm = 1,
Sticky = 2,
Plain = 3,
Any = 4,
Grass = 5,
none = -1
}
public enum HarvestAnimation
{
Low,
Medium,
High,
Shake
}
public class GardenItemInformationData : AdditionalItemInformationData
{
[SerializeField]
[ItemID(allowQualityLevels: false)]
[FormerlySerializedAs("produceID")]
private string _ProduceID = "";
[Space]
[SerializeField]
[FormerlySerializedAs("cropType")]
private CropType _CropType = CropType.Ground;
[SerializeField]
[AutoComplete("GetFamily")]
[FormerlySerializedAs("family")]
private string _Family = "";
[SerializeField]
[FormerlySerializedAs("season")]
private Season _Season = Season.Spring;
[SerializeField]
private GameRegion _Biome = GameRegion.None;
[Header("Soil")]
[SerializeField]
[FormerlySerializedAs("perfectSoil")]
private SoilType _PerfectSoil = SoilType.none;
[SerializeField]
[FormerlySerializedAs("badSoil")]
private SoilType _BadSoil = SoilType.none;
[SerializeField]
[FormerlySerializedAs("soilDepletion")]
private SoilType _SoilDepletion = SoilType.none;
[Header("Text")]
[SerializeField]
private string _GardeningTip;
[Header("Stages")]
[CSVItem(10, 20)]
[SerializeField]
[FormerlySerializedAs("stages")]
private PlantStageData[] _Stages = Array.Empty<PlantStageData>();
public int SeedYieldMinimum => 0;
public int SeedYieldMaximum => 0;
public string DefaultProduceID => _ProduceID;
public Season Season => _Season;
public GameRegion Biome => _Biome;
public SoilType PerfectSoil => _PerfectSoil;
public SoilType BadSoil => _BadSoil;
public SoilType SoilDepletion => _SoilDepletion;
public GameObject OnHearMusicParticlesPrefab => null;
public string[] GetFamily()
{
return new[] { "Rosaceae", "Solanaceae", "Cucurbiteae", "Apiaceae", "Asteraceae", "Brassicaceae", "Amaryllidaceae", "Poaceae", "Polygonaceae", "Amaranthaceae", "Bromeliaceae" };
}
public string Name => ItemDatabase.Items[_ProduceID].Uid;
public int StageCount => _Stages.Length;
public CropType CropType => _CropType;
public string Family { get => _Family; set => _Family = value; }
public string GetGardeningTip()
{
var key = $"item-{_ProduceID}-tip";
if (GameManager.Strings.ContainsKey(key))
{
return GameManager.Strings[key];
}
return _GardeningTip;
}
public IGrowthInfo GetStage(int index)
{
if (0 > index || index >= _Stages.Length)
{
return null;
}
return _Stages[index];
}
public bool TryGetStage(PlantGrowthStage stage, out IGrowthInfo info)
{
for (int i = 0; i < _Stages.Length; i++)
{
if (_Stages[i].CurrentStage == stage)
{
info = _Stages[i];
return true;
}
}
info = null;
return false;
}
public bool HasCropStages() => _Stages.Any(s => !s.IsTree && !s.IsBush);
public bool HasTreeStages() => _Stages.Any(s => s.IsTree);
public bool HasBushStages() => _Stages.Any(s => s.IsBush);
public bool HasStage<TStageInfo>() where TStageInfo : IGrowthInfo
{
for (int i = 0; i < _Stages.Length; i++)
{
if (_Stages[i] is TStageInfo)
{
return true;
}
}
return false;
}
public bool HasStage(PlantGrowthStage stage)
{
for (int i = 0; i < _Stages.Length; i++)
{
if (_Stages[i].CurrentStage == stage)
{
return true;
}
}
return false;
}
public string GetItemByQuality(int quality) => ItemDatabase.Items[_ProduceID].GetUidForQualityLevel(quality);
public string GetItemWithHighestQuality() => GetItemByQuality(ItemData.HighestQuality);
public string GetItemWithLowestQuality() => _ProduceID;
public string GetItemWithMiddleQuality() => GetItemByQuality(Mathf.RoundToInt(ItemData.HighestQuality / 2f));
private void OnValidate()
{
for (int i = 0; i < _Stages.Length; i++)
{
if (_Stages[i] == null)
{
var list = new List<PlantStageData>();
for (int j = 0; j < _Stages.Length; j++)
{
if (_Stages[j] != null)
{
list.Add(_Stages[j]);
}
}
_Stages = list.ToArray();
break;
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using ItalicPig.PaleoPines.Global;
using ItalicPig.PaleoPines.Inventories;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using Object = UnityEngine.Object;
namespace ItalicPig.PaleoPines.Editor.Inventory
{
[CustomEditor(typeof(GardenItemInformationData))]
[CanEditMultipleObjects]
public class GardenItemInformationDataEditor : AdditionalItemInformationDataEditor
{
protected override void OnEnable()
{
base.OnEnable();
if (serializedObject.targetObjects.Length == 1)
{
RefreshReorderableList();
}
}
protected override void OnDisable()
{
base.OnDisable();
reorderableList = null;
}
protected override void DrawProperties()
{
base.DrawProperties();
if (reorderableList != null && reorderableList.serializedProperty != null)
{
reorderableList.DoLayoutList();
}
}
protected override IEnumerable<string> GetExcludedProperties()
{
foreach (string baseItems in base.GetExcludedProperties())
{
yield return baseItems;
}
yield return "_Stages";
}
#region Private
private void RefreshReorderableList()
{
SerializedProperty stagesProperty = serializedObject.FindProperty("_Stages");
reorderableList = new ReorderableList(serializedObject, stagesProperty)
{
drawHeaderCallback = delegate (Rect rect)
{
EditorGUI.LabelField(rect, $"Stages \t{UI.Plantdex.CalculateDaysToMature((GardenItemInformationData)target)}");
},
drawElementCallback = DrawElementCallback,
onReorderCallback = OnReorderCallback,
onAddDropdownCallback = OnAddDropdownCallback,
onRemoveCallback = OnRemoveCallback
};
}
private void DrawElementCallback(Rect rect, int index, bool isActive, bool isFocused)
{
var stagesProperty = reorderableList.serializedProperty;
using (var elementProperty = stagesProperty.GetArrayElementAtIndex(index))
{
var stageData = elementProperty.objectReferenceValue;
if (stageData == null)
{
EditorGUI.LabelField(rect, "ERROR");
return;
}
var openContent = new GUIContent("Open");
var openStyle = new GUIStyle(EditorStyles.miniButton);
var openSize = openStyle.CalcSize(openContent);
var openWidth = openSize.x + 50f;
var rWidth = (rect.width - openWidth) / 3f;
var r1Rect = new Rect(rect.x, rect.y, rWidth, rect.height);
var r2Rect = new Rect(rect.x + rWidth, rect.y, rWidth, rect.height);
var r3Rect = new Rect(rect.x + rWidth + rWidth, rect.y, rWidth, rect.height);
var lRect = new Rect(
rect.x + rect.width - openWidth,
rect.y + Mathf.Floor((rect.height - openSize.y) * 0.5f),
openWidth,
rect.height);
using (var stageDataSerializedObject = new SerializedObject(stageData))
{
EditorGUI.LabelField(r1Rect, getName(stageDataSerializedObject));
EditorGUI.LabelField(r2Rect, getType(stageData, out var typeCol), getStyle(typeCol));
EditorGUI.LabelField(r3Rect, getSeason(stageData as IGrowthInfo, out var styleCol), getStyle(styleCol));
}
if (GUI.Button(lRect, openContent, openStyle))
{
Selection.objects = new[] { stageData };
}
}
string getName(SerializedObject stageDataSerializedObject)
{
string enumName;
using (var property = stageDataSerializedObject.FindProperty("_Stage"))
{
enumName = property.enumNames[property.enumValueIndex];
}
var split = enumName.Split('_');
var type = split.First();
var stageName = split.Skip(1);
return $"{type.ToUpper()}: {Helper.CamelCaseToTitle(string.Join(" ", stageName.ToArray()))}";
}
string getSeason(IGrowthInfo growthInfo, out Color color)
{
if (growthInfo == null || !growthInfo.OnlyEnterStageDuringSeason)
{
color = Color.gray;
return "Any Season";
}
string season = growthInfo.SeasonAllowedToEnterOn.ToString();
switch (growthInfo.SeasonAllowedToEnterOn)
{
case Season.Spring:
color = Color.green;
break;
case Season.Summer:
color = Color.yellow;
break;
case Season.Autumn:
color = new Color(1, 0.4f, 0);
break;
default:
color = Color.gray;
break;
}
if (growthInfo.OnlyEnterStageDuringLastWeekOfSeason)
{
season = $"Last week of {season}";
}
return season;
}
string getType(object stageData, out Color color)
{
if (stageData is WitherYoungStageData || stageData is WitherStageData)
{
color = Color.black;
return "Wither";
}
if (stageData is HarvestStageData)
{
color = Color.red;
return "Harvest";
}
if (stageData is GrowingStageData)
{
color = new Color(0, 0.7f, 0.1f);
return "Growing";
}
if (stageData is SparseStageData)
{
color = Color.gray;
return "Sparse";
}
color = Color.gray;
return "n/a";
}
GUIStyle getStyle(Color color)
{
var style = new GUIStyle(EditorStyles.label);
style.ToAllStyleStates(s => s.textColor = color);
return style;
}
}
private void OnAddDropdownCallback(Rect buttonRect, ReorderableList list)
{
var stagesProperty = reorderableList.serializedProperty;
var menu = new GenericMenu();
int j;
var values = Enum.GetValues(typeof(PlantGrowthStage));
foreach (PlantGrowthStage value in values)
{
if (value == PlantGrowthStage.count || value == PlantGrowthStage.none || value == PlantGrowthStage.BOTH_Dead)
{
continue;
}
string stage = value.ToString();
bool exists = false;
for (j = 0; j < stagesProperty.arraySize; j++)
{
using (var elementProperty = stagesProperty.GetArrayElementAtIndex(j))
using (var stageDataSerializedObject = new SerializedObject(elementProperty.objectReferenceValue))
using (var stageProperty = stageDataSerializedObject.FindProperty("_Stage"))
{
if (stage.Equals(stageProperty.enumNames[stageProperty.enumValueIndex]))
{
exists = true;
break;
}
}
}
var menuPath = string.Join("/", stage.Split('_')
.Select(b => char.ToUpper(b[0]) + b.Substring(1).ToLower())
.ToArray());
var menuPathContent = new GUIContent(menuPath);
if (exists)
{
menu.AddDisabledItem(menuPathContent);
}
else
{
menu.AddItem(menuPathContent,
false,
OnAdd,
value);
}
}
menu.DropDown(buttonRect);
}
private void OnAdd(object userData)
{
var stage = (PlantGrowthStage)userData;
var stageStr = stage.ToString();
var stagesProperty = reorderableList.serializedProperty;
var indexToAdd = reorderableList.index == -1 ? stagesProperty.arraySize : reorderableList.index + 1;
stagesProperty.InsertArrayElementAtIndex(indexToAdd);
var newType = GetTypeOfStage(stage);
var newObj = ScriptableObject.CreateInstance(newType);
AssetDatabase.AddObjectToAsset(newObj, target);
newObj.name = serializedObject.targetObject.name + " (" + indexToAdd + ": " + stageStr + ")";
using (var newSerializedObject = new SerializedObject(newObj))
{
using (var uniqueIDProperty = newSerializedObject.FindProperty("_ProduceID"))
using (var existingUniqueID = serializedObject.FindProperty("_Uid"))
{
uniqueIDProperty.stringValue = existingUniqueID.stringValue;
}
using (var indexProperty = newSerializedObject.FindProperty("_Index"))
{
indexProperty.intValue = indexToAdd;
}
using (var stageProperty = newSerializedObject.FindProperty("_Stage"))
{
stageProperty.SetEnumValue(stage);
}
if (newObj is GrowingStageData)
{
using (var stageLengthProperty = newSerializedObject.FindProperty("stageLength"))
{
stageLengthProperty.intValue = stage.IsCrop() ? 1 : 7;
}
using (var chanceOfWeedsProperty = newSerializedObject.FindProperty("chanceOfWeeds"))
{
chanceOfWeedsProperty.floatValue = stage.IsCrop() ? 0.2f : 0f;
}
using (var chanceOfWeedsProperty = newSerializedObject.FindProperty("chanceOfWeeds"))
{
chanceOfWeedsProperty.floatValue = stage.IsCrop() ? 0.2f : 0f;
}
using (var startScaleProperty = newSerializedObject.FindProperty("startScale"))
{
startScaleProperty.floatValue =
stage == PlantGrowthStage.TREE_Sprout ? 1f :
stage == PlantGrowthStage.TREE_Sapling ? 0.75f :
1f;
}
using (var endScaleProperty = newSerializedObject.FindProperty("endScale"))
{
endScaleProperty.floatValue =
stage == PlantGrowthStage.TREE_Sprout ? 1.5f :
stage == PlantGrowthStage.TREE_Sprout ? 2f :
1f;
}
using (var enterableViaTimelineProperty = newSerializedObject.FindProperty("enterableViaTimeline"))
{
enterableViaTimelineProperty.boolValue = stage != PlantGrowthStage.CROP_Mature && stage != PlantGrowthStage.TREE_Mature && stage != PlantGrowthStage.BUSH_Mature && stage != PlantGrowthStage.BUSH_Sparse;
}
using (var onlyEnterStageDuringSeasonProperty = newSerializedObject.FindProperty("_OnlyEnterStageDuringSeason"))
{
onlyEnterStageDuringSeasonProperty.boolValue = stage == PlantGrowthStage.TREE_Ripe || stage == PlantGrowthStage.BUSH_Ripe_Partial || stage == PlantGrowthStage.BUSH_Ripe_Full;
}
}
if (newObj is HarvestStageData)
{
using (var infiniteHarvestProperty = newSerializedObject.FindProperty("infiniteHarvest"))
{
infiniteHarvestProperty.boolValue = stage == PlantGrowthStage.TREE_Ripe || stage == PlantGrowthStage.BUSH_Ripe_Partial || stage == PlantGrowthStage.BUSH_Ripe_Full;
}
using (var numberOfHarvestProperty = newSerializedObject.FindProperty("numberOfHarvest"))
{
numberOfHarvestProperty.intValue = stage == PlantGrowthStage.TREE_Ripe || stage == PlantGrowthStage.BUSH_Ripe_Partial || stage == PlantGrowthStage.BUSH_Ripe_Full ? 0 : 1;
}
using (var infiniteHarvestProperty = newSerializedObject.FindProperty("stageToGoToOnHarvest"))
{
infiniteHarvestProperty.SetEnumValue(stage == PlantGrowthStage.TREE_Ripe ? PlantGrowthStage.TREE_Mature : stage == PlantGrowthStage.BUSH_Ripe_Partial || stage == PlantGrowthStage.BUSH_Ripe_Full ? PlantGrowthStage.BUSH_Mature : PlantGrowthStage.CROP_Mature);
}
using (var harvestAnimationProperty = newSerializedObject.FindProperty("harvestAnimation"))
{
harvestAnimationProperty.SetEnumValue(stage == PlantGrowthStage.TREE_Ripe ? HarvestAnimation.Shake : HarvestAnimation.Low);
}
}
if (newObj is BushHarvestStageData)
{
using (var bushDataProperty = newSerializedObject.FindProperty("_BushData"))
{
using (var harvestChanceProperty = bushDataProperty.FindPropertyRelative("HarvestChance"))
{
harvestChanceProperty.floatValue = 0.25f;
}
using (var harvestChanceWithMusicProperty = bushDataProperty.FindPropertyRelative("HarvestChanceWithMusic"))
{
harvestChanceWithMusicProperty.floatValue = 0.5f;
}
}
}
newSerializedObject.ApplyModifiedProperties();
}
using (var newProperty = stagesProperty.GetArrayElementAtIndex(indexToAdd))
{
newProperty.objectReferenceValue = newObj;
}
ResyncIndices(stagesProperty);
reorderableList.index = indexToAdd;
serializedObject.ApplyModifiedProperties();
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
AssetDatabase.Refresh();
}
private void OnRemoveCallback(ReorderableList list)
{
//ReorderableList.defaultBehaviours.DoRemoveButton(list);
if (0 > list.index || list.index >= list.serializedProperty.arraySize)
{
return;
}
list.serializedProperty.DeleteArrayElementAtIndex(list.index);
list.serializedProperty.serializedObject.ApplyModifiedProperties();
DeleteUnusedAssets();
RefreshReorderableList();
Repaint();
}
private void OnReorderCallback(ReorderableList list)
{
ResyncIndices(reorderableList.serializedProperty);
}
private void DeleteUnusedAssets()
{
Object[] loaded = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(target));
IEnumerable<Object> existingStages = loaded.Where(a => a is PlantStageData);
IEnumerable<PlantStageData> referencedStages = loaded.Where(a => a is GardenItemInformationData).SelectMany(GetStagesFromAsset);
if (referencedStages.Any() ||
EditorUtility.DisplayDialog("Error", "Could not find any referenced stages at all in this asset. Something may have gone wrong!", "Continue", "Cancel"))
{
IEnumerable<Object> except = existingStages.Except(referencedStages);
if (except.Any())
{
foreach (Object item in except)
{
UnityEngine.Object.DestroyImmediate(item, true);
}
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
AssetDatabase.Refresh();
Repaint();
}
}
}
private void ResyncIndices(SerializedProperty stagesProperty)
{
bool reImportNeeded = false;
for (int i = 0; i < stagesProperty.arraySize; i++)
{
using (var elementProperty = stagesProperty.GetArrayElementAtIndex(i))
{
Object stageData = elementProperty.objectReferenceValue;
using (var stageDataSerializedObject = new SerializedObject(stageData))
{
using (var stageProperty = stageDataSerializedObject.FindProperty("_Index"))
{
if (stageProperty.intValue != i)
{
stageProperty.intValue = i;
stageDataSerializedObject.ApplyModifiedProperties();
}
using (var stageEnumProperty = stageDataSerializedObject.FindProperty("_Stage"))
{
string newName = serializedObject.targetObject.name + " (" + stageProperty.intValue + ": " + stageEnumProperty.GetEnumValue<PlantGrowthStage>().ToString() + ")";
if (!stageData.name.Equals(newName))
{
stageData.name = newName;
reImportNeeded = true;
}
}
}
}
}
}
if (reImportNeeded)
{
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
AssetDatabase.Refresh();
}
}
private Type GetTypeOfStage(PlantGrowthStage stage)
{
switch (stage)
{
case PlantGrowthStage.CROP_Ripe:
case PlantGrowthStage.TREE_Ripe:
return typeof(HarvestStageData);
case PlantGrowthStage.BUSH_Ripe_Partial:
case PlantGrowthStage.BUSH_Ripe_Full:
return typeof(BushHarvestStageData);
case PlantGrowthStage.BUSH_Sparse:
return typeof(SparseStageData);
case PlantGrowthStage.CROP_WitheredYoung:
return typeof(WitherYoungStageData);
case PlantGrowthStage.CROP_WitheredMature:
return typeof(WitherStageData);
}
return typeof(GrowingStageData);
}
private IEnumerable<PlantStageData> GetStagesFromAsset(Object asset)
{
using (var assetSerializedObject = new SerializedObject(asset))
{
using (var stagesSerializedProperty = assetSerializedObject.FindProperty("_Stages"))
{
if (stagesSerializedProperty != null)
{
for (int i = 0; i < stagesSerializedProperty.arraySize; i++)
{
using (var elementSerializedProperty = stagesSerializedProperty.GetArrayElementAtIndex(i))
{
var plantStageData = elementSerializedProperty.objectReferenceValue as PlantStageData;
if (plantStageData != null)
{
yield return plantStageData;
}
}
}
}
}
}
}
private ReorderableList reorderableList = null;
#endregion
}
}
using ItalicPig.PaleoPines.Global;
using UnityEngine;
using UnityEngine.Serialization;
namespace ItalicPig.PaleoPines.Inventories
{
public class GrowingStageData : PlantStageData, IGrowableGrowthInfo
{
public bool MaturesOld => maturesOld;
public int StageLength => lengthAsSeasons ? Mathf.RoundToInt(CalendarData.DaysPerSeason * seasonLength) : stageLength;
public float ChanceOfWeeds => chanceOfWeeds;
public WiltingData WiltingInfo => wiltingInfo;
public BoostData BoostInfo => boostInfo;
public override bool IsEnterableViaTimeline => enterableViaTimeline;
public float StartScale => startScale;
public float EndScale => endScale;
public override bool OnlyEnterStageDuringSeason => _OnlyEnterStageDuringSeason;
public override Season SeasonAllowedToEnterOn => _SeasonAllowedToEnterOn;
public override bool OnlyEnterStageDuringLastWeekOfSeason => _LastWeekOfSeason;
public override bool GoToAnotherStageIfOutOfSeason => _GoToAnotherStage;
public override PlantGrowthStage StageToGoAfterSeason => _GoToAnotherStage ? _StageToGoAfterSeason : PlantGrowthStage.none;
public override bool TryNextStageIfOutOfSeason => _TryNextStageIfOutOfSeason;
public override bool NeedsWatering
{
get
{
switch (CurrentStage)
{
case PlantGrowthStage.none:
case PlantGrowthStage.CROP_Seed:
case PlantGrowthStage.TREE_Sprout:
case PlantGrowthStage.TREE_Sapling:
case PlantGrowthStage.TREE_Mature:
case PlantGrowthStage.TREE_Picked:
case PlantGrowthStage.TREE_Flowering:
case PlantGrowthStage.TREE_Ripe:
case PlantGrowthStage.BUSH_Seeded:
case PlantGrowthStage.BUSH_Sprout:
case PlantGrowthStage.BUSH_Sapling:
case PlantGrowthStage.BUSH_Flowering:
case PlantGrowthStage.BUSH_Ripe_Partial:
case PlantGrowthStage.BUSH_Ripe_Full:
case PlantGrowthStage.BUSH_Mature:
case PlantGrowthStage.BUSH_Sparse:
case PlantGrowthStage.BOTH_Dead:
case PlantGrowthStage.count:
return false;
default:
return WiltingInfo.InitialWiltChance > 0 || WiltingInfo.CumulativeChanceIncrease > 0;
}
}
}
#region Serailized Variables
[SerializeField]
[MinMaxPair("endScale")]
private float startScale = 1f;
[SerializeField]
[MinMaxPair("startScale", "Start", "End", 0, 2, "Scale over Lifetime")]
private float endScale = 1f;
[Header("Growing Info")]
[SerializeField]
private bool maturesOld = false;
[SerializeField]
private bool lengthAsSeasons = false;
[SerializeField, Toggle("lengthAsSeasons", invert = true)]
private int stageLength = 1;
[SerializeField, Toggle("lengthAsSeasons", invert = false)]
private float seasonLength = 0.5f;
[SerializeField, Range(0f, 1f)]
private float chanceOfWeeds = 0.2f;
[SerializeField]
private WiltingData wiltingInfo;
[SerializeField]
private BoostData boostInfo = BoostData.Default;
[Header("Staging info")]
[SerializeField]
private bool enterableViaTimeline = true;
[SerializeField]
private bool _OnlyEnterStageDuringSeason;
[SerializeField, Toggle("_OnlyEnterStageDuringSeason")]
private Season _SeasonAllowedToEnterOn;
[SerializeField, Toggle("_OnlyEnterStageDuringSeason")]
private bool _LastWeekOfSeason;
[SerializeField, Toggle("_OnlyEnterStageDuringSeason")]
private bool _GoToAnotherStage;
[SerializeField, Toggle("_GoToAnotherStage")]
[FormerlySerializedAs("_StageToGoWhenOutOfSeason")]
private PlantGrowthStage _StageToGoAfterSeason = PlantGrowthStage.none;
[SerializeField, Toggle("_OnlyEnterStageDuringSeason")]
[FormerlySerializedAs("_StageToGoWhenOutOfSeason")]
private bool _TryNextStageIfOutOfSeason;
#endregion
#region Unity Message
private void OnValidate()
{
stageLength = Mathf.Max(0, stageLength);
seasonLength = Mathf.Max(0, seasonLength);
}
#endregion
}
}
using UnityEngine;
using UnityEngine.Serialization;
namespace ItalicPig.PaleoPines.Inventories
{
public class HarvestStageData : GrowingStageData, IHarvestStageGrowthInfo
{
[Header("Harvest Info")]
[SerializeField, FormerlySerializedAs("harvestAnimation")]
private HarvestAnimation _HarvestAnimation = HarvestAnimation.Low;
[SerializeField, FormerlySerializedAs("vfxPrefab")]
private GameObject _VfxPrefab = null;
[SerializeField, FormerlySerializedAs("vfxOffset")]
private Vector3 _VfxOffset = Vector3.zero;
[Space]
[SerializeField, FormerlySerializedAs("numberOfHarvest")]
private int _NumberOfReharvests = 1;
[SerializeField, FormerlySerializedAs("infiniteHarvest")]
private bool _InfiniteHarvest = false;
[SerializeField, FormerlySerializedAs("stageToGoToOnHarvest")]
private PlantGrowthStage _StageToGoToOnHarvest = PlantGrowthStage.none;
[Header("Yield")]
[SerializeField, FormerlySerializedAs("cropYieldMin"), MinMaxPair("_CropYieldMax")]
private int _CropYieldMin = 1;
[SerializeField, FormerlySerializedAs("cropYieldMax"), MinMaxPair("_CropYieldMin", "Min", "Max", 0, 20, "Crop Yield")]
private int _CropYieldMax = 1;
[SerializeField, FormerlySerializedAs("cropBumper")]
private int _CropBumper = 1;
[SerializeField, FormerlySerializedAs("seedBumper")]
private int _SeedBumper = 1;
[Space]
[SerializeField, FormerlySerializedAs("bumper"), FormerlySerializedAs("_CropBumper")]
private BumperData _BumperData = BumperData.Default;
public int NumberOfReharvests => _NumberOfReharvests;
public PlantGrowthStage StageToGoToOnHarvest => _StageToGoToOnHarvest;
public bool InfiniteHarvest => _InfiniteHarvest;
public int CropYieldMinimum => _CropYieldMin;
public int CropYieldMaximum => _CropYieldMax;
public int BumperCropYieldMinimum => _CropBumper;
public int BumperCropYieldMaximum => _CropBumper;
public int BumperSeedYieldMinimum => _SeedBumper;
public int BumperSeedYieldMaximum => _SeedBumper;
public BumperData BumperData => _BumperData;
public HarvestAnimation HarvestAnimation => _HarvestAnimation;
public GameObject VFXPrefab => _VfxPrefab;
public Vector3 VFXOffset => _VfxOffset;
}
}
namespace ItalicPig.PaleoPines.Inventories
{
public interface IGrowableGrowthInfo : IGrowthInfo
{
bool MaturesOld { get; }
int StageLength { get; }
float ChanceOfWeeds { get; }
WiltingData WiltingInfo { get; }
BoostData BoostInfo { get; }
float StartScale { get; }
float EndScale { get; }
}
}
using ItalicPig.PaleoPines.Global;
using UnityEngine;
namespace ItalicPig.PaleoPines.Inventories
{
public interface IGrowthInfo
{
int Index { get; }
PlantGrowthStage CurrentStage { get; }
GameObject Prefab { get; }
bool IsTree { get; }
bool IsBush { get; }
bool NeedsWatering { get; }
bool CanBeFertilized { get; }
bool IsEnterableViaTimeline { get; }
bool OnlyEnterStageDuringSeason { get; }
bool OnlyEnterStageDuringLastWeekOfSeason { get; }
Season SeasonAllowedToEnterOn { get; }
bool GoToAnotherStageIfOutOfSeason { get; }
PlantGrowthStage StageToGoAfterSeason { get; }
bool TryNextStageIfOutOfSeason { get; }
void InitialiseCache();
void DawnEvent();
void ReCacheOrDestroy(GameObject gameObject);
GameObject GetPrefab(out bool isInstantiated);
bool CanEnterSeason(int gameDay);
}
}
using UnityEngine;
namespace ItalicPig.PaleoPines.Inventories
{
public interface IHarvestableStage
{
HarvestAnimation HarvestAnimation { get; }
GameObject VFXPrefab { get; }
Vector3 VFXOffset { get; }
}
}
namespace ItalicPig.PaleoPines.Inventories
{
public interface IHarvestStageGrowthInfo : IGrowableGrowthInfo, IHarvestableStage
{
int NumberOfReharvests { get; }
PlantGrowthStage StageToGoToOnHarvest { get; }
bool InfiniteHarvest { get; }
int CropYieldMinimum { get; }
int CropYieldMaximum { get; }
int BumperCropYieldMinimum { get; }
int BumperCropYieldMaximum { get; }
int BumperSeedYieldMinimum { get; }
int BumperSeedYieldMaximum { get; }
BumperData BumperData { get; }
}
}
using System;
using System.Collections.Generic;
using System.Globalization;
using ItalicPig.PaleoPines.Audio;
using ItalicPig.PaleoPines.Global;
using UnityEditor;
using UnityEngine;
namespace ItalicPig.PaleoPines.Inventories
{
public class ItemData : ScriptableObject
{
public string Uid => _Uid;
public FoodItemInformationData FoodInfo => _AdditionalData.FoodInfo;
public EdibleItemInformationData EdibleInfo => _AdditionalData.EdibleInfo;
public DecorItemInformationData DecorInfo => _AdditionalData.DecorInfo;
public GardenItemInformationData GardenInfo => _AdditionalData.GardenInfo;
public FertiliserItemInformationData FertiliserInfo => _AdditionalData.FertiliserInfo;
public WildCropItemInformationData WildCropInfo => _AdditionalData.WildCropInfo;
public string DisplayNameStringKey => $"item-{BaseUid}";
public string DisplayDescriptionStringKey => $"item-{BaseUid}-desc";
public string GetDisplayName(bool noMessageIfNoKey = false)
{
#if UNITY_EDITOR
if (!Application.isPlaying && !GameManager.Strings.ContainsKey(DisplayNameStringKey))
{
return ObjectNames.NicifyVariableName(BaseUid);
}
#endif
if (noMessageIfNoKey && !GameManager.Strings.ContainsKey(DisplayNameStringKey))
{
return $"*{DisplayNameStringKey}*";
}
return GameManager.Strings[DisplayNameStringKey];
}
public string GetDisplayDescription()
{
return GameManager.Strings[DisplayDescriptionStringKey];
}
#region Private
#region Private
[SerializeField]
[Tooltip("Each item must have a unique identifier, e.g. 'shovel' or 'medium-trough'.")]
private string _Uid = "";
// Additional data - separate assets which are generated from a spreadsheet
[Serializable]
private struct AdditionalData
{
public FoodItemInformationData FoodInfo;
public EdibleItemInformationData EdibleInfo;
public DecorItemInformationData DecorInfo;
public GardenItemInformationData GardenInfo;
public FertiliserItemInformationData FertiliserInfo;
public WildCropItemInformationData WildCropInfo;
}
[Header("Additional Data")]
[SerializeField]
private AdditionalData _AdditionalData;
#endregion
}
}
namespace ItalicPig.PaleoPines.Inventories
{
public interface IWitherStageGrowthInfo : IGrowthInfo, IHarvestableStage
{
}
}
#if UNITY_EDITOR
#define USE_EDITOR
#endif
using System.Collections.Generic;
using ItalicPig.PaleoPines.Global;
using UnityEngine;
using UnityEngine.Serialization;
namespace ItalicPig.PaleoPines.Inventories
{
[System.Serializable]
public abstract class PlantStageData : ScriptableObject, IGrowthInfo
{
private const int NUMBER_OF_PREFABS_TO_CACHE = 4;
private static Transform cacheParent;
[SerializeField, ReadOnly]
[FormerlySerializedAs("uniqueID")]
private string _ProduceID;
[SerializeField, ReadOnly]
[FormerlySerializedAs("index")]
private int _Index;
[Space]
[SerializeField]
[FormerlySerializedAs("stage")]
private PlantGrowthStage _Stage;
[SerializeField]
private bool _CanBeFertilized;
[Header("GameObject")]
[SerializeField]
[FormerlySerializedAs("prefab")]
private GameObject _Prefab;
public int Index => _Index;
public PlantGrowthStage CurrentStage => _Stage;
public bool CanBeFertilized => _CanBeFertilized;
public GameObject Prefab => _Prefab;
private Stack<GameObject> prefabCache = null;
public bool IsTree => CurrentStage.IsTree();
public bool IsBush => CurrentStage.IsBush();
public virtual bool NeedsWatering => false;
public virtual bool IsEnterableViaTimeline => true;
public virtual bool OnlyEnterStageDuringSeason => false;
public virtual Season SeasonAllowedToEnterOn => Season.Spring;
public virtual bool OnlyEnterStageDuringLastWeekOfSeason => false;
public virtual bool GoToAnotherStageIfOutOfSeason => false;
public virtual bool TryNextStageIfOutOfSeason => false;
public virtual PlantGrowthStage StageToGoAfterSeason => PlantGrowthStage.none;
public void InitialiseCache()
{
if (Prefab == null)
{
return;
}
if (cacheParent == null)
{
var CacheGameObject = new GameObject("[PLANT MODEL CACHE]");
DontDestroyOnLoad(CacheGameObject);
cacheParent = CacheGameObject.transform;
}
if (prefabCache == null)
{
prefabCache = new Stack<GameObject>(NUMBER_OF_PREFABS_TO_CACHE);
}
TimeMaster.MorningEvent += DawnEvent;
}
public void DawnEvent()
{
if (cacheParent == null)
{
return;
}
int count = prefabCache.Count;
for (int i = count; i < NUMBER_OF_PREFABS_TO_CACHE; i++)
{
ReCacheOrDestroy(Instantiate(Prefab, cacheParent));
}
}
public void ReCacheOrDestroy(GameObject gameObject)
{
if (gameObject == null)
{
return;
}
if (prefabCache == null || prefabCache.Count >= NUMBER_OF_PREFABS_TO_CACHE)
{
Destroy(gameObject);
return;
}
gameObject.SetActive(false);
gameObject.transform.SetParent(cacheParent);
prefabCache.Push(gameObject);
}
public GameObject GetPrefab(out bool isInstantiated)
{
if (prefabCache != null)
{
while (prefabCache.Count > 0)
{
GameObject instantiated = prefabCache.Pop();
if (instantiated != null)
{
instantiated.SetActive(true);
isInstantiated = true;
return instantiated;
}
}
}
isInstantiated = false;
return Prefab;
}
public virtual bool CanEnterSeason(int gameDay)
{
if (!OnlyEnterStageDuringSeason)
{
return true;
}
var currentSeason = CalendarData.GetSeason(gameDay);
if (currentSeason != SeasonAllowedToEnterOn)
{
return false;
}
if (OnlyEnterStageDuringLastWeekOfSeason)
{
var dayOfWeek = CalendarData.GetDayInSeason(gameDay);
var dayOfLastWeek = CalendarData.DaysPerSeason - CalendarData.DaysPerWeek;
var inFinalWeek = dayOfWeek >= dayOfLastWeek;
if (!inFinalWeek)
{
return false;
}
}
return true;
}
}
}
using UnityEditor;
using UnityEngine;
namespace ItalicPig.PaleoPines.Inventories
{
[CanEditMultipleObjects]
[CustomEditor(typeof(PlantStageData), editorForChildClasses: true)]
public class PlantStageDataEditor : UnityEditor.Editor
{
private void OnEnable()
{
string MyUniqueID;
int MyIndex;
using (var UniqueIDProperty = serializedObject.FindProperty("_ProduceID"))
{
MyUniqueID = UniqueIDProperty.stringValue;
}
using (var IndexProperty = serializedObject.FindProperty("_Index"))
{
MyIndex = IndexProperty.intValue;
}
var MainAsset = GetAsset();
if (MainAsset != null)
{
using var MainSerializedObject = new SerializedObject(MainAsset);
using var InfoDataArrayProperty = MainSerializedObject.FindProperty("_infoData");
for (int i = 0; i < InfoDataArrayProperty.arraySize; i++)
{
Object Plant;
using (var InfoDataProperty = InfoDataArrayProperty.GetArrayElementAtIndex(i))
{
Plant = InfoDataProperty.objectReferenceValue;
}
using var InfoDataSerializedObject = new SerializedObject(Plant);
using (var UniqueIDProperty = InfoDataSerializedObject.FindProperty("_Uid"))
{
if (string.CompareOrdinal(UniqueIDProperty.stringValue, MyUniqueID) != 0)
{
continue;
}
}
_ParentPlant = Plant;
_CentreButtonContent = new GUIContent(Plant.name);
using var StagesProperty = InfoDataSerializedObject.FindProperty("_Stages");
if (MyIndex > 0)
{
using var PreviousProperty = StagesProperty.GetArrayElementAtIndex(MyIndex - 1);
_PreviousStage = PreviousProperty.objectReferenceValue;
_LeftButtonContent = new GUIContent($"Previous:\n{_PreviousStage.name}");
}
else
{
_PreviousStage = null;
_LeftButtonContent = GUIContent.none;
}
if (MyIndex < StagesProperty.arraySize - 1)
{
using var NextProperty = StagesProperty.GetArrayElementAtIndex(MyIndex + 1);
_NextStage = NextProperty.objectReferenceValue;
_RightButtonContent = new GUIContent($"Next:\n{_NextStage.name}");
}
else
{
_NextStage = null;
_RightButtonContent = GUIContent.none;
}
break;
}
}
}
private Object GetAsset()
{
var Path = AssetDatabase.GetAssetPath(target);
var MainAsset = AssetDatabase.LoadMainAssetAtPath(Path);
if (MainAsset is GardenInventoryInformationData)
{
return MainAsset;
}
foreach (var Item in AssetDatabase.LoadAllAssetsAtPath(Path))
{
if (Item is GardenInventoryInformationData)
{
return MainAsset;
}
}
return null;
}
public override void OnInspectorGUI()
{
if (_LeftStyle == null || _CentreStyle == null || _RightStyle == null || _LeftTab == null || _RightTab == null)
{
_LeftTab = new GUIContent(EditorGUIUtility.FindTexture("tab_prev"));
_RightTab = new GUIContent(EditorGUIUtility.FindTexture("tab_next"));
var HeaderStyle = new GUIStyle("IN BigTitle")
{
fontStyle = FontStyle.Bold
};
HeaderStyle.padding = new RectOffset(HeaderStyle.padding.left + 5, HeaderStyle.padding.right, HeaderStyle.padding.top, HeaderStyle.padding.bottom);
_LeftStyle = new GUIStyle(HeaderStyle)
{
alignment = TextAnchor.MiddleLeft
};
_CentreStyle = new GUIStyle(HeaderStyle)
{
alignment = TextAnchor.MiddleCenter
};
_RightStyle = new GUIStyle(HeaderStyle)
{
alignment = TextAnchor.MiddleRight,
imagePosition = ImagePosition.ImageAbove
};
}
EditorGUI.BeginChangeCheck();
float Y = 0;
float YSize = Mathf.Max(
_LeftButtonContent == null ? 0 : _LeftStyle.CalcSize(_LeftButtonContent).y,
_CentreButtonContent == null ? 0 : _CentreStyle.CalcSize(_CentreButtonContent).y,
_RightButtonContent == null ? 0 : _RightStyle.CalcSize(_RightButtonContent).y,
EditorGUIUtility.singleLineHeight);
float TabX = (_LeftStyle.CalcSize(_LeftTab).x + _RightStyle.CalcSize(_RightTab).x) * 0.5f;
float Height = YSize * 1.25f;
float Width = Screen.width / 3;
if (_ParentPlant == null)
{
var DeleteContent = new GUIContent("No parent found. Click here to delete");
YSize = Mathf.Max(YSize, _CentreStyle.CalcSize(DeleteContent).y);
if (GUI.Button(new Rect(0, 0, Screen.width, YSize), DeleteContent, _CentreStyle))
{
if (EditorUtility.DisplayDialog("Delete", "Are you sure you want to delete this asset?", "Yes", "No"))
{
var Path = AssetDatabase.GetAssetPath(target);
Selection.objects = new Object[] { AssetDatabase.LoadMainAssetAtPath(Path) };
UnityEngine.Object.DestroyImmediate(target, true);
AssetDatabase.ImportAsset(Path);
AssetDatabase.Refresh();
return;
}
}
}
else
{
if (_PreviousStage != null)
{
if (GUI.Button(new Rect(0, Y, TabX, Height), _LeftTab, _LeftStyle) ||
GUI.Button(new Rect(TabX, Y, Width - TabX, Height), _LeftButtonContent, _LeftStyle))
{
Selection.objects = new Object[] { _PreviousStage };
}
}
else
{
GUI.Box(new Rect(0, Y, Width, Height), GUIContent.none, _LeftStyle);
}
if (GUI.Button(new Rect(Width, Y, Width, Height), _CentreButtonContent, _CentreStyle))
{
Selection.objects = new Object[] { _ParentPlant };
}
if (_NextStage != null)
{
if (GUI.Button(new Rect(Width + Width, Y, Width - TabX, Height), _RightButtonContent, _RightStyle) ||
GUI.Button(new Rect(Width + Width + Width - TabX, Y, TabX, Height), _RightTab, _RightStyle))
{
Selection.objects = new Object[] { _NextStage };
}
}
else
{
GUI.Box(new Rect(Width + Width, Y, Width, Height), GUIContent.none, _LeftStyle);
}
}
GUILayout.Space(Height);
DrawPropertiesExcluding(serializedObject, "m_Script");
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
}
}
private GUIStyle _LeftStyle;
private GUIStyle _CentreStyle;
private GUIStyle _RightStyle;
private GUIContent _LeftTab;
private GUIContent _RightTab;
private GUIContent _LeftButtonContent;
private GUIContent _CentreButtonContent;
private GUIContent _RightButtonContent;
private Object _ParentPlant;
private Object _PreviousStage;
private Object _NextStage;
}
}
using UnityEngine;
using UnityEngine.Serialization;
namespace ItalicPig.PaleoPines.Inventories
{
public class WitherStageData : PlantStageData, IWitherStageGrowthInfo
{
#pragma warning disable CS0414
[Header("Harvest")]
[SerializeField, MinMaxPair("_SeedYieldMax")]
[FormerlySerializedAs("seedYieldMin")]
private int _SeedYieldMin = 1;
[SerializeField, MinMaxPair("_SeedYieldMin", "Min", "Max", 0, 10, "Seed Yield")]
[FormerlySerializedAs("seedYieldMax")]
private int _SeedYieldMax = 1;
[Space]
[SerializeField]
[FormerlySerializedAs("harvestAnimation")]
private HarvestAnimation _HarvestAnimation = HarvestAnimation.Low;
[SerializeField]
[FormerlySerializedAs("vfxPrefab")]
private GameObject _VfxPrefab = null;
[SerializeField]
[FormerlySerializedAs("vfxOffset")]
private Vector3 _VfxOffset = Vector3.zero;
#pragma warning restore CS0414
public HarvestAnimation HarvestAnimation => _HarvestAnimation;
public GameObject VFXPrefab => _VfxPrefab;
public Vector3 VFXOffset => _VfxOffset;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment