double inventory screen

This commit is contained in:
Aggtaa 2026-01-12 12:51:59 +03:00
parent 511914955b
commit e102c651a3
29 changed files with 462 additions and 1144 deletions

View File

@ -52,24 +52,26 @@
<Compile Include="Assets\Scripts\DataPersistence\FileDataHandler.cs" />
<Compile Include="Assets\Scripts\Shelf.cs" />
<Compile Include="Assets\Scripts\DataPersistence\IDataPersistence.cs" />
<Compile Include="Assets\Scripts\DataPersistence\Data\StorageData.cs" />
<Compile Include="Assets\Scripts\InventoryHolder.cs" />
<Compile Include="Assets\Scripts\DataPersistence\Data\GameData.cs" />
<Compile Include="Assets\Scripts\Storage.cs" />
<Compile Include="Assets\Scripts\Player.cs" />
<Compile Include="Assets\Scripts\DataPersistence\Data\PlayerData.cs" />
<Compile Include="Assets\Scripts\Shelves.cs" />
<Compile Include="Assets\Scripts\DataPersistence\SerializableTypes\SerializableDictionary.cs" />
<Compile Include="Assets\Scripts\Inventory\UIToolkitInfoPanel.cs" />
<Compile Include="Assets\Scripts\Blackboard.cs" />
<Compile Include="Assets\Scripts\UI\InventoryScreenInvoker.cs" />
<Compile Include="Assets\Scripts\DataPersistence\Data\ShelfData.cs" />
<Compile Include="Assets\Scripts\UI\InfoBox.cs" />
<Compile Include="Assets\Scripts\UI\InventoryScreen.cs" />
<Compile Include="Assets\Scripts\DataPersistence\DataPersistenceManager.cs" />
<Compile Include="Assets\Scripts\IInventoryHolder.cs" />
<Compile Include="Assets\Scripts\DataPersistence\Data\InventoryData.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Assets\UI\InventoryScreen.uss" />
<None Include="Assets\UI\InfoBox.uss" />
<None Include="Assets\UI\InventoryScreenInventory.uxml" />
<None Include="Assets\UI\InfoBox.uxml" />
<None Include="Assets\UI\InventoryScreenItem.uxml" />
<None Include="Assets\UI\InventoryScreen.uxml" />

View File

@ -1,439 +0,0 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityObject = UnityEngine.Object;
using System.Reflection;
public abstract class DictionaryDrawer<TK, TV> : PropertyDrawer
{
private Dictionary<TK, TV> _Dictionary;
private bool _Foldout;
private const float kButtonWidth = 18f;
private static float lineHeight = EditorGUIUtility.singleLineHeight + 4;
private float spacing = 12f;
private float fieldPadding = 1f;
private GUIStyle addEntryStyle;
private GUIContent addEntryContent;
private GUIStyle clearDictionaryStyle;
private GUIContent clearDictionaryContent;
//reuses clearDictionaryStyle. I am adding it for readability
private GUIStyle removeEntryStyle;
private GUIContent removeEntryContent;
private GUIStyle HeaderStyle;
private Rect buttonRect;
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
CheckInitialize(property, label);
if (_Foldout)
{
//Height of the main Header and the two column headers + height of all the drawn dictionary entries + a little padding on the bottom.
return (GetDictionaryElementsHeight() + (lineHeight * 2)) + 14f;
}
return lineHeight+ 4f;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
CheckInitialize(property, label);
position.height = 20f;
DrawHeader(position, property, label);
if (!_Foldout)
return;
position.y += 5f + lineHeight * 2;
foreach (var item in _Dictionary)
{
var key = item.Key;
var value = item.Value;
var keyRect = position;
keyRect.width /= 3;
keyRect.x += 10;
//Apply vertical padding
keyRect.y += fieldPadding;
keyRect.height -= fieldPadding * 2;
EditorGUI.BeginChangeCheck();
var newKey = DoField(keyRect, typeof(TK), (TK)key);
if (EditorGUI.EndChangeCheck())
{
try
{
_Dictionary.Remove(key);
_Dictionary.Add(newKey, value);
}
catch (Exception e)
{
_Dictionary.Remove(key);
Debug.Log(e.Message);
}
break;
}
var valueRect = position;
valueRect.x = keyRect.xMax + spacing;
valueRect.y += fieldPadding;
//Apply vertical padding
valueRect.height -= fieldPadding * 2;
valueRect.width = (position.width - keyRect.width) - ((kButtonWidth + 2) * 2f) - valueRect.size.y - (spacing* 2.5f);
EditorGUI.BeginChangeCheck();
value = DoField(valueRect, typeof(TV), (TV)value);
Rect changeValueRect = new Rect(new Vector2(buttonRect.x - 2f, valueRect.position.y), new Vector2(kButtonWidth, valueRect.size.y));
value = ChangeValueType(changeValueRect, key, value);
if (EditorGUI.EndChangeCheck())
{
_Dictionary[key] = value;
break;
}
EditorGUIUtility.AddCursorRect(changeValueRect, MouseCursor.Link);
var removeRect = valueRect;
removeRect.x = buttonRect.x + kButtonWidth;
removeRect.width = kButtonWidth;
if (GUI.Button(removeRect, removeEntryContent, removeEntryStyle))
{
RemoveItem(key);
break;
}
EditorGUIUtility.AddCursorRect(removeRect, MouseCursor.Link);
position.y += Mathf.Max(GetEntryHeight(key) ,GetEntryHeight(value));
}
}
/// <summary>
/// Gets the combined height of all dictionary elements
/// </summary>
/// <returns></returns>
private float GetDictionaryElementsHeight()
{
float height = 0;
foreach(var item in _Dictionary)
{
var key = item.Key;
var value = item.Value;
height += Mathf.Max(GetEntryHeight(key), GetEntryHeight(value));
}
return height;
}
private void DrawColumn(Rect position, GUIStyle style)
{
Rect columnRect = new Rect(position.x, position.yMax - 1, position.width, GetDictionaryElementsHeight() + 12f);
GUI.Box(columnRect, GUIContent.none, style);
}
private void DrawHeader(Rect position, SerializedProperty property, GUIContent label)
{
Rect headerRect = new Rect(position.position, new Vector2(position.size.x - kButtonWidth * 1.5f, lineHeight));
GUI.Box(headerRect, GUIContent.none, HeaderStyle);
var foldoutRect = position;
foldoutRect.x += 4f;
foldoutRect.width -= 2 * kButtonWidth;
EditorGUI.BeginChangeCheck();
if(_Dictionary.Count > 0)
{
_Foldout = EditorGUI.Foldout(foldoutRect, _Foldout, label, true);
}
else
{
foldoutRect.x += 4f;
EditorGUI.LabelField(foldoutRect, label);
_Foldout = false;
}
if (EditorGUI.EndChangeCheck())
{
EditorPrefs.SetBool(label.text, _Foldout);
}
//Draw the Add Item Button
buttonRect = position;
buttonRect.x = position.width - 20 - kButtonWidth + position.x + 1;
buttonRect.width = kButtonWidth;
GUIStyle headerButtonStyle = new GUIStyle(HeaderStyle);
headerButtonStyle.padding = new RectOffset(0, 0, 0, 0);
Rect headerButtonRect = new Rect(buttonRect.position, new Vector2(kButtonWidth * 1.5f, lineHeight));
if (GUI.Button(headerButtonRect, addEntryContent, headerButtonStyle))
{
AddNewItem();
}
EditorGUIUtility.AddCursorRect(headerButtonRect, MouseCursor.Link);
buttonRect.x -= kButtonWidth;
//Draw the Item count label
GUIStyle headerItemCountLabelStyle = new GUIStyle("MiniLabel");
GUIContent headerItemCountLabelContent = new GUIContent();
if(_Dictionary.Count == 0)
{
headerItemCountLabelContent = new GUIContent("Empty");
}
else
{
headerItemCountLabelContent = new GUIContent($"{_Dictionary.Count} Item{(_Dictionary.Count == 1 ? "" : "s")}");
}
GUI.Label(new Rect(buttonRect.x - 30f, buttonRect.y, 50f, headerRect.height), headerItemCountLabelContent, headerItemCountLabelStyle);
//Draw the header labels (Keys - Values)
if(_Foldout)
{
//Draw "Keys" header
position.y += headerRect.height;
Rect keyHeaderRect = new Rect(position.x, position.y - 1, position.width /3f + kButtonWidth - 1, headerRect.height);
GUIStyle columnHeaderStyle = new GUIStyle("GroupBox");
columnHeaderStyle.padding = new RectOffset(0, 0, 0, 0);
columnHeaderStyle.contentOffset = new Vector2(0, 3f);
GUI.Box(keyHeaderRect, new GUIContent("Keys"), columnHeaderStyle);
//Draw "Values" header
Rect valuesHeaderRect = new Rect(keyHeaderRect.xMax - 1, keyHeaderRect.y, (position.width - keyHeaderRect.width - kButtonWidth * 0.5f), keyHeaderRect.height);
GUI.Box(valuesHeaderRect, new GUIContent("Values"), columnHeaderStyle);
//Draw the Columns for the keys and values.
DrawColumn(keyHeaderRect, columnHeaderStyle);
DrawColumn(valuesHeaderRect, columnHeaderStyle);
position.y += headerRect.height;
}
/*
if (GUI.Button(buttonRect, clearDictionaryContent, clearDictionaryStyle))
{
ClearDictionary();
}
*/
}
#region TypeControls
private static float GetEntryHeight<T>(T value)
{
switch (value)
{
case Bounds: return lineHeight * 2;
case BoundsInt: return lineHeight * 2;
case Rect: return lineHeight * 2;
case RectInt: return lineHeight * 2;
default: return lineHeight;
}
}
private static T DoField<T>(Rect rect, Type type, T value)
{
if (typeof(UnityObject).IsAssignableFrom(type))
return (T)(object)EditorGUI.ObjectField(rect, (UnityObject)(object)value, type, true);
switch (value)
{
case null: EditorGUI.LabelField(rect, "null"); return value;
case long: return (T)(object)EditorGUI.LongField(rect, (long)(object)value);
case int: return (T)(object)EditorGUI.IntField(rect, (int)(object)value);
case float: return (T)(object)EditorGUI.FloatField(rect, (float)(object)value);
case double: return (T)(object)EditorGUI.DoubleField(rect, (double)(object)value);
case string: return (T)(object)EditorGUI.TextField(rect, (string)(object)value);
case bool: return (T)(object)EditorGUI.Toggle(rect, (bool)(object)value);
case Vector2Int: return (T)(object)EditorGUI.Vector2IntField(rect, GUIContent.none, (Vector2Int)(object)value);
case Vector3Int: return (T)(object)EditorGUI.Vector3IntField(rect, GUIContent.none, (Vector3Int)(object)value);
case Vector2: return (T)(object)EditorGUI.Vector2Field(rect, GUIContent.none, (Vector2)(object)value);
case Vector3: return (T)(object)EditorGUI.Vector3Field(rect, GUIContent.none, (Vector3)(object)value);
case Vector4: return (T)(object)EditorGUI.Vector4Field(rect, GUIContent.none, (Vector4)(object)value);
case BoundsInt: return (T)(object)EditorGUI.BoundsIntField(rect, (BoundsInt)(object)value);
case Bounds: return (T)(object)EditorGUI.BoundsField(rect, (Bounds)(object)value);
case RectInt: return (T)(object)EditorGUI.RectIntField(rect, (RectInt)(object)value);
case Rect: return (T)(object)EditorGUI.RectField(rect, (Rect)(object)value);
case Color: return (T)(object)EditorGUI.ColorField(rect, (Color)(object)value);
case AnimationCurve: return (T)(object)EditorGUI.CurveField(rect, (AnimationCurve)(object)value);
case Gradient: return (T)(object)EditorGUI.GradientField(rect, (Gradient)(object)value);
case UnityObject: return (T)(object)EditorGUI.ObjectField(rect, (UnityObject)(object)value, type, true);
}
if (value.GetType().IsEnum)
{
if (Enum.TryParse(value.GetType(), value.ToString(), out object enumValue))
{
return (T)(object)EditorGUI.EnumPopup(rect, (Enum)enumValue);
}
}
//Setup GUIStyle and GUIContent for the "Clear Dictionary" button
GUIStyle style = new GUIStyle(EditorStyles.miniButton);
style.padding = new RectOffset(2, 2, 2, 2);
GUIContent content = new GUIContent(EditorGUIUtility.IconContent("d_UnityEditor.ConsoleWindow@2x"));
content.tooltip = "Debug Values";
Type fieldType = value.GetType();
bool isStruct = fieldType.IsValueType && !fieldType.IsEnum;
EditorGUI.LabelField(rect, $"{fieldType.ToString().Replace("+", ".")} {(isStruct ? "struct" : "class")} instance");
if( GUI.Button(new Rect(rect.xMax - kButtonWidth, rect.y, kButtonWidth, kButtonWidth), content, style))
{
Debug.Log(JsonUtility.ToJson(value));
}
//DrawSerializableObject(rect, value);
return value;
}
//Unfinished
/*
public static void DrawSerializableObject(Rect rect, object obj)
{
if (obj == null)
{
Console.WriteLine("Object is null.");
return;
}
Type type = obj.GetType();
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
foreach (FieldInfo field in fields)
{
object value = field.GetValue(obj);
rect.y += GetEntryHeight(value);
Debug.Log($"{field.Name}: {value}");
if(value != null)
{
DoField(rect, value.GetType(), value);
}
}
}
*/
private TV ChangeValueType(Rect rect, TK key, TV value)
{
GUIContent content = EditorGUIUtility.IconContent("_Popup");
content.tooltip = "Change Value Type";
GUIStyle changeItemStyle = new GUIStyle(EditorStyles.miniButton);
changeItemStyle.padding = new RectOffset(2, 2, 2, 2);
if (GUI.Button(rect, content, changeItemStyle))
{
GenericMenu genericMenu = new GenericMenu();
genericMenu.AddItem(new GUIContent("Numbers/int"), value is int, () => { _Dictionary[key] = (TV)(object)default(int); });
genericMenu.AddItem(new GUIContent("Numbers/float"), value is float, () => { _Dictionary[key] = (TV)(object)default(float); });
genericMenu.AddItem(new GUIContent("Numbers/double"), value is double, () => { _Dictionary[key] = (TV)(object)default(double); });
genericMenu.AddItem(new GUIContent("Numbers/long"), value is long, () => { _Dictionary[key] = (TV)(object)default(long); });
genericMenu.AddItem(new GUIContent("Vectors/Vector2"), (value is Vector2 && !(value is Vector2Int)), () => { _Dictionary[key] = (TV)(object)default(Vector2); });
genericMenu.AddItem(new GUIContent("Vectors/Vector3"), (value is Vector3 && !(value is Vector3Int)), () => { _Dictionary[key] = (TV)(object)default(Vector3); });
genericMenu.AddItem(new GUIContent("Vectors/Vector4"), value is Vector4, () => { _Dictionary[key] = (TV)(object)default(Vector4); });
genericMenu.AddItem(new GUIContent("Vectors/Vector2Int"), value is Vector2Int, () => { _Dictionary[key] = (TV)(object)default(Vector2Int); });
genericMenu.AddItem(new GUIContent("Vectors/Vector3Int"), value is Vector3Int, () => { _Dictionary[key] = (TV)(object)default(Vector3Int); });
genericMenu.AddItem(new GUIContent("Bounds/Bounds"), value is Bounds && value is not BoundsInt, () => { _Dictionary[key] = (TV)(object)default(Bounds); });
genericMenu.AddItem(new GUIContent("Bounds/BoundsInt"), value is BoundsInt, () => { _Dictionary[key] = (TV)(object)default(BoundsInt); });
genericMenu.AddItem(new GUIContent("Rects/Rect"), value is Rect && value is not RectInt, () => { _Dictionary[key] = (TV)(object)default(Rect); });
genericMenu.AddItem(new GUIContent("Rects/RectInt"), value is RectInt, () => { _Dictionary[key] = (TV)(object)default(RectInt); });
genericMenu.AddItem(new GUIContent("string"), value is string, () => { _Dictionary[key] = (TV)(object)""; });
genericMenu.AddItem(new GUIContent("bool"), value is bool, () => { _Dictionary[key] = (TV)(object)default(bool); });
genericMenu.AddItem(new GUIContent("Color"), value is Color, () => { _Dictionary[key] = (TV)(object)default(Color); });
genericMenu.AddItem(new GUIContent("AnimationCurve"), value is AnimationCurve, () => { _Dictionary[key] = (TV)(object)(new AnimationCurve()); });
genericMenu.AddItem(new GUIContent("Gradient"), value is Gradient, () => { _Dictionary[key] = (TV)(object)(new Gradient()); });
genericMenu.AddItem(new GUIContent("Unity Object"), value is UnityObject, () => { _Dictionary[key] = (TV)(object)(new UnityObject()); });
genericMenu.ShowAsContext();
}
return (TV)value;
}
#endregion
private void RemoveItem(TK key)
{
_Dictionary.Remove(key);
}
private void CheckInitialize(SerializedProperty property, GUIContent label)
{
if (_Dictionary == null)
{
SetupStyles();
var target = property.serializedObject.targetObject;
_Dictionary = fieldInfo.GetValue(target) as Dictionary<TK, TV>;
if (_Dictionary == null)
{
_Dictionary = new Dictionary<TK, TV>();
fieldInfo.SetValue(target, _Dictionary);
}
_Foldout = EditorPrefs.GetBool(label.text);
}
}
private void SetupStyles()
{
//Setup GUIStyle and GUIContent for the "Add Item" button
addEntryStyle = new GUIStyle(EditorStyles.miniButton);
addEntryStyle.padding = new RectOffset(3, 3, 3, 3);
addEntryContent = new GUIContent(EditorGUIUtility.IconContent("d_CreateAddNew@2x"));
addEntryContent.tooltip = "Add Item";
//Setup GUIStyle and GUIContent for the "Clear Dictionary" button
clearDictionaryStyle = new GUIStyle(EditorStyles.miniButton);
clearDictionaryStyle.padding = new RectOffset(2, 2, 2, 2);
clearDictionaryContent = new GUIContent(EditorGUIUtility.IconContent("d_winbtn_win_close@2x"));
clearDictionaryContent.tooltip = "Clear dictionary";
removeEntryContent = new GUIContent(EditorGUIUtility.IconContent("d_winbtn_win_close@2x"));
removeEntryContent.tooltip = "Remove Item";
removeEntryStyle = new GUIStyle(clearDictionaryStyle);
HeaderStyle = new GUIStyle("MiniToolbarButton");
HeaderStyle.fixedHeight = 0;
HeaderStyle.fixedWidth = 0;
HeaderStyle.padding = new RectOffset(2,2,2,2);
}
private void ClearDictionary()
{
_Dictionary.Clear();
}
private void AddNewItem()
{
TK key;
if (typeof(TK) == typeof(string))
key = (TK)(object)"";
else key = default(TK);
if (typeof(TV) == typeof(object))
{
var value = (TV)(object)1;
try
{
_Dictionary.Add(key, value);
}
catch (Exception e)
{
Debug.Log(e.Message);
}
}
else
{
var value = default(TV);
try
{
_Dictionary.Add(key, value);
}
catch (Exception e)
{
Debug.Log(e.Message);
}
}
}
}
[CustomPropertyDrawer(typeof(Blackboard))]
public class BlackboardDrawer : DictionaryDrawer<string, object> { }
// [CustomPropertyDrawer(typeof(Inventory))]
// public class InventoryDrawer : DictionaryDrawer<string, int> { }

View File

@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: d98eeb23cea688d4c9a9ce396d927919

View File

@ -181,3 +181,5 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 38451aa38ba98df4f939ff6b7b8214c2, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::InventoryScreenInvoker
SourceInventory: {fileID: 0}
TargetInventory: {fileID: -5117840549013073363}

View File

@ -0,0 +1,182 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &4557172615047839809
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2592813772834325640}
- component: {fileID: 6329482849752991534}
- component: {fileID: 5507466453634029947}
- component: {fileID: 5465635363533564358}
- component: {fileID: -3570956179444851343}
- component: {fileID: -1329949174847138657}
m_Layer: 0
m_Name: Storage
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2592813772834325640
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4557172615047839809}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0.44873, y: 0.92241, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!212 &6329482849752991534
SpriteRenderer:
serializedVersion: 2
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4557172615047839809}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 0
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 0
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
m_DrawMode: 0
m_Size: {x: 1, y: 1}
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
m_WasSpriteAssigned: 1
m_SpriteSortPoint: 0
--- !u!61 &5507466453634029947
BoxCollider2D:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4557172615047839809}
m_Enabled: 1
serializedVersion: 3
m_Density: 1
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_ForceSendLayers:
serializedVersion: 2
m_Bits: 4294967295
m_ForceReceiveLayers:
serializedVersion: 2
m_Bits: 4294967295
m_ContactCaptureLayers:
serializedVersion: 2
m_Bits: 4294967295
m_CallbackLayers:
serializedVersion: 2
m_Bits: 4294967295
m_IsTrigger: 0
m_UsedByEffector: 0
m_CompositeOperation: 0
m_CompositeOrder: 0
m_Offset: {x: 0, y: 0}
m_SpriteTilingProperty:
border: {x: 0, y: 0, z: 0, w: 0}
pivot: {x: 0.5, y: 0.5}
oldSize: {x: 1, y: 1}
newSize: {x: 1, y: 1}
adaptiveTilingThreshold: 0.5
drawMode: 0
adaptiveTiling: 0
m_AutoTiling: 0
m_Size: {x: 1, y: 1}
m_EdgeRadius: 0
--- !u!114 &5465635363533564358
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4557172615047839809}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 003acbbf759b3bc4ea37150bcd331f99, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Storage
--- !u!114 &-3570956179444851343
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4557172615047839809}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 687937cfe3daa04489c5323f36aef2e7, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::InfoBox
uiAsset: {fileID: 9197481963319205126, guid: 6b3866a73cab45c429ffb420315993ca, type: 3}
uiPanelSettings: {fileID: 11400000, guid: 7b1015287071c934bb8054c1ae46eccd, type: 2}
AlwaysVisible: 1
--- !u!114 &-1329949174847138657
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4557172615047839809}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 38451aa38ba98df4f939ff6b7b8214c2, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::InventoryScreenInvoker

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c60f8ab2809e8c242be075b99cf9e734
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -149,6 +149,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 543349003}
- {fileID: 1188620131}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &519420028
@ -349,6 +350,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 9b472ba6d08a54940a9db7abce45bb03, type: 3}
m_Name:
m_EditorClassIdentifier: '::'
storage: {fileID: 1202152176}
ShelfPrefab: {fileID: 4557172615047839809, guid: 6bda07d3031c8084e91a4cec9ed7e579, type: 3}
--- !u!1 &619394800
GameObject:
@ -481,6 +483,103 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &1188620130
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 339608289}
m_Modifications:
- target: {fileID: -1329949174847138657, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: SourceInventory
value:
objectReference: {fileID: 1202152176}
- target: {fileID: 2592813772834325640, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_LocalScale.x
value: 2.7598
objectReference: {fileID: 0}
- target: {fileID: 2592813772834325640, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_LocalScale.y
value: 2.2123
objectReference: {fileID: 0}
- target: {fileID: 2592813772834325640, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_LocalPosition.x
value: -7.55
objectReference: {fileID: 0}
- target: {fileID: 2592813772834325640, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_LocalPosition.y
value: -2.83
objectReference: {fileID: 0}
- target: {fileID: 2592813772834325640, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2592813772834325640, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 2592813772834325640, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2592813772834325640, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2592813772834325640, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2592813772834325640, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2592813772834325640, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2592813772834325640, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4557172615047839809, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_Name
value: "\u0421\u043A\u043B\u0430\u0434"
objectReference: {fileID: 0}
- target: {fileID: 6329482849752991534, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_Color.b
value: 0.057271264
objectReference: {fileID: 0}
- target: {fileID: 6329482849752991534, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_Color.g
value: 0.057271264
objectReference: {fileID: 0}
- target: {fileID: 6329482849752991534, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
propertyPath: m_Color.r
value: 0.122641504
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
--- !u!4 &1188620131 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 2592813772834325640, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
m_PrefabInstance: {fileID: 1188620130}
m_PrefabAsset: {fileID: 0}
--- !u!114 &1202152176 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 5465635363533564358, guid: c60f8ab2809e8c242be075b99cf9e734, type: 3}
m_PrefabInstance: {fileID: 1188620130}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 003acbbf759b3bc4ea37150bcd331f99, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Storage
--- !u!1 &1754384484
GameObject:
m_ObjectHideFlags: 0
@ -605,9 +704,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 631c59a16a4091a4caa7b4ff24839552, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::InventoryScreen
uiAsset: {fileID: 9197481963319205126, guid: 3f702f69419923044856bc754559430b, type: 3}
uiInventoryAsset: {fileID: 9197481963319205126, guid: 473047aab40dd3b42870b44f023fbaa5, type: 3}
uiItemAsset: {fileID: 9197481963319205126, guid: eb46dce908061864c935406ab889f172, type: 3}
uiPanelSettings: {fileID: 11400000, guid: 7b1015287071c934bb8054c1ae46eccd, type: 2}
--- !u!114 &2016876942
MonoBehaviour:
m_ObjectHideFlags: 0
@ -683,11 +781,30 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7458587233354274444, guid: 19c1ccebaf45a40478633ddde15bf4d7, type: 3}
propertyPath: SourceInventory
value:
objectReference: {fileID: 3377531241049282649}
- target: {fileID: 7458587233354274444, guid: 19c1ccebaf45a40478633ddde15bf4d7, type: 3}
propertyPath: TargetInventory
value:
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 19c1ccebaf45a40478633ddde15bf4d7, type: 3}
--- !u!114 &3377531241049282649 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 1184499778079033655, guid: 19c1ccebaf45a40478633ddde15bf4d7, type: 3}
m_PrefabInstance: {fileID: 3377531241049282641}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: cffc1654223acc54f9aa045c5a7730a3, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::PlayerInventory
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0

View File

@ -1,631 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;
using UnityEditor;
using System.Text.RegularExpressions;
[Serializable]
public class Blackboard : Dictionary<string, object>, ISerializationCallbackReceiver
{
[Serializable]
//struct represents the string key, and the serialized value from the dictionary.
private struct SaveItem
{
public string key;
public string value;
public int index;
public SaveItem(string key, string val, int index)
{
this.key = key;
this.value = val;
this.index = index;
}
}
//All serialized items except for objects in a scene, which have to be handled separately.
[SerializeField, HideInInspector]
private List<SaveItem> saveItems;
//We need a different struct and list for Object references in scene :(
[Serializable]
private struct NonAssetSaveItem
{
public string key;
public UnityEngine.Object obj;
public int index;
public NonAssetSaveItem(string key, UnityEngine.Object obj, int index)
{
this.key = key;
this.obj = obj;
this.index = index;
}
}
[SerializeField, HideInInspector]
private List<NonAssetSaveItem> sceneObjectSaveItems;
/// <summary>
/// Takes all of the keyvalue pairs from the Dictionary and stores them as Serializable lists.
/// </summary>
public void OnBeforeSerialize()
{
sceneObjectSaveItems = new List<NonAssetSaveItem>();
saveItems = new List<SaveItem>();
List<string> keys = this.Keys.ToList();
List<object> values = this.Values.ToList();
for (int i = 0; i < Count; i++)
{
object value = values[i];
string encode = "";
//Unhandled Enum Types
if (value is Enum)
{
Enum enumValue = (Enum)value;
Console.WriteLine("Enum Value: " + enumValue.ToString());
encode = $"({value.GetType().AssemblyQualifiedName}){enumValue}";
saveItems.Add(new SaveItem(keys[i], encode, i));
continue;
}
switch (value)
{
case null: encode = "(null)"; break;
case int: encode = "(int)" + ((int)value).ToString("F9"); break;
case float: encode = "(float)" + ((float)value).ToString("F9"); break;
case double: encode = "(double)" + ((double)value).ToString("F9"); break;
case long: encode = "(long)" + ((long)value).ToString(); break;
case string: encode = "(string)" + (string)value; break;
case bool: encode = "(bool)" + (((bool)value) == true ? "true" : "false"); break;
case Vector2Int: encode = "(Vector2Int)" + ((Vector2Int)value).ToString(); break;
case Vector3Int: encode = "(Vector3Int)" + ((Vector3Int)value).ToString(); break;
case Vector2: encode = "(Vector2)" + ((Vector2)value).ToString(); break;
case Vector3: encode = "(Vector3)" + ((Vector3)value).ToString(); break;
case Vector4: encode = "(Vector4)" + ((Vector4)value).ToString(); break;
case Bounds: encode = "(Bounds)" + ((Bounds)value).ToString(); break;
case Rect: encode = "(Rect)" + ((Rect)value).ToString("F9"); break;
case Color: encode = "(Color)" + JsonUtility.ToJson((Color)value); break;
case AnimationCurve: encode = "(AnimationCurve)" + Serializer.SerializeAnimationCurve((AnimationCurve)value); break;
case Gradient: encode = "(Gradient)" + Serializer.SerializeGradient((Gradient)value); break;
case UnityEngine.Object obj:
string assetPath = Application.isEditor ? AssetDatabase.GetAssetPath(obj) : null;
if (!string.IsNullOrEmpty(assetPath))
{
encode = "(UnityEngine.Object)" + assetPath;
}
else
{
sceneObjectSaveItems.Add(new NonAssetSaveItem(keys[i], obj, i));
}
break;
//Try to serialize to JSON. May be empty if type is not supported
default: encode = $"({value.GetType().AssemblyQualifiedName}){JsonUtility.ToJson(value)}"; break;
}
if (!string.IsNullOrEmpty(encode))
{
saveItems.Add(new SaveItem(keys[i], encode, i));
}
}
}
/// <summary>
/// Loads the two lists back into the Dictionary, using the Merge Linked Lists method.
/// </summary>
public void OnAfterDeserialize()
{
this.Clear();
int i = 0;
int j = 0;
//Ensure that the lists are not null to ensure no errors when accessing list.Count
saveItems = saveItems == null ? new List<SaveItem>() : saveItems;
sceneObjectSaveItems = sceneObjectSaveItems == null ? new List<NonAssetSaveItem>() : sceneObjectSaveItems;
while (i < saveItems.Count && j < sceneObjectSaveItems.Count)
{
if (saveItems[i].index < sceneObjectSaveItems[j].index)
{
string key = saveItems[i].key;
int openIndex = saveItems[i].value.IndexOf('(');
int closeIndex = saveItems[i].value.IndexOf(')');
string contentType = saveItems[i].value.Substring(openIndex + 1, closeIndex - openIndex - 1);
string encode = saveItems[i].value.Substring(closeIndex + 1);
DeserializeItem(contentType, key, encode);
i++;
}
else
{
Add(sceneObjectSaveItems[j].key, sceneObjectSaveItems[j].obj);
j++;
}
}
for(; i < saveItems.Count;i++)
{
string key = saveItems[i].key;
int openIndex = saveItems[i].value.IndexOf('(');
int closeIndex = saveItems[i].value.IndexOf(')');
string contentType = saveItems[i].value.Substring(openIndex + 1, closeIndex - openIndex - 1);
string encode = saveItems[i].value.Substring(closeIndex + 1);
DeserializeItem(contentType, key, encode);
}
for (; j < sceneObjectSaveItems.Count; j++)
{
Add(sceneObjectSaveItems[j].key, sceneObjectSaveItems[j].obj);
}
}
/// <summary>
/// Takes the key and encoded string from a serialized item and adds it back into the dictionary.
/// </summary>
private void DeserializeItem(string contentType, string key, string encodedValue)
{
switch (contentType)
{
case "null": Add(key, null); return;
case "int": Add(key, (int)int.Parse(encodedValue)); return;
case "float": Add(key, (float)float.Parse(encodedValue)); return;
case "double": Add(key, (double)double.Parse(encodedValue)); return;
case "long": Add(key, (long)long.Parse(encodedValue)); return;
case "string": Add(key, (string)encodedValue); return;
case "bool": Add(key, (bool)(encodedValue == "true" ? true : false)); return;
case "Vector2": Add(key, Serializer.ParseVector2(encodedValue)); return;
case "Vector3": Add(key, Serializer.ParseVector3(encodedValue)); return;
case "Vector2Int": Add(key, Serializer.ParseVector2Int(encodedValue)); return;
case "Vector3Int": Add(key, Serializer.ParseVector3Int(encodedValue)); return;
case "Vector4": Add(key, Serializer.ParseVector4(encodedValue)); return;
case "Bounds": Add(key, Serializer.ParseBounds(encodedValue)); return;
case "Rect": Add(key, Serializer.ParseRect(encodedValue)); return;
case "Color": Add(key, JsonUtility.FromJson<Color>(encodedValue)); return;
case "AnimationCurve": Add(key, Serializer.DeserializeAnimationCurve(encodedValue)); return;
case "Gradient": Add(key, Serializer.DeserializeGradient(encodedValue)); return;
case "UnityEngine.Object":
if(Application.isEditor)
{
EditorApplication.delayCall += () => Add(key, AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(encodedValue));
}
else
{
Add(key, Resources.Load(encodedValue));
}
return;
default: break;
}
//Different process for enums (of any type)
if(Serializer.EnumDeserialize(contentType, encodedValue, out object enumValue))
{
Add(key, enumValue);
}
//Tries to de-serialize a struct or class using JsonUtility.FromJson
if(Serializer.TryDeserializeJSON(contentType, encodedValue, out object result))
{
Add(key, result);
}
}
public void SetOrAdd(string key, object ob)
{
if (this.ContainsKey(key))
{
this[key] = ob;
}
else
{
this.Add(key, ob);
}
}
[System.Serializable]
private static class Serializer
{
#region GradientSerialization
[System.Serializable]
private class SerializableGradient
{
public SerializableColorKey[] colorKeys;
public SerializableAlphaKey[] alphaKeys;
public GradientMode mode;
public SerializableGradient(Gradient gradient)
{
colorKeys = new SerializableColorKey[gradient.colorKeys.Length];
for (int i = 0; i < gradient.colorKeys.Length; i++)
{
colorKeys[i] = new SerializableColorKey(gradient.colorKeys[i]);
}
alphaKeys = new SerializableAlphaKey[gradient.alphaKeys.Length];
for (int i = 0; i < gradient.alphaKeys.Length; i++)
{
alphaKeys[i] = new SerializableAlphaKey(gradient.alphaKeys[i]);
}
mode = gradient.mode;
}
public Gradient ToGradient()
{
Gradient gradient = new Gradient();
GradientColorKey[] gradientColorKeys = new GradientColorKey[colorKeys.Length];
for (int i = 0; i < colorKeys.Length; i++)
{
gradientColorKeys[i] = colorKeys[i].ToGradientColorKey();
}
GradientAlphaKey[] gradientAlphaKeys = new GradientAlphaKey[alphaKeys.Length];
for (int i = 0; i < alphaKeys.Length; i++)
{
gradientAlphaKeys[i] = alphaKeys[i].ToGradientAlphaKey();
}
gradient.SetKeys(gradientColorKeys, gradientAlphaKeys);
gradient.mode = mode;
return gradient;
}
}
[System.Serializable]
private class SerializableColorKey
{
public Color color;
public float time;
public SerializableColorKey(GradientColorKey colorKey)
{
color = colorKey.color;
time = colorKey.time;
}
public GradientColorKey ToGradientColorKey()
{
return new GradientColorKey(color, time);
}
}
[System.Serializable]
private class SerializableAlphaKey
{
public float alpha;
public float time;
public SerializableAlphaKey(GradientAlphaKey alphaKey)
{
alpha = alphaKey.alpha;
time = alphaKey.time;
}
public GradientAlphaKey ToGradientAlphaKey()
{
return new GradientAlphaKey(alpha, time);
}
}
public static string SerializeGradient(Gradient gradient)
{
SerializableGradient serializableGradient = new SerializableGradient(gradient);
return JsonUtility.ToJson(serializableGradient);
}
public static Gradient DeserializeGradient(string json)
{
SerializableGradient serializableGradient = JsonUtility.FromJson<SerializableGradient>(json);
if (serializableGradient != null)
{
return serializableGradient.ToGradient();
}
Debug.LogError("Failed to deserialize Gradient from JSON: " + json);
return new Gradient(); // Return a default Gradient or handle the error as needed
}
#endregion
#region AnimationCurveSerialization
[System.Serializable]
private struct SerializableKeyframe
{
public float time;
public float value;
public float inTangent;
public float outTangent;
public SerializableKeyframe(Keyframe keyframe)
{
time = keyframe.time;
value = keyframe.value;
inTangent = keyframe.inTangent;
outTangent = keyframe.outTangent;
}
}
[System.Serializable]
private struct SerializableAnimationCurve
{
public WrapMode preWrapMode;
public WrapMode postWrapMode;
public SerializableKeyframe[] keys;
public SerializableAnimationCurve(AnimationCurve curve)
{
preWrapMode = curve.preWrapMode;
postWrapMode = curve.postWrapMode;
keys = new SerializableKeyframe[curve.length];
for (int i = 0; i < curve.length; i++)
{
keys[i] = new SerializableKeyframe(curve[i]);
}
}
}
/// <summary>
/// Serializes an AnimationCurve to a JSON string.
/// </summary>
public static string SerializeAnimationCurve(AnimationCurve curve)
{
SerializableAnimationCurve serializableCurve = new SerializableAnimationCurve(curve);
string json = JsonUtility.ToJson(serializableCurve);
return json;
}
/// <summary>
/// Produces an AnimationCurve from a json string.
/// </summary>
public static AnimationCurve DeserializeAnimationCurve(string json)
{
SerializableAnimationCurve serializableCurve = JsonUtility.FromJson<SerializableAnimationCurve>(json);
Keyframe[] keyframes = new Keyframe[serializableCurve.keys.Length];
for (int i = 0; i < keyframes.Length; i++)
{
keyframes[i] = new Keyframe(
serializableCurve.keys[i].time,
serializableCurve.keys[i].value,
serializableCurve.keys[i].inTangent,
serializableCurve.keys[i].outTangent
);
}
AnimationCurve curve = new AnimationCurve(keyframes);
curve.postWrapMode = serializableCurve.postWrapMode;
curve.preWrapMode = serializableCurve.postWrapMode;
return curve;
}
#endregion
#region VectorSerialization
public static Vector2 ParseVector2(string vectorString)
{
vectorString = vectorString.Replace("(", "").Replace(")", "");
string[] components = vectorString.Split(',');
if (components.Length == 2 &&
float.TryParse(components[0], out float x) &&
float.TryParse(components[1], out float y))
{
return new Vector2(x, y);
}
Debug.LogError("Failed to parse Vector2 from string: " + vectorString);
return Vector2.zero;
}
public static Vector2Int ParseVector2Int(string vectorString)
{
vectorString = vectorString.Replace("(", "").Replace(")", "");
string[] components = vectorString.Split(',');
if (components.Length == 2 &&
int.TryParse(components[0], out int x) &&
int.TryParse(components[1], out int y))
{
return new Vector2Int(x, y);
}
Debug.LogError("Failed to parse Vector2 from string: " + vectorString);
return Vector2Int.zero;
}
public static Vector3 ParseVector3(string vectorString)
{
vectorString = vectorString.Replace("(", "").Replace(")", "");
string[] components = vectorString.Split(',');
if (components.Length == 3 &&
float.TryParse(components[0], out float x) &&
float.TryParse(components[1], out float y) &&
float.TryParse(components[2], out float z))
{
return new Vector3(x, y, z);
}
Debug.LogError("Failed to parse Vector3 from string: " + vectorString);
return Vector3.zero;
}
public static Vector3Int ParseVector3Int(string vectorString)
{
vectorString = vectorString.Replace("(", "").Replace(")", "");
string[] components = vectorString.Split(',');
if (components.Length == 3 &&
int.TryParse(components[0], out int x) &&
int.TryParse(components[1], out int y) &&
int.TryParse(components[2], out int z))
{
return new Vector3Int(x, y, z);
}
Debug.LogError("Failed to parse Vector3Int from string: " + vectorString);
return Vector3Int.zero;
}
public static Vector4 ParseVector4(string vectorString)
{
vectorString = vectorString.Replace("(", "").Replace(")", "");
string[] components = vectorString.Split(',');
if (components.Length == 4 &&
float.TryParse(components[0], out float x) &&
float.TryParse(components[1], out float y) &&
float.TryParse(components[2], out float z) &&
float.TryParse(components[3], out float w))
{
return new Vector4(x, y, z, w);
}
Debug.LogError("Failed to parse Vector4 from string: " + vectorString);
return Vector4.zero;
}
#endregion
#region BoundsSerialization
/// <summary>
/// Produces a Bounds object from the result of Bounds.ToString(). Returns a Bounds with all zero values if unable to parse.
/// </summary>
public static Bounds ParseBounds(string boundsString)
{
// Remove parentheses and labels from the string
boundsString = Regex.Replace(boundsString, @"[^\d\.\-,]", "");
string[] components = boundsString.Split(',');
if (components.Length == 6 &&
float.TryParse(components[0], out float center_x) &&
float.TryParse(components[1], out float center_y) &&
float.TryParse(components[2], out float center_z) &&
float.TryParse(components[3], out float extent_x) &&
float.TryParse(components[4], out float extent_y) &&
float.TryParse(components[5], out float extent_z))
{
Vector3 center = new Vector3(center_x, center_y, center_z);
Vector3 size = new Vector3(extent_x, extent_y, extent_z) * 2f;
return new Bounds(center, size);
}
Debug.LogWarning("Failed to parse Bounds from string: " + boundsString);
return new Bounds(Vector3.zero, Vector3.zero);
}
/// <summary>
/// Produces a BoundsInt object from the result of BoundsInt.ToString(). Returns a Bounds with all zero values if unable to parse.
/// </summary>
public static BoundsInt ParseBoundsInt(string boundsString)
{
// Remove parentheses and labels and any unwanted decimals from the string
boundsString = Regex.Replace(boundsString, @"[^\d\-,]", "");
string[] components = boundsString.Split(',');
if (components.Length == 6 &&
int.TryParse(components[0], out int center_x) &&
int.TryParse(components[1], out int center_y) &&
int.TryParse(components[2], out int center_z) &&
int.TryParse(components[3], out int extent_x) &&
int.TryParse(components[4], out int extent_y) &&
int.TryParse(components[5], out int extent_z))
{
Vector3Int center = new Vector3Int(center_x, center_y, center_z);
Vector3Int size = new Vector3Int(extent_x, extent_y, extent_z) * 2;
return new BoundsInt(center, size);
}
Debug.LogWarning("Failed to parse BoundsInt from string: " + boundsString);
return new BoundsInt(Vector3Int.zero, Vector3Int.zero);
}
#endregion
#region RectSerialization
/// <summary>
/// Takes the string result of Rect.ToString() and produces the original Rect. Returns a zero-rect if unable to parse.
/// </summary>
public static Rect ParseRect(string rectString)
{
// Remove parentheses and labels from the string
rectString = Regex.Replace(rectString, @"[^\d\.\-,]", "");
string[] components = rectString.Split(',');
if (components.Length == 4 &&
float.TryParse(components[0], out float x) &&
float.TryParse(components[1], out float y) &&
float.TryParse(components[2], out float width) &&
float.TryParse(components[3], out float height))
{
Rect rect = new Rect(x, y, width, height);
return rect;
}
Debug.LogWarning("Failed to parse Rect from string: " + rectString);
return new Rect(0, 0, 0, 0);
}
/// <summary>
/// Takes the string result of RectInt.ToString() and produces the original RectInt. Returns a zero-rect if unable to parse.
/// </summary>
public static RectInt ParseRectInt(string rectString)
{
// Remove parentheses and labels from the string
rectString = Regex.Replace(rectString, @"[^\d\-,]", "");
string[] components = rectString.Split(',');
if (components.Length == 4 &&
int.TryParse(components[0], out int x) &&
int.TryParse(components[1], out int y) &&
int.TryParse(components[2], out int width) &&
int.TryParse(components[3], out int height))
{
RectInt rect = new RectInt(x, y, width, height);
return rect;
}
Debug.LogWarning("Failed to parse RectInt from string: " + rectString);
return new RectInt(0, 0, 0, 0);
}
#endregion
/// <summary>
/// Takes the type, encoded as string, and the enum value and produces an Enum of the proper type.
/// </summary>
public static bool EnumDeserialize(string contentType, string encodedValue, out object enumValue)
{
Type type = Type.GetType(contentType);
if (type != null && type.IsEnum)
{
if (Enum.TryParse(type, encodedValue, out object enumIntermediateValue))
{
enumValue = Convert.ChangeType(enumIntermediateValue, type);
return true;
}
}
enumValue = null;
return false;
}
/// <summary>
/// Takes as input a string to be converted to a type, which is used to produce a Deserialized object.
/// </summary>
public static bool TryDeserializeJSON(string contentType, string json, out object result)
{
Type type = Type.GetType(contentType);
if (type != null)
{
result = JsonUtility.FromJson(json, type);
if (result != null)
{
return true;
}
}
result = null;
return false;
}
}
}

View File

@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 5514fe3cae16a7e4bb756eb9393ae1fd

View File

@ -9,11 +9,7 @@ public class GameData
public PlayerData player = new PlayerData();
public List<ShelfData> shelves = new List<ShelfData>();
public StorageData storage = new StorageData();
// the values defined in this constructor will be the default values
// the game starts with when there's no data to load
public GameData()
{
}
public List<ShelfData> shelves = new List<ShelfData>();
}

View File

@ -0,0 +1,7 @@
using System;
[System.Serializable]
public class StorageData
{
public InventoryData inventory = new InventoryData();
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9691713479005104ea634e90c3338df3

View File

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

View File

@ -1,5 +0,0 @@
public interface IInventoryHolder
{
public Inventory Inventory { get; }
public string Name { get; }
}

View File

@ -0,0 +1,8 @@
using UnityEngine;
// class, not interface so Unity shows fields in Editor
public abstract class InventoryHolder : MonoBehaviour
{
public abstract Inventory Inventory { get; }
public abstract string Name { get; }
}

View File

@ -1,12 +1,12 @@
using UnityEngine;
public class Player : MonoBehaviour, IInventoryHolder, IDataPersistence<GameData>
public class Player : InventoryHolder, IDataPersistence<GameData>
{
private Inventory inventory = new Inventory(50);
public Inventory Inventory => inventory;
public override Inventory Inventory => inventory;
public string Name => gameObject.name;
public override string Name => gameObject.name;
void Awake()
{

View File

@ -1,12 +1,12 @@
using UnityEngine;
public class Shelf : MonoBehaviour, IInventoryHolder, IDataPersistence<ShelfData>
public class Shelf : InventoryHolder, IDataPersistence<ShelfData>
{
private Inventory inventory = new Inventory(50);
public Inventory Inventory => inventory;
public override Inventory Inventory => inventory;
public string Name => type;
public override string Name => type;
public string type = "shelf";

View File

@ -5,6 +5,8 @@ using UnityEngine;
public class Shelves : MonoBehaviour, IDataPersistence<GameData>
{
public Storage storage;
public GameObject ShelfPrefab;
private List<Shelf> items = new List<Shelf>();
@ -42,6 +44,9 @@ public class Shelves : MonoBehaviour, IDataPersistence<GameData>
Shelf shelf = instance.GetComponent<Shelf>();
shelf.LoadData(data);
InventoryScreenInvoker inventoryScreen = instance.GetComponent<InventoryScreenInvoker>();
inventoryScreen.SourceInventory = storage;
items.Add(shelf);
}

38
Assets/Scripts/Storage.cs Normal file
View File

@ -0,0 +1,38 @@
using UnityEngine;
public class Storage : InventoryHolder, IDataPersistence<GameData>
{
private Inventory inventory = new Inventory(-1);
public override Inventory Inventory => inventory;
public override string Name => gameObject.name;
void Awake()
{
// Add("Лимонад", 5);
// Add("Тортик", 22);
// Add("Спичка", 100);
}
// private void Add(string key, int value)
// {
// int added = inventory.inventory.Add(key, value, true);
// Debug.Log($"{key}: добавлено {added} из {value}");
// if (added < value) {
// int dropped = DropToInventory.inventory.Add(key, value - added);
// Debug.Log($"{key}: брошено {dropped} из {value - added}");
// }
// }
public void LoadData(GameData data)
{
inventory.LoadData(data.storage.inventory);
}
public void SaveData(GameData data)
{
inventory.SaveData(data.storage.inventory);
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 003acbbf759b3bc4ea37150bcd331f99

View File

@ -14,13 +14,13 @@ public class InfoBox : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
private UIDocument uiDocument;
private Camera mainCamera;
private IInventoryHolder inventoryHolder;
private InventoryHolder inventoryHolder;
private Label infoBox;
void Start()
{
mainCamera = Camera.main;
inventoryHolder = GetComponent<IInventoryHolder>();
inventoryHolder = GetComponent<InventoryHolder>();
uiDocument = gameObject.AddComponent<UIDocument>();
uiDocument.panelSettings = uiPanelSettings;

View File

@ -1,39 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UIElements;
public class InventoryScreen : MonoBehaviour
{
[SerializeField]
private VisualTreeAsset uiInventoryAsset;
[SerializeField]
private VisualTreeAsset uiItemAsset;
private UIDocument uiDocument;
private VisualElement root;
private VisualElement itemList;
private Label headerLabel;
private Label footerLabel;
private VisualElement sourceInventory;
private VisualElement targetInventory;
private IInventoryHolder inventoryHolder;
private IInventoryHolder targetInventoryHolder;
// private InventoryHolder inventoryHolder;
// private InventoryHolder targetInventoryHolder;
void OnEnable()
{
uiDocument = GetComponent<UIDocument>();
root = uiDocument.rootVisualElement;
var inventory = root.Q("Inventory");
sourceInventory = root.Q("SourceInventory");
sourceInventory.style.display = DisplayStyle.None;
targetInventory = root.Q("TargetInventory");
targetInventory.style.display = DisplayStyle.None;
root.style.display = DisplayStyle.None;
itemList = inventory.Q("Inventory").Q("ContainerScroll");
headerLabel = inventory.Q<Label>("Header");
footerLabel = inventory.Q<Label>("Footer");
Hide();
root.RegisterCallback<ClickEvent>(OnRootClicked);
inventory.RegisterCallback<ClickEvent>(evt => evt.StopPropagation());
sourceInventory.RegisterCallback<ClickEvent>(evt => evt.StopPropagation());
targetInventory.RegisterCallback<ClickEvent>(evt => evt.StopPropagation());
}
private void OnRootClicked(ClickEvent evt)
@ -52,14 +55,37 @@ public class InventoryScreen : MonoBehaviour
root.style.display = DisplayStyle.None;
}
public void Display(IInventoryHolder inventory, IInventoryHolder targetInventory = null)
public void Display(InventoryHolder sourceInventory, InventoryHolder targetInventory = null)
{
this.inventoryHolder = inventory;
this.targetInventoryHolder = inventory;
ShowInventory(this.sourceInventory, sourceInventory);
ShowInventory(this.targetInventory, targetInventory);
Show();
}
public void ShowInventory(VisualElement inventory, InventoryHolder holder)
{
inventory.Clear();
if (holder == null)
{
inventory.style.display = DisplayStyle.None;
return;
}
inventory.style.display = DisplayStyle.Flex;
uiInventoryAsset.CloneTree(inventory);
// TemplateContainer inventory = uiInventoryAsset.Instantiate();
// container.Add(inventory);
var itemList = inventory.Q("Inventory").Q("ContainerScroll");
var headerLabel = inventory.Q<Label>("Header");
var footerLabel = inventory.Q<Label>("Footer");
itemList.Clear();
foreach (var item in inventory.Inventory.Items)
foreach (var item in holder.Inventory.Items)
{
var child = uiItemAsset.Instantiate();
// child.AddToClassList(".item");
@ -68,9 +94,7 @@ public class InventoryScreen : MonoBehaviour
itemList.Add(child);
}
headerLabel.text = inventory.Name;
footerLabel.text = $"Свободно: {inventory.Inventory.Free}";
Show();
headerLabel.text = holder.Name;
footerLabel.text = $"Свободно: {holder.Inventory.Free}";
}
}

View File

@ -5,6 +5,9 @@ using UnityEngine.UIElements;
public class InventoryScreenInvoker : MonoBehaviour, IPointerClickHandler
{
public InventoryHolder SourceInventory;
public InventoryHolder TargetInventory;
public void OnPointerClick(PointerEventData eventData)
{
Show();
@ -19,13 +22,6 @@ public class InventoryScreenInvoker : MonoBehaviour, IPointerClickHandler
return;
}
var inventory = GetComponent<IInventoryHolder>();
if (inventory == null)
{
Debug.Log("Cannot show inventory screen on an object without an inventory");
return;
}
inventoryScreen.Display(inventory);
inventoryScreen.Display(SourceInventory, TargetInventory);
}
}

View File

@ -10,13 +10,18 @@
margin: 30px;
}
.inventoryContainer {
flex-shrink: 0;
flex-grow: 0;
flex-direction: row;
}
.inventory {
width: initial;
aspect-ratio: 0.7;
background-color: rgb(255, 0, 0);
/* max-width: 40%; */
margin: 10px;
flex-grow: 1;
}
.inventory > .header {

View File

@ -1,12 +1,7 @@
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<Style src="project://database/Assets/UI/InventoryScreen.uss?fileID=7433441132597879392&amp;guid=32cc109c30db4d449bcd8b7bffbef9ba&amp;type=3#InventoryScreen"/>
<ui:VisualElement name="Screen">
<ui:VisualElement name="Inventory" class="inventory" style="flex-grow: 0;">
<ui:Label text="Inventory Holder Name" name="Header" enable-rich-text="true" class="header"/>
<ui:VisualElement name="Container" class="container" style="flex-grow: 1; flex-basis: auto;">
<ui:ScrollView name="ContainerScroll" style="height: 100%; width: 100%; flex-direction: column; flex-wrap: wrap; align-items: flex-start; flex-grow: 1;"/>
</ui:VisualElement>
<ui:Label text="Footer" name="Footer" class="footer"/>
</ui:VisualElement>
<ui:VisualElement name="SourceInventory" class="inventoryContainer" />
<ui:VisualElement name="TargetInventory" class="inventoryContainer" />
</ui:VisualElement>
</ui:UXML>

View File

@ -0,0 +1,9 @@
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:VisualElement name="Inventory" class="inventory" style="flex-grow: 0;">
<ui:Label text="Inventory Holder Name" name="Header" enable-rich-text="true" class="header"/>
<ui:VisualElement name="Container" class="container" style="flex-grow: 1; flex-basis: auto;">
<ui:ScrollView name="ContainerScroll" style="height: 100%; width: 100%; flex-direction: column; flex-wrap: wrap; align-items: flex-start; flex-grow: 1;"/>
</ui:VisualElement>
<ui:Label text="Footer" name="Footer" class="footer"/>
</ui:VisualElement>
</ui:UXML>

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 473047aab40dd3b42870b44f023fbaa5
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@ -1,4 +1,3 @@
<Solution>
<Project Path="Assembly-CSharp.csproj" />
<Project Path="Assembly-CSharp-Editor.csproj" />
</Solution>