initial commit
This commit is contained in:
parent
6715289efe
commit
788c3389af
37645 changed files with 2526849 additions and 80 deletions
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 296771b4ca0d031561adfd16fb87090c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using SLZ.Marrow;
|
||||
|
||||
using SLZ.MarrowEditor;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
[InitializeOnLoad]
|
||||
public static class AWToolbarButton
|
||||
{
|
||||
static Type m_toolbarType = typeof(Editor).Assembly.GetType("UnityEditor.Toolbar");
|
||||
static ScriptableObject m_currentToolbar;
|
||||
public static GUIStyle iconButtonStyle;
|
||||
public static Action OnToolbarGUILeft;
|
||||
private static GUIContent iconButton;
|
||||
private static GUIStyle iconStyle;
|
||||
private static Texture2D spawnableIcon;
|
||||
private static FieldInfo mRootFieldInfo;
|
||||
static AWToolbarButton()
|
||||
{
|
||||
EditorApplication.update -= OnUpdate;
|
||||
EditorApplication.update += OnUpdate;
|
||||
Type toolbarType = typeof(Editor).Assembly.GetType("UnityEditor.Toolbar");
|
||||
string fieldName = "k_ToolCount";
|
||||
FieldInfo toolIcons = toolbarType.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
|
||||
OnToolbarGUILeft = GUILeft;
|
||||
}
|
||||
|
||||
public static void GUILeft()
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
OnToolbarGUI();
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
public static void OnToolbarGUI()
|
||||
{
|
||||
GUILayout.Space(4);
|
||||
if (iconButton == null)
|
||||
{
|
||||
string buttonIconPath = MarrowSDK.GetPackagePath("Editor/Assets/Icons/Warehouse/hunter.png");
|
||||
spawnableIcon = EditorGUIUtility.Load(buttonIconPath) as Texture2D;
|
||||
iconButton = new GUIContent(spawnableIcon, "Asset Warehouse");
|
||||
}
|
||||
|
||||
if (iconButtonStyle == null)
|
||||
{
|
||||
iconButtonStyle = new GUIStyle("Command")
|
||||
{
|
||||
fontSize = 16,
|
||||
alignment = TextAnchor.MiddleCenter,
|
||||
imagePosition = ImagePosition.ImageAbove,
|
||||
fontStyle = FontStyle.Bold,
|
||||
fixedHeight = 20,
|
||||
padding = new RectOffset(1, 1, 1, 1)
|
||||
};
|
||||
}
|
||||
|
||||
if (GUILayout.Button(iconButton, iconButtonStyle))
|
||||
{
|
||||
AssetWarehouseWindow.ShowWindow();
|
||||
}
|
||||
}
|
||||
|
||||
static void OnUpdate()
|
||||
{
|
||||
if (m_currentToolbar == null)
|
||||
{
|
||||
var toolbars = Resources.FindObjectsOfTypeAll(m_toolbarType);
|
||||
m_currentToolbar = toolbars.Length > 0 ? (ScriptableObject)toolbars[0] : null;
|
||||
if (m_currentToolbar != null)
|
||||
{
|
||||
if (mRootFieldInfo == null)
|
||||
{
|
||||
mRootFieldInfo = m_currentToolbar.GetType().GetField("m_Root", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
}
|
||||
|
||||
var rawRoot = mRootFieldInfo.GetValue(m_currentToolbar);
|
||||
var mRoot = rawRoot as VisualElement;
|
||||
RegisterCallback("ToolbarZoneLeftAlign", OnToolbarGUILeft);
|
||||
void RegisterCallback(string root, Action cb)
|
||||
{
|
||||
var toolbarZone = mRoot.Q(root);
|
||||
var parent = new VisualElement()
|
||||
{
|
||||
style =
|
||||
{
|
||||
flexGrow = 1,
|
||||
flexDirection = FlexDirection.Row,
|
||||
}
|
||||
};
|
||||
var container = new IMGUIContainer();
|
||||
container.style.flexGrow = 1;
|
||||
container.onGUIHandler += () =>
|
||||
{
|
||||
cb?.Invoke();
|
||||
};
|
||||
parent.Add(container);
|
||||
toolbarZone.Add(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 50bbea8e730eb7f46870942bf7981de8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
using System;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using SLZ.MarrowEditor;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public class MarrowProjectValidationWindow : EditorWindow
|
||||
{
|
||||
private GUIStyle windowStyle = null;
|
||||
private GUIStyle boldLabelStyle = null;
|
||||
private GUIStyle issueBoxStyle = null;
|
||||
private GUIStyle wrapStyle = null;
|
||||
[NonSerialized]
|
||||
public List<MarrowProjectValidation.MarrowValidationRule> ruleIssues = new List<MarrowProjectValidation.MarrowValidationRule>();
|
||||
[NonSerialized]
|
||||
public bool validateChecked = false;
|
||||
[NonSerialized]
|
||||
public bool issuesExist = false;
|
||||
public Action OnClose;
|
||||
[MenuItem("Stress Level Zero/Void Tools/Validate Marrow Project Settings", false, 50)]
|
||||
public static MarrowProjectValidationWindow ShowWindow()
|
||||
{
|
||||
var window = GetWindow<MarrowProjectValidationWindow>();
|
||||
window.titleContent = new GUIContent(" Marrow Project Validation", EditorGUIUtility.IconContent("Error@2x").image);
|
||||
window.minSize = new Vector2(500.0f, 300.0f);
|
||||
window.CheckValidation(true);
|
||||
window.Show();
|
||||
return window;
|
||||
}
|
||||
|
||||
private void CacheStyles()
|
||||
{
|
||||
if (windowStyle == null)
|
||||
{
|
||||
windowStyle = new GUIStyle(EditorStyles.label)
|
||||
{
|
||||
margin = new RectOffset(5, 5, 5, 5),
|
||||
};
|
||||
}
|
||||
|
||||
if (boldLabelStyle == null)
|
||||
{
|
||||
boldLabelStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
stretchWidth = false
|
||||
};
|
||||
}
|
||||
|
||||
if (issueBoxStyle == null)
|
||||
{
|
||||
issueBoxStyle = new GUIStyle(EditorStyles.helpBox)
|
||||
{
|
||||
};
|
||||
var paddingOffset = issueBoxStyle.padding;
|
||||
int offset = (int)(EditorGUIUtility.singleLineHeight / 4f);
|
||||
paddingOffset.bottom += offset;
|
||||
paddingOffset.top += offset;
|
||||
paddingOffset.left += offset;
|
||||
paddingOffset.right += offset;
|
||||
}
|
||||
|
||||
if (wrapStyle == null)
|
||||
{
|
||||
wrapStyle = new GUIStyle(EditorStyles.label)
|
||||
{
|
||||
wordWrap = true,
|
||||
alignment = TextAnchor.MiddleLeft,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckValidation(bool force = false)
|
||||
{
|
||||
if (!validateChecked || force)
|
||||
{
|
||||
MarrowProjectValidation.GetIssues(ruleIssues);
|
||||
issuesExist = ruleIssues.Count > 0;
|
||||
validateChecked = true;
|
||||
if (issuesExist)
|
||||
{
|
||||
titleContent = new GUIContent(" Marrow Project Validation", EditorGUIUtility.IconContent("Error@2x").image);
|
||||
}
|
||||
else
|
||||
{
|
||||
titleContent = new GUIContent(" Marrow Project Validation", EditorGUIUtility.IconContent("P4_CheckOutRemote@2x").image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
CacheStyles();
|
||||
CheckValidation();
|
||||
using (new EditorGUILayout.VerticalScope(windowStyle))
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
if (ruleIssues.Count <= 0)
|
||||
{
|
||||
EditorGUILayout.LabelField("No issues found in project.");
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button("Cool", MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.LabelField("Issues found in project!");
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.LabelField($"{ruleIssues.Count} Issue{(ruleIssues.Count > 1 ? "s" : "")}", boldLabelStyle);
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button("Fix All", MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
MarrowProjectValidation.FixIssues(ruleIssues);
|
||||
validateChecked = false;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
foreach (var issue in ruleIssues)
|
||||
{
|
||||
using (new EditorGUILayout.HorizontalScope(issueBoxStyle))
|
||||
{
|
||||
GUILayout.Label(EditorGUIUtility.IconContent("Error"));
|
||||
GUILayout.Label(issue.message, wrapStyle);
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button(new GUIContent("Fix", issue.fixMessage), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
try
|
||||
{
|
||||
issue.FixRule();
|
||||
validateChecked = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"MarrowProjectValidation: Failed to run fix validation on \"{issue.message}\"");
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
OnClose?.Invoke();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bc7cff9c17a1e2b42af5f0ec03e27566
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#if false
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8149728211e47c646919eaa05048a287
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"name": "SLZ.Marrow.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"SLZ.Algorithms.Unity.Editor",
|
||||
"SLZ.Algorithms.Unity",
|
||||
"SLZ.Algorithms",
|
||||
"SLZ.Marrow",
|
||||
"SLZ.Marrow.Unprivated",
|
||||
"SLZ.Marrow.Unprivated.Editor",
|
||||
"SLZ.Marrow.Unprivated.Unsafe",
|
||||
"SLZ.Marrow.VoidLogic.Core",
|
||||
"UltEvents",
|
||||
"UniTask.Addressables",
|
||||
"UniTask.Linq",
|
||||
"UniTask",
|
||||
"Unity.Addressables.Editor",
|
||||
"Unity.Addressables",
|
||||
"Unity.Mathematics",
|
||||
"Unity.RenderPipelines.Universal.Runtime",
|
||||
"Unity.ResourceManager",
|
||||
"Unity.ScriptableBuildPipeline",
|
||||
"Unity.ScriptableBuildPipeline.Editor",
|
||||
"Unity.Splines",
|
||||
"Unity.XR.Management.Editor",
|
||||
"Unity.XR.Management",
|
||||
"Unity.XR.Oculus",
|
||||
"Unity.Profiling.Core",
|
||||
"ModResources",
|
||||
"ZString"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.render-pipelines.universal",
|
||||
"expression": "",
|
||||
"define": "UNIVERSAL_RP"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c86a26d8b8257bb4fa71737f63116422
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 56be2341a9d36c77e3a56b49d0f69179
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using SLZ.MarrowEditor;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using WebSocketSharp;
|
||||
|
||||
namespace SLZ.Marrow
|
||||
{
|
||||
public sealed class DevModeWindow : EditorWindow
|
||||
{
|
||||
[MenuItem("Stress Level Zero/Void Tools/DevMode", false, 104)]
|
||||
public static void ShowConsoleCommandTester()
|
||||
{
|
||||
var window = GetWindow<DevModeWindow>();
|
||||
window.ShowUtility();
|
||||
}
|
||||
|
||||
private static WebSocketSharp.WebSocket websocket;
|
||||
public string path = "ws://127.0.0.1:50152/console";
|
||||
public string command = "";
|
||||
public static bool DevModeEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return websocket != null && websocket.ReadyState == WebSocketState.Open;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Pallet> cachedPallets;
|
||||
private void OnGUI()
|
||||
{
|
||||
using (new EditorGUILayout.VerticalScope())
|
||||
{
|
||||
path = EditorGUILayout.TextField("WebSocket", path);
|
||||
command = EditorGUILayout.TextField("Command", command);
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
using (new EditorGUI.DisabledScope(websocket is { ReadyState: WebSocketState.Open }))
|
||||
{
|
||||
if (GUILayout.Button("Connect"))
|
||||
{
|
||||
if (websocket != null)
|
||||
{
|
||||
((IDisposable)websocket).Dispose();
|
||||
websocket = null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
websocket = new WebSocketSharp.WebSocket(path);
|
||||
websocket.OnMessage += (sender, e) => Debug.Log(e.Data);
|
||||
websocket.Connect();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (new EditorGUI.DisabledScope(websocket is not { ReadyState: WebSocketState.Open or WebSocketState.Connecting }))
|
||||
{
|
||||
if (GUILayout.Button("Disconnect"))
|
||||
{
|
||||
try
|
||||
{
|
||||
websocket.Close();
|
||||
((IDisposable)websocket).Dispose();
|
||||
websocket = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (websocket != null)
|
||||
{
|
||||
GUILayout.Label($"Ready state: {websocket.ReadyState.ToString()}");
|
||||
if (GUILayout.Button("Send"))
|
||||
{
|
||||
websocket.Send(command);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
if (DevModeEnabled)
|
||||
{
|
||||
EditorGUILayout.LabelField("Dev Tools: ", EditorStyles.boldLabel);
|
||||
if (GUILayout.Button(new GUIContent("Reload Level", "Reloads current loaded level"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
websocket.Send($"level.reload");
|
||||
}
|
||||
|
||||
if (AssetWarehouse.Instance != null)
|
||||
{
|
||||
EditorGUILayout.LabelField("Reload Pallet: ", EditorStyles.boldLabel);
|
||||
AssetWarehouse.Instance.GetPallets(ref cachedPallets);
|
||||
foreach (var pallet in cachedPallets)
|
||||
{
|
||||
if (GUILayout.Button(new GUIContent(pallet.Title, $"Reload {pallet.Title}"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
websocket.Send($"assetwarehouse.reload {pallet.Barcode}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 25e8734031b04f30902a04f5044aaea1
|
||||
timeCreated: 1661110022
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.Marrow
|
||||
{
|
||||
public class DragAndDropManipulatorListHelper : PointerManipulator
|
||||
{
|
||||
Label dropLabel;
|
||||
public Object[] droppedObjects = null;
|
||||
string assetPath = string.Empty;
|
||||
public DragAndDropManipulatorListHelper(VisualElement root)
|
||||
{
|
||||
target = root.Q<VisualElement>(className: "drop-area");
|
||||
dropLabel = root.Q<Label>(className: "drop-area__label");
|
||||
}
|
||||
|
||||
protected override void RegisterCallbacksOnTarget()
|
||||
{
|
||||
target.RegisterCallback<PointerDownEvent>(OnPointerDown);
|
||||
target.RegisterCallback<DragEnterEvent>(OnDragEnter);
|
||||
target.RegisterCallback<DragLeaveEvent>(OnDragLeave);
|
||||
target.RegisterCallback<DragUpdatedEvent>(OnDragUpdate);
|
||||
target.RegisterCallback<DragPerformEvent>(OnDragPerform);
|
||||
}
|
||||
|
||||
protected override void UnregisterCallbacksFromTarget()
|
||||
{
|
||||
target.UnregisterCallback<PointerDownEvent>(OnPointerDown);
|
||||
target.UnregisterCallback<DragEnterEvent>(OnDragEnter);
|
||||
target.UnregisterCallback<DragLeaveEvent>(OnDragLeave);
|
||||
target.UnregisterCallback<DragUpdatedEvent>(OnDragUpdate);
|
||||
target.UnregisterCallback<DragPerformEvent>(OnDragPerform);
|
||||
}
|
||||
|
||||
void OnPointerDown(PointerDownEvent _)
|
||||
{
|
||||
if (droppedObjects != null)
|
||||
{
|
||||
DragAndDrop.PrepareStartDrag();
|
||||
DragAndDrop.objectReferences = droppedObjects;
|
||||
if (assetPath != string.Empty)
|
||||
{
|
||||
DragAndDrop.paths = new[]
|
||||
{
|
||||
assetPath
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
DragAndDrop.paths = new string[]
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
DragAndDrop.StartDrag(string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
void OnDragEnter(DragEnterEvent _)
|
||||
{
|
||||
var draggedName = string.Empty;
|
||||
if (DragAndDrop.paths.Length > 0)
|
||||
{
|
||||
assetPath = DragAndDrop.paths[0];
|
||||
var splitPath = assetPath.Split('/');
|
||||
draggedName = splitPath[splitPath.Length - 1];
|
||||
}
|
||||
else if (DragAndDrop.objectReferences.Length > 0)
|
||||
{
|
||||
draggedName = DragAndDrop.objectReferences[0].name;
|
||||
}
|
||||
|
||||
dropLabel.text = $"Dropping '{draggedName}'...";
|
||||
target.AddToClassList("drop-area--dropping");
|
||||
}
|
||||
|
||||
void OnDragLeave(DragLeaveEvent _)
|
||||
{
|
||||
assetPath = string.Empty;
|
||||
droppedObjects = null;
|
||||
dropLabel.text = "Drag an asset here...";
|
||||
target.RemoveFromClassList("drop-area--dropping");
|
||||
}
|
||||
|
||||
void OnDragUpdate(DragUpdatedEvent _)
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
|
||||
}
|
||||
|
||||
void OnDragPerform(DragPerformEvent _)
|
||||
{
|
||||
droppedObjects = DragAndDrop.objectReferences;
|
||||
string draggedName = "";
|
||||
if (assetPath != string.Empty)
|
||||
{
|
||||
var splitPath = assetPath.Split('/');
|
||||
draggedName = splitPath[splitPath.Length - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var droppedObject in droppedObjects)
|
||||
{
|
||||
draggedName += droppedObject.name;
|
||||
}
|
||||
}
|
||||
|
||||
target.RemoveFromClassList("drop-area--dropping");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d9771bb522870a441a3ac411f57437b7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,704 @@
|
|||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using SLZ.Marrow.Utilities;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using SLZ.MarrowEditor;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.Marrow
|
||||
{
|
||||
[CanEditMultipleObjects]
|
||||
[CustomEditor(typeof(ImpactProperties))]
|
||||
public class ImpactPropertiesEditor : Editor
|
||||
{
|
||||
ImpactProperties script;
|
||||
private static GUIContent previewMeshGizmoIcon = null;
|
||||
private static GUIContent materialIconOn = null;
|
||||
private static GUIContent materialIconOff = null;
|
||||
public ToolbarToggle showPreviewMeshToolbarToggle;
|
||||
private static List<GameObject> allGameObjects = new List<GameObject>();
|
||||
private static List<GameObject> unattachedColsMissingImpactProperties = new List<GameObject>();
|
||||
private static List<GameObject> rbAttachedColsMissingImpactProperties = new List<GameObject>();
|
||||
VisualElement applyPhysMatsContainer;
|
||||
private static GameObject m_LastHoveredObject;
|
||||
private void OnEnable()
|
||||
{
|
||||
script = (ImpactProperties)target;
|
||||
if (previewMeshGizmoIcon == null)
|
||||
{
|
||||
previewMeshGizmoIcon = new GUIContent(EditorGUIUtility.IconContent("d_GizmosToggle On@2x"));
|
||||
previewMeshGizmoIcon.tooltip = "Toggle Preview Mesh Gizmo";
|
||||
}
|
||||
|
||||
if (allGameObjects == null)
|
||||
{
|
||||
allGameObjects = new List<GameObject>();
|
||||
}
|
||||
|
||||
if (allGameObjects?.Count == 0)
|
||||
{
|
||||
allGameObjects = FindObjectsOfType<GameObject>().ToList();
|
||||
foreach (GameObject gameObj in allGameObjects)
|
||||
{
|
||||
if (gameObj.TryGetComponent<Collider>(out var gameObjHasCol) && !gameObjHasCol.isTrigger)
|
||||
{
|
||||
if (!gameObj.GetComponent<ImpactProperties>())
|
||||
{
|
||||
if (gameObjHasCol.attachedRigidbody == null)
|
||||
{
|
||||
if (!unattachedColsMissingImpactProperties.Contains(gameObj))
|
||||
{
|
||||
unattachedColsMissingImpactProperties.Add(gameObj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gameObjHasCol.attachedRigidbody.gameObject.GetComponent<ImpactProperties>() == null)
|
||||
{
|
||||
if (!rbAttachedColsMissingImpactProperties.Contains(gameObjHasCol.attachedRigidbody.gameObject))
|
||||
{
|
||||
rbAttachedColsMissingImpactProperties.Add(gameObjHasCol.attachedRigidbody.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("2956736148bce0e4eb269d7c6a26fb1f");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
PropertyField surfaceDataCardField = tree.Q<PropertyField>("_surfaceDataCard");
|
||||
EnumField decalTypeField = tree.Q<EnumField>("DecalType");
|
||||
PropertyField surfaceDataField = tree.Q<PropertyField>("surfaceData");
|
||||
if (serializedObject.FindProperty("surfaceData") == null)
|
||||
{
|
||||
surfaceDataField.style.display = DisplayStyle.None;
|
||||
}
|
||||
|
||||
applyPhysMatsContainer = tree.Q<VisualElement>("applyPhysMatsContainer");
|
||||
PhysicMaterial suggestedPhysMat = null;
|
||||
Label suggsetedPhysMatLabel = tree.Q<Label>("suggsetedPhysMatLabel");
|
||||
suggsetedPhysMatLabel.text = "";
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
};
|
||||
if (ImpactPropertiesMeshGizmo.ShowGizmo == false)
|
||||
{
|
||||
SceneVisibilityManager.instance.EnableAllPicking();
|
||||
}
|
||||
|
||||
string[] surfaceDCBarcode = new string[targets.Length];
|
||||
string[] surfaceDataName = new string[targets.Length];
|
||||
for (int t = 0; t < targets.Length; t++)
|
||||
{
|
||||
ImpactProperties impactProperties = (ImpactProperties)targets[t];
|
||||
if (impactProperties != null && impactProperties.SurfaceDataCard != null)
|
||||
{
|
||||
surfaceDCBarcode[t] = impactProperties.SurfaceDataCard.Barcode.ToString();
|
||||
}
|
||||
|
||||
#if false
|
||||
#endif
|
||||
ShowImpactPropsFieldHasOverride(impactProperties, decalTypeField);
|
||||
ShowImpactPropsFieldHasOverride(impactProperties, surfaceDataCardField);
|
||||
}
|
||||
|
||||
suggestedPhysMat = UpdateSuggestedPhysMat(script);
|
||||
if (suggestedPhysMat != null && suggsetedPhysMatLabel.text.Replace(" (Instance)", "").Trim() != suggestedPhysMat.name.Trim())
|
||||
{
|
||||
suggsetedPhysMatLabel.text = suggestedPhysMat.name;
|
||||
}
|
||||
|
||||
surfaceDataCardField.RegisterValueChangeCallback((evt) =>
|
||||
{
|
||||
for (int t = 0; t < targets.Length; t++)
|
||||
{
|
||||
ImpactProperties impactProperties = (ImpactProperties)targets[t];
|
||||
if (impactProperties != null && impactProperties.SurfaceDataCard != null && impactProperties.SurfaceDataCard.IsValid() && impactProperties.SurfaceDataCard.TryGetDataCard(out SurfaceDataCard sdc))
|
||||
{
|
||||
if (sdc != null && sdc.Barcode.ToString() != surfaceDCBarcode[t])
|
||||
{
|
||||
ImpactPropertiesMeshGizmo.DisableGizmo(impactProperties);
|
||||
Undo.RecordObject(impactProperties, impactProperties.name + "SD Card updated");
|
||||
surfaceDCBarcode[t] = sdc.Barcode.ToString();
|
||||
EditorUtility.SetDirty(impactProperties);
|
||||
if (PrefabUtility.GetPrefabAssetType(impactProperties) == PrefabAssetType.Regular || PrefabUtility.GetPrefabAssetType(impactProperties) == PrefabAssetType.Variant)
|
||||
{
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(impactProperties);
|
||||
ShowImpactPropsFieldHasOverride(impactProperties, surfaceDataCardField);
|
||||
}
|
||||
}
|
||||
|
||||
suggestedPhysMat = UpdateSuggestedPhysMat(impactProperties);
|
||||
if (suggestedPhysMat != null && suggsetedPhysMatLabel.text.Replace(" (Instance)", "").Trim() != suggestedPhysMat.name.Trim())
|
||||
{
|
||||
suggsetedPhysMatLabel.text = suggestedPhysMat.name;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (impactProperties != null && ImpactPropertiesMeshGizmo.ShowGizmo)
|
||||
{
|
||||
ImpactPropertiesMeshGizmo.DisableGizmo(impactProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
decalTypeField.RegisterValueChangedCallback((evt) =>
|
||||
{
|
||||
foreach (UnityEngine.Object target in targets)
|
||||
{
|
||||
ImpactProperties impactProperties = (ImpactProperties)target;
|
||||
Undo.RecordObject(impactProperties, impactProperties.name + "DecalType updated");
|
||||
impactProperties.decalType = (ImpactProperties.DecalType)decalTypeField.value;
|
||||
EditorUtility.SetDirty(impactProperties);
|
||||
if (PrefabUtility.GetPrefabAssetType(impactProperties) == PrefabAssetType.Regular || PrefabUtility.GetPrefabAssetType(impactProperties) == PrefabAssetType.Variant)
|
||||
{
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(impactProperties);
|
||||
ShowImpactPropsFieldHasOverride(impactProperties, decalTypeField);
|
||||
}
|
||||
}
|
||||
});
|
||||
decalTypeField.value = script.decalType;
|
||||
#if false
|
||||
#endif
|
||||
Texture physmatIcon = EditorGUIUtility.ObjectContent(null, typeof(PhysicMaterial)).image;
|
||||
Image physmatIconImage = new Image();
|
||||
physmatIconImage.image = physmatIcon;
|
||||
physmatIconImage.style.flexShrink = 0;
|
||||
physmatIconImage.StretchToParentSize();
|
||||
VisualElement suggestPhysMatsIcon = tree.Q<VisualElement>("suggestPhysMatsIcon");
|
||||
suggestPhysMatsIcon.style.flexShrink = 0;
|
||||
suggestPhysMatsIcon.Add(physmatIconImage);
|
||||
Button applyPhysMatsButton = tree.Q<Button>("applyPhysMatsButton");
|
||||
applyPhysMatsButton.style.flexShrink = 0;
|
||||
applyPhysMatsButton.tooltip = "Applies the suggested Physics Material to this Impact Properties sibling collider(s)";
|
||||
applyPhysMatsButton.clickable.clicked += () =>
|
||||
{
|
||||
for (int t = 0; t < targets.Length; t++)
|
||||
{
|
||||
ImpactProperties impactProperties = (ImpactProperties)targets[t];
|
||||
if (impactProperties != null && impactProperties.SurfaceDataCard != null && impactProperties.SurfaceDataCard.IsValid() && suggestedPhysMat != null)
|
||||
{
|
||||
if (impactProperties.TryGetComponent<Collider>(out var siblingCol))
|
||||
{
|
||||
if (siblingCol.sharedMaterial != suggestedPhysMat)
|
||||
{
|
||||
if (PrefabUtility.HasPrefabInstanceAnyOverrides(impactProperties.gameObject, false))
|
||||
{
|
||||
siblingCol.sharedMaterial = suggestedPhysMat;
|
||||
}
|
||||
else
|
||||
{
|
||||
siblingCol.sharedMaterial = suggestedPhysMat;
|
||||
}
|
||||
|
||||
EditorUtility.SetDirty(siblingCol);
|
||||
if (PrefabUtility.GetPrefabAssetType(siblingCol) == PrefabAssetType.Regular || PrefabUtility.GetPrefabAssetType(siblingCol) == PrefabAssetType.Variant)
|
||||
{
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(siblingCol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/ImpactProperties");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
showPreviewMeshToolbarToggle = tree.Q<ToolbarToggle>("showPreviewMeshToolbarToggle");
|
||||
Image showPreviewMeshIconImage = new Image
|
||||
{
|
||||
image = previewMeshGizmoIcon.image
|
||||
};
|
||||
showPreviewMeshToolbarToggle.Add(showPreviewMeshIconImage);
|
||||
showPreviewMeshToolbarToggle.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
ImpactPropertiesMeshGizmo.ShowGizmo = showPreviewMeshToolbarToggle.value;
|
||||
UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
|
||||
if (ImpactPropertiesMeshGizmo.ShowGizmo)
|
||||
{
|
||||
SurfaceDataPainterOverlay.DoWithInstances(instance => instance.displayed = true);
|
||||
SurfaceDataPainterOverlay.DoWithInstances(instance => instance.collapsed = false);
|
||||
}
|
||||
else
|
||||
{
|
||||
SurfaceDataPainterOverlay.DoWithInstances(instance => instance.displayed = false);
|
||||
}
|
||||
});
|
||||
SliderInt gizmoVisRangeSlider = tree.Q<SliderInt>("gizmoVisRangeSlider");
|
||||
gizmoVisRangeSlider.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
ImpactPropertiesMeshGizmo.gizmoVisRange = gizmoVisRangeSlider.value;
|
||||
});
|
||||
showPreviewMeshToolbarToggle.SetValueWithoutNotify(ImpactPropertiesMeshGizmo.ShowGizmo);
|
||||
gizmoVisRangeSlider.SetValueWithoutNotify((int)ImpactPropertiesMeshGizmo.gizmoVisRange);
|
||||
return tree;
|
||||
}
|
||||
|
||||
private PhysicMaterial UpdateSuggestedPhysMat(ImpactProperties impactProperties)
|
||||
{
|
||||
bool colMatSuggestedMismatch = false;
|
||||
PhysicMaterial suggestedPhysMat;
|
||||
impactProperties.TryGetComponent(out Rigidbody ipRigidBody);
|
||||
if (impactProperties.SurfaceDataCard.TryGetDataCard(out SurfaceDataCard sdc))
|
||||
{
|
||||
if (ipRigidBody)
|
||||
{
|
||||
suggestedPhysMat = (PhysicMaterial)AssetDatabase.LoadMainAssetAtPath(AssetDatabase.GUIDToAssetPath(sdc.PhysicsMaterial.AssetGUID));
|
||||
}
|
||||
else
|
||||
{
|
||||
suggestedPhysMat = (PhysicMaterial)AssetDatabase.LoadMainAssetAtPath(AssetDatabase.GUIDToAssetPath(sdc.PhysicsMaterialStatic.AssetGUID));
|
||||
;
|
||||
}
|
||||
|
||||
for (int t = 0; t < targets.Length; t++)
|
||||
{
|
||||
ImpactProperties impactProp = (ImpactProperties)targets[t];
|
||||
if (impactProp.TryGetComponent<Collider>(out var siblingColSelected))
|
||||
{
|
||||
if (siblingColSelected.sharedMaterial != suggestedPhysMat)
|
||||
{
|
||||
colMatSuggestedMismatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (impactProperties.TryGetComponent<Collider>(out var siblingCol))
|
||||
{
|
||||
if (siblingCol.sharedMaterial != suggestedPhysMat)
|
||||
{
|
||||
applyPhysMatsContainer.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
else if (colMatSuggestedMismatch)
|
||||
{
|
||||
applyPhysMatsContainer.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
else
|
||||
{
|
||||
applyPhysMatsContainer.style.display = DisplayStyle.None;
|
||||
}
|
||||
}
|
||||
|
||||
return suggestedPhysMat;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ShowImpactPropsFieldHasOverride(ImpactProperties impactProperties, VisualElement overrideField)
|
||||
{
|
||||
Color overrideMarginColor = new Color32(5, 147, 224, 255);
|
||||
if (PrefabUtility.HasPrefabInstanceAnyOverrides(impactProperties.gameObject, false))
|
||||
{
|
||||
PropertyModification[] prefabOverrides = PrefabUtility.GetPropertyModifications(impactProperties.gameObject);
|
||||
int decalOverrideCount = 0;
|
||||
int sdCardOverrideCount = 0;
|
||||
int obsSDOverrideCount = 0;
|
||||
foreach (var prefabOverride in prefabOverrides)
|
||||
{
|
||||
if (PrefabStageUtility.GetCurrentPrefabStage() == null)
|
||||
{
|
||||
if (prefabOverride.propertyPath == "_surfaceDataCard._barcode._id" && overrideField.name == "_surfaceDataCard")
|
||||
{
|
||||
overrideField.style.marginLeft = 3;
|
||||
overrideField.style.paddingLeft = 3;
|
||||
overrideField.style.unityFontStyleAndWeight = FontStyle.Bold;
|
||||
overrideField.style.borderLeftColor = overrideMarginColor;
|
||||
overrideField.style.borderLeftWidth = 3;
|
||||
sdCardOverrideCount++;
|
||||
}
|
||||
|
||||
if (prefabOverride.propertyPath == "decalType" && overrideField.name == "DecalType")
|
||||
{
|
||||
overrideField.style.marginLeft = 3;
|
||||
overrideField.style.paddingLeft = 3;
|
||||
overrideField.style.unityFontStyleAndWeight = FontStyle.Bold;
|
||||
overrideField.style.borderLeftColor = overrideMarginColor;
|
||||
overrideField.style.borderLeftWidth = 3;
|
||||
decalOverrideCount++;
|
||||
}
|
||||
|
||||
if (prefabOverride.propertyPath == "surfaceData" && overrideField.name == "surfaceData")
|
||||
{
|
||||
overrideField.style.paddingLeft = 3;
|
||||
overrideField.style.unityFontStyleAndWeight = FontStyle.Bold;
|
||||
overrideField.style.borderLeftColor = overrideMarginColor;
|
||||
overrideField.style.borderLeftWidth = 3;
|
||||
obsSDOverrideCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sdCardOverrideCount == 0 && overrideField.name == "_surfaceDataCard")
|
||||
{
|
||||
overrideField.style.marginLeft = 0;
|
||||
overrideField.style.paddingLeft = 0;
|
||||
overrideField.style.unityFontStyleAndWeight = FontStyle.Normal;
|
||||
overrideField.style.borderLeftColor = overrideMarginColor;
|
||||
overrideField.style.borderLeftWidth = 0;
|
||||
}
|
||||
|
||||
if (decalOverrideCount == 0 && overrideField.name == "DecalType")
|
||||
{
|
||||
overrideField.style.paddingLeft = 0;
|
||||
overrideField.style.unityFontStyleAndWeight = FontStyle.Normal;
|
||||
overrideField.style.borderLeftColor = overrideMarginColor;
|
||||
overrideField.style.borderLeftWidth = 0;
|
||||
}
|
||||
|
||||
if (sdCardOverrideCount == 0 && overrideField.name == "surfaceData")
|
||||
{
|
||||
overrideField.style.paddingLeft = 0;
|
||||
overrideField.style.unityFontStyleAndWeight = FontStyle.Normal;
|
||||
overrideField.style.borderLeftColor = overrideMarginColor;
|
||||
overrideField.style.borderLeftWidth = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyObsoleteSurfaceDataMats(ImpactProperties impactProperties)
|
||||
{
|
||||
object[] parametersArray = new Transform[]
|
||||
{
|
||||
impactProperties.transform
|
||||
};
|
||||
Type type = impactProperties.GetType();
|
||||
MethodInfo methodInfo = type.GetMethod("ObsoleteUpdateMaterialRecursive", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
methodInfo.Invoke(impactProperties, parametersArray);
|
||||
}
|
||||
|
||||
private void ApplySurfaceDataCardMats(ImpactProperties impactProperties)
|
||||
{
|
||||
object[] parametersArray = new Transform[]
|
||||
{
|
||||
impactProperties.transform
|
||||
};
|
||||
Type type = impactProperties.GetType();
|
||||
MethodInfo methodInfo = type.GetMethod("ApplyPhysMatsRecursive", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
methodInfo.Invoke(impactProperties, parametersArray);
|
||||
}
|
||||
|
||||
private static void OnGlobalSceneGUI(SceneView sceneView)
|
||||
{
|
||||
if (ImpactPropertiesMeshGizmo.ShowGizmo)
|
||||
{
|
||||
PickHoverObject();
|
||||
GenerateHoverText();
|
||||
}
|
||||
|
||||
if (ImpactProperties.showMissingImpactProperties)
|
||||
{
|
||||
foreach (GameObject gameObj in unattachedColsMissingImpactProperties)
|
||||
{
|
||||
Gizmos.color = Color.red;
|
||||
DrawGizmoHelper.DrawText("MISSING IMPACT PROPS", gameObj.transform.position);
|
||||
}
|
||||
|
||||
foreach (GameObject gameObj in rbAttachedColsMissingImpactProperties)
|
||||
{
|
||||
Gizmos.color = Color.red;
|
||||
DrawGizmoHelper.DrawText("ATTACHED RB MISSING IMPACT PROPS", gameObj.transform.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void PickHoverObject()
|
||||
{
|
||||
var evt = Event.current;
|
||||
if (evt.type == EventType.MouseMove)
|
||||
{
|
||||
var picked = HandleUtility.PickGameObject(evt.mousePosition, false);
|
||||
if (picked != m_LastHoveredObject)
|
||||
{
|
||||
m_LastHoveredObject = picked;
|
||||
}
|
||||
}
|
||||
else if (evt.type == EventType.MouseDrag && evt.button == 1)
|
||||
{
|
||||
var picked = HandleUtility.PickGameObject(evt.mousePosition, false);
|
||||
if (picked != m_LastHoveredObject)
|
||||
{
|
||||
m_LastHoveredObject = picked;
|
||||
}
|
||||
}
|
||||
|
||||
HoverHighlight();
|
||||
}
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
static void InitSceneGUICallback()
|
||||
{
|
||||
SceneView.duringSceneGui += OnGlobalSceneGUI;
|
||||
}
|
||||
|
||||
private static GameObject lastHoveredObject;
|
||||
private static Collider lastHighlightedCollider = null;
|
||||
private static List<Collider> currentSelectedColliders = new List<Collider>();
|
||||
private static List<Collider> lastSelectedColliders = new List<Collider>();
|
||||
private static Color selectColor = new Color(0.5f, 0.5f, 0.5f);
|
||||
private static Color hoverColor = new Color(0.25f, 0.25f, 0.25f);
|
||||
private static HashSet<int> selectedColliderIDs = new HashSet<int>();
|
||||
static void HoverHighlight()
|
||||
{
|
||||
if (ImpactPropertiesMeshGizmo.ShowGizmo)
|
||||
{
|
||||
var evt = Event.current;
|
||||
var selectedGOs = Selection.gameObjects;
|
||||
selectedColliderIDs.Clear();
|
||||
currentSelectedColliders.Clear();
|
||||
foreach (var selected in selectedGOs)
|
||||
{
|
||||
if (selected.TryGetComponent<Collider>(out var selectedCollider) && !selectedCollider.isTrigger)
|
||||
{
|
||||
currentSelectedColliders.Add(selectedCollider);
|
||||
selectedColliderIDs.Add(selectedCollider.GetInstanceID());
|
||||
}
|
||||
}
|
||||
|
||||
var deselected = lastSelectedColliders.Except(currentSelectedColliders);
|
||||
foreach (var lastSelected in deselected)
|
||||
{
|
||||
ImpactPropertiesMeshGizmo.HighlightGizmo(lastSelected, false);
|
||||
}
|
||||
|
||||
var newSelection = currentSelectedColliders.Except(lastSelectedColliders);
|
||||
foreach (var newSelected in newSelection)
|
||||
{
|
||||
ImpactPropertiesMeshGizmo.HighlightGizmo(newSelected, selectColor);
|
||||
}
|
||||
|
||||
lastSelectedColliders.Clear();
|
||||
foreach (var selectedCollider in currentSelectedColliders)
|
||||
{
|
||||
lastSelectedColliders.Add(selectedCollider);
|
||||
}
|
||||
|
||||
if (evt.type != EventType.Repaint)
|
||||
{
|
||||
switch (evt.type)
|
||||
{
|
||||
case EventType.MouseMove:
|
||||
case EventType.MouseDown:
|
||||
case EventType.MouseUp:
|
||||
var picked = HandleUtility.PickGameObject(evt.mousePosition, out _);
|
||||
if (picked != null && (lastHoveredObject == null || picked != lastHoveredObject))
|
||||
{
|
||||
Collider pickedCollider = null;
|
||||
if (picked.activeInHierarchy)
|
||||
{
|
||||
if (!picked.TryGetComponent<Collider>(out pickedCollider) || pickedCollider.isTrigger)
|
||||
{
|
||||
if (picked.TryGetComponent<ImpactPropertiesMeshGizmo>(out var gizmo) && !gizmo.Collider.isTrigger)
|
||||
{
|
||||
pickedCollider = gizmo.Collider;
|
||||
}
|
||||
}
|
||||
|
||||
if (pickedCollider && selectedColliderIDs.Contains(pickedCollider.GetInstanceID()))
|
||||
{
|
||||
if (lastHighlightedCollider && !selectedColliderIDs.Contains(lastHighlightedCollider.GetInstanceID()))
|
||||
{
|
||||
ImpactPropertiesMeshGizmo.HighlightGizmo(lastHighlightedCollider, false);
|
||||
}
|
||||
|
||||
lastHighlightedCollider = null;
|
||||
lastHoveredObject = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pickedCollider)
|
||||
{
|
||||
if (lastHighlightedCollider)
|
||||
{
|
||||
if (!selectedColliderIDs.Contains(lastHighlightedCollider.GetInstanceID()))
|
||||
{
|
||||
ImpactPropertiesMeshGizmo.HighlightGizmo(lastHighlightedCollider, false);
|
||||
}
|
||||
|
||||
lastHighlightedCollider = null;
|
||||
}
|
||||
|
||||
if (!lastHighlightedCollider || pickedCollider != lastHighlightedCollider)
|
||||
{
|
||||
ImpactPropertiesMeshGizmo.HighlightGizmo(pickedCollider, hoverColor);
|
||||
lastHighlightedCollider = pickedCollider;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lastHighlightedCollider)
|
||||
ImpactPropertiesMeshGizmo.HighlightGizmo(lastHighlightedCollider, false);
|
||||
}
|
||||
|
||||
lastHoveredObject = picked;
|
||||
}
|
||||
else if (picked == null)
|
||||
{
|
||||
if (lastHoveredObject)
|
||||
{
|
||||
if (lastHighlightedCollider)
|
||||
{
|
||||
if (!selectedColliderIDs.Contains(lastHighlightedCollider.GetInstanceID()))
|
||||
{
|
||||
ImpactPropertiesMeshGizmo.HighlightGizmo(lastHighlightedCollider, false);
|
||||
}
|
||||
|
||||
lastHighlightedCollider = null;
|
||||
}
|
||||
|
||||
lastHoveredObject = null;
|
||||
}
|
||||
|
||||
if (lastHighlightedCollider)
|
||||
{
|
||||
if (!selectedColliderIDs.Contains(lastHighlightedCollider.GetInstanceID()))
|
||||
{
|
||||
ImpactPropertiesMeshGizmo.HighlightGizmo(lastHighlightedCollider, false);
|
||||
}
|
||||
|
||||
lastHighlightedCollider = null;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void GenerateHoverText()
|
||||
{
|
||||
if (m_LastHoveredObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Camera sceneCam = SceneView.lastActiveSceneView.camera;
|
||||
Vector3 mousePosition = Event.current.mousePosition;
|
||||
mousePosition.y = SceneView.lastActiveSceneView.camera.pixelHeight - mousePosition.y;
|
||||
mousePosition.z = sceneCam.nearClipPlane + 0.5f;
|
||||
Vector3 cursorPos = sceneCam.ScreenToWorldPoint(mousePosition);
|
||||
int fontSize = 15;
|
||||
Collider hitCol = m_LastHoveredObject?.GetComponentInParent<Collider>();
|
||||
string mouseInfoString = "";
|
||||
GUIStyle linkHandleStyle = new GUIStyle();
|
||||
linkHandleStyle.richText = true;
|
||||
;
|
||||
if (hitCol != null && hitCol.isTrigger == false)
|
||||
{
|
||||
if (Camera.current != null && Camera.current == SceneView.lastActiveSceneView.camera && Vector3.Dot(hitCol.transform.position - Camera.current.transform.position, Camera.current.transform.forward) < ImpactPropertiesMeshGizmo.gizmoVisRange)
|
||||
{
|
||||
if (hitCol.attachedRigidbody == null)
|
||||
{
|
||||
ImpactProperties impactProp = hitCol.GetComponent<ImpactProperties>();
|
||||
ImpactProperties.surfaceDataBrushTarget = null;
|
||||
if (impactProp == null)
|
||||
{
|
||||
mouseInfoString = $"\n<size={fontSize}><color=red> <b>MISSING IMPACT PROPERTIES</b></color>\n";
|
||||
if (ImpactProperties.surfaceDataBrush)
|
||||
{
|
||||
string hexColor = ColorUtility.ToHtmlStringRGB(ImpactPropertiesMeshGizmo.surfaceDataCardColorDict[ImpactProperties.surfaceDataBrush.Barcode]);
|
||||
mouseInfoString += $" <color=#{hexColor}>Brush: {ImpactProperties.surfaceDataBrush.Title}</color></size>";
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseInfoString += $" <color=grey>Brush: No brush selected</color></size>";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseInfoString = "";
|
||||
if (impactProp.SurfaceDataCard != null && impactProp.SurfaceDataCard.IsValid() && impactProp.SurfaceDataCard.TryGetDataCard(out var dataCard))
|
||||
{
|
||||
mouseInfoString = $"\n<size={fontSize}><color=white> Surface Data: {dataCard.Title}</color>\n";
|
||||
ImpactProperties.surfaceDataBrushTarget = dataCard;
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseInfoString = $"\n<size={fontSize}><color=red> Surface Data: <b>SURFACE DATA MISSING</b></color>\n";
|
||||
}
|
||||
|
||||
if (ImpactProperties.surfaceDataBrush)
|
||||
{
|
||||
string hexColor = ColorUtility.ToHtmlStringRGB(ImpactPropertiesMeshGizmo.surfaceDataCardColorDict[ImpactProperties.surfaceDataBrush.Barcode]);
|
||||
mouseInfoString += $" <color=#{hexColor}>Brush: {ImpactProperties.surfaceDataBrush.Title}</color></size>";
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseInfoString += $" <color=grey>Brush: No brush selected</color></size>";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImpactProperties impactPropsRB = hitCol.attachedRigidbody.GetComponent<ImpactProperties>();
|
||||
ImpactProperties.surfaceDataBrushTarget = null;
|
||||
if (impactPropsRB == null)
|
||||
{
|
||||
mouseInfoString = $"\n<size={fontSize}><color=red> <b>ATTACHED RB MISSING IMPACT PROPERTIES</b></color>\n";
|
||||
if (ImpactProperties.surfaceDataBrush)
|
||||
{
|
||||
string hexColor = ColorUtility.ToHtmlStringRGB(ImpactPropertiesMeshGizmo.surfaceDataCardColorDict[ImpactProperties.surfaceDataBrush.Barcode]);
|
||||
mouseInfoString += $" <color=#{hexColor}>Brush: {ImpactProperties.surfaceDataBrush.Title}</color></size>";
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseInfoString += $" <color=grey>Brush: No brush selected</color></size>";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseInfoString = "";
|
||||
if (impactPropsRB.SurfaceDataCard != null && impactPropsRB.SurfaceDataCard.IsValid() && impactPropsRB.SurfaceDataCard.TryGetDataCard(out var rbDataCard))
|
||||
{
|
||||
mouseInfoString = $"\n<size={fontSize}><color=white> Surface Data: {rbDataCard.Title}</color>\n";
|
||||
ImpactProperties.surfaceDataBrushTarget = rbDataCard;
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseInfoString = $"\n<size={fontSize}><color=red> Surface Data: <b>SURFACE DATA MISSING</b></color>\n";
|
||||
}
|
||||
|
||||
if (ImpactProperties.surfaceDataBrush)
|
||||
{
|
||||
string hexColor = ColorUtility.ToHtmlStringRGB(ImpactPropertiesMeshGizmo.surfaceDataCardColorDict[ImpactProperties.surfaceDataBrush.Barcode]);
|
||||
mouseInfoString += $" <color=#{hexColor}>Brush: {ImpactProperties.surfaceDataBrush.Title}</color></size>";
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseInfoString += $" <color=grey>Brush: No brush selected</color></size>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Handles.Label(cursorPos, $"{mouseInfoString}", linkHandleStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b0fe28adbd7aca44790bf8938f32c98a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 861b16b8107293d4989544a256ed3793
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c841e30038fe87fdf7534d72b7e592dd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
|
||||
|
||||
|
||||
using SLZ.Marrow;
|
||||
|
||||
|
||||
using SLZ.Marrow.Utilities;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.MarrowEditor.Interaction
|
||||
{
|
||||
public class MarrowEntityPoseDecoratorEditor
|
||||
{
|
||||
[CustomEditor(typeof(MarrowEntityPoseDecorator))]
|
||||
[CanEditMultipleObjects]
|
||||
public class MarrowEntityPoseDecoratorEditorInspector : Editor
|
||||
{
|
||||
private PropertyField propField;
|
||||
private ScannableReferenceElement scannableReferenceElement;
|
||||
private ScannableSelector.ScannableSelectorFilter scannableSelectorFilter;
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = "Packages/com.stresslevelzero.marrow.sdk/Editor/Assets/EditorStyleSheets/MarrowEntityPoseDecorator.uxml";
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
tree.Bind(serializedObject);
|
||||
if (targets.Length == 1)
|
||||
{
|
||||
propField = tree.Q<PropertyField>("MarrowEntityPose");
|
||||
propField.RegisterCallback<MouseOverEvent>(evt =>
|
||||
{
|
||||
scannableReferenceElement = propField.Q<VisualElement>("ScannableReferenceElement") as ScannableReferenceElement;
|
||||
scannableReferenceElement.onOpenSelector -= OnOpenSelector;
|
||||
scannableReferenceElement.onOpenSelector += OnOpenSelector;
|
||||
OnOpenSelector();
|
||||
});
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (scannableReferenceElement != null)
|
||||
scannableReferenceElement.onOpenSelector -= OnOpenSelector;
|
||||
}
|
||||
|
||||
private void OnOpenSelector()
|
||||
{
|
||||
if (target is MarrowEntityPoseDecorator poseDecorator && poseDecorator.CrateSpawner != null)
|
||||
{
|
||||
scannableReferenceElement.SetScannableQueryFilter(new ScannableSelector.ScannableSelectorFilter("ep", scannable =>
|
||||
{
|
||||
if (scannable is EntityPose entityPose)
|
||||
{
|
||||
return entityPose.Spawnable.Barcode.ToString();
|
||||
}
|
||||
|
||||
if (scannable.Title == "None")
|
||||
{
|
||||
return poseDecorator.CrateSpawner.spawnableCrateReference.Barcode.ToString();
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}, poseDecorator.CrateSpawner.spawnableCrateReference.Barcode.ID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.Active | GizmoType.Selected | GizmoType.NonSelected)]
|
||||
private static void DrawPreviewGizmo(MarrowEntityPoseDecorator decorator, GizmoType gizmoType)
|
||||
{
|
||||
bool gizmoInRange = Camera.current != null && Vector3.Dot(decorator.transform.position - Camera.current.transform.position, Camera.current.transform.forward) < CrateSpawner.gizmoVisRange;
|
||||
if (!Application.isPlaying && decorator.gameObject.scene != default)
|
||||
{
|
||||
if (decorator.MarrowEntityPose.TryGetDataCard(out var entityPose))
|
||||
{
|
||||
if (decorator.CrateSpawner.showPreviewGizmo)
|
||||
decorator.CrateSpawner.showPreviewGizmo = false;
|
||||
if (CrateSpawner.showLitMaterialPreview && CrateSpawner.defaultLitMat == null)
|
||||
{
|
||||
CrateSpawner.defaultLitMat = AssetDatabase.LoadAssetAtPath<Material>("Packages/com.unity.render-pipelines.universal/Runtime/Materials/Lit.mat");
|
||||
}
|
||||
|
||||
if (decorator != null && entityPose != null)
|
||||
{
|
||||
Bounds bounds = CrateSpawner.showColliderBounds && gizmoInRange ? entityPose.ColliderBounds : default;
|
||||
Mesh previewMesh = null;
|
||||
var editorAsset = entityPose.PosePreviewMesh.EditorAsset;
|
||||
if (editorAsset)
|
||||
{
|
||||
previewMesh = editorAsset;
|
||||
}
|
||||
else if (entityPose.PosePreviewMesh.Asset)
|
||||
{
|
||||
previewMesh = entityPose.PosePreviewMesh.Asset;
|
||||
}
|
||||
else if (!entityPose.PosePreviewMesh.Asset)
|
||||
{
|
||||
PreviewMeshLoadQueue.QueueLoadMesh(entityPose.PosePreviewMesh);
|
||||
}
|
||||
|
||||
EditorMeshGizmo.Draw("PosePreviewMesh", decorator.gameObject, previewMesh, CrateSpawner.showLitMaterialPreview ? CrateSpawner.defaultLitMat : MarrowSDK.VoidMaterial, bounds, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!decorator.CrateSpawner.showPreviewGizmo)
|
||||
decorator.CrateSpawner.showPreviewGizmo = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f920926d30cc1cf4c844da0e65a64eee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 950ecbc4c56a5e4aa560eb19d91c2dc2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#if UNITY_EDITOR
|
||||
using SLZ.Marrow;
|
||||
using SLZ.Marrow.SceneStreaming;
|
||||
using SLZ.Marrow.Utilities;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.MarrowEditor.Zones
|
||||
{
|
||||
[CustomEditor(typeof(PlayerMarker))]
|
||||
public class PlayerMarkerEditor : Editor
|
||||
{
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("105fcf4ae79ed4845b52781ab981fee1");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
};
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/PlayerMarker");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
return tree;
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.Selected | GizmoType.Active | GizmoType.NonSelected | GizmoType.Pickable)]
|
||||
static void DrawPlayerMarkerGizmo(PlayerMarker playerMarker, GizmoType gizmoType)
|
||||
{
|
||||
if (!Application.isPlaying && playerMarker.gameObject.scene != default)
|
||||
{
|
||||
EditorMeshGizmo.Draw("PlayerMarker Preview", playerMarker.gameObject, MarrowSDK.GenericHumanMesh, MarrowSDK.VoidMaterialAlt, MarrowSDK.GenericHumanMesh.bounds);
|
||||
}
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.Selected | GizmoType.Pickable)]
|
||||
static void DrawSelectedPlayerMarkerInfoGizmo(PlayerMarker playerMarker, GizmoType gizmoType)
|
||||
{
|
||||
if (!Application.isPlaying && playerMarker.gameObject.scene != default)
|
||||
{
|
||||
DrawGizmoHelper.DrawText("Default: Mortal / Level Reloads on Death", playerMarker.transform.position + new Vector3(0f, -0.25f, 0f));
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/MarrowSDK/Player Marker", priority = 1)]
|
||||
private static void MenuCreatePlacer(MenuCommand menuCommand)
|
||||
{
|
||||
GameObject go = new GameObject("Player Marker", typeof(PlayerMarker));
|
||||
go.transform.localScale = Vector3.one;
|
||||
GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject);
|
||||
Selection.activeObject = go;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b19e6884d4103f2409b1bf74cb2431d5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,318 @@
|
|||
#if UNITY_EDITOR
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using SLZ.Marrow.Zones;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.MarrowEditor.Zones
|
||||
{
|
||||
[CustomEditor(typeof(SceneChunk))]
|
||||
public class SceneChunkEditor : Editor
|
||||
{
|
||||
static private Color sceneChunkColor = new Color(0.5f, 0f, 1f, 0.8f);
|
||||
static private Color sceneChunkColorFade = new Color(0.5f, 0f, 1f, 0.05f);
|
||||
List<ZoneCuller> zoneCullersList;
|
||||
List<ZoneCuller> zoneCullersInSceneChunksList;
|
||||
SceneChunk script;
|
||||
[DrawGizmo(GizmoType.Selected)]
|
||||
static void DrawSelectedSceneChunkGizmo(SceneChunk sceneChunk, GizmoType gizmoType)
|
||||
{
|
||||
DrawSelectedSceneChunk(sceneChunk);
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.Pickable | GizmoType.Selected)]
|
||||
static void DrawPickableSelectedSceneChunkGizmo(SceneChunk sceneChunk, GizmoType gizmoType)
|
||||
{
|
||||
DrawSelectedSceneChunk(sceneChunk);
|
||||
}
|
||||
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
script = (SceneChunk)target;
|
||||
zoneCullersList = Object.FindObjectsOfType<ZoneCuller>().ToList();
|
||||
zoneCullersInSceneChunksList = new List<ZoneCuller>();
|
||||
foreach (SceneChunk sceneChunk in Object.FindObjectsOfType<SceneChunk>())
|
||||
{
|
||||
foreach (ZoneCuller zoneCuller in sceneChunk.zoneCullers)
|
||||
{
|
||||
if (zoneCuller != null && !zoneCullersInSceneChunksList.Contains(zoneCuller))
|
||||
{
|
||||
zoneCullersInSceneChunksList.Add(zoneCuller);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("03f2fc96c9ed7e74db7465a8c67312a8");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
};
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/SceneChunk");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void OnSceneGUI()
|
||||
{
|
||||
if (SceneChunk.showZoneCullerHandles)
|
||||
{
|
||||
foreach (ZoneCuller zoneCuller in zoneCullersList)
|
||||
{
|
||||
BoxCollider boxCollider = null;
|
||||
SphereCollider sphereCollider = null;
|
||||
CapsuleCollider capsuleCollider = null;
|
||||
MeshCollider meshCollider = null;
|
||||
Collider selectedZoneCol = zoneCuller.GetComponent<Collider>();
|
||||
Vector3 zoneCenter = Vector3.zero;
|
||||
if (selectedZoneCol != null && selectedZoneCol is BoxCollider)
|
||||
{
|
||||
boxCollider = (BoxCollider)selectedZoneCol;
|
||||
}
|
||||
else if (selectedZoneCol != null && selectedZoneCol is SphereCollider)
|
||||
{
|
||||
sphereCollider = (SphereCollider)selectedZoneCol;
|
||||
}
|
||||
else if (selectedZoneCol != null && selectedZoneCol is CapsuleCollider)
|
||||
{
|
||||
capsuleCollider = (CapsuleCollider)selectedZoneCol;
|
||||
}
|
||||
else if (selectedZoneCol != null && selectedZoneCol is MeshCollider)
|
||||
{
|
||||
meshCollider = (MeshCollider)selectedZoneCol;
|
||||
}
|
||||
|
||||
if (boxCollider && boxCollider.isTrigger == true)
|
||||
{
|
||||
zoneCenter = selectedZoneCol.transform.TransformPoint(boxCollider.center);
|
||||
}
|
||||
else if (sphereCollider && sphereCollider.isTrigger == true)
|
||||
{
|
||||
zoneCenter = selectedZoneCol.transform.TransformPoint(sphereCollider.center);
|
||||
}
|
||||
else if (capsuleCollider && capsuleCollider.isTrigger == true)
|
||||
{
|
||||
zoneCenter = selectedZoneCol.transform.TransformPoint(capsuleCollider.center);
|
||||
}
|
||||
else if (meshCollider && meshCollider.isTrigger == true)
|
||||
{
|
||||
Transform[] zonePosList =
|
||||
{
|
||||
selectedZoneCol.transform
|
||||
};
|
||||
zoneCenter = FindCenterOfSelection(zonePosList);
|
||||
}
|
||||
|
||||
if (!script.zoneCullers.Contains(zoneCuller))
|
||||
{
|
||||
if (zoneCuller != null)
|
||||
{
|
||||
if (!zoneCullersInSceneChunksList.Contains(zoneCuller))
|
||||
{
|
||||
GUIStyle scHandleStyleAdd = new GUIStyle();
|
||||
scHandleStyleAdd.normal.textColor = Color.magenta;
|
||||
Handles.color = Color.magenta;
|
||||
bool addZoneCullerHandle = Handles.Button(zoneCenter + new Vector3(0f, -0.5f, 0f), Quaternion.identity, HandleUtility.GetHandleSize(zoneCenter) * 0.25f, HandleUtility.GetHandleSize(zoneCenter) * 0.25f, Handles.SphereHandleCap);
|
||||
Handles.Label(zoneCenter + new Vector3(0.25f, -0.5f, 0f), "Add to Chunk", scHandleStyleAdd);
|
||||
if (addZoneCullerHandle)
|
||||
{
|
||||
Undo.RecordObject(script, "Added ZC " + zoneCuller.name + " to SceneChunk " + script.name);
|
||||
List<ZoneCuller> zoneCullerList = script.zoneCullers.ToList();
|
||||
zoneCullerList.Add(zoneCuller);
|
||||
script.zoneCullers = zoneCullerList.ToArray();
|
||||
zoneCullersInSceneChunksList.Add(zoneCuller);
|
||||
Debug.Log("Added ZC: " + zoneCuller.name + " to SceneChunk: " + script.name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIStyle scHandleStyleExists = new GUIStyle();
|
||||
scHandleStyleExists.normal.textColor = Color.gray;
|
||||
Handles.Label(zoneCenter + new Vector3(0.25f, -0.5f, 0f), "Already in Chunk", scHandleStyleExists);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIStyle scHandleStyleRem = new GUIStyle();
|
||||
scHandleStyleRem.normal.textColor = Color.red;
|
||||
Handles.color = Color.red;
|
||||
bool delZoneCullerHandle = Handles.Button(zoneCenter + new Vector3(0f, -0.5f, 0f), Quaternion.identity, HandleUtility.GetHandleSize(zoneCenter) * 0.25f, HandleUtility.GetHandleSize(zoneCenter) * 0.25f, Handles.SphereHandleCap);
|
||||
Handles.Label(zoneCenter + new Vector3(0.25f, -0.5f, 0f), "Rem from Chunk", scHandleStyleRem);
|
||||
if (delZoneCullerHandle)
|
||||
{
|
||||
Undo.RecordObject(script, "Removed ZC " + zoneCuller.name + " from SceneChunk " + script.name);
|
||||
List<ZoneCuller> zoneCullerList = script.zoneCullers.ToList();
|
||||
zoneCullerList.Remove(zoneCuller);
|
||||
script.zoneCullers = zoneCullerList.ToArray();
|
||||
zoneCullersInSceneChunksList.Remove(zoneCuller);
|
||||
Debug.Log("Removed ZC: " + zoneCuller.name + " from SceneChunk: " + script.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawSelectedSceneChunk(SceneChunk sceneChunk)
|
||||
{
|
||||
foreach (ZoneCuller zoneCuller in sceneChunk.zoneCullers)
|
||||
{
|
||||
if (zoneCuller != null)
|
||||
{
|
||||
BoxCollider boxCollider = null;
|
||||
SphereCollider sphereCollider = null;
|
||||
CapsuleCollider capsuleCollider = null;
|
||||
MeshCollider meshCollider = null;
|
||||
Gizmos.matrix = zoneCuller.transform.localToWorldMatrix;
|
||||
Collider selectedZoneCol = zoneCuller.GetComponent<Collider>();
|
||||
Vector3 zoneCenter = Vector3.zero;
|
||||
if (selectedZoneCol != null && selectedZoneCol is BoxCollider)
|
||||
{
|
||||
boxCollider = (BoxCollider)selectedZoneCol;
|
||||
}
|
||||
else if (selectedZoneCol != null && selectedZoneCol is SphereCollider)
|
||||
{
|
||||
sphereCollider = (SphereCollider)selectedZoneCol;
|
||||
}
|
||||
else if (selectedZoneCol != null && selectedZoneCol is CapsuleCollider)
|
||||
{
|
||||
capsuleCollider = (CapsuleCollider)selectedZoneCol;
|
||||
}
|
||||
else if (selectedZoneCol != null && selectedZoneCol is MeshCollider)
|
||||
{
|
||||
meshCollider = (MeshCollider)selectedZoneCol;
|
||||
}
|
||||
|
||||
if (boxCollider && boxCollider.isTrigger == true)
|
||||
{
|
||||
zoneCenter = boxCollider.center;
|
||||
}
|
||||
else if (sphereCollider && sphereCollider.isTrigger == true)
|
||||
{
|
||||
zoneCenter = sphereCollider.center;
|
||||
}
|
||||
else if (capsuleCollider && capsuleCollider.isTrigger == true)
|
||||
{
|
||||
zoneCenter = capsuleCollider.center;
|
||||
}
|
||||
else if (meshCollider && meshCollider.isTrigger == true)
|
||||
{
|
||||
Transform[] zonePosList =
|
||||
{
|
||||
selectedZoneCol.transform
|
||||
};
|
||||
zoneCenter = zoneCuller.transform.InverseTransformPoint(FindCenterOfSelection(zonePosList));
|
||||
}
|
||||
|
||||
Gizmos.color = sceneChunkColor;
|
||||
if (boxCollider && boxCollider.enabled && boxCollider.isTrigger)
|
||||
{
|
||||
Gizmos.DrawWireCube(zoneCenter, Vector3.Scale(zoneCuller.transform.lossyScale, boxCollider.size) * 0.95f);
|
||||
}
|
||||
else if (sphereCollider && sphereCollider.enabled && sphereCollider.isTrigger)
|
||||
{
|
||||
Gizmos.DrawWireSphere(zoneCenter, sphereCollider.radius * 0.99f);
|
||||
}
|
||||
else if (capsuleCollider && capsuleCollider.enabled && capsuleCollider.isTrigger)
|
||||
{
|
||||
GameObject capsulePrimitive;
|
||||
if (!capsuleCollider.GetComponentInChildren<MeshFilter>())
|
||||
{
|
||||
capsulePrimitive = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||||
capsulePrimitive.name = "CapsuleZoneGizmo of " + capsuleCollider.name;
|
||||
DestroyImmediate(capsulePrimitive.GetComponent<CapsuleCollider>());
|
||||
DestroyImmediate(capsulePrimitive.GetComponent<MeshRenderer>());
|
||||
capsulePrimitive.transform.parent = capsuleCollider.transform;
|
||||
}
|
||||
else
|
||||
{
|
||||
capsulePrimitive = capsuleCollider.GetComponentInChildren<MeshFilter>().gameObject;
|
||||
}
|
||||
|
||||
capsulePrimitive.transform.position = capsuleCollider.transform.position;
|
||||
capsulePrimitive.transform.rotation = capsuleCollider.transform.rotation;
|
||||
capsulePrimitive.transform.localScale = new Vector3(capsuleCollider.radius * 2, capsuleCollider.height / 2, capsuleCollider.radius * 2);
|
||||
Mesh mesh = capsulePrimitive.GetComponent<MeshFilter>().sharedMesh;
|
||||
Gizmos.DrawWireMesh(mesh, zoneCenter, Quaternion.identity, capsulePrimitive.transform.lossyScale * 0.99f);
|
||||
}
|
||||
else if (meshCollider && meshCollider.isTrigger)
|
||||
{
|
||||
Mesh mesh = meshCollider.sharedMesh;
|
||||
Gizmos.color = sceneChunkColorFade;
|
||||
Gizmos.DrawWireMesh(mesh, zoneCenter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Vector3 FindCenterOfSelection(Transform[] transformList)
|
||||
{
|
||||
if (transformList == null || transformList.Length == 0)
|
||||
{
|
||||
return Vector3.zero;
|
||||
}
|
||||
|
||||
if (transformList.Length == 1)
|
||||
{
|
||||
return transformList[0].position;
|
||||
}
|
||||
|
||||
float minX = Mathf.Infinity;
|
||||
float minY = Mathf.Infinity;
|
||||
float minZ = Mathf.Infinity;
|
||||
float maxX = -Mathf.Infinity;
|
||||
float maxY = -Mathf.Infinity;
|
||||
float maxZ = -Mathf.Infinity;
|
||||
foreach (Transform transformObj in transformList)
|
||||
{
|
||||
if (transformObj.position.x < minX)
|
||||
{
|
||||
minX = transformObj.position.x;
|
||||
}
|
||||
|
||||
if (transformObj.position.y < minY)
|
||||
{
|
||||
minY = transformObj.position.y;
|
||||
}
|
||||
|
||||
if (transformObj.position.z < minZ)
|
||||
{
|
||||
minZ = transformObj.position.z;
|
||||
}
|
||||
|
||||
if (transformObj.position.x > maxX)
|
||||
{
|
||||
maxX = transformObj.position.x;
|
||||
}
|
||||
|
||||
if (transformObj.position.y > maxY)
|
||||
{
|
||||
maxY = transformObj.position.y;
|
||||
}
|
||||
|
||||
if (transformObj.position.z > maxZ)
|
||||
{
|
||||
maxZ = transformObj.position.z;
|
||||
}
|
||||
}
|
||||
|
||||
return new Vector3((minX + maxX) / 2.0f, (minY + maxY) / 2.0f, (minZ + maxZ) / 2.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a165e6f1c81c05f4183a32b5b20bd3b3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using SLZ.Marrow.Zones;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.MarrowEditor.Zones
|
||||
{
|
||||
[CustomEditor(typeof(SpawnForce))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SpawnForceEditor : Editor
|
||||
{
|
||||
SpawnForce script;
|
||||
private static GUIContent gizmoIcon = null;
|
||||
private PropertyField spawnAngularVelField;
|
||||
private PropertyField maxSpawnAngVelField;
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
script = (SpawnForce)target;
|
||||
if (gizmoIcon == null)
|
||||
{
|
||||
gizmoIcon = new GUIContent(EditorGUIUtility.IconContent("d_GizmosToggle On@2x"));
|
||||
gizmoIcon.tooltip = "Toggle Preview Mesh Gizmo";
|
||||
}
|
||||
}
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("3e3f940b32a30e244bdf54810430d033");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
CrateSpawner _crateSpawner = null;
|
||||
Type type = script.GetType();
|
||||
FieldInfo fieldInfo = null;
|
||||
while (fieldInfo == null && type != null)
|
||||
{
|
||||
fieldInfo = type.GetField("_crateSpawner", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
if (fieldInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("propName", "Field _crateSpawner was not found in Type " + script.GetType().FullName);
|
||||
}
|
||||
|
||||
_crateSpawner = fieldInfo.GetValue(script) as CrateSpawner;
|
||||
if (_crateSpawner == null)
|
||||
{
|
||||
EditorGUILayout.HelpBox("SpawnForce's CrateSpawner is missing.", MessageType.Error);
|
||||
}
|
||||
};
|
||||
#if false
|
||||
#endif
|
||||
spawnAngularVelField = tree.Q<PropertyField>("spawnAngularVelocity");
|
||||
maxSpawnAngVelField = tree.Q<PropertyField>("maxSpawnAngularVelocity");
|
||||
bool usingRandomValue = serializedObject.FindProperty(nameof(SpawnForce.maxSpawnAngularVelocity)).floatValue > 0;
|
||||
spawnAngularVelField.SetEnabled(!usingRandomValue);
|
||||
tree.Q<Foldout>("RandomAngularVelocityFoldout").value = usingRandomValue;
|
||||
maxSpawnAngVelField.RegisterValueChangeCallback(evt =>
|
||||
{
|
||||
spawnAngularVelField.SetEnabled(evt.changedProperty.floatValue <= 0);
|
||||
});
|
||||
ToolbarToggle showGizmoToggle = tree.Q<ToolbarToggle>("showGizmoToggle");
|
||||
Image gizmoImage = new Image
|
||||
{
|
||||
image = gizmoIcon.image
|
||||
};
|
||||
showGizmoToggle.Add(gizmoImage);
|
||||
showGizmoToggle.value = SpawnForce.drawVelocityStatic;
|
||||
showGizmoToggle.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
SpawnForce.drawVelocityStatic = evt.newValue;
|
||||
InternalEditorUtility.RepaintAllViews();
|
||||
});
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/SpawnForce");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 91404453d94aec742af7cf22e38912b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#if UNITY_EDITOR
|
||||
using SLZ.Marrow.Zones;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.MarrowEditor.Zones
|
||||
{
|
||||
[CustomEditor(typeof(ZoneAggro))]
|
||||
[CanEditMultipleObjects]
|
||||
public class ZoneAggroEditor : Editor
|
||||
{
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("b97fb3262b9ca5c4f87dd77babf87b79");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
};
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/ZoneAggro");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 299ed10f8c603db43a705549d4ba6c6f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using SLZ.Marrow.Zones;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using static SLZ.Marrow.Zones.ZoneLinkItem;
|
||||
|
||||
namespace SLZ.MarrowEditor.Zones
|
||||
{
|
||||
[CustomEditor(typeof(ZoneAmbience), true)]
|
||||
[CanEditMultipleObjects]
|
||||
public class ZoneAmbienceEditor : Editor
|
||||
{
|
||||
ZoneAmbience script;
|
||||
public enum EventTypesFiltered
|
||||
{
|
||||
Nothing = 0,
|
||||
Primary = 1
|
||||
}
|
||||
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
script = (ZoneAmbience)target;
|
||||
EditorApplication.hierarchyWindowItemOnGUI += ZoneAmbiencePasteCommand;
|
||||
if (ZoneAmbience.zoneAmbiencePasted)
|
||||
{
|
||||
ZoneLink _zoneLink = null;
|
||||
Type type = script.GetType();
|
||||
FieldInfo fieldInfo = null;
|
||||
while (fieldInfo == null && type != null)
|
||||
{
|
||||
fieldInfo = type.GetField("_zoneLink", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
if (fieldInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("propName", "Field _zoneLink was not found in Type " + script.GetType().FullName);
|
||||
}
|
||||
|
||||
_zoneLink = fieldInfo.GetValue(script) as ZoneLink;
|
||||
ZoneLink parentZoneLink = script.GetComponentInParent<ZoneLink>();
|
||||
if (parentZoneLink != null && _zoneLink != parentZoneLink)
|
||||
{
|
||||
fieldInfo.SetValue(script, parentZoneLink);
|
||||
script.gameObject.name = parentZoneLink.gameObject.name + " ZoneAmbience";
|
||||
}
|
||||
|
||||
ZoneAmbience.zoneAmbiencePasted = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("0528c6fdc94c90e4e8499e29c55f2ddd");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
ZoneLink _zoneLink = null;
|
||||
Type type = script.GetType();
|
||||
FieldInfo fieldInfo = null;
|
||||
while (fieldInfo == null && type != null)
|
||||
{
|
||||
fieldInfo = type.GetField("_zoneLink", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
if (fieldInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("propName", "Field _zoneLink was not found in Type " + script.GetType().FullName);
|
||||
}
|
||||
|
||||
_zoneLink = fieldInfo.GetValue(script) as ZoneLink;
|
||||
if (_zoneLink == null)
|
||||
{
|
||||
EditorGUILayout.HelpBox("ZoneAmbience's ZoneLink is missing.", MessageType.Error);
|
||||
}
|
||||
};
|
||||
EnumField eventTypesFiltered = tree.Q<EnumField>("EventTypesFiltered");
|
||||
Type eventTypesType = script.GetType();
|
||||
FieldInfo eventTypesFieldInfo = null;
|
||||
while (eventTypesFieldInfo == null && eventTypesType != null)
|
||||
{
|
||||
eventTypesFieldInfo = eventTypesType.GetField("_eventTypes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
eventTypesType = eventTypesType.BaseType;
|
||||
}
|
||||
|
||||
if (eventTypesFieldInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("propName", "Field _eventTypes was not found in Type " + script.GetType().FullName);
|
||||
}
|
||||
|
||||
eventTypesFiltered.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
if (eventTypesFiltered.value.ToString() == "Nothing")
|
||||
{
|
||||
eventTypesFieldInfo.SetValue(script, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
eventTypesFieldInfo.SetValue(script, EventTypes.Primary);
|
||||
}
|
||||
});
|
||||
if ((EventTypes)eventTypesFieldInfo.GetValue(script) == 0)
|
||||
{
|
||||
eventTypesFiltered.value = EventTypesFiltered.Nothing;
|
||||
}
|
||||
else
|
||||
{
|
||||
eventTypesFiltered.value = EventTypesFiltered.Primary;
|
||||
eventTypesFieldInfo.SetValue(script, EventTypes.Primary);
|
||||
}
|
||||
|
||||
#if false
|
||||
#endif
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/ZoneAmbience");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void ZoneAmbiencePasteCommand(int n, Rect rt)
|
||||
{
|
||||
string cmdName = Event.current.commandName;
|
||||
switch (cmdName)
|
||||
{
|
||||
case null:
|
||||
break;
|
||||
case "":
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (Event.current != null && Event.current.type == EventType.ValidateCommand && "Paste" == Event.current.commandName)
|
||||
{
|
||||
ZoneAmbience.zoneAmbiencePasted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d23aa53a720cc9a438615739f25c27fc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using SLZ.Marrow.Zones;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.MarrowEditor.Zones
|
||||
{
|
||||
[CustomEditor(typeof(ZoneChunkLoader))]
|
||||
[CanEditMultipleObjects]
|
||||
public class ZoneChunkLoaderEditor : Editor
|
||||
{
|
||||
ZoneChunkLoader script;
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
script = (ZoneChunkLoader)target;
|
||||
ZoneLink zoneLink = script.GetComponent<ZoneLink>();
|
||||
if (zoneLink != null)
|
||||
{
|
||||
ZoneLink _zoneLink = null;
|
||||
Type type = script.GetType();
|
||||
FieldInfo fieldInfo = null;
|
||||
while (fieldInfo == null && type != null)
|
||||
{
|
||||
fieldInfo = type.GetField("_zoneLink", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
if (fieldInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("propName", "Field _zoneLink was not found in Type " + script.GetType().FullName);
|
||||
}
|
||||
else
|
||||
{
|
||||
_zoneLink = fieldInfo.GetValue(script) as ZoneLink;
|
||||
if (_zoneLink != null && _zoneLink != zoneLink)
|
||||
{
|
||||
fieldInfo.SetValue(script, zoneLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("c630897a080b9e14bb27aa9e012f8e74");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
};
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/ZoneChunkLoader");
|
||||
};
|
||||
Button addSelectedSceneChunksButton = tree.Q<Button>("addSelectedSceneChunksButton");
|
||||
addSelectedSceneChunksButton.clickable.clicked += () =>
|
||||
{
|
||||
List<ZoneChunkLoader> selectedZoneChunkLoaders = new List<ZoneChunkLoader>();
|
||||
List<SceneChunk> selectedSceneChunks = new List<SceneChunk>();
|
||||
foreach (GameObject go in Selection.gameObjects)
|
||||
{
|
||||
ZoneChunkLoader zcLoader = go.GetComponent<ZoneChunkLoader>();
|
||||
if (zcLoader != null && !selectedZoneChunkLoaders.Contains(zcLoader))
|
||||
{
|
||||
selectedZoneChunkLoaders.Add(zcLoader);
|
||||
}
|
||||
|
||||
SceneChunk sceneChunk = go.GetComponent<SceneChunk>();
|
||||
if (sceneChunk != null && !selectedSceneChunks.Contains(sceneChunk))
|
||||
{
|
||||
selectedSceneChunks.Add(sceneChunk);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (ZoneChunkLoader zcl in selectedZoneChunkLoaders)
|
||||
{
|
||||
if (zcl.chunks.Length > 0)
|
||||
{
|
||||
zcl.chunks = zcl.chunks.Union(selectedSceneChunks).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
zcl.chunks = selectedSceneChunks.ToArray();
|
||||
}
|
||||
}
|
||||
};
|
||||
Button overwriteSelectedSceneChunksButton = tree.Q<Button>("overwriteSelectedSceneChunksButton");
|
||||
overwriteSelectedSceneChunksButton.clickable.clicked += () =>
|
||||
{
|
||||
List<ZoneChunkLoader> selectedZoneChunkLoaders = new List<ZoneChunkLoader>();
|
||||
List<SceneChunk> selectedSceneChunks = new List<SceneChunk>();
|
||||
foreach (GameObject go in Selection.gameObjects)
|
||||
{
|
||||
ZoneChunkLoader zcLoader = go.GetComponent<ZoneChunkLoader>();
|
||||
if (zcLoader != null && !selectedZoneChunkLoaders.Contains(zcLoader))
|
||||
{
|
||||
selectedZoneChunkLoaders.Add(zcLoader);
|
||||
}
|
||||
|
||||
SceneChunk sceneChunk = go.GetComponent<SceneChunk>();
|
||||
if (sceneChunk != null && !selectedSceneChunks.Contains(sceneChunk))
|
||||
{
|
||||
selectedSceneChunks.Add(sceneChunk);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (ZoneChunkLoader zcl in selectedZoneChunkLoaders)
|
||||
{
|
||||
zcl.chunks = selectedSceneChunks.ToArray();
|
||||
}
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 34be8dd2f5493754ea8783e1e7429ee8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
#if UNITY_EDITOR
|
||||
|
||||
|
||||
using SLZ.Marrow.Zones;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.MarrowEditor.Zones
|
||||
{
|
||||
[CustomEditor(typeof(ZoneEvents))]
|
||||
[CanEditMultipleObjects]
|
||||
public class ZoneEventsEditor : Editor
|
||||
{
|
||||
ZoneEvents script;
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
script = (ZoneEvents)target;
|
||||
}
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("c3f7d84fcbc974541a988a1ed243a152");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
};
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/ZoneEvents");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
return tree;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/MarrowSDK/Zone Event", priority = 5)]
|
||||
private static void MenuCreateSpawner(MenuCommand menuCommand)
|
||||
{
|
||||
GameObject go = new GameObject("Zone Event");
|
||||
GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject);
|
||||
if (go.GetComponent<Zone>() == null)
|
||||
go.AddComponent<Zone>();
|
||||
BoxCollider boxCol = go.GetComponent<BoxCollider>();
|
||||
if (go.GetComponent<BoxCollider>() == null)
|
||||
{
|
||||
boxCol = go.AddComponent<BoxCollider>();
|
||||
}
|
||||
|
||||
boxCol.isTrigger = true;
|
||||
ZoneEvents zoneEvent = go.GetComponent<ZoneEvents>();
|
||||
if (zoneEvent == null)
|
||||
{
|
||||
zoneEvent = go.AddComponent<ZoneEvents>();
|
||||
zoneEvent.activatorTags.Tags.Clear();
|
||||
}
|
||||
|
||||
Selection.activeObject = go;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b463de59b85d13c4592a22f16000fa5b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bf29dba01cdbb4f46a3de39d082d7436
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,298 @@
|
|||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using SLZ.Marrow;
|
||||
using SLZ.Marrow.Zones;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.MarrowEditor.Zones
|
||||
{
|
||||
[CustomEditor(typeof(ZoneLink))]
|
||||
[CanEditMultipleObjects]
|
||||
public class ZoneLinkEditor : Editor
|
||||
{
|
||||
ZoneLink script;
|
||||
DragAndDropManipulatorListHelper dragDropManip;
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
script = (ZoneLink)target;
|
||||
}
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("c5aafdd8cc492914e8f64ddd3e546045");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
Button addZoneMusicButton = tree.Q<Button>("addZoneMusicButton");
|
||||
addZoneMusicButton.clickable.clicked += () =>
|
||||
{
|
||||
AddZoneMusicChildToZoneOnClick();
|
||||
};
|
||||
Button addZoneAmbienceButton = tree.Q<Button>("addZoneAmbienceButton");
|
||||
addZoneAmbienceButton.clickable.clicked += () =>
|
||||
{
|
||||
AddZoneAmbienceChildToZoneOnClick();
|
||||
};
|
||||
Button connectChildAudioToZoneButton = tree.Q<Button>("connectChildAudioToZoneButton");
|
||||
connectChildAudioToZoneButton.clickable.clicked += () =>
|
||||
{
|
||||
ConnectChildAudioToZoneButtonOnClick();
|
||||
};
|
||||
dragDropManip = new(tree);
|
||||
VisualElement zoneLinkDragDropTarget = tree.Q<VisualElement>("zoneLinkDragDropTarget");
|
||||
Label zoneLinkDragDropHint = tree.Q<Label>("zoneLinkDragDropHint");
|
||||
Label preDragHintText = tree.Q<Label>("preDragHintText");
|
||||
zoneLinkDragDropTarget.RegisterCallback<DragUpdatedEvent>(evt =>
|
||||
{
|
||||
DropAreaDragActive(zoneLinkDragDropTarget, zoneLinkDragDropHint, preDragHintText);
|
||||
});
|
||||
zoneLinkDragDropTarget.RegisterCallback<DragLeaveEvent>(evt =>
|
||||
{
|
||||
DropAreaDefaults(zoneLinkDragDropTarget, zoneLinkDragDropHint, preDragHintText);
|
||||
});
|
||||
zoneLinkDragDropTarget.RegisterCallback<DragPerformEvent>(evt =>
|
||||
{
|
||||
List<ZoneLink> zoneLinksList = script.zoneLinks.ToList();
|
||||
foreach (var droppedObject in dragDropManip.droppedObjects)
|
||||
{
|
||||
GameObject droppedGO = (GameObject)droppedObject;
|
||||
ZoneLink droppedZL = droppedGO.GetComponent<ZoneLink>();
|
||||
if (droppedZL != script.GetComponent<ZoneLink>())
|
||||
{
|
||||
if (droppedZL != null && !script.zoneLinks.Contains(droppedZL))
|
||||
{
|
||||
zoneLinksList.Add(droppedZL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Undo.RecordObject(script, "ZoneLinks DragDrop Updated");
|
||||
script.zoneLinks = zoneLinksList.ToArray();
|
||||
EditorUtility.SetDirty(script);
|
||||
List<ZoneLink> zoneList = UnityEngine.Object.FindObjectsOfType<ZoneLink>().ToList();
|
||||
foreach (ZoneLink zoneLink in zoneList)
|
||||
{
|
||||
foreach (ZoneLink zl in zoneLink.zoneLinks)
|
||||
{
|
||||
List<ZoneLink> linksOfZoneLink = zl.zoneLinks.ToList();
|
||||
if (!linksOfZoneLink.Contains(zoneLink))
|
||||
{
|
||||
linksOfZoneLink.Add(zoneLink);
|
||||
Undo.RecordObject(zl, "OneWay Link fix during DragDrop");
|
||||
zl.zoneLinks = linksOfZoneLink.ToArray();
|
||||
EditorUtility.SetDirty(zl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DropAreaDefaults(zoneLinkDragDropTarget, zoneLinkDragDropHint, preDragHintText);
|
||||
zoneLinkDragDropTarget.RemoveFromClassList("drop-area--dropping");
|
||||
});
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
};
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/ZoneLinks");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
DropAreaDefaults(zoneLinkDragDropTarget, zoneLinkDragDropHint, preDragHintText);
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void DropAreaDefaults(VisualElement zoneLinkDragDropTarget, Label zoneLinkDragDropHint, Label preDragHintText)
|
||||
{
|
||||
preDragHintText.style.display = DisplayStyle.Flex;
|
||||
zoneLinkDragDropTarget.style.borderTopWidth = 0;
|
||||
zoneLinkDragDropTarget.style.borderBottomWidth = 0;
|
||||
zoneLinkDragDropTarget.style.borderLeftWidth = 0;
|
||||
zoneLinkDragDropTarget.style.borderRightWidth = 0;
|
||||
zoneLinkDragDropHint.style.display = DisplayStyle.None;
|
||||
}
|
||||
|
||||
private void DropAreaDragActive(VisualElement zoneLinkDragDropTarget, Label zoneLinkDragDropHint, Label preDragHintText)
|
||||
{
|
||||
preDragHintText.style.display = DisplayStyle.None;
|
||||
zoneLinkDragDropTarget.style.borderTopWidth = 1;
|
||||
zoneLinkDragDropTarget.style.borderBottomWidth = 1;
|
||||
zoneLinkDragDropTarget.style.borderLeftWidth = 1;
|
||||
zoneLinkDragDropTarget.style.borderRightWidth = 1;
|
||||
zoneLinkDragDropHint.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
|
||||
{
|
||||
if (Time.frameCount != 0 && Time.renderedFrameCount != 0)
|
||||
{
|
||||
if (!ActiveEditorTracker.sharedTracker.isLocked)
|
||||
{
|
||||
RemoveEmptyOrDupLinksOnDestroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private void RemoveEmptyOrDupLinksOnDestroy()
|
||||
{
|
||||
List<ZoneLink> zoneList = UnityEngine.Object.FindObjectsOfType<ZoneLink>().ToList();
|
||||
List<ZoneLink> linkedZoneNoEmpties = new List<ZoneLink>();
|
||||
foreach (var zone in zoneList)
|
||||
{
|
||||
linkedZoneNoEmpties.Clear();
|
||||
if (zone.zoneLinks != null)
|
||||
{
|
||||
foreach (var linkedZone in zone.zoneLinks)
|
||||
{
|
||||
if (linkedZone != null && !linkedZoneNoEmpties.Contains(linkedZone) && linkedZone != zone)
|
||||
{
|
||||
linkedZoneNoEmpties.Add(linkedZone);
|
||||
}
|
||||
}
|
||||
|
||||
Undo.RecordObject(zone, "Cull Dup/Empty Zone ZoneLinks");
|
||||
zone.zoneLinks = linkedZoneNoEmpties.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddZoneMusicChildToZoneOnClick()
|
||||
{
|
||||
ZoneLink parentZoneLink = script.GetComponent<ZoneLink>();
|
||||
ZoneLinkItem parentZoneLinkItem = script.GetComponent<ZoneLinkItem>();
|
||||
GameObject zoneMusicChildObj = new GameObject(script.name + " ZoneMusic");
|
||||
zoneMusicChildObj.transform.position = parentZoneLink.transform.position;
|
||||
ZoneMusic zoneMusicChild = zoneMusicChildObj.AddComponent<ZoneMusic>();
|
||||
zoneMusicChildObj.transform.parent = script.transform;
|
||||
zoneMusicChildObj.layer = LayerMask.NameToLayer("Default");
|
||||
SetZoneMusicZoneLink(zoneMusicChild, parentZoneLink);
|
||||
SetZoneMusicEventType(zoneMusicChild, parentZoneLinkItem);
|
||||
Selection.activeGameObject = zoneMusicChildObj;
|
||||
}
|
||||
|
||||
private void AddZoneAmbienceChildToZoneOnClick()
|
||||
{
|
||||
ZoneLink parentZoneLink = script.GetComponent<ZoneLink>();
|
||||
ZoneLinkItem parentZoneLinkItem = script.GetComponent<ZoneLinkItem>();
|
||||
GameObject zoneAmbienceChildObj = new GameObject(script.name + " ZoneAmbience");
|
||||
zoneAmbienceChildObj.transform.position = parentZoneLink.transform.position;
|
||||
ZoneAmbience zoneAmbienceChild = zoneAmbienceChildObj.AddComponent<ZoneAmbience>();
|
||||
zoneAmbienceChildObj.transform.parent = script.transform;
|
||||
zoneAmbienceChildObj.layer = LayerMask.NameToLayer("Default");
|
||||
SetZoneAmbienceZoneLink(zoneAmbienceChild, parentZoneLink);
|
||||
SetZoneAmbienceEventType(zoneAmbienceChild, parentZoneLinkItem);
|
||||
Selection.activeGameObject = zoneAmbienceChildObj;
|
||||
}
|
||||
|
||||
private void ConnectChildAudioToZoneButtonOnClick()
|
||||
{
|
||||
ZoneLink parentZoneLink = script.GetComponent<ZoneLink>();
|
||||
foreach (ZoneMusic zoneMusic in script.GetComponentsInChildren<ZoneMusic>())
|
||||
{
|
||||
SetZoneMusicZoneLink(zoneMusic, parentZoneLink);
|
||||
}
|
||||
|
||||
foreach (ZoneAmbience zoneAmbience in script.GetComponentsInChildren<ZoneAmbience>())
|
||||
{
|
||||
SetZoneAmbienceZoneLink(zoneAmbience, parentZoneLink);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetZoneMusicZoneLink(ZoneMusic zoneMusicChild, ZoneLink parentZoneLink)
|
||||
{
|
||||
Type type = zoneMusicChild.GetType();
|
||||
FieldInfo fieldInfo = null;
|
||||
while (fieldInfo == null && type != null)
|
||||
{
|
||||
fieldInfo = type.GetField("_zoneLink", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
if (fieldInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("propName", "Field _zoneLink was not found in Type " + zoneMusicChild.GetType().FullName);
|
||||
}
|
||||
|
||||
if (parentZoneLink != null)
|
||||
{
|
||||
fieldInfo.SetValue(zoneMusicChild, parentZoneLink);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetZoneAmbienceZoneLink(ZoneAmbience zoneAmbienceChild, ZoneLink parentZoneLink)
|
||||
{
|
||||
Type type = zoneAmbienceChild.GetType();
|
||||
FieldInfo fieldInfo = null;
|
||||
while (fieldInfo == null && type != null)
|
||||
{
|
||||
fieldInfo = type.GetField("_zoneLink", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
if (fieldInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("propName", "Field _zoneLink was not found in Type " + zoneAmbienceChild.GetType().FullName);
|
||||
}
|
||||
|
||||
if (parentZoneLink != null)
|
||||
{
|
||||
fieldInfo.SetValue(zoneAmbienceChild, parentZoneLink);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetZoneMusicEventType(ZoneMusic zoneMusicChild, ZoneLinkItem parentZoneLinkItem)
|
||||
{
|
||||
Type type = zoneMusicChild.GetType();
|
||||
FieldInfo fieldInfo = null;
|
||||
while (fieldInfo == null && type != null)
|
||||
{
|
||||
fieldInfo = type.GetField("_eventTypes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
if (fieldInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("propName", "Field _eventTypes was not found in Type " + zoneMusicChild.GetType().FullName);
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldInfo.SetValue(zoneMusicChild, ZoneLinkItem.EventTypes.Primary);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetZoneAmbienceEventType(ZoneAmbience zoneAmbienceChild, ZoneLinkItem parentZoneLinkItem)
|
||||
{
|
||||
Type type = zoneAmbienceChild.GetType();
|
||||
FieldInfo fieldInfo = null;
|
||||
while (fieldInfo == null && type != null)
|
||||
{
|
||||
fieldInfo = type.GetField("_eventTypes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
if (fieldInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("propName", "Field _eventTypes was not found in Type " + zoneAmbienceChild.GetType().FullName);
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldInfo.SetValue(zoneAmbienceChild, ZoneLinkItem.EventTypes.Primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 676cff689cffd2c41b73f7c7608a7851
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using SLZ.Marrow.Utilities;
|
||||
using SLZ.Marrow.Zones;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SLZ.MarrowEditor.Zones
|
||||
{
|
||||
[CustomEditor(typeof(ZoneLinkItem))]
|
||||
public class ZoneLinkItemEditor : Editor
|
||||
{
|
||||
[DrawGizmo(GizmoType.Selected)]
|
||||
static void DrawSelectedZoneLinkItemGizmo(ZoneLinkItem zoneLinkItem, GizmoType gizmoType)
|
||||
{
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.NonSelected)]
|
||||
static void DrawNonSelectedZoneLinkItemGizmo(ZoneLinkItem zoneLinkItem, GizmoType gizmoType)
|
||||
{
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.Pickable | GizmoType.Selected)]
|
||||
static void DrawPickableSelectedZoneLinkItemGizmo(ZoneLinkItem zoneLinkItem, GizmoType gizmoType)
|
||||
{
|
||||
DrawZoneLinkItemGizmo(zoneLinkItem);
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.Pickable | GizmoType.NonSelected)]
|
||||
static void DrawPickableNonSelectedZoneLinkItemGizmo(ZoneLinkItem zoneLinkItem, GizmoType gizmoType)
|
||||
{
|
||||
DrawZoneLinkItemGizmo(zoneLinkItem);
|
||||
}
|
||||
|
||||
static void DrawZoneLinkItemGizmo(ZoneLinkItem zoneLinkItem)
|
||||
{
|
||||
if (MarrowSDKPreferences.gizmoZoneItemGizmos)
|
||||
{
|
||||
Vector3 itemLabelOffset = Vector3.down * 0.5f;
|
||||
if (MarrowSDKPreferences.gizmoZoneAmbience && zoneLinkItem.GetComponent<ZoneAmbience>())
|
||||
{
|
||||
Gizmos.color = new Color(1f, 0.6f, 0f, MarrowSDKPreferences.gizmoZoneLinkItemOpacity);
|
||||
DrawZoneLinkItem(zoneLinkItem, itemLabelOffset);
|
||||
}
|
||||
else if (MarrowSDKPreferences.gizmoZoneMusic && zoneLinkItem.GetComponent<ZoneMusic>())
|
||||
{
|
||||
Gizmos.color = new Color(1f, 0.6f, 0f, MarrowSDKPreferences.gizmoZoneLinkItemOpacity);
|
||||
DrawZoneLinkItem(zoneLinkItem, itemLabelOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MarrowSDKPreferences.gizmoZoneItemGizmos && !zoneLinkItem.GetComponent<ZoneMusic>() && !zoneLinkItem.GetComponent<ZoneAmbience>() && !zoneLinkItem.GetComponent<ZoneChunkLoader>())
|
||||
{
|
||||
Gizmos.color = new Color(1f, 1f, 0.25f, MarrowSDKPreferences.gizmoZoneLinkItemOpacity);
|
||||
DrawZoneLinkItem(zoneLinkItem, itemLabelOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawZoneLinkItem(ZoneLinkItem zoneLinkItem, Vector3 itemLabelOffset)
|
||||
{
|
||||
Gizmos.DrawCube(zoneLinkItem.transform.position, Vector3.one * 0.15f);
|
||||
if (Camera.current != null && Vector3.Dot(zoneLinkItem.transform.position - Camera.current.transform.position, Camera.current.transform.forward) < MarrowSDKPreferences.gizmoShowZoneLabelsRange)
|
||||
{
|
||||
DrawGizmoHelper.DrawText(zoneLinkItem.name, zoneLinkItem.transform.position + itemLabelOffset);
|
||||
}
|
||||
|
||||
if (ZoneCreateLinkOverlayToolbar.gizmoZonelabItemMode && MarrowSDKPreferences.gizmoZoneLinkItemRelations)
|
||||
{
|
||||
ZoneLink zoneLinkItemZone = null;
|
||||
Type type = zoneLinkItem.GetType();
|
||||
FieldInfo fieldInfo = null;
|
||||
while (fieldInfo == null && type != null)
|
||||
{
|
||||
fieldInfo = type.GetField("_zoneLink", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
if (fieldInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("propName", "Field _zoneLink was not found in Type " + zoneLinkItem.GetType().FullName);
|
||||
}
|
||||
|
||||
zoneLinkItemZone = fieldInfo.GetValue(zoneLinkItem) as ZoneLink;
|
||||
Vector3 zonePosition = zoneLinkItemZone.transform.position;
|
||||
Gizmos.DrawLine(zonePosition, zoneLinkItem.transform.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0d0e8932ac0a3954197aa312b304cc2f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#if UNITY_EDITOR
|
||||
|
||||
using SLZ.Marrow.Zones;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.MarrowEditor.Zones
|
||||
{
|
||||
[CustomEditor(typeof(ZoneLoadLevel))]
|
||||
[CanEditMultipleObjects]
|
||||
public class ZoneLoadLevelEditor : Editor
|
||||
{
|
||||
ZoneLoadLevel script;
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
script = (ZoneLoadLevel)target;
|
||||
}
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("a370a12f2faa65f419fa06fd2c69a65e");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
};
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/ZoneLoadLevel");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 80a34bb5e1ad60c489279668b93b682a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using SLZ.Marrow.Zones;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using static SLZ.Marrow.Zones.ZoneLinkItem;
|
||||
|
||||
namespace SLZ.MarrowEditor.Zones
|
||||
{
|
||||
[CustomEditor(typeof(ZoneMusic), true)]
|
||||
[CanEditMultipleObjects]
|
||||
public class ZoneMusicEditor : Editor
|
||||
{
|
||||
ZoneMusic script;
|
||||
public enum EventTypesFiltered
|
||||
{
|
||||
Nothing = 0,
|
||||
Primary = 1
|
||||
}
|
||||
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
script = (ZoneMusic)target;
|
||||
EditorApplication.hierarchyWindowItemOnGUI += ZoneMusicPasteCommand;
|
||||
if (ZoneMusic.zoneMusicPasted)
|
||||
{
|
||||
ZoneLink _zoneLink = null;
|
||||
Type type = script.GetType();
|
||||
FieldInfo fieldInfo = null;
|
||||
while (fieldInfo == null && type != null)
|
||||
{
|
||||
fieldInfo = type.GetField("_zoneLink", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
if (fieldInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("propName", "Field _zoneLink was not found in Type " + script.GetType().FullName);
|
||||
}
|
||||
|
||||
_zoneLink = fieldInfo.GetValue(script) as ZoneLink;
|
||||
ZoneLink parentZoneLink = script.GetComponentInParent<ZoneLink>();
|
||||
if (parentZoneLink != null && _zoneLink != parentZoneLink)
|
||||
{
|
||||
fieldInfo.SetValue(script, parentZoneLink);
|
||||
script.gameObject.name = parentZoneLink.gameObject.name + " ZoneMusic";
|
||||
}
|
||||
|
||||
ZoneMusic.zoneMusicPasted = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("efdf19c375a6f8149ba17183d8295fca");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
ZoneLink _zoneLink = null;
|
||||
Type type = script.GetType();
|
||||
FieldInfo fieldInfo = null;
|
||||
while (fieldInfo == null && type != null)
|
||||
{
|
||||
fieldInfo = type.GetField("_zoneLink", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
if (fieldInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("propName", "Field _zoneLink was not found in Type " + script.GetType().FullName);
|
||||
}
|
||||
|
||||
_zoneLink = fieldInfo.GetValue(script) as ZoneLink;
|
||||
if (_zoneLink == null)
|
||||
{
|
||||
EditorGUILayout.HelpBox("ZoneMusic's ZoneLink is missing.", MessageType.Error);
|
||||
}
|
||||
};
|
||||
EnumField eventTypesFiltered = tree.Q<EnumField>("EventTypesFiltered");
|
||||
Type eventTypesType = script.GetType();
|
||||
FieldInfo eventTypesFieldInfo = null;
|
||||
while (eventTypesFieldInfo == null && eventTypesType != null)
|
||||
{
|
||||
eventTypesFieldInfo = eventTypesType.GetField("_eventTypes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
eventTypesType = eventTypesType.BaseType;
|
||||
}
|
||||
|
||||
if (eventTypesFieldInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("propName", "Field _eventTypes was not found in Type " + script.GetType().FullName);
|
||||
}
|
||||
|
||||
eventTypesFiltered.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
if (eventTypesFiltered.value.ToString() == "Nothing")
|
||||
{
|
||||
eventTypesFieldInfo.SetValue(script, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
eventTypesFieldInfo.SetValue(script, EventTypes.Primary);
|
||||
}
|
||||
});
|
||||
if ((EventTypes)eventTypesFieldInfo.GetValue(script) == 0)
|
||||
{
|
||||
eventTypesFiltered.value = EventTypesFiltered.Nothing;
|
||||
}
|
||||
else
|
||||
{
|
||||
eventTypesFiltered.value = EventTypesFiltered.Primary;
|
||||
eventTypesFieldInfo.SetValue(script, EventTypes.Primary);
|
||||
}
|
||||
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/ZoneMusic");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void ZoneMusicPasteCommand(int n, Rect rt)
|
||||
{
|
||||
string cmdName = Event.current.commandName;
|
||||
switch (cmdName)
|
||||
{
|
||||
case null:
|
||||
break;
|
||||
case "":
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (Event.current != null && Event.current.type == EventType.ValidateCommand && "Paste" == Event.current.commandName)
|
||||
{
|
||||
ZoneMusic.zoneMusicPasted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c6b8afd44b97a70409a56eea12916344
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1f24404b0ab13c01fdc326967932ab4a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,315 @@
|
|||
#if UNITY_EDITOR
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SLZ.Marrow;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
public class AWSpawnerEditorWin : EditorWindow
|
||||
{
|
||||
private const string PREFAB_PATH = "Assets/Prefabs/Crate Spawner (Template).prefab";
|
||||
private GameObject spawnablePrefab = null;
|
||||
private SpawnableCrate currentCrate = null;
|
||||
private ScrollView spawnablesGridScrollView;
|
||||
private Button initializeOverlayButton;
|
||||
[MenuItem("Stress Level Zero/Void Tools/AW Spawner Window", false, 5000)]
|
||||
public static void ShowAWSpawnerWindowEditor()
|
||||
{
|
||||
EditorWindow awSpawnWin = GetWindow<AWSpawnerEditorWin>();
|
||||
awSpawnWin.titleContent = new GUIContent("Asset Warehouse CrateSpawner");
|
||||
awSpawnWin.minSize = new Vector2(800, 800);
|
||||
}
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("7a3d2236aa2e2f749846efe6fa9df7cb");
|
||||
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
tree.StretchToParentSize();
|
||||
rootVisualElement.Add(tree);
|
||||
initializeOverlayButton = new Button();
|
||||
initializeOverlayButton.text = "Initialize Overlay";
|
||||
initializeOverlayButton.clickable.clicked += InitializeOverlay;
|
||||
Toggle spawnableShowPreviewsToggle = rootVisualElement.Q<Toggle>("spawnableShowPreviewsToggle");
|
||||
#if false
|
||||
#else
|
||||
spawnableShowPreviewsToggle.value = false;
|
||||
MarrowSDKPreferences.awSpawnerWinPreviews = false;
|
||||
#endif
|
||||
spawnablesGridScrollView = rootVisualElement.Q<ScrollView>("spawnablesGridScrollView");
|
||||
ToolbarSearchField spawnablesSearchField = rootVisualElement.Q<ToolbarSearchField>("spawnablesSearchField");
|
||||
Toggle spawnableShowBitsToggle = rootVisualElement.Q<Toggle>("spawnableShowBitsToggle");
|
||||
spawnablesGridScrollView.RegisterCallback<MouseEnterEvent>(evt =>
|
||||
{
|
||||
CheckOverlayPrefabInit(initializeOverlayButton, spawnablesGridScrollView);
|
||||
});
|
||||
CheckOverlayPrefabInit(initializeOverlayButton, spawnablesGridScrollView);
|
||||
AssetWarehouse.OnReady(() =>
|
||||
{
|
||||
List<Pallet> AWPalletsList = AssetWarehouse.Instance.GetPallets();
|
||||
List<SpawnableCrate> spawnableCratesList = new List<SpawnableCrate>();
|
||||
CreateSpawnableCratesGrid(AWPalletsList, spawnableCratesList, spawnablesGridScrollView, spawnablesSearchField.value, spawnableShowBitsToggle.value);
|
||||
spawnablesSearchField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
ScannableQueryEngine.scanQuerySearchErrorCount = 0;
|
||||
CreateSpawnableCratesGrid(AWPalletsList, spawnableCratesList, spawnablesGridScrollView, spawnablesSearchField.value, spawnableShowBitsToggle.value);
|
||||
});
|
||||
spawnableShowPreviewsToggle.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
if (spawnableShowPreviewsToggle.value == true)
|
||||
{
|
||||
MarrowSDKPreferences.awSpawnerWinPreviews = true;
|
||||
CreateSpawnableCratesGrid(AWPalletsList, spawnableCratesList, spawnablesGridScrollView, spawnablesSearchField.value, spawnableShowBitsToggle.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
MarrowSDKPreferences.awSpawnerWinPreviews = false;
|
||||
CreateSpawnableCratesGrid(AWPalletsList, spawnableCratesList, spawnablesGridScrollView, spawnablesSearchField.value, spawnableShowBitsToggle.value);
|
||||
}
|
||||
|
||||
Repaint();
|
||||
});
|
||||
spawnableShowBitsToggle.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
if (spawnableShowBitsToggle.value == true)
|
||||
{
|
||||
CreateSpawnableCratesGrid(AWPalletsList, spawnableCratesList, spawnablesGridScrollView, spawnablesSearchField.value, spawnableShowBitsToggle.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateSpawnableCratesGrid(AWPalletsList, spawnableCratesList, spawnablesGridScrollView, spawnablesSearchField.value, spawnableShowBitsToggle.value);
|
||||
}
|
||||
|
||||
Repaint();
|
||||
});
|
||||
});
|
||||
rootVisualElement.Add(initializeOverlayButton);
|
||||
}
|
||||
|
||||
private void CreateSpawnableCratesGrid(List<Pallet> AWPalletsList, List<SpawnableCrate> spawnableCratesList, ScrollView spawnablesGridScrollView, string spawnablesSearchFieldString, bool spawnableShowBits)
|
||||
{
|
||||
spawnableCratesList.Clear();
|
||||
spawnablesGridScrollView.Clear();
|
||||
var queryEngine = ScannableQueryEngine.SetupQueryEngine();
|
||||
List<Scannable> allScannables = new List<Scannable>();
|
||||
allScannables = allScannables.OrderBy(s => s.Title).ToList();
|
||||
if (AWPalletsList != null)
|
||||
{
|
||||
AWPalletsList = AWPalletsList.OrderBy(x => x.Title).ToList();
|
||||
for (int p = 0; p < AWPalletsList.Count; p++)
|
||||
{
|
||||
AWPalletsList[p].GetScannables(ref allScannables);
|
||||
List<Scannable> filteredScannables = new List<Scannable>();
|
||||
filteredScannables = ScannableQueryEngine.FilterScannableData(spawnablesSearchFieldString, queryEngine, allScannables).ToList();
|
||||
foreach (var scannable in filteredScannables)
|
||||
{
|
||||
if (scannable == null)
|
||||
continue;
|
||||
if (spawnableShowBits == false && scannable.Title.Contains("Fragment -"))
|
||||
continue;
|
||||
if (spawnableShowBits == false && scannable is SpawnableCrate spawnCrate && spawnCrate != null && spawnCrate.Tags != null)
|
||||
{
|
||||
foreach (var sCrateTag in spawnCrate.Tags)
|
||||
{
|
||||
if (sCrateTag.ToLower().ToString() == "fragment")
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (spawnableShowBits == false && scannable is SpawnableCrate spawnCrateBT && spawnCrateBT != null && spawnCrateBT.BoneTags != null)
|
||||
{
|
||||
if (spawnCrateBT.BoneTags.Tags != null)
|
||||
{
|
||||
foreach (var bTag in spawnCrateBT.BoneTags.Tags)
|
||||
{
|
||||
if (bTag.DataCard.Title.ToLower().ToString() == "fragment")
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scannable.GetType() == typeof(SpawnableCrate) && !spawnableCratesList.Contains(scannable))
|
||||
{
|
||||
spawnableCratesList.Add(scannable as SpawnableCrate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Exists(PREFAB_PATH) && spawnablePrefab == null)
|
||||
{
|
||||
SetSpawnablePrefab();
|
||||
}
|
||||
|
||||
for (int i = 0; i < spawnableCratesList.Count; i++)
|
||||
{
|
||||
VisualElement spawnContainer = new VisualElement();
|
||||
Color origBackground = spawnContainer.style.backgroundColor.value;
|
||||
spawnContainer.style.position = Position.Relative;
|
||||
spawnContainer.style.width = 150;
|
||||
spawnContainer.style.height = 32;
|
||||
spawnContainer.style.marginTop = 5;
|
||||
spawnContainer.style.marginBottom = 5;
|
||||
spawnContainer.style.marginLeft = 5;
|
||||
spawnContainer.style.marginRight = 5;
|
||||
spawnContainer.style.flexDirection = FlexDirection.Column;
|
||||
Label spawnLabel = new Label();
|
||||
spawnLabel.text = spawnableCratesList[i].Title;
|
||||
spawnLabel.style.whiteSpace = WhiteSpace.Normal;
|
||||
spawnLabel.style.marginTop = 2;
|
||||
spawnLabel.style.marginLeft = 2;
|
||||
if (MarrowSDKPreferences.awSpawnerWinPreviews == true)
|
||||
{
|
||||
spawnContainer.style.height = 132;
|
||||
Image spawnableImage = new Image();
|
||||
SetSpawnableListPreview(spawnableImage, spawnableCratesList[i]);
|
||||
spawnableImage.StretchToParentSize();
|
||||
spawnableImage.style.alignContent = Align.FlexEnd;
|
||||
spawnableImage.style.marginTop = 16;
|
||||
spawnContainer.Add(spawnableImage);
|
||||
}
|
||||
|
||||
spawnContainer.Add(spawnLabel);
|
||||
spawnContainer.RegisterCallback<MouseDownEvent>(evt =>
|
||||
{
|
||||
foreach (var spawnableContainer in spawnablesGridScrollView.Children())
|
||||
{
|
||||
spawnableContainer.style.backgroundColor = origBackground;
|
||||
}
|
||||
|
||||
spawnContainer.style.backgroundColor = new Color(0.15f, 0.4f, 0.66f);
|
||||
spawnContainer.style.borderBottomLeftRadius = 5;
|
||||
spawnContainer.style.borderBottomRightRadius = 5;
|
||||
spawnContainer.style.borderTopLeftRadius = 5;
|
||||
spawnContainer.style.borderTopRightRadius = 5;
|
||||
DragAndDrop.PrepareStartDrag();
|
||||
if (spawnablePrefab != null)
|
||||
{
|
||||
DragAndDrop.StartDrag("Dragging");
|
||||
DragAndDrop.objectReferences = new Object[]
|
||||
{
|
||||
spawnablePrefab
|
||||
};
|
||||
foreach (SpawnableCrate spawnableCrate in spawnableCratesList)
|
||||
{
|
||||
if (spawnableCrate != null && spawnableCrate.Title == spawnLabel.text)
|
||||
{
|
||||
currentCrate = spawnableCrate;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
spawnContainer.RegisterCallback<DragUpdatedEvent>(evt =>
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Move;
|
||||
if (spawnablePrefab != null && spawnablePrefab.GetComponent<CrateSpawner>() && spawnablePrefab.name != "Crate Spawner (" + currentCrate.name.ToString() + ")")
|
||||
{
|
||||
spawnablePrefab.name = "Crate Spawner (" + currentCrate.name.ToString() + ")";
|
||||
spawnablePrefab.GetComponent<CrateSpawner>().spawnableCrateReference = new SpawnableCrateReference(currentCrate.Barcode);
|
||||
spawnablePrefab.GetComponent<MeshFilter>().sharedMesh = currentCrate.PreviewMesh.EditorAsset;
|
||||
}
|
||||
});
|
||||
spawnablesGridScrollView.Add(spawnContainer);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckOverlayPrefabInit(Button initializeOverlayButton, VisualElement spawnablesGridScrollView)
|
||||
{
|
||||
if (!File.Exists(PREFAB_PATH))
|
||||
{
|
||||
spawnablePrefab = null;
|
||||
spawnablesGridScrollView.style.display = DisplayStyle.None;
|
||||
initializeOverlayButton.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
else
|
||||
{
|
||||
initializeOverlayButton.style.display = DisplayStyle.None;
|
||||
spawnablesGridScrollView.style.display = DisplayStyle.Flex;
|
||||
if (spawnablePrefab == null)
|
||||
{
|
||||
SetSpawnablePrefab();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeOverlay()
|
||||
{
|
||||
GameObject createPrefab = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
createPrefab.name = "Crate Spawner (Template)";
|
||||
var box = createPrefab.GetComponent<BoxCollider>();
|
||||
DestroyImmediate(box);
|
||||
CreateSpawnablePrefab(createPrefab);
|
||||
if (File.Exists(PREFAB_PATH))
|
||||
{
|
||||
spawnablesGridScrollView.style.display = DisplayStyle.Flex;
|
||||
initializeOverlayButton.style.display = DisplayStyle.None;
|
||||
}
|
||||
|
||||
Repaint();
|
||||
}
|
||||
|
||||
private void CreateSpawnablePrefab(GameObject createPrefab)
|
||||
{
|
||||
if (!Directory.Exists("Assets/Prefabs"))
|
||||
{
|
||||
AssetDatabase.CreateFolder("Assets", "Prefabs");
|
||||
}
|
||||
|
||||
if (File.Exists(PREFAB_PATH))
|
||||
{
|
||||
Debug.Log("File already exists, skipping creation");
|
||||
}
|
||||
else
|
||||
{
|
||||
bool prefabCreated = false;
|
||||
createPrefab.AddComponent<CrateSpawner>();
|
||||
createPrefab.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterial;
|
||||
PrefabUtility.SaveAsPrefabAsset(createPrefab, PREFAB_PATH, out prefabCreated);
|
||||
if (prefabCreated == true)
|
||||
{
|
||||
DestroyImmediate(createPrefab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetSpawnablePrefab()
|
||||
{
|
||||
if (spawnablePrefab == null)
|
||||
{
|
||||
spawnablePrefab = AssetDatabase.LoadAssetAtPath<GameObject>(PREFAB_PATH);
|
||||
if (spawnablePrefab.GetComponent<CrateSpawner>() == null)
|
||||
{
|
||||
spawnablePrefab.AddComponent<CrateSpawner>();
|
||||
}
|
||||
|
||||
if (spawnablePrefab.GetComponent<MeshRenderer>() == null)
|
||||
{
|
||||
spawnablePrefab.AddComponent<MeshRenderer>().material = MarrowSDK.VoidMaterial;
|
||||
}
|
||||
|
||||
if (spawnablePrefab.GetComponent<MeshFilter>() == null)
|
||||
{
|
||||
spawnablePrefab.AddComponent<MeshFilter>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetSpawnableListPreview(Image spawnablePreviewTexture, Crate crate)
|
||||
{
|
||||
if (crate.MainAsset.EditorAsset != null)
|
||||
{
|
||||
if (AssetPreview.GetAssetPreview(crate.MainAsset.EditorAsset) != null)
|
||||
{
|
||||
spawnablePreviewTexture.image = AssetPreview.GetAssetPreview(crate.MainAsset.EditorAsset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 47e06000c59f97a418147e7bbbffd4db
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,764 @@
|
|||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SLZ.Marrow;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Overlays;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using Image = UnityEngine.UIElements.Image;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[Icon(AW_ICON)]
|
||||
[Overlay(typeof(SceneView), id: ID_OVERLAY_AWSPAWNABLE, displayName: "AW Spawner")]
|
||||
public class AWSpawnerOverlayToolbar : Overlay
|
||||
{
|
||||
private const string ID_OVERLAY_AWSPAWNABLE = "aw-spawnable-overlay-toolbar";
|
||||
private const string COLLAPSED_TOOLTIP = "Select a Spawnable and Drag it into the Scene";
|
||||
private const string EXPANDED_TOOLTIP = "Select a Spawnable";
|
||||
private const string PREFAB_PATH = "Assets/Prefabs/Crate Spawner (Template).prefab";
|
||||
private const string AW_ICON = "Packages/com.stresslevelzero.marrow.sdk/Editor/Assets/Icons/Warehouse/crate-ball";
|
||||
private string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("dbfc5de6760262742b53757740b68b9f");
|
||||
private SpawnableCrate currentCrate = null;
|
||||
GameObject spawnablePrefab = null;
|
||||
Toggle spawnableShowPreviewsToggle;
|
||||
Toggle spawnableGridModeToggle;
|
||||
Toggle awOverlaySettingsToggle;
|
||||
private string zoneIconPath = MarrowSDK.GetPackagePath("Editor/Assets/Zone_Icons");
|
||||
public override VisualElement CreatePanelContent()
|
||||
{
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement rootVisualElement = new VisualElement();
|
||||
rootVisualElement.Add(tree);
|
||||
Label dragSpawnableLabel = rootVisualElement.Q<Label>("dragSpawnableLabel");
|
||||
Button initializeOverlayButton = new Button();
|
||||
VisualElement awSpawnerParentContainer = rootVisualElement.Q<VisualElement>("awSpawnerParentContainer");
|
||||
VisualElement awOverlaySettingsContainer = rootVisualElement.Q<VisualElement>("awOverlaySettingsContainer");
|
||||
VisualElement spawnablesListParentContainer = rootVisualElement.Q<VisualElement>("spawnablesListParentContainer");
|
||||
VisualElement dragSpawnablePreviewContainer = rootVisualElement.Q<VisualElement>("dragSpawnablePreviewContainer");
|
||||
VisualElement dragSpawnableImageContainer = rootVisualElement.Q<VisualElement>("dragSpawnableImageContainer");
|
||||
VisualElement spawnablesListContainer = rootVisualElement.Q<VisualElement>("spawnablesListContainer");
|
||||
ScrollView spawnablesGridScrollView = rootVisualElement.Q<ScrollView>("spawnablesGridScrollView");
|
||||
ToolbarSearchField spawnablesSearchField = rootVisualElement.Q<ToolbarSearchField>("spawnablesSearchField");
|
||||
ListView spawnablesListView = rootVisualElement.Q<ListView>("spawnablesListView");
|
||||
spawnableShowPreviewsToggle = rootVisualElement.Q<Toggle>("spawnableShowPreviewsToggle");
|
||||
awOverlaySettingsToggle = rootVisualElement.Q<Toggle>("awOverlaySettingsToggle");
|
||||
spawnableGridModeToggle = rootVisualElement.Q<Toggle>("spawnableGridModeToggle");
|
||||
Toggle spawnableShowBitsToggle = rootVisualElement.Q<Toggle>("spawnableShowBitsToggle");
|
||||
Image awSettingsIconImage = new Image
|
||||
{
|
||||
image = EditorGUIUtility.Load(Path.Combine(zoneIconPath, "Icon_marrow_settingsConfigurationa.png")) as Texture2D
|
||||
};
|
||||
if (awSettingsIconImage != null)
|
||||
{
|
||||
awOverlaySettingsToggle.label = "";
|
||||
}
|
||||
|
||||
awOverlaySettingsToggle.Add(awSettingsIconImage);
|
||||
awSettingsIconImage.StretchToParentSize();
|
||||
SliderInt awImageSizeSlider = rootVisualElement.Q<SliderInt>("awImageSizeSlider");
|
||||
SliderInt awGridSceneHorizPercentSlider = rootVisualElement.Q<SliderInt>("awGridSceneHorizPercentSlider");
|
||||
SliderInt awGridSceneVertPercentSlider = rootVisualElement.Q<SliderInt>("awGridSceneVertPercentSlider");
|
||||
SliderInt awListSceneVertPercentSlider = rootVisualElement.Q<SliderInt>("awListSceneVertPercentSlider");
|
||||
Button awSettingsApplyButton = rootVisualElement.Q<Button>("awSettingsApplyButton");
|
||||
List<SpawnableCrate> spawnableCratesList = new List<SpawnableCrate>();
|
||||
AssetWarehouse.OnReady(() =>
|
||||
{
|
||||
List<Pallet> AWPalletsList = AssetWarehouse.Instance.GetPallets();
|
||||
if (MarrowSDKPreferences.awSpawnerGridMode == true)
|
||||
{
|
||||
spawnablesGridScrollView.style.display = DisplayStyle.Flex;
|
||||
spawnablesListView.style.display = DisplayStyle.None;
|
||||
dragSpawnableLabel.style.display = DisplayStyle.None;
|
||||
CreateSpawnableCratesGrid(AWPalletsList, spawnableCratesList, spawnablesGridScrollView, spawnablesSearchField.value, spawnableShowBitsToggle.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
spawnablesGridScrollView.style.display = DisplayStyle.None;
|
||||
spawnablesListView.style.display = DisplayStyle.Flex;
|
||||
dragSpawnableLabel.style.display = DisplayStyle.Flex;
|
||||
CreateSpawnableCratesList(AWPalletsList, spawnableCratesList, spawnablesListView, spawnablesSearchField.value, spawnableShowBitsToggle.value);
|
||||
}
|
||||
|
||||
spawnablesSearchField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
ScannableQueryEngine.scanQuerySearchErrorCount = 0;
|
||||
if (MarrowSDKPreferences.awSpawnerGridMode == true)
|
||||
{
|
||||
CreateSpawnableCratesGrid(AWPalletsList, spawnableCratesList, spawnablesGridScrollView, spawnablesSearchField.value, spawnableShowBitsToggle.value);
|
||||
dragSpawnableLabel.style.display = DisplayStyle.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateSpawnableCratesList(AWPalletsList, spawnableCratesList, spawnablesListView, spawnablesSearchField.value, spawnableShowBitsToggle.value);
|
||||
dragSpawnableLabel.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
});
|
||||
});
|
||||
spawnableShowPreviewsToggle.value = MarrowSDKPreferences.awSpawnerOverlayPreviews;
|
||||
spawnableGridModeToggle.value = MarrowSDKPreferences.awSpawnerGridMode;
|
||||
awImageSizeSlider.value = MarrowSDKPreferences.awSpawnerImageSize;
|
||||
awGridSceneHorizPercentSlider.value = MarrowSDKPreferences.awSpawnerGridSceneHorizPercent;
|
||||
awGridSceneVertPercentSlider.value = MarrowSDKPreferences.awSpawnerGridSceneVertPercent;
|
||||
awListSceneVertPercentSlider.value = MarrowSDKPreferences.awSpawnerListSceneVertPercent;
|
||||
initializeOverlayButton.text = "Initialize Overlay";
|
||||
initializeOverlayButton.clickable.clicked += InitializeOverlay;
|
||||
awSettingsApplyButton.clickable.clicked += AWSettingsApplyButtonOnClick;
|
||||
if (MarrowSDKPreferences.awSpawnerGridMode == true)
|
||||
{
|
||||
dragSpawnableLabel.style.visibility = Visibility.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
dragSpawnableLabel.style.visibility = Visibility.Visible;
|
||||
if (this.collapsed)
|
||||
{
|
||||
dragSpawnableLabel.style.paddingTop = 5;
|
||||
dragSpawnableLabel.style.paddingBottom = 5;
|
||||
if (currentCrate)
|
||||
{
|
||||
dragSpawnableLabel.text = "Drag To Scene";
|
||||
}
|
||||
else
|
||||
{
|
||||
dragSpawnableLabel.text = "Select Spawnable";
|
||||
}
|
||||
|
||||
dragSpawnableLabel.tooltip = COLLAPSED_TOOLTIP;
|
||||
}
|
||||
else
|
||||
{
|
||||
dragSpawnableLabel.style.paddingTop = 5;
|
||||
dragSpawnableLabel.style.paddingBottom = 5;
|
||||
dragSpawnableLabel.text = "Select AW\nSpawnable";
|
||||
dragSpawnableLabel.tooltip = EXPANDED_TOOLTIP;
|
||||
}
|
||||
}
|
||||
|
||||
Texture2D spawnableIcon = EditorGUIUtility.Load(MarrowSDK.GetPackagePath("Editor/Assets/Icons/Warehouse/crate-ball.png")) as Texture2D;
|
||||
Image dragSpawnableTexture = new Image();
|
||||
dragSpawnableImageContainer.Add(dragSpawnableTexture);
|
||||
if (this.collapsed)
|
||||
{
|
||||
dragSpawnableTexture.image = spawnableIcon;
|
||||
dragSpawnableTexture.tooltip = COLLAPSED_TOOLTIP;
|
||||
}
|
||||
else
|
||||
{
|
||||
dragSpawnableTexture.image = spawnableIcon;
|
||||
dragSpawnableTexture.tooltip = EXPANDED_TOOLTIP;
|
||||
}
|
||||
|
||||
dragSpawnableTexture.RegisterCallback<MouseDownEvent>(evt =>
|
||||
{
|
||||
DragAndDrop.PrepareStartDrag();
|
||||
if (spawnablePrefab != null)
|
||||
{
|
||||
DragAndDrop.StartDrag("Dragging");
|
||||
DragAndDrop.objectReferences = new Object[]
|
||||
{
|
||||
spawnablePrefab
|
||||
};
|
||||
}
|
||||
});
|
||||
dragSpawnableTexture.RegisterCallback<DragUpdatedEvent>(evt =>
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Move;
|
||||
if (spawnablePrefab != null && currentCrate != null && spawnablePrefab.GetComponent<CrateSpawner>() && spawnablePrefab.name != "Crate Spawner (" + currentCrate.name.ToString() + ")")
|
||||
{
|
||||
spawnablePrefab.name = "Crate Spawner (" + currentCrate.name.ToString() + ")";
|
||||
spawnablePrefab.GetComponent<CrateSpawner>().spawnableCrateReference = new SpawnableCrateReference(currentCrate.Barcode);
|
||||
spawnablePrefab.GetComponent<MeshFilter>().sharedMesh = currentCrate.PreviewMesh.EditorAsset;
|
||||
}
|
||||
});
|
||||
dragSpawnableLabel.RegisterCallback<MouseDownEvent>(evt =>
|
||||
{
|
||||
DragAndDrop.PrepareStartDrag();
|
||||
if (spawnablePrefab != null && currentCrate != null)
|
||||
{
|
||||
DragAndDrop.StartDrag("Dragging");
|
||||
DragAndDrop.objectReferences = new Object[]
|
||||
{
|
||||
spawnablePrefab
|
||||
};
|
||||
}
|
||||
});
|
||||
dragSpawnableLabel.RegisterCallback<DragUpdatedEvent>(evt =>
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Move;
|
||||
if (spawnablePrefab != null && currentCrate != null && spawnablePrefab.GetComponent<CrateSpawner>() && spawnablePrefab.name != "Crate Spawner (" + currentCrate.name.ToString() + ")")
|
||||
{
|
||||
spawnablePrefab.name = "Spawnable Placer (" + currentCrate.name.ToString() + ")";
|
||||
spawnablePrefab.GetComponent<CrateSpawner>().spawnableCrateReference = new SpawnableCrateReference(currentCrate.Barcode);
|
||||
spawnablePrefab.GetComponent<MeshFilter>().sharedMesh = currentCrate.PreviewMesh.EditorAsset;
|
||||
PrefabUtility.RevertObjectOverride(spawnablePrefab, InteractionMode.AutomatedAction);
|
||||
}
|
||||
});
|
||||
rootVisualElement.Add(initializeOverlayButton);
|
||||
if (this.collapsed && currentCrate != null)
|
||||
{
|
||||
SetOverlayContents(dragSpawnableLabel, dragSpawnableTexture);
|
||||
this.collapsed = false;
|
||||
this.collapsed = true;
|
||||
}
|
||||
|
||||
CheckOverlayPrefabInit(dragSpawnableLabel, dragSpawnableTexture, initializeOverlayButton, spawnablesListContainer);
|
||||
spawnablesListView.onSelectionChange += selectedObjects =>
|
||||
{
|
||||
SpawnableCrate selectedSpawnable = (SpawnableCrate)selectedObjects.First();
|
||||
CheckOverlayPrefabInit(dragSpawnableLabel, dragSpawnableTexture, initializeOverlayButton, spawnablesListContainer);
|
||||
if (File.Exists(PREFAB_PATH) && spawnablePrefab == null)
|
||||
{
|
||||
SetSpawnablePrefab();
|
||||
}
|
||||
|
||||
if (selectedSpawnable != null && spawnablePrefab != null)
|
||||
{
|
||||
if (selectedSpawnable is SpawnableCrate)
|
||||
{
|
||||
SpawnableCrate crateObj = selectedSpawnable;
|
||||
currentCrate = crateObj;
|
||||
dragSpawnableLabel.tooltip = "Click here and drag into the Scene to create a Crate Spawner for [" + crateObj.name.ToString() + "]";
|
||||
dragSpawnableTexture.tooltip = "Click here and drag into the Scene to create a Crate Spawner for [" + crateObj.name.ToString() + "]";
|
||||
SetOverlayContents(dragSpawnableLabel, dragSpawnableTexture);
|
||||
}
|
||||
}
|
||||
};
|
||||
spawnableShowPreviewsToggle.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
if (spawnableShowPreviewsToggle.value == true)
|
||||
{
|
||||
MarrowSDKPreferences.awSpawnerOverlayPreviews = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MarrowSDKPreferences.awSpawnerOverlayPreviews = false;
|
||||
}
|
||||
|
||||
if (this.collapsed)
|
||||
{
|
||||
this.collapsed = false;
|
||||
this.collapsed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.collapsed = true;
|
||||
this.collapsed = false;
|
||||
}
|
||||
});
|
||||
spawnableGridModeToggle.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
if (spawnableGridModeToggle.value == true)
|
||||
{
|
||||
MarrowSDKPreferences.awSpawnerOverlayPreviews = true;
|
||||
MarrowSDKPreferences.awSpawnerGridMode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MarrowSDKPreferences.awSpawnerGridMode = false;
|
||||
}
|
||||
|
||||
if (this.collapsed)
|
||||
{
|
||||
this.collapsed = false;
|
||||
this.collapsed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.collapsed = true;
|
||||
this.collapsed = false;
|
||||
}
|
||||
});
|
||||
awOverlaySettingsToggle.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
if (awOverlaySettingsToggle.value == true)
|
||||
{
|
||||
awOverlaySettingsContainer.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
else
|
||||
{
|
||||
awOverlaySettingsContainer.style.display = DisplayStyle.None;
|
||||
}
|
||||
});
|
||||
awImageSizeSlider.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
MarrowSDKPreferences.awSpawnerImageSize = awImageSizeSlider.value;
|
||||
});
|
||||
awGridSceneHorizPercentSlider.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
MarrowSDKPreferences.awSpawnerGridSceneHorizPercent = awGridSceneHorizPercentSlider.value;
|
||||
});
|
||||
awGridSceneVertPercentSlider.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
MarrowSDKPreferences.awSpawnerGridSceneVertPercent = awGridSceneVertPercentSlider.value;
|
||||
});
|
||||
awListSceneVertPercentSlider.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
MarrowSDKPreferences.awSpawnerListSceneVertPercent = awListSceneVertPercentSlider.value;
|
||||
});
|
||||
if (MarrowSDKPreferences.awSpawnerGridMode == true)
|
||||
{
|
||||
spawnablesGridScrollView.style.maxWidth = Screen.width * MarrowSDKPreferences.awSpawnerGridSceneHorizPercent / 100;
|
||||
spawnablesGridScrollView.style.maxHeight = Screen.height * MarrowSDKPreferences.awSpawnerGridSceneVertPercent / 100;
|
||||
dragSpawnablePreviewContainer.style.display = DisplayStyle.None;
|
||||
if (MarrowSDKPreferences.awSpawnerOverlayPreviews == true)
|
||||
{
|
||||
spawnableShowPreviewsToggle.SetValueWithoutNotify(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
spawnableShowPreviewsToggle.SetValueWithoutNotify(false);
|
||||
}
|
||||
|
||||
spawnableGridModeToggle.SetValueWithoutNotify(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MarrowSDKPreferences.awSpawnerOverlayPreviews == true)
|
||||
{
|
||||
dragSpawnablePreviewContainer.style.display = DisplayStyle.None;
|
||||
spawnablesListView.style.maxHeight = Screen.height * MarrowSDKPreferences.awSpawnerListSceneVertPercent / 100;
|
||||
spawnablesListView.fixedItemHeight = MarrowSDKPreferences.awSpawnerImageSize + 16;
|
||||
spawnableShowPreviewsToggle.SetValueWithoutNotify(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
dragSpawnablePreviewContainer.style.display = DisplayStyle.Flex;
|
||||
spawnablesListView.style.maxHeight = Screen.height * MarrowSDKPreferences.awSpawnerListSceneVertPercent / 100;
|
||||
spawnablesListView.fixedItemHeight = 16;
|
||||
spawnableShowPreviewsToggle.SetValueWithoutNotify(false);
|
||||
}
|
||||
|
||||
spawnableGridModeToggle.SetValueWithoutNotify(false);
|
||||
}
|
||||
|
||||
Selection.selectionChanged += () =>
|
||||
{
|
||||
CheckOverlayPrefabInit(dragSpawnableLabel, dragSpawnableTexture, initializeOverlayButton, spawnablesListContainer);
|
||||
if (File.Exists(PREFAB_PATH) && spawnablePrefab == null)
|
||||
{
|
||||
SetSpawnablePrefab();
|
||||
}
|
||||
|
||||
if (dragSpawnableLabel != null && spawnablePrefab != null && Selection.instanceIDs.Length == 1)
|
||||
{
|
||||
if (Selection.activeObject is SpawnableCrate)
|
||||
{
|
||||
SpawnableCrate crateObj = (SpawnableCrate)Selection.activeObject;
|
||||
currentCrate = crateObj;
|
||||
dragSpawnableLabel.tooltip = "Click here and drag into the Scene to create a Crate Spawner for [" + crateObj.name.ToString() + "]";
|
||||
dragSpawnableTexture.tooltip = "Click here and drag into the Scene to create a Crate Spawner for [" + crateObj.name.ToString() + "]";
|
||||
SetOverlayContents(dragSpawnableLabel, dragSpawnableTexture);
|
||||
}
|
||||
}
|
||||
};
|
||||
awOverlaySettingsContainer.style.display = DisplayStyle.None;
|
||||
return rootVisualElement;
|
||||
}
|
||||
|
||||
private void CreateSpawnableCratesList(List<Pallet> AWPalletsList, List<SpawnableCrate> spawnableCratesList, ListView spawnablesListView, string spawnablesSearchFieldString, bool spawnableShowBits)
|
||||
{
|
||||
spawnableCratesList.Clear();
|
||||
var queryEngine = ScannableQueryEngine.SetupQueryEngine();
|
||||
List<Scannable> allScannables = new List<Scannable>();
|
||||
allScannables = allScannables.OrderBy(s => s.Title).ToList();
|
||||
if (AWPalletsList != null)
|
||||
{
|
||||
AWPalletsList = AWPalletsList.OrderBy(x => x.Title).ToList();
|
||||
for (int p = 0; p < AWPalletsList.Count; p++)
|
||||
{
|
||||
AWPalletsList[p].GetScannables(ref allScannables);
|
||||
List<Scannable> filteredScannables = new List<Scannable>();
|
||||
filteredScannables = ScannableQueryEngine.FilterScannableData(spawnablesSearchFieldString, queryEngine, allScannables).ToList();
|
||||
foreach (var scannable in filteredScannables)
|
||||
{
|
||||
if (scannable == null)
|
||||
continue;
|
||||
if (spawnableShowBits == false && scannable.Title.Contains("Fragment -"))
|
||||
continue;
|
||||
if (spawnableShowBits == false && scannable is SpawnableCrate spawnCrate && spawnCrate != null && spawnCrate.Tags != null)
|
||||
{
|
||||
foreach (var sCrateTag in spawnCrate.Tags)
|
||||
{
|
||||
if (sCrateTag.ToLower().ToString() == "fragment")
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (spawnableShowBits == false && scannable is SpawnableCrate spawnCrateBT && spawnCrateBT != null && spawnCrateBT.BoneTags != null)
|
||||
{
|
||||
if (spawnCrateBT.BoneTags.Tags != null)
|
||||
{
|
||||
foreach (var bTag in spawnCrateBT.BoneTags.Tags)
|
||||
{
|
||||
if (bTag.DataCard.Title.ToLower().ToString() == "fragment")
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scannable.GetType() == typeof(SpawnableCrate) && !spawnableCratesList.Contains(scannable))
|
||||
{
|
||||
spawnableCratesList.Add(scannable as SpawnableCrate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Exists(PREFAB_PATH) && spawnablePrefab == null)
|
||||
{
|
||||
SetSpawnablePrefab();
|
||||
}
|
||||
|
||||
Func<VisualElement> makeItem = () => new VisualElement();
|
||||
Action<VisualElement, int> bindItem = (spawnContainer, i) =>
|
||||
{
|
||||
if (spawnContainer != null && spawnableCratesList[i] != null)
|
||||
{
|
||||
spawnContainer.style.flexDirection = FlexDirection.Column;
|
||||
Label spawnLabel = spawnContainer.ElementAt(0) as Label;
|
||||
Image spawnableImage = new Image();
|
||||
if (spawnLabel != null)
|
||||
{
|
||||
spawnLabel.text = spawnableCratesList[i].Title;
|
||||
spawnLabel.style.justifyContent = Justify.FlexStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("spawnLabel is NULL");
|
||||
}
|
||||
|
||||
spawnContainer.style.height = 16;
|
||||
if (MarrowSDKPreferences.awSpawnerOverlayPreviews == true)
|
||||
{
|
||||
spawnableImage.style.marginTop = 16;
|
||||
spawnContainer.style.width = MarrowSDKPreferences.awSpawnerImageSize;
|
||||
spawnContainer.style.height = MarrowSDKPreferences.awSpawnerImageSize + 16;
|
||||
SetSpawnableListPreview(spawnableImage, spawnableCratesList[i]);
|
||||
spawnableImage.StretchToParentWidth();
|
||||
spawnableImage.style.width = MarrowSDKPreferences.awSpawnerImageSize;
|
||||
spawnableImage.style.height = MarrowSDKPreferences.awSpawnerImageSize;
|
||||
spawnableImage.tooltip = spawnableCratesList[i].Title;
|
||||
spawnContainer.Add(spawnableImage);
|
||||
}
|
||||
}
|
||||
};
|
||||
spawnablesListView.itemsSource = spawnableCratesList;
|
||||
spawnablesListView.makeItem = OnMakeSpawnListItem;
|
||||
spawnablesListView.bindItem = bindItem;
|
||||
spawnablesListView.style.flexShrink = 1;
|
||||
}
|
||||
|
||||
private void CreateSpawnableCratesGrid(List<Pallet> AWPalletsList, List<SpawnableCrate> spawnableCratesList, ScrollView spawnablesGridScrollView, string spawnablesSearchFieldString, bool spawnableShowBits)
|
||||
{
|
||||
spawnableCratesList.Clear();
|
||||
spawnablesGridScrollView.Clear();
|
||||
var queryEngine = ScannableQueryEngine.SetupQueryEngine();
|
||||
List<Scannable> allScannables = new List<Scannable>();
|
||||
allScannables = allScannables.OrderBy(s => s.Title).ToList();
|
||||
if (AWPalletsList != null)
|
||||
{
|
||||
AWPalletsList = AWPalletsList.OrderBy(x => x.Title).ToList();
|
||||
for (int p = 0; p < AWPalletsList.Count; p++)
|
||||
{
|
||||
AWPalletsList[p].GetScannables(ref allScannables);
|
||||
List<Scannable> filteredScannables = new List<Scannable>();
|
||||
filteredScannables = ScannableQueryEngine.FilterScannableData(spawnablesSearchFieldString, queryEngine, allScannables).ToList();
|
||||
foreach (var scannable in filteredScannables)
|
||||
{
|
||||
if (scannable == null)
|
||||
continue;
|
||||
if (spawnableShowBits == false && scannable.Title.Contains("Fragment -"))
|
||||
continue;
|
||||
if (spawnableShowBits == false && scannable is SpawnableCrate spawnCrate && spawnCrate != null && spawnCrate.Tags != null)
|
||||
{
|
||||
foreach (var sCrateTag in spawnCrate.Tags)
|
||||
{
|
||||
if (sCrateTag.ToLower().ToString() == "fragment")
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (spawnableShowBits == false && scannable is SpawnableCrate spawnCrateBT && spawnCrateBT != null && spawnCrateBT.BoneTags != null)
|
||||
{
|
||||
if (spawnCrateBT.BoneTags.Tags != null)
|
||||
{
|
||||
foreach (var bTag in spawnCrateBT.BoneTags.Tags)
|
||||
{
|
||||
if (bTag.DataCard.Title.ToLower().ToString() == "fragment")
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scannable.GetType() == typeof(SpawnableCrate) && !spawnableCratesList.Contains(scannable))
|
||||
{
|
||||
spawnableCratesList.Add(scannable as SpawnableCrate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Exists(PREFAB_PATH) && spawnablePrefab == null)
|
||||
{
|
||||
SetSpawnablePrefab();
|
||||
}
|
||||
|
||||
for (int i = 0; i < spawnableCratesList.Count; i++)
|
||||
{
|
||||
VisualElement spawnContainer = new VisualElement();
|
||||
spawnContainer.style.position = Position.Relative;
|
||||
spawnContainer.style.width = 100;
|
||||
spawnContainer.style.height = 16;
|
||||
spawnContainer.style.marginTop = 5;
|
||||
spawnContainer.style.marginBottom = 5;
|
||||
spawnContainer.style.marginLeft = 5;
|
||||
spawnContainer.style.marginRight = 5;
|
||||
spawnContainer.style.flexDirection = FlexDirection.Column;
|
||||
Label spawnLabel = new Label();
|
||||
spawnLabel.text = spawnableCratesList[i].Title;
|
||||
spawnLabel.style.whiteSpace = WhiteSpace.Normal;
|
||||
spawnLabel.style.flexDirection = FlexDirection.Column;
|
||||
if (MarrowSDKPreferences.awSpawnerOverlayPreviews == true)
|
||||
{
|
||||
Image spawnableImage = new Image();
|
||||
SetSpawnableListPreview(spawnableImage, spawnableCratesList[i]);
|
||||
spawnContainer.style.height = MarrowSDKPreferences.awSpawnerImageSize;
|
||||
spawnContainer.style.width = MarrowSDKPreferences.awSpawnerImageSize;
|
||||
spawnableImage.style.height = MarrowSDKPreferences.awSpawnerImageSize;
|
||||
spawnableImage.style.width = MarrowSDKPreferences.awSpawnerImageSize;
|
||||
spawnableImage.tooltip = spawnableCratesList[i].Title;
|
||||
spawnableImage.StretchToParentWidth();
|
||||
spawnContainer.Add(spawnableImage);
|
||||
if (MarrowSDKPreferences.awSpawnerImageSize > 99)
|
||||
{
|
||||
spawnContainer.style.height = MarrowSDKPreferences.awSpawnerImageSize + 16;
|
||||
spawnContainer.Add(spawnLabel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
spawnContainer.Add(spawnLabel);
|
||||
}
|
||||
|
||||
spawnContainer.RegisterCallback<MouseDownEvent>(evt =>
|
||||
{
|
||||
DragAndDrop.PrepareStartDrag();
|
||||
if (spawnablePrefab != null)
|
||||
{
|
||||
DragAndDrop.StartDrag("Dragging");
|
||||
DragAndDrop.objectReferences = new Object[]
|
||||
{
|
||||
spawnablePrefab
|
||||
};
|
||||
foreach (SpawnableCrate spawnableCrate in spawnableCratesList)
|
||||
{
|
||||
if (spawnableCrate != null && spawnableCrate.Title == spawnLabel.text)
|
||||
{
|
||||
currentCrate = spawnableCrate;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
spawnContainer.RegisterCallback<DragUpdatedEvent>(evt =>
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Move;
|
||||
if (spawnablePrefab != null && currentCrate != null && spawnablePrefab.GetComponent<CrateSpawner>() && spawnablePrefab.name != "Crate Spawner (" + currentCrate.name.ToString() + ")")
|
||||
{
|
||||
spawnablePrefab.name = "Crate Spawner (" + currentCrate.name.ToString() + ")";
|
||||
spawnablePrefab.GetComponent<CrateSpawner>().spawnableCrateReference = new SpawnableCrateReference(currentCrate.Barcode);
|
||||
spawnablePrefab.GetComponent<MeshFilter>().sharedMesh = currentCrate.PreviewMesh.EditorAsset;
|
||||
}
|
||||
});
|
||||
spawnablesGridScrollView.Add(spawnContainer);
|
||||
spawnablesGridScrollView.style.flexShrink = 1;
|
||||
}
|
||||
}
|
||||
|
||||
VisualElement OnMakeSpawnListItem()
|
||||
{
|
||||
var spawnListItem = new VisualElement();
|
||||
spawnListItem.Add(new Label());
|
||||
spawnListItem.RegisterCallback<MouseDownEvent>(evt =>
|
||||
{
|
||||
DragAndDrop.PrepareStartDrag();
|
||||
if (spawnablePrefab != null)
|
||||
{
|
||||
DragAndDrop.StartDrag("Dragging");
|
||||
DragAndDrop.objectReferences = new Object[]
|
||||
{
|
||||
spawnablePrefab
|
||||
};
|
||||
}
|
||||
});
|
||||
spawnListItem.RegisterCallback<DragUpdatedEvent>(evt =>
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Move;
|
||||
if (spawnablePrefab != null && currentCrate != null && spawnablePrefab.GetComponent<CrateSpawner>() && spawnablePrefab.name != "Crate Spawner (" + currentCrate.name.ToString() + ")")
|
||||
{
|
||||
spawnablePrefab.name = "Crate Spawner (" + currentCrate.name.ToString() + ")";
|
||||
spawnablePrefab.GetComponent<CrateSpawner>().spawnableCrateReference = new SpawnableCrateReference(currentCrate.Barcode);
|
||||
spawnablePrefab.GetComponent<MeshFilter>().sharedMesh = currentCrate.PreviewMesh.EditorAsset;
|
||||
}
|
||||
});
|
||||
return spawnListItem;
|
||||
}
|
||||
|
||||
private void CheckOverlayPrefabInit(Label dragSpawnableLabel, Image dragSpawnableTexture, Button initializeOverlayButton, VisualElement spawnablesListContainer)
|
||||
{
|
||||
if (!File.Exists(PREFAB_PATH))
|
||||
{
|
||||
spawnablePrefab = null;
|
||||
spawnablesListContainer.style.display = DisplayStyle.None;
|
||||
dragSpawnableLabel.style.display = DisplayStyle.None;
|
||||
dragSpawnableTexture.style.display = DisplayStyle.None;
|
||||
initializeOverlayButton.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
else
|
||||
{
|
||||
initializeOverlayButton.style.display = DisplayStyle.None;
|
||||
dragSpawnableLabel.style.display = DisplayStyle.Flex;
|
||||
dragSpawnableTexture.style.display = DisplayStyle.Flex;
|
||||
spawnablesListContainer.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
}
|
||||
|
||||
private void AWSettingsApplyButtonOnClick()
|
||||
{
|
||||
if (this.collapsed)
|
||||
{
|
||||
this.collapsed = false;
|
||||
this.collapsed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.collapsed = true;
|
||||
this.collapsed = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeOverlay()
|
||||
{
|
||||
GameObject createPrefab = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
createPrefab.name = "Crate Spawner (Template)";
|
||||
var box = createPrefab.GetComponent<BoxCollider>();
|
||||
Object.DestroyImmediate(box);
|
||||
CreateSpawnablePrefab(createPrefab);
|
||||
if (this.collapsed)
|
||||
{
|
||||
this.collapsed = false;
|
||||
this.collapsed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.collapsed = true;
|
||||
this.collapsed = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateSpawnablePrefab(GameObject createPrefab)
|
||||
{
|
||||
if (!Directory.Exists("Assets/Prefabs"))
|
||||
{
|
||||
AssetDatabase.CreateFolder("Assets", "Prefabs");
|
||||
}
|
||||
|
||||
if (File.Exists(PREFAB_PATH))
|
||||
{
|
||||
Debug.Log("File already exists, skipping creation");
|
||||
}
|
||||
else
|
||||
{
|
||||
bool prefabCreated = false;
|
||||
createPrefab.AddComponent<CrateSpawner>();
|
||||
createPrefab.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterial;
|
||||
PrefabUtility.SaveAsPrefabAsset(createPrefab, PREFAB_PATH, out prefabCreated);
|
||||
if (prefabCreated == true)
|
||||
{
|
||||
Object.DestroyImmediate(createPrefab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetOverlayContents(Label dragSpawnableLabel, Image dragSpawnableTexture)
|
||||
{
|
||||
dragSpawnableLabel.text = "Drag to Scene\n" + currentCrate.name.ToString();
|
||||
SetSpawnableListPreview(dragSpawnableTexture, currentCrate);
|
||||
dragSpawnableTexture.StretchToParentSize();
|
||||
}
|
||||
|
||||
private void SetSpawnableListPreview(Image spawnablePreviewTexture, Crate crate)
|
||||
{
|
||||
if (crate.MainAsset.EditorAsset != null)
|
||||
{
|
||||
if (AssetPreview.GetAssetPreview(crate.MainAsset.EditorAsset) != null)
|
||||
{
|
||||
spawnablePreviewTexture.image = AssetPreview.GetAssetPreview(crate.MainAsset.EditorAsset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetSpawnablePrefab()
|
||||
{
|
||||
if (spawnablePrefab == null)
|
||||
{
|
||||
spawnablePrefab = AssetDatabase.LoadAssetAtPath<GameObject>(PREFAB_PATH);
|
||||
if (spawnablePrefab.GetComponent<CrateSpawner>() == null)
|
||||
{
|
||||
spawnablePrefab.AddComponent<CrateSpawner>();
|
||||
}
|
||||
|
||||
if (spawnablePrefab.GetComponent<MeshRenderer>() == null)
|
||||
{
|
||||
spawnablePrefab.AddComponent<MeshRenderer>().material = MarrowSDK.VoidMaterial;
|
||||
}
|
||||
|
||||
if (spawnablePrefab.GetComponent<MeshFilter>() == null)
|
||||
{
|
||||
spawnablePrefab.AddComponent<MeshFilter>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Texture2D LoadPNG(string filePath)
|
||||
{
|
||||
Texture2D tex = null;
|
||||
byte[] fileData;
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
fileData = File.ReadAllBytes(filePath);
|
||||
tex = new Texture2D(2, 2);
|
||||
tex.LoadImage(fileData);
|
||||
}
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
private static List<AWSpawnerOverlayToolbar> instances = new List<AWSpawnerOverlayToolbar>();
|
||||
public override void OnCreated()
|
||||
{
|
||||
instances.Add(this);
|
||||
}
|
||||
|
||||
public override void OnWillBeDestroyed()
|
||||
{
|
||||
instances.Remove(this);
|
||||
}
|
||||
|
||||
public static void DoWithInstances(Action<AWSpawnerOverlayToolbar> doWithInstance)
|
||||
{
|
||||
foreach (var instance in instances)
|
||||
{
|
||||
doWithInstance(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5e0d01c7444c54644ad02ef79ae8a1d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using SLZ.Marrow.Circuits;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[CustomEditor(typeof(AddCircuit))]
|
||||
public class AddCircuitEditor : Editor
|
||||
{
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("21f31679846b59f4c82cbe6766ce28b4");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
};
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/AddCircuit");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a2c609ea93777664a90fb1257967d779
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,396 @@
|
|||
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AddressableAssets;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
|
||||
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using UnityEditor.AddressableAssets.Build;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
|
||||
using UnityEditor.Presets;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.AddressableAssets.Initialization;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
public class AddressablesManager
|
||||
{
|
||||
public static AddressableAssetSettings Settings
|
||||
{
|
||||
get
|
||||
{
|
||||
return AddressableAssetSettingsDefaultObject.Settings;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
AddressableAssetSettingsDefaultObject.Settings = value;
|
||||
}
|
||||
}
|
||||
|
||||
public const string ProfilePalletID = "Pallet";
|
||||
public const string ProfileGamePalletID = "Game Pallet";
|
||||
public const string MarrowAASettingsFileName = "AddressableAssetSettings";
|
||||
private static AddressableAssetGroupTemplate _packedPalletGroupTemplate;
|
||||
public static AddressableAssetGroupTemplate PackedPalletGroupTemplate
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_packedPalletGroupTemplate == null)
|
||||
{
|
||||
AddressableAssetGroupTemplate loadedTemplate = null;
|
||||
foreach (var template in Settings.GroupTemplateObjects)
|
||||
{
|
||||
if (template.name.Equals("Packed Pallet Assets") && template is AddressableAssetGroupTemplate aaTemplate)
|
||||
loadedTemplate = aaTemplate;
|
||||
}
|
||||
|
||||
if (loadedTemplate != null)
|
||||
{
|
||||
_packedPalletGroupTemplate = loadedTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
return _packedPalletGroupTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
private static AddressableAssetGroupTemplate _palletsGroupTemplate;
|
||||
public static AddressableAssetGroupTemplate PalletsGroupTemplate
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_palletsGroupTemplate == null)
|
||||
{
|
||||
AddressableAssetGroupTemplate loadedTemplate = null;
|
||||
foreach (var template in Settings.GroupTemplateObjects)
|
||||
{
|
||||
if (template.name.Equals("Pallets") && template is AddressableAssetGroupTemplate aaTemplate)
|
||||
loadedTemplate = aaTemplate;
|
||||
}
|
||||
|
||||
if (loadedTemplate != null)
|
||||
{
|
||||
_palletsGroupTemplate = loadedTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
return _palletsGroupTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
private static System.Reflection.FieldInfo _groupGuidField;
|
||||
public static FieldInfo GroupGuidField
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_groupGuidField == null)
|
||||
_groupGuidField = typeof(AddressableAssetGroup).GetField("m_GUID", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
return _groupGuidField;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ApplyPresetAASettings()
|
||||
{
|
||||
var settings = Settings;
|
||||
string presetPath = AssetDatabase.GUIDToAssetPath("c737533b10b487f4394b3e2e80a6d40c");
|
||||
Preset aaSettingsPreset = AssetDatabase.LoadAssetAtPath<Preset>(presetPath);
|
||||
aaSettingsPreset.ApplyTo(settings);
|
||||
AddressableAssetSettingsDefaultObject.Settings = settings;
|
||||
CallAddressablesAwake();
|
||||
}
|
||||
|
||||
public static AddressableAssetSettings CreateAASettings(bool force = false)
|
||||
{
|
||||
if (force)
|
||||
{
|
||||
if (Directory.Exists(AddressableAssetSettingsDefaultObject.kDefaultConfigFolder))
|
||||
{
|
||||
Directory.Delete(AddressableAssetSettingsDefaultObject.kDefaultConfigFolder, true);
|
||||
}
|
||||
|
||||
if (File.Exists(AssetDatabase.GetTextMetaFilePathFromAssetPath(AddressableAssetSettingsDefaultObject.kDefaultConfigFolder)))
|
||||
File.Delete(AssetDatabase.GetTextMetaFilePathFromAssetPath(AddressableAssetSettingsDefaultObject.kDefaultConfigFolder));
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
var settings = AddressableAssetSettings.Create(AddressableAssetSettingsDefaultObject.kDefaultConfigFolder, MarrowAASettingsFileName, true, true);
|
||||
AddressableAssetSettingsDefaultObject.Settings = settings;
|
||||
settings.RemoveGroup(settings.DefaultGroup);
|
||||
settings.RemoveGroup(settings.FindGroup(AddressableAssetSettings.PlayerDataGroupName));
|
||||
if (Directory.Exists(settings.DataBuilderFolder))
|
||||
AssetDatabase.DeleteAsset(settings.DataBuilderFolder);
|
||||
if (Directory.Exists(settings.GroupFolder))
|
||||
AssetDatabase.DeleteAsset(settings.GroupFolder);
|
||||
if (Directory.Exists(settings.GroupTemplateFolder))
|
||||
AssetDatabase.DeleteAsset(settings.GroupTemplateFolder);
|
||||
PlayerPrefs.DeleteKey(Addressables.kAddressablesRuntimeDataPath);
|
||||
ApplyPresetAASettings();
|
||||
CallAddressablesAwake();
|
||||
return settings;
|
||||
}
|
||||
|
||||
public static AddressableAssetSettings SetupAASettingsForPallet(Pallet pallet)
|
||||
{
|
||||
return SetupAASettings(ProfilePalletID, null, pallet);
|
||||
}
|
||||
|
||||
private static AddressableAssetSettings SetupAASettings(string profilePath, string customContentName = null, Pallet pallet = null, bool setupPalletGroup = true)
|
||||
{
|
||||
var settings = AddressableAssetSettingsDefaultObject.Settings;
|
||||
if (settings == null)
|
||||
settings = CreateAASettings(true);
|
||||
UnityEditor.Build.Pipeline.Utilities.ScriptableBuildPipeline.useDetailedBuildLog = true;
|
||||
UnityEditor.AddressableAssets.Settings.ProjectConfigData.GenerateBuildLayout = true;
|
||||
ClearGroups();
|
||||
ApplyPresetAASettings();
|
||||
AddressablesRuntimeProperties.ClearCachedPropertyValues();
|
||||
string buildPath = EvaluateProfileValueBuildPathForPallet(pallet, profilePath);
|
||||
string loadPath = EvaluateProfileValueLoadPathForPallet(pallet, profilePath);
|
||||
FixDefaultGroup(buildPath, loadPath);
|
||||
AddressablesRuntimeProperties.ClearCachedPropertyValues();
|
||||
var contentName = !string.IsNullOrEmpty(customContentName) ? customContentName : pallet.Barcode.ID;
|
||||
if (settings.OverridePlayerVersion != contentName)
|
||||
{
|
||||
settings.OverridePlayerVersion = contentName;
|
||||
EditorUtility.SetDirty(settings);
|
||||
}
|
||||
|
||||
if (settings.BuildRemoteCatalog == false)
|
||||
{
|
||||
settings.BuildRemoteCatalog = true;
|
||||
EditorUtility.SetDirty(settings);
|
||||
}
|
||||
|
||||
if (settings.ShaderBundleNaming != ShaderBundleNaming.Custom)
|
||||
{
|
||||
settings.ShaderBundleNaming = ShaderBundleNaming.Custom;
|
||||
EditorUtility.SetDirty(settings);
|
||||
}
|
||||
|
||||
if (settings.ShaderBundleCustomNaming != contentName)
|
||||
{
|
||||
settings.ShaderBundleCustomNaming = contentName;
|
||||
EditorUtility.SetDirty(settings);
|
||||
}
|
||||
|
||||
if (settings.MonoScriptBundleNaming != MonoScriptBundleNaming.Custom)
|
||||
{
|
||||
settings.MonoScriptBundleNaming = MonoScriptBundleNaming.Custom;
|
||||
EditorUtility.SetDirty(settings);
|
||||
}
|
||||
|
||||
if (settings.MonoScriptBundleCustomNaming != contentName)
|
||||
{
|
||||
settings.MonoScriptBundleCustomNaming = contentName;
|
||||
EditorUtility.SetDirty(settings);
|
||||
}
|
||||
|
||||
if (settings.RemoteCatalogBuildPath.Id != buildPath)
|
||||
{
|
||||
SetRemoteCatalogBuildPath(settings, buildPath);
|
||||
EditorUtility.SetDirty(settings);
|
||||
}
|
||||
|
||||
if (settings.RemoteCatalogLoadPath.Id != loadPath)
|
||||
{
|
||||
SetRemoteCatalogLoadPath(settings, loadPath);
|
||||
EditorUtility.SetDirty(settings);
|
||||
}
|
||||
|
||||
if (setupPalletGroup && !settings.FindGroup("Pallets"))
|
||||
{
|
||||
var palletsGroup = settings.CreateGroup("Pallets", false, false, false, AddressablesManager.PalletsGroupTemplate.SchemaObjects);
|
||||
string palletsGUID = AssetDatabase.GUIDFromAssetPath(AssetDatabase.GetAssetPath(palletsGroup)).ToString();
|
||||
GroupGuidField.SetValue(palletsGroup, palletsGUID);
|
||||
palletsGroup.SetDirty(AddressableAssetSettings.ModificationEvent.GroupAdded, palletsGroup, true, true);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssetIfDirty(settings);
|
||||
return settings;
|
||||
}
|
||||
|
||||
public static void ClearGroups()
|
||||
{
|
||||
var settings = Settings;
|
||||
for (var i = settings.groups.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var group = settings.groups[i];
|
||||
if (group != null)
|
||||
{
|
||||
if (group.Default)
|
||||
{
|
||||
foreach (var entry in group.entries.ToList())
|
||||
{
|
||||
group.RemoveAssetEntry(entry);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.RemoveGroup(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void FixDefaultGroup(string buildPath, string loadPath)
|
||||
{
|
||||
var settings = Settings;
|
||||
string metaGuid = "e4a20b55993a1fb40b1596966b14c9ae";
|
||||
string presetPath = AssetDatabase.GUIDToAssetPath("e473fee2058c3c84ead989aa134b6304");
|
||||
Preset bundledSchemaPreset = AssetDatabase.LoadAssetAtPath<Preset>(presetPath);
|
||||
var defaultGroup = settings.DefaultGroup;
|
||||
var bundledAssetSchema = defaultGroup.GetSchema<BundledAssetGroupSchema>();
|
||||
if (bundledAssetSchema != null)
|
||||
{
|
||||
string path = AssetDatabase.GetAssetPath(bundledAssetSchema);
|
||||
string guid = AssetDatabase.GUIDFromAssetPath(path).ToString();
|
||||
if (guid != metaGuid || !path.Contains("Assets"))
|
||||
{
|
||||
defaultGroup.RemoveSchema<BundledAssetGroupSchema>();
|
||||
}
|
||||
|
||||
bundledAssetSchema = null;
|
||||
}
|
||||
|
||||
if (bundledAssetSchema == null)
|
||||
{
|
||||
bundledAssetSchema = defaultGroup.AddSchema<BundledAssetGroupSchema>();
|
||||
string assetPath = AssetDatabase.GetAssetPath(bundledAssetSchema);
|
||||
string metaPath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetPath);
|
||||
string yamlContent = File.ReadAllText(metaPath);
|
||||
string replacedContent = Regex.Replace(yamlContent, @"guid:\s*(\w+)", "guid: " + metaGuid);
|
||||
File.WriteAllText(metaPath, replacedContent);
|
||||
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(bundledAssetSchema));
|
||||
defaultGroup.Schemas.RemoveAll(schema => schema is not ContentUpdateGroupSchema);
|
||||
bundledAssetSchema = AssetDatabase.LoadAssetAtPath<BundledAssetGroupSchema>(assetPath);
|
||||
defaultGroup.Schemas.Add(bundledAssetSchema);
|
||||
}
|
||||
|
||||
bundledSchemaPreset.ApplyTo(bundledAssetSchema);
|
||||
SetCustomBuildPath(bundledAssetSchema, buildPath);
|
||||
SetCustomLoadPath(bundledAssetSchema, loadPath);
|
||||
}
|
||||
|
||||
public static string EvaluateProfileValue(string variableName)
|
||||
{
|
||||
string value;
|
||||
if (Settings == null)
|
||||
{
|
||||
value = "SETTINGS NULL";
|
||||
}
|
||||
else
|
||||
{
|
||||
value = Settings.profileSettings.GetValueByName(Settings.activeProfileId, variableName);
|
||||
value = Settings.profileSettings.EvaluateString(Settings.activeProfileId, value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public static string EvaluateProfileValueForPallet(string variableName, Pallet pallet)
|
||||
{
|
||||
return ProfileValueForPallet(EvaluateProfileValue(variableName), pallet);
|
||||
}
|
||||
|
||||
public static string EvaluateProfileValueBuildPathForPallet(Pallet pallet, string profile)
|
||||
{
|
||||
return EvaluateProfileValueForPallet($"{profile}.BuildPath", pallet);
|
||||
}
|
||||
|
||||
public static string EvaluateProfileValueLoadPathForPallet(Pallet pallet, string profile)
|
||||
{
|
||||
return EvaluateProfileValueForPallet($"{profile}.LoadPath", pallet);
|
||||
}
|
||||
|
||||
public static void SetRemoteCatalogBuildPath(AddressableAssetSettings settings, string buildPath)
|
||||
{
|
||||
typeof(ProfileValueReference).GetProperty("Id").SetValue(settings.RemoteCatalogBuildPath, buildPath);
|
||||
}
|
||||
|
||||
private static void SetRemoteCatalogLoadPath(AddressableAssetSettings settings, string loadPath)
|
||||
{
|
||||
typeof(ProfileValueReference).GetProperty("Id").SetValue(settings.RemoteCatalogLoadPath, loadPath);
|
||||
}
|
||||
|
||||
public static void SetCustomBuildPath(BundledAssetGroupSchema schema, string buildPath)
|
||||
{
|
||||
typeof(ProfileValueReference).GetProperty("Id").SetValue(schema.BuildPath, buildPath);
|
||||
typeof(BundledAssetGroupSchema).GetField("m_UseCustomPaths", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(schema, true);
|
||||
EditorUtility.SetDirty(schema);
|
||||
}
|
||||
|
||||
public static void SetCustomLoadPath(BundledAssetGroupSchema schema, string loadPath)
|
||||
{
|
||||
typeof(ProfileValueReference).GetProperty("Id").SetValue(schema.LoadPath, loadPath);
|
||||
typeof(BundledAssetGroupSchema).GetField("m_UseCustomPaths", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(schema, true);
|
||||
EditorUtility.SetDirty(schema);
|
||||
}
|
||||
|
||||
public static string ProfileValueForPallet(string profileValue, Pallet pallet)
|
||||
{
|
||||
if (profileValue.Contains("~PALLETBARCODE~") && pallet != null)
|
||||
{
|
||||
profileValue = profileValue.Replace("~PALLETBARCODE~", pallet.Barcode.ID);
|
||||
}
|
||||
|
||||
return profileValue;
|
||||
}
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
public static void CallAddressablesAwake()
|
||||
{
|
||||
if (AddressableAssetSettingsDefaultObject.Settings != null)
|
||||
{
|
||||
typeof(AddressableAssetSettings).GetMethod("Awake", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(AddressableAssetSettingsDefaultObject.Settings, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OpenFolder(string folderPath)
|
||||
{
|
||||
string folderToOpen = folderPath;
|
||||
if (Directory.Exists(folderToOpen))
|
||||
{
|
||||
folderToOpen = Path.GetFullPath(folderPath);
|
||||
EditorUtility.RevealInFinder(folderToOpen);
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("Stress Level Zero/Void Tools/Open Built Pallet Folder")]
|
||||
public static void OpenBuiltdddModFolder()
|
||||
{
|
||||
var pallet = Selection.activeObject as Pallet;
|
||||
OpenBuiltModFolder(pallet);
|
||||
}
|
||||
|
||||
public static string GetBuiltModFolder(Pallet pallet = null)
|
||||
{
|
||||
return pallet != null ? EvaluateProfileValueBuildPathForPallet(pallet, AddressablesManager.ProfilePalletID) : string.Empty;
|
||||
}
|
||||
|
||||
public static void OpenBuiltModFolder(Pallet pallet = null)
|
||||
{
|
||||
if (pallet != null)
|
||||
{
|
||||
var buildPath = EvaluateProfileValueBuildPathForPallet(pallet, AddressablesManager.ProfilePalletID);
|
||||
OpenFolder(Path.GetFullPath(buildPath));
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenContainingBuiltModFolder(Pallet pallet = null)
|
||||
{
|
||||
if (pallet != null)
|
||||
{
|
||||
var buildPath = EvaluateProfileValueBuildPathForPallet(pallet, AddressablesManager.ProfilePalletID);
|
||||
OpenFolder(Path.GetFullPath(Path.Combine(buildPath, "..")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1d7192b11d43eb2459093e9787a90889
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using System.Linq;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
public class AssetWarehouseAuthsPopupWindow : PopupWindowContent
|
||||
{
|
||||
TreeViewState treeViewState;
|
||||
AssetWarehouseTreeView treeViewAW;
|
||||
private Vector2 toolScrollPos;
|
||||
int buttonsPerRow = 4;
|
||||
int padding = 5;
|
||||
Vector2 buttonSize = new Vector2(120, 20);
|
||||
public AssetWarehouseAuthsPopupWindow(AssetWarehouseTreeView treeViewAW)
|
||||
{
|
||||
this.treeViewAW = treeViewAW;
|
||||
}
|
||||
|
||||
public override Vector2 GetWindowSize()
|
||||
{
|
||||
float winSizeFromCount = 10;
|
||||
if (treeViewAW.uniqueAuthors.Count > 9)
|
||||
{
|
||||
winSizeFromCount = treeViewAW.uniqueAuthors.Count;
|
||||
}
|
||||
|
||||
return new Vector2((buttonSize.x * buttonsPerRow) + (padding * 5), ((winSizeFromCount / buttonsPerRow) * buttonSize.y) + (buttonSize.y * 4));
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect rect)
|
||||
{
|
||||
padding = 5;
|
||||
GUIStyle style = new GUIStyle();
|
||||
style.padding = new RectOffset(padding, padding, padding, padding);
|
||||
toolScrollPos = EditorGUILayout.BeginScrollView(toolScrollPos, false, false, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
|
||||
using (new GUILayout.VerticalScope(style))
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
if (treeViewAW != null)
|
||||
{
|
||||
int buttonCount = 0;
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Authors: ", GUILayout.Width(65));
|
||||
if (GUILayout.Button(new GUIContent("All", "Select All Authors"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
foreach (var kvp in treeViewAW.uniqueAuthors.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueAuthors[kvp.Key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (GUILayout.Button(new GUIContent("None", "Deselect All Authors"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
foreach (var kvp in treeViewAW.uniqueAuthors.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueAuthors[kvp.Key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button(new GUIContent("X", "Close Authors Window"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
editorWindow.Close();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
foreach (var kvp in treeViewAW.uniqueAuthors.ToArray())
|
||||
{
|
||||
if (buttonCount % buttonsPerRow == 0)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
}
|
||||
|
||||
treeViewAW.uniqueAuthors[kvp.Key] = GUILayout.Toggle(treeViewAW.uniqueAuthors[kvp.Key], new GUIContent(kvp.Key.ToString(), "Filter by Author: " + kvp.Key.ToString()), MarrowGUIStyles.DefaultButton, GUILayout.Width(buttonSize.x), GUILayout.Height(buttonSize.y));
|
||||
if (buttonCount % buttonsPerRow == buttonsPerRow - 1)
|
||||
{
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
buttonCount++;
|
||||
}
|
||||
|
||||
if (buttonCount % buttonsPerRow != 0 && buttonCount % buttonsPerRow > 4)
|
||||
{
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buttonCount == treeViewAW.uniqueAuthors.Count)
|
||||
{
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
ApplyCrateFilters();
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
private void ApplyCrateFilters()
|
||||
{
|
||||
if (!treeViewAW.list)
|
||||
{
|
||||
RefreshTree();
|
||||
treeViewAW.CollapseAll();
|
||||
for (int t = 0; t < treeViewAW.orderedObjs.Count; t++)
|
||||
{
|
||||
if (treeViewAW.orderedObjs[t] != null && treeViewAW.showAvatars && treeViewAW.orderedObjs[t].GetType() == typeof(AvatarCrate))
|
||||
{
|
||||
treeViewAW.FrameItem(t);
|
||||
}
|
||||
|
||||
if (treeViewAW.orderedObjs[t] != null && treeViewAW.showLevels && treeViewAW.orderedObjs[t].GetType() == typeof(LevelCrate))
|
||||
{
|
||||
treeViewAW.FrameItem(t);
|
||||
}
|
||||
|
||||
if (treeViewAW.orderedObjs[t] != null && treeViewAW.showSpawnables && treeViewAW.orderedObjs[t].GetType() == typeof(SpawnableCrate))
|
||||
{
|
||||
treeViewAW.FrameItem(t);
|
||||
}
|
||||
}
|
||||
|
||||
treeViewAW.ExpandAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
RefreshTree();
|
||||
treeViewAW.ExpandAll();
|
||||
}
|
||||
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
StoreAWState();
|
||||
}
|
||||
}
|
||||
|
||||
private void StoreAWState()
|
||||
{
|
||||
EditorPrefs.SetBool("awSettingsListOrTree", treeViewAW.list);
|
||||
EditorPrefs.SetBool("awSettingsShowLevels", treeViewAW.showLevels);
|
||||
EditorPrefs.SetBool("awSettingsShowAvatars", treeViewAW.showAvatars);
|
||||
EditorPrefs.SetBool("awSettingsShowSpawnabes", treeViewAW.showSpawnables);
|
||||
EditorPrefs.SetBool("awSettingsShowDatacards", treeViewAW.showDataCards);
|
||||
string selIDString = "";
|
||||
foreach (int selID in treeViewAW.state.selectedIDs)
|
||||
{
|
||||
selIDString += selID.ToString() + ",";
|
||||
}
|
||||
|
||||
if (selIDString != "")
|
||||
{
|
||||
selIDString = selIDString.Remove(selIDString.Length - 1);
|
||||
}
|
||||
|
||||
EditorPrefs.SetString("awSettingsSelectedIDs", selIDString);
|
||||
}
|
||||
|
||||
private void RefreshTree()
|
||||
{
|
||||
if (treeViewAW != null)
|
||||
{
|
||||
treeViewAW.Reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bbf098f01e28bbd49b0ed16e5656adcd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using System.Linq;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
public class AssetWarehouseTagsPopupWindow : PopupWindowContent
|
||||
{
|
||||
TreeViewState treeViewState;
|
||||
AssetWarehouseTreeView treeViewAW;
|
||||
private Vector2 toolScrollPos;
|
||||
int buttonsPerRow = 4;
|
||||
int padding = 5;
|
||||
Vector2 buttonSize = new Vector2(120, 20);
|
||||
public AssetWarehouseTagsPopupWindow(AssetWarehouseTreeView treeViewAW)
|
||||
{
|
||||
this.treeViewAW = treeViewAW;
|
||||
}
|
||||
|
||||
public override Vector2 GetWindowSize()
|
||||
{
|
||||
float winSizeFromCount = 10;
|
||||
if ((treeViewAW.uniqueBoneTags.Count + treeViewAW.uniqueTags.Count) > 9)
|
||||
{
|
||||
winSizeFromCount = treeViewAW.uniqueBoneTags.Count + treeViewAW.uniqueTags.Count;
|
||||
}
|
||||
|
||||
return new Vector2((buttonSize.x * buttonsPerRow) + (padding * 5), ((winSizeFromCount / buttonsPerRow) * buttonSize.y) + (buttonSize.y * 4));
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect rect)
|
||||
{
|
||||
padding = 5;
|
||||
GUIStyle style = new GUIStyle();
|
||||
style.padding = new RectOffset(padding, padding, padding, padding);
|
||||
toolScrollPos = EditorGUILayout.BeginScrollView(toolScrollPos, false, false, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
|
||||
using (new GUILayout.VerticalScope(style))
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
if (treeViewAW != null)
|
||||
{
|
||||
int buttonCount = 0;
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Label("BoneTags: ", GUILayout.Width(65));
|
||||
if (GUILayout.Button(new GUIContent("All", "Select All BoneTags"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
foreach (var kvp in treeViewAW.uniqueBoneTags.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueBoneTags[kvp.Key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (GUILayout.Button(new GUIContent("None", "Deselect All BoneTags"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
foreach (var kvp in treeViewAW.uniqueBoneTags.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueBoneTags[kvp.Key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button(new GUIContent("X", "Close BoneTags Window"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
editorWindow.Close();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
foreach (var kvp in treeViewAW.uniqueBoneTags.ToArray())
|
||||
{
|
||||
if (buttonCount % buttonsPerRow == 0)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
}
|
||||
|
||||
treeViewAW.uniqueBoneTags[kvp.Key] = GUILayout.Toggle(treeViewAW.uniqueBoneTags[kvp.Key], new GUIContent(kvp.Key.ToString(), "Filter by BoneTag: " + kvp.Key.ToString()), MarrowGUIStyles.DefaultButton, GUILayout.Width(buttonSize.x), GUILayout.Height(buttonSize.y));
|
||||
if (buttonCount % buttonsPerRow == buttonsPerRow - 1)
|
||||
{
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
buttonCount++;
|
||||
}
|
||||
|
||||
if (buttonCount % buttonsPerRow != 0 && buttonCount % buttonsPerRow > 4)
|
||||
{
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buttonCount == treeViewAW.uniqueBoneTags.Count)
|
||||
{
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
buttonCount = 0;
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Tags: ", GUILayout.Width(50));
|
||||
if (GUILayout.Button(new GUIContent("All", "Select All Tags"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
foreach (var kvp in treeViewAW.uniqueTags.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueTags[kvp.Key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (GUILayout.Button(new GUIContent("None", "Deselect All Tags"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
foreach (var kvp in treeViewAW.uniqueTags.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueTags[kvp.Key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
foreach (var kvp in treeViewAW.uniqueTags.ToArray())
|
||||
{
|
||||
if (buttonCount % buttonsPerRow == 0)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
}
|
||||
|
||||
treeViewAW.uniqueTags[kvp.Key] = GUILayout.Toggle(treeViewAW.uniqueTags[kvp.Key], new GUIContent(kvp.Key.ToString(), "Filter by Tag: " + kvp.Key.ToString()), MarrowGUIStyles.DefaultButton, GUILayout.Width(buttonSize.x), GUILayout.Height(buttonSize.y));
|
||||
if (buttonCount % buttonsPerRow == buttonsPerRow - 1)
|
||||
{
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
buttonCount++;
|
||||
}
|
||||
|
||||
if (buttonCount % buttonsPerRow != 0 && buttonCount % buttonsPerRow > 4)
|
||||
{
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
ApplyCrateFilters();
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
private void ApplyCrateFilters()
|
||||
{
|
||||
if (!treeViewAW.list)
|
||||
{
|
||||
RefreshTree();
|
||||
treeViewAW.CollapseAll();
|
||||
for (int t = 0; t < treeViewAW.orderedObjs.Count; t++)
|
||||
{
|
||||
if (treeViewAW.orderedObjs[t] != null && treeViewAW.showAvatars && treeViewAW.orderedObjs[t].GetType() == typeof(AvatarCrate))
|
||||
{
|
||||
treeViewAW.FrameItem(t);
|
||||
}
|
||||
|
||||
if (treeViewAW.orderedObjs[t] != null && treeViewAW.showLevels && treeViewAW.orderedObjs[t].GetType() == typeof(LevelCrate))
|
||||
{
|
||||
treeViewAW.FrameItem(t);
|
||||
}
|
||||
|
||||
if (treeViewAW.orderedObjs[t] != null && treeViewAW.showSpawnables && treeViewAW.orderedObjs[t].GetType() == typeof(SpawnableCrate))
|
||||
{
|
||||
treeViewAW.FrameItem(t);
|
||||
}
|
||||
}
|
||||
|
||||
treeViewAW.ExpandAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
RefreshTree();
|
||||
treeViewAW.ExpandAll();
|
||||
}
|
||||
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
StoreAWState();
|
||||
}
|
||||
}
|
||||
|
||||
private void StoreAWState()
|
||||
{
|
||||
EditorPrefs.SetBool("awSettingsListOrTree", treeViewAW.list);
|
||||
EditorPrefs.SetBool("awSettingsShowLevels", treeViewAW.showLevels);
|
||||
EditorPrefs.SetBool("awSettingsShowAvatars", treeViewAW.showAvatars);
|
||||
EditorPrefs.SetBool("awSettingsShowSpawnabes", treeViewAW.showSpawnables);
|
||||
EditorPrefs.SetBool("awSettingsShowDatacards", treeViewAW.showDataCards);
|
||||
string selIDString = "";
|
||||
foreach (int selID in treeViewAW.state.selectedIDs)
|
||||
{
|
||||
selIDString += selID.ToString() + ",";
|
||||
}
|
||||
|
||||
if (selIDString != "")
|
||||
{
|
||||
selIDString = selIDString.Remove(selIDString.Length - 1);
|
||||
}
|
||||
|
||||
EditorPrefs.SetString("awSettingsSelectedIDs", selIDString);
|
||||
}
|
||||
|
||||
private void RefreshTree()
|
||||
{
|
||||
if (treeViewAW != null)
|
||||
{
|
||||
treeViewAW.Reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ada888e8ddae922459d91ba8fb74d752
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,656 @@
|
|||
using SLZ.Marrow.Warehouse;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using System;
|
||||
using SLZ.Marrow;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
public class ScannableTreeViewItem : TreeViewItem
|
||||
{
|
||||
public Barcode barcode;
|
||||
}
|
||||
|
||||
public class AssetWarehouseTreeView : TreeView
|
||||
{
|
||||
public List<Object> orderedObjs = new List<Object>();
|
||||
public string search = "";
|
||||
public bool list = false;
|
||||
public bool showAvatars = true;
|
||||
public bool showLevels = true;
|
||||
public bool showSpawnables = true;
|
||||
public bool showDataCards = true;
|
||||
public bool showUntagged = true;
|
||||
public bool showSpawnFragments = false;
|
||||
public Texture2D palletIcon;
|
||||
public Texture2D avatarIcon;
|
||||
public Texture2D levelIcon;
|
||||
public Texture2D spawnableIcon;
|
||||
public Texture2D dataCardIcon;
|
||||
public Dictionary<string, bool> uniqueTags = new Dictionary<string, bool>();
|
||||
public Dictionary<string, bool> uniqueBoneTags = new Dictionary<string, bool>();
|
||||
public Dictionary<string, bool> uniqueAuthors = new Dictionary<string, bool>();
|
||||
private static Dictionary<System.Type, Texture2D> iconCache = new Dictionary<Type, Texture2D>();
|
||||
public AssetWarehouseTreeView(TreeViewState treeViewState) : base(treeViewState)
|
||||
{
|
||||
Reload();
|
||||
}
|
||||
|
||||
protected override TreeViewItem BuildRoot()
|
||||
{
|
||||
AssetPreview.SetPreviewTextureCacheSize(10000);
|
||||
var queryEngine = ScannableQueryEngine.SetupQueryEngine();
|
||||
if (palletIcon == null)
|
||||
palletIcon = GetIconForMonoScript(typeof(Pallet));
|
||||
if (avatarIcon == null)
|
||||
avatarIcon = GetIconForMonoScript(typeof(AvatarCrate));
|
||||
if (levelIcon == null)
|
||||
levelIcon = GetIconForMonoScript(typeof(LevelCrate));
|
||||
if (spawnableIcon == null)
|
||||
spawnableIcon = GetIconForMonoScript(typeof(SpawnableCrate));
|
||||
if (dataCardIcon == null)
|
||||
dataCardIcon = GetIconForMonoScript(typeof(DataCard));
|
||||
orderedObjs = new List<Object>();
|
||||
int id = 0;
|
||||
TreeViewItem root = new TreeViewItem
|
||||
{
|
||||
id = 0,
|
||||
depth = -1,
|
||||
displayName = "Root"
|
||||
};
|
||||
TreeViewItem workingPalletItem = null;
|
||||
TreeViewItem externalPalletItem = null;
|
||||
if (!list)
|
||||
{
|
||||
workingPalletItem = new TreeViewItem
|
||||
{
|
||||
id = id++,
|
||||
displayName = "Pallets"
|
||||
};
|
||||
orderedObjs.Add(null);
|
||||
root.AddChild(workingPalletItem);
|
||||
externalPalletItem = new TreeViewItem
|
||||
{
|
||||
id = id++,
|
||||
displayName = "External Pallets"
|
||||
};
|
||||
orderedObjs.Add(null);
|
||||
root.AddChild(externalPalletItem);
|
||||
}
|
||||
|
||||
List<Pallet> pallets = AssetWarehouse.Instance.GetPallets();
|
||||
pallets = pallets.OrderBy(x => x.Title).ToList();
|
||||
List<string> distinctTags = new List<string>();
|
||||
List<string> distinctBoneTags = new List<string>();
|
||||
List<string> distinctAuthors = new List<string>();
|
||||
List<Scannable> allScannables = new List<Scannable>();
|
||||
distinctAuthors = GetDistinctAuthorsFromPallets(pallets);
|
||||
for (var a = 0; a < distinctAuthors.Count; a++)
|
||||
{
|
||||
if (!uniqueAuthors.ContainsKey(distinctAuthors[a].ToString().ToLower()))
|
||||
{
|
||||
uniqueAuthors.Add(distinctAuthors[a].ToString().ToLower(), true);
|
||||
}
|
||||
}
|
||||
|
||||
distinctBoneTags = GetDistinctBoneTagsFromPallets(pallets);
|
||||
for (var b = 0; b < distinctBoneTags.Count; b++)
|
||||
{
|
||||
if (!uniqueBoneTags.ContainsKey(distinctBoneTags[b].ToString().ToLower()))
|
||||
{
|
||||
uniqueBoneTags.Add(distinctBoneTags[b].ToString().ToLower(), true);
|
||||
}
|
||||
}
|
||||
|
||||
distinctTags = GetDistinctTagsFromCrates(pallets);
|
||||
for (var u = 0; u < distinctTags.Count; u++)
|
||||
{
|
||||
if (!uniqueTags.ContainsKey(distinctTags[u].ToString().ToLower()))
|
||||
{
|
||||
uniqueTags.Add(distinctTags[u].ToString().ToLower(), true);
|
||||
}
|
||||
}
|
||||
|
||||
allScannables = allScannables.OrderBy(s => s.Title).ToList();
|
||||
for (int p = 0; p < pallets.Count; p++)
|
||||
{
|
||||
pallets[p].GetScannables(ref allScannables);
|
||||
List<Scannable> filteredScannables = new List<Scannable>();
|
||||
filteredScannables = ScannableQueryEngine.FilterScannableData(search, queryEngine, allScannables).ToList();
|
||||
HashSet<Crate> scanAvatars = new HashSet<Crate>();
|
||||
HashSet<Crate> scanLevels = new HashSet<Crate>();
|
||||
HashSet<Crate> scanSpawnables = new HashSet<Crate>();
|
||||
Dictionary<System.Type, List<DataCard>> scanDataCards = new Dictionary<Type, List<DataCard>>();
|
||||
foreach (var scannable in filteredScannables)
|
||||
{
|
||||
if (scannable == null)
|
||||
continue;
|
||||
if (uniqueAuthors != null && uniqueAuthors.Count > 0 && uniqueAuthors.Keys.Contains(pallets[p].Author.ToLower().ToString()) && uniqueAuthors[pallets[p].Author.ToLower().ToString()] == true)
|
||||
{
|
||||
Crate scanCrate = scannable as Crate;
|
||||
if (scanCrate != null)
|
||||
{
|
||||
if ((scanCrate.BoneTags == null || scanCrate.BoneTags.Tags == null || scanCrate.BoneTags.Tags.Count == 0) && (scanCrate.Tags == null || scanCrate.Tags.Count == 0))
|
||||
{
|
||||
if (showUntagged)
|
||||
{
|
||||
if (showAvatars && scannable.GetType() == typeof(AvatarCrate))
|
||||
{
|
||||
scanAvatars.Add(scannable as Crate);
|
||||
}
|
||||
|
||||
if (showLevels && scannable.GetType() == typeof(LevelCrate))
|
||||
{
|
||||
scanLevels.Add(scannable as Crate);
|
||||
}
|
||||
|
||||
if (showSpawnables && scannable.GetType() == typeof(SpawnableCrate))
|
||||
{
|
||||
if (scannable.Title.Contains("Fragment -") && !showSpawnFragments)
|
||||
continue;
|
||||
scanSpawnables.Add(scannable as Crate);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int t = 0; t < scanCrate.BoneTags.Tags.Count; t++)
|
||||
{
|
||||
if (scanCrate.BoneTags != null && scanCrate.BoneTags.Tags != null && scanCrate.BoneTags.Tags[t] != null && uniqueBoneTags != null && scanCrate.BoneTags.Tags[t].DataCard != null && !String.IsNullOrEmpty(scanCrate.BoneTags.Tags[t].DataCard.Title.ToLower().ToString()))
|
||||
{
|
||||
if (uniqueBoneTags.Keys.Contains(scanCrate.BoneTags.Tags[t].DataCard.Title.ToLower().ToString()) && uniqueBoneTags[scanCrate.BoneTags.Tags[t].DataCard.Title.ToLower().ToString()] == true)
|
||||
{
|
||||
if (showAvatars && scannable.GetType() == typeof(AvatarCrate) && !scanAvatars.Contains(scanCrate))
|
||||
{
|
||||
scanAvatars.Add(scannable as Crate);
|
||||
}
|
||||
|
||||
if (showLevels && scannable.GetType() == typeof(LevelCrate) && !scanLevels.Contains(scanCrate))
|
||||
{
|
||||
scanLevels.Add(scannable as Crate);
|
||||
}
|
||||
|
||||
if (showSpawnables && scannable.GetType() == typeof(SpawnableCrate) && !scanSpawnables.Contains(scanCrate))
|
||||
{
|
||||
if (!showSpawnFragments && (scannable.Title.Contains("Fragment -") || scanCrate.BoneTags.Tags[t].DataCard.Title.ToLower().ToString() == "fragment"))
|
||||
continue;
|
||||
scanSpawnables.Add(scannable as Crate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int t = 0; t < scanCrate.Tags.Count; t++)
|
||||
{
|
||||
if (uniqueTags.Keys.Contains(scanCrate.Tags[t].ToLower().ToString()) && uniqueTags[scanCrate.Tags[t].ToLower().ToString()] == true)
|
||||
{
|
||||
if (showAvatars && scannable.GetType() == typeof(AvatarCrate) && !scanAvatars.Contains(scanCrate))
|
||||
{
|
||||
scanAvatars.Add(scannable as Crate);
|
||||
}
|
||||
|
||||
if (showLevels && scannable.GetType() == typeof(LevelCrate) && !scanLevels.Contains(scanCrate))
|
||||
{
|
||||
scanLevels.Add(scannable as Crate);
|
||||
}
|
||||
|
||||
if (showSpawnables && scannable.GetType() == typeof(SpawnableCrate) && !scanSpawnables.Contains(scanCrate))
|
||||
{
|
||||
if (!showSpawnFragments && (scannable.Title.Contains("Fragment -") || scanCrate.Tags[t].ToLower().ToString() == "fragment"))
|
||||
continue;
|
||||
scanSpawnables.Add(scannable as Crate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showDataCards && scannable is DataCard dataCard)
|
||||
{
|
||||
if (!scanDataCards.ContainsKey(dataCard.GetType()))
|
||||
{
|
||||
scanDataCards[dataCard.GetType()] = new List<DataCard>();
|
||||
}
|
||||
|
||||
if (!scanDataCards[dataCard.GetType()].Contains(scannable))
|
||||
{
|
||||
scanDataCards[dataCard.GetType()].Add(dataCard);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int idCache = id;
|
||||
if (palletIcon == null)
|
||||
{
|
||||
palletIcon = (Texture2D)AssetDatabase.GetCachedIcon(AssetDatabase.GetAssetPath(pallets[p]));
|
||||
}
|
||||
|
||||
var palletTreeItemAdded = new ScannableTreeViewItem
|
||||
{
|
||||
id = id,
|
||||
displayName = pallets[p].Title,
|
||||
barcode = pallets[p].Barcode
|
||||
};
|
||||
palletTreeItemAdded.icon = (Texture2D)palletIcon;
|
||||
orderedObjs.Add(pallets[p]);
|
||||
if (list)
|
||||
{
|
||||
root.AddChild(palletTreeItemAdded);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AssetWarehouse.Instance.WorkingPallets.ContainsKey(pallets[p].Barcode))
|
||||
{
|
||||
workingPalletItem.AddChild(palletTreeItemAdded);
|
||||
}
|
||||
else
|
||||
{
|
||||
externalPalletItem.AddChild(palletTreeItemAdded);
|
||||
}
|
||||
}
|
||||
|
||||
id++;
|
||||
if (scanAvatars.Count > 0 || scanLevels.Count > 0 || scanSpawnables.Count > 0)
|
||||
{
|
||||
var crateTypeTreeItemAdded = new TreeViewItem
|
||||
{
|
||||
id = id,
|
||||
displayName = nameof(Crate)
|
||||
};
|
||||
if (!list)
|
||||
{
|
||||
crateTypeTreeItemAdded.icon = GetIconForMonoScript(typeof(Crate));
|
||||
orderedObjs.Add(null);
|
||||
palletTreeItemAdded.AddChild(crateTypeTreeItemAdded);
|
||||
id++;
|
||||
}
|
||||
|
||||
var scanAvatarsList = scanAvatars.OrderBy(crate => crate.Title).ToList();
|
||||
var scanLevelsList = scanLevels.OrderBy(crate => crate.Title).ToList();
|
||||
var scanSpawnablesList = scanSpawnables.OrderBy(crate => crate.Title).ToList();
|
||||
if (scanAvatars != null && scanAvatars.Count > 0)
|
||||
SetupCrateType(scanAvatarsList, ref id, typeof(AvatarCrate), crateTypeTreeItemAdded, root);
|
||||
if (scanLevels != null && scanLevels.Count > 0)
|
||||
SetupCrateType(scanLevelsList, ref id, typeof(LevelCrate), crateTypeTreeItemAdded, root);
|
||||
if (scanSpawnables != null && scanSpawnables.Count > 0)
|
||||
SetupCrateType(scanSpawnablesList, ref id, typeof(SpawnableCrate), crateTypeTreeItemAdded, root);
|
||||
}
|
||||
|
||||
if (showDataCards)
|
||||
{
|
||||
bool dataCardsExist = false;
|
||||
foreach (var dataCardList in scanDataCards)
|
||||
{
|
||||
if (dataCardList.Value.Count > 0)
|
||||
{
|
||||
dataCardsExist = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var dataCardTypeTreeItemAdded = new TreeViewItem
|
||||
{
|
||||
id = id,
|
||||
displayName = nameof(DataCard)
|
||||
};
|
||||
if (!list && dataCardsExist)
|
||||
{
|
||||
dataCardTypeTreeItemAdded.icon = GetIconForMonoScript(typeof(DataCard));
|
||||
orderedObjs.Add(null);
|
||||
palletTreeItemAdded.AddChild(dataCardTypeTreeItemAdded);
|
||||
id++;
|
||||
}
|
||||
|
||||
foreach (var dataCardType in scanDataCards.Keys.ToList())
|
||||
{
|
||||
scanDataCards[dataCardType] = scanDataCards[dataCardType].OrderBy(crate => crate.Title).ToList();
|
||||
}
|
||||
|
||||
foreach (var typeDataCard in scanDataCards)
|
||||
{
|
||||
SetupDataCardType(typeDataCard.Value, ref id, typeDataCard.Key, dataCardTypeTreeItemAdded, root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (root.children == null)
|
||||
{
|
||||
var emptyList = new TreeViewItem
|
||||
{
|
||||
id = 1,
|
||||
displayName = "No items found"
|
||||
};
|
||||
root.AddChild(emptyList);
|
||||
}
|
||||
|
||||
SetupDepthsFromParentsAndChildren(root);
|
||||
return root;
|
||||
}
|
||||
|
||||
public void ResetDefaultExpandState()
|
||||
{
|
||||
CollapseAll();
|
||||
SetExpanded(new List<int>() { 1 });
|
||||
}
|
||||
|
||||
public void ExpandToWorkingContent()
|
||||
{
|
||||
ResetDefaultExpandState();
|
||||
SetExpanded(new[] { 0 });
|
||||
}
|
||||
|
||||
public static Texture2D GetIconForMonoScript(System.Type monoScriptType)
|
||||
{
|
||||
Texture2D icon = null;
|
||||
if (!iconCache.TryGetValue(monoScriptType, out icon))
|
||||
{
|
||||
icon = EditorGUIUtility.ObjectContent(null, monoScriptType).image as Texture2D;
|
||||
var guids = AssetDatabase.FindAssets($"t:script {monoScriptType.Name}");
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (!string.IsNullOrEmpty(path) && AssetDatabase.GetMainAssetTypeAtPath(path) == typeof(MonoScript))
|
||||
{
|
||||
var scriptAsset = AssetDatabase.LoadAssetAtPath<MonoScript>(path);
|
||||
if (scriptAsset != null && scriptAsset.GetClass() == monoScriptType)
|
||||
{
|
||||
icon = AssetDatabase.GetCachedIcon(path) as Texture2D;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (icon != null)
|
||||
{
|
||||
iconCache[monoScriptType] = icon;
|
||||
}
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
private List<Scannable> GetAllScannables(List<Pallet> pallets)
|
||||
{
|
||||
List<Scannable> allScannables = new List<Scannable>();
|
||||
for (int p = 0; p < pallets.Count; p++)
|
||||
{
|
||||
pallets[p].GetScannables(ref allScannables);
|
||||
}
|
||||
|
||||
return allScannables;
|
||||
}
|
||||
|
||||
private List<string> GetDistinctAuthorsFromPallets(List<Pallet> pallets)
|
||||
{
|
||||
List<string> distinctAuthors = new List<string>();
|
||||
for (int p = 0; p < pallets.Count; p++)
|
||||
{
|
||||
if (pallets[p].Author != null)
|
||||
{
|
||||
if (!distinctAuthors.Contains(pallets[p].Author))
|
||||
{
|
||||
distinctAuthors.Add(pallets[p].Author);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return distinctAuthors;
|
||||
}
|
||||
|
||||
private List<string> GetDistinctBoneTagsFromPallets(List<Pallet> pallets)
|
||||
{
|
||||
List<string> distinctBoneTags = new List<string>();
|
||||
for (int p = 0; p < pallets.Count; p++)
|
||||
{
|
||||
if (pallets[p].DataCards != null)
|
||||
{
|
||||
foreach (var dataCard in pallets[p].DataCards)
|
||||
{
|
||||
if (dataCard.GetType() == typeof(BoneTag) && !distinctBoneTags.Contains(dataCard.Title))
|
||||
{
|
||||
distinctBoneTags.Add(dataCard.Title);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return distinctBoneTags;
|
||||
}
|
||||
|
||||
private List<string> GetDistinctTagsFromCrates(List<Pallet> pallets)
|
||||
{
|
||||
List<string> distinctTags = new List<string>();
|
||||
for (int p = 0; p < pallets.Count; p++)
|
||||
{
|
||||
for (int c = 0; c < pallets[p].Crates.Count; c++)
|
||||
{
|
||||
if (pallets[p].Crates[c].Tags != null)
|
||||
{
|
||||
for (int t = 0; t < pallets[p].Crates[c].Tags.Count; t++)
|
||||
{
|
||||
if (!distinctTags.Contains(pallets[p].Crates[c].Tags[t]))
|
||||
{
|
||||
distinctTags.Add(pallets[p].Crates[c].Tags[t]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return distinctTags;
|
||||
}
|
||||
|
||||
protected override void DoubleClickedItem(int id)
|
||||
{
|
||||
base.DoubleClickedItem(id);
|
||||
var selectedObject = orderedObjs[id];
|
||||
if (selectedObject != null && AssetDatabase.CanOpenAssetInEditor(selectedObject.GetInstanceID()))
|
||||
{
|
||||
AssetDatabase.OpenAsset(selectedObject);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SelectionChanged(IList<int> selectedIds)
|
||||
{
|
||||
base.SelectionChanged(selectedIds);
|
||||
var selectedObjects = selectedIds.Select(id => orderedObjs[id]).ToArray();
|
||||
if (selectedObjects.Length > 0)
|
||||
{
|
||||
Selection.objects = selectedObjects;
|
||||
}
|
||||
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
string selIDString = "";
|
||||
foreach (int selID in selectedIds)
|
||||
{
|
||||
selIDString += selID.ToString() + ",";
|
||||
}
|
||||
|
||||
selIDString = selIDString.Remove(selIDString.Length - 1);
|
||||
EditorPrefs.SetString("awSettingsSelectedIDs", selIDString);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupCrateType(List<Crate> crates, ref int id, System.Type crateType, TreeViewItem crateTypeTreeItemAdded, TreeViewItem root)
|
||||
{
|
||||
bool subListSetup = false;
|
||||
Texture2D crateIcon = null;
|
||||
TreeViewItem crateTypeTreeSubItemAdded = new TreeViewItem
|
||||
{
|
||||
id = id,
|
||||
displayName = Crate.GetCrateName(crateType)
|
||||
};
|
||||
crateTypeTreeItemAdded.AddChild(crateTypeTreeSubItemAdded);
|
||||
for (int c = 0; c < crates.Count; c++)
|
||||
{
|
||||
if (crateIcon == null)
|
||||
{
|
||||
crateIcon = AssetPreview.GetMiniThumbnail(crates[c]);
|
||||
}
|
||||
|
||||
if (!subListSetup && !list)
|
||||
{
|
||||
crateTypeTreeSubItemAdded.icon = crateIcon;
|
||||
orderedObjs.Add(null);
|
||||
id++;
|
||||
subListSetup = true;
|
||||
}
|
||||
|
||||
bool loadedInWarehouse = AssetWarehouse.Instance.HasCrate(crates[c].Barcode);
|
||||
var crateTreeItemAdded = new ScannableTreeViewItem
|
||||
{
|
||||
id = id,
|
||||
displayName = crates[c].GetNameNoExtension() + (loadedInWarehouse ? "" : " -NOT in Warehouse!"),
|
||||
barcode = crates[c].Barcode
|
||||
};
|
||||
crateTreeItemAdded.icon = crateIcon;
|
||||
SetCrateIcon(crateTreeItemAdded, crates[c]).Forget();
|
||||
orderedObjs.Add(crates[c]);
|
||||
if (list)
|
||||
{
|
||||
root.AddChild(crateTreeItemAdded);
|
||||
}
|
||||
else
|
||||
{
|
||||
crateTypeTreeSubItemAdded.AddChild(crateTreeItemAdded);
|
||||
}
|
||||
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<Type, Texture2D> scannableIconCache = new Dictionary<Type, Texture2D>();
|
||||
private void SetupDataCardType(List<DataCard> dataCards, ref int id, System.Type dataCardType, TreeViewItem dataCardTypeTreeItem, TreeViewItem root)
|
||||
{
|
||||
bool subListSetup = false;
|
||||
Texture2D dataCardIcon = null;
|
||||
if (!scannableIconCache.ContainsKey(typeof(DataCard)))
|
||||
{
|
||||
scannableIconCache[typeof(DataCard)] = AssetDatabase.LoadAssetAtPath<Texture2D>(MarrowSDK.GetPackagePath("Editor/Assets/Icons/Warehouse/datacard.png"));
|
||||
}
|
||||
|
||||
string dataCardScriptsPath = String.Empty;
|
||||
var dataCardTypeTreeSubItemAdded = new TreeViewItem
|
||||
{
|
||||
id = id,
|
||||
displayName = dataCardType.Name
|
||||
};
|
||||
dataCardTypeTreeItem.AddChild(dataCardTypeTreeSubItemAdded);
|
||||
for (int i = 0; i < dataCards.Count; i++)
|
||||
{
|
||||
if (dataCardIcon == null)
|
||||
{
|
||||
if (!scannableIconCache.TryGetValue(dataCardType, out dataCardIcon))
|
||||
{
|
||||
if (string.IsNullOrEmpty(dataCardScriptsPath))
|
||||
{
|
||||
DataCard dataCard = ScriptableObject.CreateInstance(dataCardType) as DataCard;
|
||||
dataCardScriptsPath = AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(dataCard)).Replace($"{dataCardType.Name}.cs", "");
|
||||
Object.DestroyImmediate(dataCard);
|
||||
}
|
||||
|
||||
var dataCardMonoScript = AssetDatabase.LoadAssetAtPath<MonoScript>($"{dataCardScriptsPath}/{dataCardType.Name}.cs");
|
||||
if (dataCardMonoScript != null)
|
||||
{
|
||||
dataCardIcon = EditorGUIUtility.GetIconForObject(dataCardMonoScript);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataCardIcon = scannableIconCache[typeof(DataCard)];
|
||||
}
|
||||
|
||||
scannableIconCache[dataCardType] = dataCardIcon;
|
||||
}
|
||||
}
|
||||
|
||||
if (!subListSetup && !list)
|
||||
{
|
||||
dataCardTypeTreeSubItemAdded.icon = dataCardIcon;
|
||||
orderedObjs.Add(null);
|
||||
id++;
|
||||
subListSetup = true;
|
||||
}
|
||||
|
||||
bool loadedInWarehouse = AssetWarehouse.Instance.HasDataCard(dataCards[i].Barcode);
|
||||
var dataCardTreeItemAdded = new ScannableTreeViewItem
|
||||
{
|
||||
id = id,
|
||||
displayName = dataCards[i].Title + (loadedInWarehouse ? "" : " -NOT in Warehouse!"),
|
||||
barcode = dataCards[i].Barcode
|
||||
};
|
||||
dataCardTreeItemAdded.icon = dataCardIcon;
|
||||
orderedObjs.Add(dataCards[i]);
|
||||
if (list)
|
||||
{
|
||||
root.AddChild(dataCardTreeItemAdded);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataCardTypeTreeSubItemAdded.AddChild(dataCardTreeItemAdded);
|
||||
}
|
||||
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTaskVoid SetCrateIcon(TreeViewItem treeItem, Crate crate)
|
||||
{
|
||||
if (crate.MainAsset.EditorAsset != null)
|
||||
{
|
||||
await UniTask.WaitUntil(() => !AssetPreview.IsLoadingAssetPreview(crate.MainAsset.EditorAsset.GetInstanceID()));
|
||||
if (AssetPreview.GetAssetPreview(crate.MainAsset.EditorAsset) != null)
|
||||
treeItem.icon = AssetPreview.GetAssetPreview(crate.MainAsset.EditorAsset);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool CanStartDrag(CanStartDragArgs args)
|
||||
{
|
||||
return AssetWarehouse.ready;
|
||||
}
|
||||
|
||||
protected override void SetupDragAndDrop(SetupDragAndDropArgs args)
|
||||
{
|
||||
base.SetupDragAndDrop(args);
|
||||
if (AssetWarehouse.ready)
|
||||
{
|
||||
var dragItems = FindRows(args.draggedItemIDs);
|
||||
List<Barcode> crateBarcodes = new List<Barcode>();
|
||||
List<Barcode> palletBarcodes = new List<Barcode>();
|
||||
List<Object> allScannables = new List<Object>();
|
||||
foreach (var dragItem in dragItems)
|
||||
{
|
||||
if (dragItem is ScannableTreeViewItem scannableItem)
|
||||
{
|
||||
if (AssetWarehouse.Instance.TryGetScannable(scannableItem.barcode, out var scannable))
|
||||
{
|
||||
allScannables.Add(scannable);
|
||||
if (scannable is Pallet pallet)
|
||||
{
|
||||
palletBarcodes.Add(pallet.Barcode);
|
||||
}
|
||||
else if (scannable is Crate crate)
|
||||
{
|
||||
crateBarcodes.Add(crate.Barcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DragAndDrop.PrepareStartDrag();
|
||||
if (crateBarcodes.Count > 0)
|
||||
DragAndDrop.SetGenericData("_cratesBarcodes", crateBarcodes);
|
||||
if (palletBarcodes.Count > 0)
|
||||
DragAndDrop.SetGenericData("_palletBarcodes", palletBarcodes);
|
||||
DragAndDrop.objectReferences = allScannables.ToArray();
|
||||
DragAndDrop.StartDrag("Draggin scannables");
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Move;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 35923a1511ddd22468c145d1bac2bead
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,776 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using System.Collections.Generic;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using SLZ.Marrow;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using System.Linq;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
public class AssetWarehouseWindow : EditorWindow
|
||||
{
|
||||
[SerializeField]
|
||||
TreeViewState treeViewState;
|
||||
AssetWarehouseTreeView treeViewAW;
|
||||
private string searchString = "";
|
||||
private Rect warehouseRect;
|
||||
private Rect searchBarRect;
|
||||
private Vector2 warehouseScrollPos;
|
||||
private Rect tagsButtonRect;
|
||||
private Rect authsButtonRect;
|
||||
private int palletIndex = 0;
|
||||
private int buildIndex = 0;
|
||||
Texture2D palletIcon;
|
||||
Texture2D palletPlusIcon;
|
||||
Texture2D palletPlusIconBig;
|
||||
Texture2D refreshIcon;
|
||||
Texture2DArray refreshIconArrayAsset;
|
||||
private Texture2D[] refreshIconArray;
|
||||
private static bool reloadingWarehouse = false;
|
||||
void OnEnable()
|
||||
{
|
||||
autoRepaintOnSceneChange = true;
|
||||
if (treeViewState == null)
|
||||
treeViewState = new TreeViewState();
|
||||
if (palletIcon == null)
|
||||
palletIcon = AssetWarehouseTreeView.GetIconForMonoScript(typeof(Pallet));
|
||||
if (palletPlusIcon == null)
|
||||
palletPlusIcon = AssetDatabase.LoadAssetAtPath<Texture2D>(MarrowSDK.GetPackagePath("Editor/Assets/Icons/Warehouse/pallet-add.png"));
|
||||
if (palletPlusIconBig == null)
|
||||
palletPlusIconBig = AssetDatabase.LoadAssetAtPath<Texture2D>(MarrowSDK.GetPackagePath("Editor/Assets/Icons/Warehouse/pallet-add-big.png"));
|
||||
refreshIcon = EditorGUIUtility.Load(MarrowSDK.GetPackagePath("Editor/Assets/Icons/Warehouse/hunter-reload.png")) as Texture2D;
|
||||
refreshIconArrayAsset = EditorGUIUtility.Load(MarrowSDK.GetPackagePath("Editor/Assets/Icons/Warehouse/hunter-reload-tiled.png")) as Texture2DArray;
|
||||
refreshIconArray = new Texture2D[8];
|
||||
for (int i = 0; i < refreshIconArray.Length; i++)
|
||||
{
|
||||
Texture2D refreshIcon = new Texture2D(refreshIconArrayAsset.width, refreshIconArrayAsset.height, refreshIconArrayAsset.format, refreshIconArrayAsset.mipmapCount, false);
|
||||
Graphics.CopyTexture(refreshIconArrayAsset, i, refreshIcon, 0);
|
||||
refreshIconArray[i] = refreshIcon;
|
||||
}
|
||||
|
||||
AssetWarehouse.OnReady(() =>
|
||||
{
|
||||
if (treeViewAW == null)
|
||||
{
|
||||
treeViewAW = new AssetWarehouseTreeView(treeViewState);
|
||||
treeViewAW.ExpandToWorkingContent();
|
||||
UpdateSearch();
|
||||
this.Repaint();
|
||||
}
|
||||
|
||||
WarehouseInit();
|
||||
AssetWarehouse.Instance.OnChanged += RefreshTree;
|
||||
});
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
private void OnPlayModeStateChanged(PlayModeStateChange stateChange)
|
||||
{
|
||||
if (treeViewState != null)
|
||||
{
|
||||
if (stateChange == PlayModeStateChange.EnteredEditMode)
|
||||
{
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
AssetWarehouse.OnReady(() =>
|
||||
{
|
||||
treeViewAW.list = EditorPrefs.GetBool("awSettingsListOrTree");
|
||||
buildIndex = EditorPrefs.GetInt("awSettingsBuildIndex");
|
||||
palletIndex = EditorPrefs.GetInt("awSettingsPalletIndex");
|
||||
treeViewAW.showLevels = EditorPrefs.GetBool("awSettingsShowLevels");
|
||||
treeViewAW.showAvatars = EditorPrefs.GetBool("awSettingsShowAvatars");
|
||||
treeViewAW.showSpawnables = EditorPrefs.GetBool("awSettingsShowSpawnabes");
|
||||
treeViewAW.showDataCards = EditorPrefs.GetBool("awSettingsShowDatacards");
|
||||
string selIDString = EditorPrefs.GetString("awSettingsSelectedIDs");
|
||||
string[] selIDStringList = selIDString.Split(",");
|
||||
List<int> selIDIntList = new List<int>();
|
||||
if (selIDStringList.Length > 0)
|
||||
{
|
||||
for (int i = 0; i < selIDStringList.Length; i++)
|
||||
{
|
||||
int.TryParse(selIDStringList[i], out int intAdded);
|
||||
if (!string.IsNullOrEmpty(selIDString) && !string.IsNullOrEmpty(selIDStringList[i]) && !selIDIntList.Contains(intAdded))
|
||||
{
|
||||
selIDIntList.Add(intAdded);
|
||||
}
|
||||
}
|
||||
|
||||
treeViewAW.SetSelection(selIDIntList);
|
||||
}
|
||||
|
||||
UpdateSearch();
|
||||
this.Repaint();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void StoreAWState()
|
||||
{
|
||||
EditorPrefs.SetBool("awSettingsListOrTree", treeViewAW.list);
|
||||
EditorPrefs.SetInt("awSettingsBuildIndex", buildIndex);
|
||||
EditorPrefs.SetInt("awSettingsPalletIndex", palletIndex);
|
||||
EditorPrefs.SetBool("awSettingsShowLevels", treeViewAW.showLevels);
|
||||
EditorPrefs.SetBool("awSettingsShowAvatars", treeViewAW.showAvatars);
|
||||
EditorPrefs.SetBool("awSettingsShowSpawnabes", treeViewAW.showSpawnables);
|
||||
EditorPrefs.SetBool("awSettingsShowDatacards", treeViewAW.showDataCards);
|
||||
string selIDString = "";
|
||||
foreach (int selID in treeViewAW.state.selectedIDs)
|
||||
{
|
||||
selIDString += selID.ToString() + ",";
|
||||
}
|
||||
|
||||
if (selIDString != "")
|
||||
{
|
||||
selIDString = selIDString.Remove(selIDString.Length - 1);
|
||||
}
|
||||
|
||||
EditorPrefs.SetString("awSettingsSelectedIDs", selIDString);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
AssetWarehouse.Instance.OnChanged -= OnWarehouseChanged;
|
||||
AssetWarehouse.Instance.OnClearEditor -= OnWarehouseClear;
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
private void WarehouseInit()
|
||||
{
|
||||
if (treeViewAW == null)
|
||||
{
|
||||
treeViewAW = new AssetWarehouseTreeView(treeViewState);
|
||||
this.Repaint();
|
||||
}
|
||||
|
||||
AssetWarehouse.Instance.OnChanged -= OnWarehouseChanged;
|
||||
AssetWarehouse.Instance.OnClearEditor -= OnWarehouseClear;
|
||||
AssetWarehouse.Instance.OnChanged += OnWarehouseChanged;
|
||||
AssetWarehouse.Instance.OnClearEditor += OnWarehouseClear;
|
||||
RefreshTree();
|
||||
}
|
||||
|
||||
private void OnWarehouseChanged()
|
||||
{
|
||||
RefreshTree();
|
||||
}
|
||||
|
||||
private void OnWarehouseClear()
|
||||
{
|
||||
AssetWarehouse.Instance.OnChanged -= RefreshTree;
|
||||
RefreshTree();
|
||||
AssetWarehouse.OnReady(WarehouseInit);
|
||||
}
|
||||
|
||||
void OnGUIHeader(bool warehouseReady, string message = null, MessageType messageType = MessageType.Info)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
if (treeViewAW != null)
|
||||
{
|
||||
}
|
||||
|
||||
bool hasWorkingPallets = AssetWarehouse.Instance != null && AssetWarehouse.Instance.WorkingPallets.Count > 0;
|
||||
if (refreshIconArray.Length > 0)
|
||||
{
|
||||
int refreshIconIndex = Time.frameCount / 4 % 8;
|
||||
var refreshImageCycle = refreshIconArray[refreshIconIndex];
|
||||
if (!reloadingWarehouse)
|
||||
{
|
||||
refreshImageCycle = refreshIcon;
|
||||
}
|
||||
|
||||
if (GUILayout.Button(new GUIContent("", refreshImageCycle, "Reload the AssetWarehouse"), MarrowGUIStyles.BigIconButton))
|
||||
{
|
||||
if (Event.current.control)
|
||||
{
|
||||
EditorUtility.RequestScriptReload();
|
||||
}
|
||||
else
|
||||
{
|
||||
ReloadWarehouseInternal().Forget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
EditorGUILayout.HelpBox(message, messageType);
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button(new GUIContent("?", "Open the Asset Warehouse Documentation in the default web browser."), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/PalletsAndCrates");
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
int padding = 5;
|
||||
GUIStyle style = new GUIStyle();
|
||||
style.padding = new RectOffset(padding, padding, padding, padding);
|
||||
using (new GUILayout.VerticalScope(style))
|
||||
{
|
||||
if (AssetWarehouse.Instance == null || (!AssetWarehouse.ready && !AssetWarehouse.Instance.Initializing && !reloadingWarehouse))
|
||||
{
|
||||
OnGUIHeader(false, "AssetWarehouse is NULL! Try refreshing...", MessageType.Error);
|
||||
}
|
||||
else if (AssetWarehouse.Instance != null && !AssetWarehouse.ready)
|
||||
{
|
||||
if (AssetWarehouse.Instance.Initializing || reloadingWarehouse)
|
||||
{
|
||||
OnGUIHeader(false, $"AssetWarehouse is loading... \n {AssetWarehouse.Instance.PalletCount()} Pallets \n {AssetWarehouse.Instance.CrateCount()} Crates \n {AssetWarehouse.Instance.DataCardCount()} DataCards", MessageType.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnGUIHeader(false, "AssetWarehouse is NULL! Try refreshing...", MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AssetWarehouse.Instance.WorkingPallets.Count == 0)
|
||||
{
|
||||
OnGUIHeader(true, "A Pallet is needed to Pack content inside of Crates and DataCards, please Create a Pallet", MessageType.Warning);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnGUIHeader(false);
|
||||
}
|
||||
|
||||
if (AssetWarehouse.Instance.WorkingPallets.Count == 0)
|
||||
{
|
||||
if (GUILayout.Button(new GUIContent("Create Pallet", palletPlusIconBig, "Create a Pallet"), GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
CreatePalletEditorWindow.ShowCreatePalletWindowEditor();
|
||||
}
|
||||
}
|
||||
|
||||
if (AssetWarehouse.Instance.WorkingPallets.Count > 0)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
if (treeViewAW != null)
|
||||
{
|
||||
using (new GUILayout.VerticalScope())
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button(new GUIContent("", palletPlusIcon, "Create a Pallet")))
|
||||
{
|
||||
CreatePalletEditorWindow.ShowCreatePalletWindowEditor();
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.VerticalScope())
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
searchString = GUILayout.TextField(searchString, GUI.skin.FindStyle("ToolbarSeachTextField"), GUILayout.MaxWidth(position.width - 60));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
UpdateSearch();
|
||||
treeViewAW.ExpandAll();
|
||||
}
|
||||
}
|
||||
|
||||
string searchTooltip = "";
|
||||
searchTooltip = "Search for a Crate or DataCard by its title or search for a full barcode";
|
||||
EditorGUI.LabelField(GUILayoutUtility.GetLastRect(), new GUIContent("", searchTooltip));
|
||||
if (GUILayout.Button(new GUIContent("Clear", "Clear the Search Bar"), MarrowGUIStyles.TrimButton))
|
||||
{
|
||||
searchString = "";
|
||||
UpdateSearch();
|
||||
treeViewAW.ResetDefaultExpandState();
|
||||
}
|
||||
|
||||
if (!treeViewAW.list)
|
||||
{
|
||||
if (GUILayout.Button(new GUIContent("+", "Expand All AW Items"), MarrowGUIStyles.TrimButton))
|
||||
{
|
||||
treeViewAW.ExpandAll();
|
||||
}
|
||||
|
||||
if (GUILayout.Button(new GUIContent("-", "Collapse All AW Items"), MarrowGUIStyles.TrimButton))
|
||||
{
|
||||
treeViewAW.ResetDefaultExpandState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
searchBarRect = GUILayoutUtility.GetLastRect();
|
||||
warehouseRect = new Rect(0, 0, position.width, treeViewAW.totalHeight);
|
||||
warehouseScrollPos = EditorGUILayout.BeginScrollView(warehouseScrollPos, false, false);
|
||||
treeViewAW.OnGUI(warehouseRect);
|
||||
GUILayout.Space(treeViewAW.totalHeight);
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.VerticalScope())
|
||||
{
|
||||
GUILayout.FlexibleSpace();
|
||||
GUILayout.Label("Filters:", EditorStyles.boldLabel);
|
||||
GUILayout.Space(5);
|
||||
if (AssetWarehouse.Instance != null && AssetWarehouse.Instance.WorkingPallets.Count > 0)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button(new GUIContent("All", "Enable all filters to view all items"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
if (treeViewAW != null)
|
||||
{
|
||||
searchString = "";
|
||||
UpdateSearch();
|
||||
EnableAllFilters();
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
StoreAWState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GUILayout.Button(new GUIContent("None", "Disable all filters and hide all items"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
if (treeViewAW != null)
|
||||
{
|
||||
searchString = "";
|
||||
UpdateSearch();
|
||||
DisableAllFilters();
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
StoreAWState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (treeViewAW != null)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
treeViewAW.showAvatars = GUILayout.Toggle(ShowAvatarsToggleContext(), new GUIContent(treeViewAW.avatarIcon, "Show Avatars"), MarrowGUIStyles.DefaultIconButton);
|
||||
treeViewAW.showLevels = GUILayout.Toggle(ShowLevelsToggleContext(), new GUIContent(treeViewAW.levelIcon, "Show Levels"), MarrowGUIStyles.DefaultIconButton);
|
||||
treeViewAW.showSpawnables = GUILayout.Toggle(ShowSpawnablesToggleContext(), new GUIContent(treeViewAW.spawnableIcon, "Show Spawnables"), MarrowGUIStyles.DefaultIconButton);
|
||||
treeViewAW.showDataCards = GUILayout.Toggle(ShowDataCardsToggleContext(), new GUIContent(treeViewAW.dataCardIcon, "Show DataCards"), MarrowGUIStyles.DefaultIconButton);
|
||||
GUILayout.Space(5);
|
||||
GUIContent bitsTextOn = new GUIContent("Bits", "Show Destructible Fragments");
|
||||
GUIContent bitsTextOff = new GUIContent("No Bits", "Hide Destructible Fragments");
|
||||
treeViewAW.showSpawnFragments = GUILayout.Toggle(treeViewAW.showSpawnFragments, treeViewAW.showSpawnFragments ? bitsTextOn : bitsTextOff, MarrowGUIStyles.TrimButton);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
StoreAWState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Authors: ", GUILayout.Width(50));
|
||||
if (treeViewAW != null)
|
||||
{
|
||||
if (GUILayout.Button(new GUIContent("All", "Select All Authors"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
foreach (var kvp in treeViewAW.uniqueAuthors.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueAuthors[kvp.Key] = true;
|
||||
}
|
||||
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
StoreAWState();
|
||||
}
|
||||
}
|
||||
|
||||
if (GUILayout.Button(new GUIContent("None", "Deselect All Authors"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
foreach (var kvp in treeViewAW.uniqueAuthors.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueAuthors[kvp.Key] = false;
|
||||
}
|
||||
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
StoreAWState();
|
||||
}
|
||||
}
|
||||
|
||||
if (GUILayout.Button(new GUIContent("Pick Authors", "Open the Authors Selector"), MarrowGUIStyles.DefaultButton, GUILayout.Width(94)))
|
||||
{
|
||||
PopupWindow.Show(authsButtonRect, new AssetWarehouseAuthsPopupWindow(treeViewAW));
|
||||
}
|
||||
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
authsButtonRect = GUILayoutUtility.GetLastRect();
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
if (treeViewAW != null)
|
||||
{
|
||||
if (GUILayout.Button(new GUIContent("All", "Select All Tags"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
foreach (var kvp in treeViewAW.uniqueBoneTags.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueBoneTags[kvp.Key] = true;
|
||||
}
|
||||
|
||||
foreach (var kvp in treeViewAW.uniqueTags.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueTags[kvp.Key] = true;
|
||||
}
|
||||
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
StoreAWState();
|
||||
}
|
||||
}
|
||||
|
||||
if (GUILayout.Button(new GUIContent("None", "Deselect All Tags"), MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
foreach (var kvp in treeViewAW.uniqueBoneTags.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueBoneTags[kvp.Key] = false;
|
||||
}
|
||||
|
||||
foreach (var kvp in treeViewAW.uniqueTags.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueTags[kvp.Key] = false;
|
||||
}
|
||||
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
StoreAWState();
|
||||
}
|
||||
}
|
||||
|
||||
if (GUILayout.Button(new GUIContent("Pick Tags", "Open the Tag Selector"), MarrowGUIStyles.DefaultButton, GUILayout.Width(94)))
|
||||
{
|
||||
PopupWindow.Show(tagsButtonRect, new AssetWarehouseTagsPopupWindow(treeViewAW));
|
||||
}
|
||||
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
tagsButtonRect = GUILayoutUtility.GetLastRect();
|
||||
GUILayout.Space(5);
|
||||
treeViewAW.showUntagged = GUILayout.Toggle(treeViewAW.showUntagged, new GUIContent("Show Untagged", "Show Crates that have No Tags"), MarrowGUIStyles.DefaultButton);
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
ApplyCrateFilters();
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
if (EditorPrefs.GetBool("UnlockEditingScannables", false))
|
||||
{
|
||||
if (GUILayout.Button("Init", MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
InitWarehouseInternal().Forget();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Clear", MarrowGUIStyles.DefaultButton))
|
||||
{
|
||||
ClearWarehouseInternal().Forget();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask InitWarehouseInternal()
|
||||
{
|
||||
QueueEditorUpdateLoop.StartEditorUpdateLoop();
|
||||
RefreshTree();
|
||||
await AssetWarehouse.Instance.InitAsync();
|
||||
RefreshTree();
|
||||
WarehouseInit();
|
||||
QueueEditorUpdateLoop.StopEditorUpdateLoop();
|
||||
}
|
||||
|
||||
private async UniTask ClearWarehouseInternal()
|
||||
{
|
||||
QueueEditorUpdateLoop.StartEditorUpdateLoop();
|
||||
RefreshTree();
|
||||
AssetWarehouse.Instance.Clear();
|
||||
RefreshTree();
|
||||
QueueEditorUpdateLoop.StopEditorUpdateLoop();
|
||||
}
|
||||
|
||||
private static async UniTask InitWarehouse()
|
||||
{
|
||||
QueueEditorUpdateLoop.StartEditorUpdateLoop();
|
||||
await AssetWarehouse.Instance.InitAsync();
|
||||
QueueEditorUpdateLoop.StopEditorUpdateLoop();
|
||||
}
|
||||
|
||||
private static void ClearWarehouse()
|
||||
{
|
||||
QueueEditorUpdateLoop.StartEditorUpdateLoop();
|
||||
AssetWarehouse.Instance.Clear();
|
||||
QueueEditorUpdateLoop.StopEditorUpdateLoop();
|
||||
}
|
||||
|
||||
public static async UniTask ReloadWarehouse()
|
||||
{
|
||||
if (!reloadingWarehouse)
|
||||
{
|
||||
reloadingWarehouse = true;
|
||||
ClearWarehouse();
|
||||
await UniTask.Delay(TimeSpan.FromMilliseconds(100));
|
||||
await InitWarehouse();
|
||||
reloadingWarehouse = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTaskVoid ReloadWarehouseInternal()
|
||||
{
|
||||
if (!reloadingWarehouse)
|
||||
{
|
||||
reloadingWarehouse = true;
|
||||
SpinForReload().Forget();
|
||||
await ClearWarehouseInternal();
|
||||
await UniTask.Delay(TimeSpan.FromMilliseconds(100));
|
||||
await InitWarehouseInternal();
|
||||
reloadingWarehouse = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTaskVoid SpinForReload()
|
||||
{
|
||||
while (reloadingWarehouse)
|
||||
{
|
||||
Repaint();
|
||||
await UniTask.DelayFrame(1);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShowAvatarsToggleContext()
|
||||
{
|
||||
if (treeViewAW.showAvatars)
|
||||
{
|
||||
if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
|
||||
{
|
||||
if (Event.current.modifiers == (EventModifiers.Control))
|
||||
{
|
||||
Debug.Log("CTRL key held on Avatars toggle");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
|
||||
{
|
||||
if (Event.current.modifiers == (EventModifiers.Control))
|
||||
{
|
||||
Debug.Log("CTRL key held on Avatars toggle");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShowLevelsToggleContext()
|
||||
{
|
||||
if (treeViewAW.showLevels)
|
||||
{
|
||||
if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
|
||||
{
|
||||
if (Event.current.modifiers == (EventModifiers.Control))
|
||||
{
|
||||
Debug.Log("CTRL key held on Levels toggle");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
|
||||
{
|
||||
if (Event.current.modifiers == (EventModifiers.Control))
|
||||
{
|
||||
Debug.Log("CTRL key held on Levels toggle");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShowSpawnablesToggleContext()
|
||||
{
|
||||
if (treeViewAW.showSpawnables)
|
||||
{
|
||||
if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
|
||||
{
|
||||
if (Event.current.modifiers == (EventModifiers.Control))
|
||||
{
|
||||
Debug.Log("CTRL key held on Spawnables toggle");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
|
||||
{
|
||||
if (Event.current.modifiers == (EventModifiers.Control))
|
||||
{
|
||||
Debug.Log("CTRL key held on Spawnables toggle");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShowDataCardsToggleContext()
|
||||
{
|
||||
if (treeViewAW.showDataCards)
|
||||
{
|
||||
if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
|
||||
{
|
||||
if (Event.current.modifiers == (EventModifiers.Control))
|
||||
{
|
||||
Debug.Log("CTRL key held on DataCards toggle");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
|
||||
{
|
||||
if (Event.current.modifiers == (EventModifiers.Control))
|
||||
{
|
||||
Debug.Log("CTRL key held on DataCards toggle");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnableAllFilters()
|
||||
{
|
||||
treeViewAW.showAvatars = true;
|
||||
treeViewAW.showLevels = true;
|
||||
treeViewAW.showSpawnables = true;
|
||||
treeViewAW.showDataCards = true;
|
||||
treeViewAW.showUntagged = true;
|
||||
foreach (var kvp in treeViewAW.uniqueBoneTags.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueBoneTags[kvp.Key] = true;
|
||||
}
|
||||
|
||||
foreach (var kvp in treeViewAW.uniqueTags.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueTags[kvp.Key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void DisableAllFilters()
|
||||
{
|
||||
treeViewAW.showAvatars = false;
|
||||
treeViewAW.showLevels = false;
|
||||
treeViewAW.showSpawnables = false;
|
||||
treeViewAW.showDataCards = false;
|
||||
treeViewAW.showUntagged = true;
|
||||
foreach (var kvp in treeViewAW.uniqueBoneTags.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueBoneTags[kvp.Key] = false;
|
||||
}
|
||||
|
||||
foreach (var kvp in treeViewAW.uniqueTags.ToArray())
|
||||
{
|
||||
treeViewAW.uniqueTags[kvp.Key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyCrateFilters()
|
||||
{
|
||||
if (treeViewAW != null)
|
||||
{
|
||||
if (!treeViewAW.list)
|
||||
{
|
||||
RefreshTree();
|
||||
for (int t = 0; t < treeViewAW.orderedObjs.Count; t++)
|
||||
{
|
||||
if (treeViewAW.orderedObjs[t] != null && treeViewAW.showAvatars && treeViewAW.orderedObjs[t].GetType() == typeof(AvatarCrate))
|
||||
{
|
||||
treeViewAW.FrameItem(t);
|
||||
}
|
||||
|
||||
if (treeViewAW.orderedObjs[t] != null && treeViewAW.showLevels && treeViewAW.orderedObjs[t].GetType() == typeof(LevelCrate))
|
||||
{
|
||||
treeViewAW.FrameItem(t);
|
||||
}
|
||||
|
||||
if (treeViewAW.orderedObjs[t] != null && treeViewAW.showSpawnables && treeViewAW.orderedObjs[t].GetType() == typeof(SpawnableCrate))
|
||||
{
|
||||
treeViewAW.FrameItem(t);
|
||||
}
|
||||
|
||||
if (treeViewAW.orderedObjs[t] != null && treeViewAW.showDataCards && treeViewAW.orderedObjs[t].GetType() == typeof(DataCard))
|
||||
{
|
||||
treeViewAW.FrameItem(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RefreshTree();
|
||||
treeViewAW.ExpandAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSearch()
|
||||
{
|
||||
treeViewAW.search = searchString;
|
||||
treeViewAW.searchString = null;
|
||||
ScannableQueryEngine.scanQuerySearchErrorCount = 0;
|
||||
RefreshTree();
|
||||
if (!string.IsNullOrEmpty(searchString))
|
||||
treeViewAW.ExpandAll();
|
||||
}
|
||||
|
||||
private void RefreshTree()
|
||||
{
|
||||
if (treeViewAW != null)
|
||||
{
|
||||
treeViewAW.Reload();
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("Stress Level Zero/Void Tools/Asset Warehouse (" + MarrowSDK.SDK_VERSION + ")", false, 10)]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
string awImagePath = MarrowSDK.GetPackagePath("Editor/Assets/Icons/Warehouse/hunter16.png");
|
||||
Texture2D awImage = EditorGUIUtility.Load(awImagePath) as Texture2D;
|
||||
var window = GetWindow<AssetWarehouseWindow>();
|
||||
window.titleContent = new GUIContent(" Asset Warehouse");
|
||||
window.titleContent.image = awImage;
|
||||
window.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 13b41c8bd14cbb340935ea964720b825
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#if UNITY_EDITOR
|
||||
using SLZ.Marrow.Data;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[CustomEditor(typeof(AudioReverbData))]
|
||||
public class AudioReverbEditor : Editor
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2e2f46ee5c53f9e48872d4b6be8438c2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[CustomEditor(typeof(AvatarCrate))]
|
||||
[CanEditMultipleObjects]
|
||||
public class AvatarCrateEditor : SpawnableCrateEditor
|
||||
{
|
||||
protected override string AssetReferenceDisplayName
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Avatar Prefab";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[CustomPreview(typeof(AvatarCrate))]
|
||||
public class AvatarCratePreview : CratePreview
|
||||
{
|
||||
public override void Cleanup()
|
||||
{
|
||||
base.Cleanup();
|
||||
ClearCachedAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1e07d245ca14ae84ebc07c39c7f8d187
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(Barcode))]
|
||||
public class BarcodePropertyDrawer : PropertyDrawer
|
||||
{
|
||||
GUIContent errorIcon = null;
|
||||
string errorText = "Barcode too long";
|
||||
private float indentSize = 0f;
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
bool prevWordWrap = EditorStyles.textField.wordWrap;
|
||||
EditorStyles.textField.wordWrap = true;
|
||||
Rect barcodePost = position;
|
||||
barcodePost.height = GetBarcodeHeight(property);
|
||||
EditorGUI.PropertyField(barcodePost, property.FindPropertyRelative("_id"), label);
|
||||
EditorGUI.LabelField(barcodePost, new GUIContent("", property.FindPropertyRelative("_id").stringValue));
|
||||
EditorStyles.textField.wordWrap = prevWordWrap;
|
||||
Rect warningPos = position;
|
||||
warningPos.x += indentSize;
|
||||
warningPos.width -= indentSize;
|
||||
warningPos.y += barcodePost.height;
|
||||
warningPos.height = EditorGUIUtility.singleLineHeight;
|
||||
if (!Barcode.IsValidSize(property.FindPropertyRelative("_id").stringValue))
|
||||
{
|
||||
SetupErrorIcon();
|
||||
errorIcon.text = errorText + " " + property.FindPropertyRelative("_id").stringValue.Length + "/" + Barcode.MAX_SIZE;
|
||||
EditorGUI.LabelField(warningPos, errorIcon);
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public float GetBarcodeHeight(SerializedProperty property)
|
||||
{
|
||||
string barcode = property.FindPropertyRelative("_id").stringValue;
|
||||
if (barcode.Length > (Barcode.MAX_SIZE * 3f / 4f))
|
||||
{
|
||||
return EditorGUIUtility.singleLineHeight * 2f;
|
||||
}
|
||||
else
|
||||
{
|
||||
return EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (Barcode.IsValidSize(property.FindPropertyRelative("_id").stringValue))
|
||||
{
|
||||
return GetBarcodeHeight(property);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupErrorIcon();
|
||||
return GetBarcodeHeight(property) + EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupErrorIcon()
|
||||
{
|
||||
if (errorIcon == null)
|
||||
{
|
||||
var errorIconUnity = EditorGUIUtility.IconContent("console.erroricon");
|
||||
errorIcon = new GUIContent();
|
||||
errorIcon.image = errorIconUnity.image;
|
||||
errorIcon.text = errorText;
|
||||
errorIcon.tooltip = errorIconUnity.tooltip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class BarcodeElement : VisualElement
|
||||
{
|
||||
public BarcodeElement(SerializedProperty serializedProperty)
|
||||
{
|
||||
var propertyField = new PropertyField(serializedProperty);
|
||||
propertyField.style.alignSelf = Align.Center;
|
||||
Add(propertyField);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e281109ab18be714cacb260f967cc686
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
|
||||
|
||||
using UnityEditor;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[CustomEditor(typeof(BoneTag))]
|
||||
[CanEditMultipleObjects]
|
||||
public class BoneTagEditor : DataCardEditor
|
||||
{
|
||||
public override bool ShowUnlockableRedactedFields()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bf69501cb332894468578b91999f0cec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
|
||||
|
||||
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
|
||||
using UnityEditor.Callbacks;
|
||||
using UnityEditor.SceneManagement;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[CustomEditor(typeof(CrateT<>), true)]
|
||||
public class CrateTEditor : CrateEditor
|
||||
{
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(Crate))]
|
||||
[CanEditMultipleObjects]
|
||||
public class CrateEditor : ScannableEditor
|
||||
{
|
||||
SerializedProperty tagsProperty;
|
||||
SerializedProperty assetReferenceProperty;
|
||||
protected SerializedProperty additionalAssetReferencesProperty;
|
||||
protected Crate crate = null;
|
||||
Crate script;
|
||||
protected virtual string AssetReferenceDisplayName
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Asset Reference";
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string AdditionalAssetReferencesDisplayName
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Additional Asset References";
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
tagsProperty = serializedObject.FindProperty("_tags");
|
||||
assetReferenceProperty = serializedObject.FindProperty("_mainAsset");
|
||||
additionalAssetReferencesProperty = serializedObject.FindProperty("_additionalAssetReferences");
|
||||
crate = serializedObject.targetObject as Crate;
|
||||
script = (Crate)target;
|
||||
}
|
||||
|
||||
public override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
[OnOpenAsset]
|
||||
public static bool OpenAssetHandler(int instanceID, int line)
|
||||
{
|
||||
var obj = EditorUtility.InstanceIDToObject(instanceID);
|
||||
if (obj is Crate crate && crate.MainAsset.EditorAsset != null)
|
||||
{
|
||||
switch (crate)
|
||||
{
|
||||
case LevelCrate levelCrate:
|
||||
if (AssetDatabase.CanOpenAssetInEditor(levelCrate.MainAsset.EditorAsset.GetInstanceID()))
|
||||
{
|
||||
if (levelCrate.MultiScene)
|
||||
{
|
||||
if (!EditorApplication.isPlaying && EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
|
||||
{
|
||||
EditorSceneManager.RestoreSceneManagerSetup(levelCrate.ToEditorSceneSetups());
|
||||
Selection.activeObject = crate;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssetDatabase.OpenAsset(levelCrate.MainAsset.EditorAsset);
|
||||
Selection.activeObject = crate;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SpawnableCrate spawnableCrate:
|
||||
default:
|
||||
if (AssetDatabase.CanOpenAssetInEditor(crate.MainAsset.EditorAsset.GetInstanceID()))
|
||||
{
|
||||
AssetDatabase.OpenAsset(crate.MainAsset.EditorAsset);
|
||||
Selection.activeObject = crate;
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void OnInspectorGUIBody()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnInspectorGUIPackedAssets()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
serializedObject.Update();
|
||||
if (!string.IsNullOrEmpty(AssetReferenceDisplayName))
|
||||
EditorGUILayout.PropertyField(assetReferenceProperty, new GUIContent(AssetReferenceDisplayName));
|
||||
else
|
||||
EditorGUILayout.PropertyField(assetReferenceProperty);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
OnInspectorGUIBody();
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.ObjectField("Pallet", crate.Pallet, typeof(Pallet), false);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
bool bonetagIsNull = false;
|
||||
if (script.BoneTags != null && script.BoneTags.Tags != null && script.BoneTags.Tags.Count > 0)
|
||||
{
|
||||
for (var bt = 0; bt < script.BoneTags.Tags.Count; bt++)
|
||||
{
|
||||
var boneTag = script.BoneTags.Tags[bt];
|
||||
if (script.BoneTags.Tags[bt] != null && !Barcode.IsValid(boneTag.Barcode) && boneTag.Barcode != null && boneTag.Barcode.ID == Barcode.EMPTY)
|
||||
{
|
||||
bonetagIsNull = true;
|
||||
}
|
||||
else if (script.BoneTags.Tags[bt] != null && !Barcode.IsValid(boneTag.Barcode))
|
||||
{
|
||||
bonetagIsNull = true;
|
||||
script.BoneTags.Tags[bt].Barcode = Barcode.EmptyBarcode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bonetagIsNull)
|
||||
{
|
||||
EditorGUILayout.HelpBox("A BoneTag on this Crate is null or empty.", MessageType.Error);
|
||||
}
|
||||
|
||||
LockedPropertyField(tagsProperty, false);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Packed Assets", EditorStyles.boldLabel);
|
||||
using (new EditorGUI.IndentLevelScope())
|
||||
{
|
||||
if (GUILayout.Button("Generate Packed Assets", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
foreach (var tar in targets)
|
||||
{
|
||||
if (tar is Crate tarCrate)
|
||||
{
|
||||
tarCrate.GeneratePackedAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OnInspectorGUIPackedAssets();
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
[InitializeOnLoad]
|
||||
static class CrateEditorGUI
|
||||
{
|
||||
static CrateEditorGUI()
|
||||
{
|
||||
Editor.finishedDefaultHeaderGUI += OnPostHeaderGUI;
|
||||
}
|
||||
|
||||
static void OnPostHeaderGUI(Editor editor)
|
||||
{
|
||||
using (new GUILayout.VerticalScope())
|
||||
{
|
||||
if (editor != null && editor.targets.Length > 0)
|
||||
{
|
||||
UnityEngine.Object target = editor.target;
|
||||
if (target != null && AssetWarehouse.ready)
|
||||
{
|
||||
if (AssetWarehouse.Instance.EditorObjectCrateLookup.TryGetValue(target, out Crate crate))
|
||||
{
|
||||
EditorGUILayout.ObjectField("Crate", crate, crate.GetType(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5becad5eec9c8d0439ebf41d4be6acd0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,394 @@
|
|||
using SLZ.Marrow;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using Quaternion = UnityEngine.Quaternion;
|
||||
using Vector2 = UnityEngine.Vector2;
|
||||
using Vector3 = UnityEngine.Vector3;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[CustomPreview(typeof(CrateT<>))]
|
||||
public class CrateTPreview : ObjectPreview
|
||||
{
|
||||
}
|
||||
|
||||
[CustomPreview(typeof(Crate))]
|
||||
public class CratePreview : ObjectPreview
|
||||
{
|
||||
protected Editor assetEditor = null;
|
||||
protected bool hasAssetPreview = false;
|
||||
protected PreviewRenderUtility previewRender = null;
|
||||
protected Barcode previewTargetBarcode = null;
|
||||
protected Texture previewTexture = null;
|
||||
protected GameObject previewGameObject = null;
|
||||
protected Bounds previewBounds = default;
|
||||
protected int previewMeshTriangles = 0;
|
||||
protected int fullTris = 0;
|
||||
protected int previewMeshVerts = 0;
|
||||
protected int fullVerts = 0;
|
||||
protected Vector2 m_PreviewDir = new Vector2(120, -20);
|
||||
protected Rect prevRect = default;
|
||||
protected bool showPreviewMesh = true;
|
||||
protected bool showColliderBounds = true;
|
||||
public override void Initialize(Object[] targets)
|
||||
{
|
||||
base.Initialize(targets);
|
||||
ClearCachedAssets();
|
||||
}
|
||||
|
||||
public override bool HasPreviewGUI()
|
||||
{
|
||||
if (m_Targets.Length > 1)
|
||||
return false;
|
||||
var crate = (Crate)target;
|
||||
return crate is GameObjectCrate objectCrate && (objectCrate && objectCrate.PreviewMesh != null || objectCrate.PreviewMesh.EditorAsset != null);
|
||||
}
|
||||
|
||||
public override void OnInteractivePreviewGUI(Rect r, GUIStyle background)
|
||||
{
|
||||
Crate crate = (Crate)target;
|
||||
if (crate != null)
|
||||
{
|
||||
var direction = Drag2D(m_PreviewDir, r);
|
||||
if (direction != m_PreviewDir)
|
||||
{
|
||||
m_PreviewDir = direction;
|
||||
ClearCachedTexture();
|
||||
}
|
||||
|
||||
var barStyle = new GUIStyle();
|
||||
barStyle.alignment = TextAnchor.MiddleLeft;
|
||||
using (new GUILayout.HorizontalScope(barStyle))
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
GUILayout.Button(EditorGUIUtility.IconContent("refresh"), GUILayout.ExpandWidth(false));
|
||||
showPreviewMesh = GUILayout.Toggle(showPreviewMesh, "Preview Mesh", GUILayout.ExpandWidth(false));
|
||||
showColliderBounds = GUILayout.Toggle(showColliderBounds, "Collider Bounds", GUILayout.ExpandWidth(false));
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.LabelField("Preview Mesh Triangles", GUI.skin.box, GUILayout.ExpandWidth(false));
|
||||
EditorGUILayout.LabelField($"{previewMeshTriangles.ToString()}/{fullTris.ToString()}", GUI.skin.box, GUILayout.ExpandWidth(false));
|
||||
EditorGUILayout.LabelField("Vertices", GUI.skin.box, GUILayout.ExpandWidth(false));
|
||||
EditorGUILayout.LabelField($"{previewMeshVerts.ToString()}/{fullVerts.ToString()}", GUI.skin.box, GUILayout.ExpandWidth(false));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
ClearCachedAssets();
|
||||
}
|
||||
}
|
||||
|
||||
if ((r.width < 5f && r.height < 5f))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (prevRect != r)
|
||||
{
|
||||
prevRect = r;
|
||||
ClearCachedTexture();
|
||||
}
|
||||
|
||||
if (crate.Barcode != previewTargetBarcode)
|
||||
{
|
||||
ClearCachedAssets();
|
||||
}
|
||||
|
||||
if (previewTexture == null)
|
||||
{
|
||||
CaptureRenderPreview(crate, r, background);
|
||||
}
|
||||
|
||||
if (previewTexture != null)
|
||||
{
|
||||
GUI.DrawTexture(r, previewTexture, ScaleMode.StretchToFill, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int sliderHash = "Slider".GetHashCode();
|
||||
public static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
|
||||
{
|
||||
int id = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
|
||||
Event evt = Event.current;
|
||||
switch (evt.GetTypeForControl(id))
|
||||
{
|
||||
case EventType.MouseDown:
|
||||
if (position.Contains(evt.mousePosition) && position.width > 50)
|
||||
{
|
||||
GUIUtility.hotControl = id;
|
||||
evt.Use();
|
||||
EditorGUIUtility.SetWantsMouseJumping(1);
|
||||
}
|
||||
|
||||
break;
|
||||
case EventType.MouseDrag:
|
||||
if (GUIUtility.hotControl == id)
|
||||
{
|
||||
scrollPosition -= evt.delta * (evt.shift ? 3 : 1) / Mathf.Min(position.width, position.height) * 140.0f;
|
||||
evt.Use();
|
||||
GUI.changed = true;
|
||||
}
|
||||
|
||||
break;
|
||||
case EventType.MouseUp:
|
||||
if (GUIUtility.hotControl == id)
|
||||
GUIUtility.hotControl = 0;
|
||||
EditorGUIUtility.SetWantsMouseJumping(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return scrollPosition;
|
||||
}
|
||||
|
||||
private void CaptureRenderPreview(Crate crate, Rect r, GUIStyle background)
|
||||
{
|
||||
if (previewRender == null)
|
||||
{
|
||||
SetupPreviewRender(crate, r, background);
|
||||
}
|
||||
|
||||
previewTexture = CreatePreviewTexture(r);
|
||||
}
|
||||
|
||||
private RenderTexture CreatePreviewTexture(Rect r)
|
||||
{
|
||||
float halfSize = Mathf.Max(previewBounds.extents.magnitude, 0.0001f);
|
||||
float distance = halfSize * 3.8f;
|
||||
Quaternion rot = Quaternion.Euler(-m_PreviewDir.y, -m_PreviewDir.x, 0);
|
||||
Vector3 pos = previewBounds.center - rot * (Vector3.forward * distance);
|
||||
previewRender.camera.transform.position = pos;
|
||||
previewRender.camera.transform.rotation = rot;
|
||||
previewRender.BeginPreview(new Rect(r), GUIStyle.none);
|
||||
previewRender.Render(true);
|
||||
var renderTexture = (RenderTexture)previewRender.EndPreview();
|
||||
renderTexture.name = "CrateEditorPreview RenderTexture";
|
||||
return renderTexture;
|
||||
}
|
||||
|
||||
private void SetupPreviewRender(Crate crate, Rect r, GUIStyle background)
|
||||
{
|
||||
ClearCachedAssets();
|
||||
GameObjectCrate gameObjectCrate = (GameObjectCrate)crate;
|
||||
previewRender = new PreviewRenderUtility(true);
|
||||
System.GC.SuppressFinalize(previewRender);
|
||||
previewBounds = gameObjectCrate.ColliderBounds;
|
||||
if (previewBounds.extents == Vector3.zero)
|
||||
previewBounds = new Bounds(Vector3.zero, Vector3.one);
|
||||
fullTris = 0;
|
||||
fullVerts = 0;
|
||||
if (gameObjectCrate.MainGameObject != null && gameObjectCrate.MainGameObject.EditorAsset != null)
|
||||
{
|
||||
foreach (var meshFilter in gameObjectCrate.MainGameObject.EditorAsset.GetComponentsInChildren<MeshFilter>())
|
||||
{
|
||||
if (meshFilter != null && meshFilter.sharedMesh != null && meshFilter.gameObject.activeSelf)
|
||||
{
|
||||
var sharedMesh = meshFilter.sharedMesh;
|
||||
fullTris += sharedMesh.triangles.Length;
|
||||
fullVerts += sharedMesh.vertexCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fullTris = -1;
|
||||
fullVerts = -1;
|
||||
}
|
||||
|
||||
previewTargetBarcode = crate.Barcode;
|
||||
previewRender.lights[0].transform.localEulerAngles = new Vector3(30, 30, 0);
|
||||
previewRender.lights[0].intensity = 2;
|
||||
previewRender.ambientColor = new Color(.1f, .1f, .1f, 0);
|
||||
SetupPreviewRenderGameObjects();
|
||||
float halfSize = Mathf.Max(previewBounds.extents.magnitude, 0.0001f);
|
||||
float distance = halfSize * 3.8f;
|
||||
var camera = previewRender.camera;
|
||||
camera.nearClipPlane = 0.001f;
|
||||
camera.farClipPlane = 1000;
|
||||
camera.fieldOfView = 30f;
|
||||
SetupPreviewRenderBoundBox(gameObjectCrate.ColliderBounds);
|
||||
Mesh previewMesh = null;
|
||||
if (gameObjectCrate.PreviewMesh != null && gameObjectCrate.PreviewMesh.EditorAsset != null)
|
||||
{
|
||||
previewMesh = gameObjectCrate.PreviewMesh.EditorAsset;
|
||||
previewBounds = previewMesh.bounds;
|
||||
if (previewMesh != null)
|
||||
{
|
||||
previewMeshTriangles = previewMesh.triangles.Length;
|
||||
previewMeshVerts = previewMesh.vertexCount;
|
||||
SetupPreviewRenderMainMesh(previewMesh);
|
||||
}
|
||||
}
|
||||
else if (gameObjectCrate.PreviewMesh != null)
|
||||
{
|
||||
QueueEditorUpdateLoop.StartEditorUpdateLoop();
|
||||
if (!string.IsNullOrEmpty(gameObjectCrate.PreviewMesh.AssetGUID))
|
||||
{
|
||||
gameObjectCrate.PreviewMesh.LoadAsset(loadedMesh =>
|
||||
{
|
||||
if (previewRender != null && loadedMesh != null)
|
||||
{
|
||||
previewMesh = loadedMesh;
|
||||
previewBounds = loadedMesh.bounds;
|
||||
if (previewMesh.isReadable)
|
||||
{
|
||||
previewMeshTriangles = previewMesh.triangles.Length;
|
||||
previewMeshVerts = previewMesh.vertexCount;
|
||||
}
|
||||
|
||||
float halfSize = Mathf.Max(previewBounds.extents.magnitude, 0.0001f);
|
||||
float distance = halfSize * 3.8f;
|
||||
var camera = previewRender.camera;
|
||||
camera.nearClipPlane = 0.001f;
|
||||
camera.farClipPlane = 1000;
|
||||
camera.fieldOfView = 30f;
|
||||
SetupPreviewRenderMainMesh(previewMesh);
|
||||
ClearCachedTexture();
|
||||
}
|
||||
|
||||
QueueEditorUpdateLoop.StopEditorUpdateLoop();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupPreviewRenderGameObjects()
|
||||
{
|
||||
previewGameObject = new GameObject("Preview Render GameObject");
|
||||
previewRender.AddSingleGO(previewGameObject);
|
||||
}
|
||||
|
||||
private void SetupPreviewRenderMainMesh(Mesh mesh)
|
||||
{
|
||||
var previewObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
previewObject.transform.parent = previewGameObject.transform;
|
||||
previewObject.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterial;
|
||||
previewObject.GetComponent<MeshFilter>().mesh = mesh;
|
||||
previewObject.GetComponent<MeshRenderer>().enabled = showPreviewMesh;
|
||||
}
|
||||
|
||||
private void SetupPreviewRenderBoundBox(Bounds bounds)
|
||||
{
|
||||
if (bounds.extents != Vector3.zero)
|
||||
{
|
||||
var boundGO = new GameObject("bound box");
|
||||
boundGO.transform.parent = previewGameObject.transform;
|
||||
GameObject boundGOBox;
|
||||
float width = bounds.extents.magnitude / 100f;
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center;
|
||||
boundGOBox.transform.localScale = new Vector3(width * 2f, width * 2f, width * 2f);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.forward * bounds.extents.z + Vector3.up * bounds.extents.y;
|
||||
boundGOBox.transform.localScale = new Vector3(bounds.size.x, width, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.back * bounds.extents.z + Vector3.up * bounds.extents.y;
|
||||
boundGOBox.transform.localScale = new Vector3(bounds.size.x, width, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.forward * bounds.extents.z + Vector3.down * bounds.extents.y;
|
||||
boundGOBox.transform.localScale = new Vector3(bounds.size.x, width, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.back * bounds.extents.z + Vector3.down * bounds.extents.y;
|
||||
boundGOBox.transform.localScale = new Vector3(bounds.size.x, width, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.name = "Crate Preview Bound Box";
|
||||
boundGOBox.transform.position = bounds.center + Vector3.forward * bounds.extents.z + Vector3.right * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, bounds.size.y, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.back * bounds.extents.z + Vector3.right * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, bounds.size.y, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.forward * bounds.extents.z + Vector3.left * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, bounds.size.y, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.back * bounds.extents.z + Vector3.left * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, bounds.size.y, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.up * bounds.extents.y + Vector3.right * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, width, bounds.size.z);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.down * bounds.extents.y + Vector3.right * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, width, bounds.size.z);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.up * bounds.extents.y + Vector3.left * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, width, bounds.size.z);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.down * bounds.extents.y + Vector3.left * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, width, bounds.size.z);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearCachedTexture()
|
||||
{
|
||||
if (previewTexture != null)
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(previewTexture);
|
||||
previewTexture = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearCachedAssets()
|
||||
{
|
||||
if (previewRender != null)
|
||||
{
|
||||
previewRender.Cleanup();
|
||||
previewRender = null;
|
||||
}
|
||||
|
||||
ClearCachedTexture();
|
||||
if (previewGameObject != null)
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(previewGameObject);
|
||||
previewGameObject = null;
|
||||
}
|
||||
|
||||
previewMeshTriangles = 0;
|
||||
fullTris = 0;
|
||||
previewMeshVerts = 0;
|
||||
fullVerts = 0;
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
base.Cleanup();
|
||||
ClearCachedAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ce1fff46a22a492381cf2dfcc0dcb46d
|
||||
timeCreated: 1673484143
|
||||
|
|
@ -0,0 +1,404 @@
|
|||
using SLZ.Marrow.Utilities;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[CustomEditor(typeof(CrateSpawner))]
|
||||
[CanEditMultipleObjects]
|
||||
public class CrateSpawnerEditor : Editor
|
||||
{
|
||||
SerializedProperty spawnableCrateReferenceProperty;
|
||||
SerializedProperty policyDataProperty;
|
||||
SerializedProperty crateQueryProperty;
|
||||
SerializedProperty useQueryProperty;
|
||||
SerializedProperty manualModeProperty;
|
||||
SerializedProperty onPlaceEventProperty;
|
||||
private static GUIContent previewMeshGizmoIcon = null;
|
||||
private static GUIContent colliderBoundsGizmoIcon = null;
|
||||
private static GUIContent materialIconOn = null;
|
||||
private static GUIContent materialIconOff = null;
|
||||
private CrateSpawner script;
|
||||
private static SceneAsset mainSceneAsset;
|
||||
private static bool levelIsMultiScene;
|
||||
private static SceneAsset spawnerSceneAsset;
|
||||
private bool fixtureHasBase = false;
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
EditorApplication.contextualPropertyMenu += OnPropertyContextMenu;
|
||||
spawnableCrateReferenceProperty = serializedObject.FindProperty("spawnableCrateReference");
|
||||
policyDataProperty = serializedObject.FindProperty("policyData");
|
||||
crateQueryProperty = serializedObject.FindProperty("crateQuery");
|
||||
useQueryProperty = serializedObject.FindProperty("useQuery");
|
||||
manualModeProperty = serializedObject.FindProperty("manualMode");
|
||||
onPlaceEventProperty = serializedObject.FindProperty("onSpawnEvent");
|
||||
script = (CrateSpawner)target;
|
||||
if (previewMeshGizmoIcon == null)
|
||||
{
|
||||
previewMeshGizmoIcon = new GUIContent(EditorGUIUtility.IconContent("d_GizmosToggle On@2x"));
|
||||
previewMeshGizmoIcon.tooltip = "Toggle Preview Mesh Gizmo";
|
||||
}
|
||||
|
||||
if (colliderBoundsGizmoIcon == null)
|
||||
{
|
||||
colliderBoundsGizmoIcon = new GUIContent(EditorGUIUtility.IconContent("d_BoxCollider2D Icon"));
|
||||
colliderBoundsGizmoIcon.tooltip = "Toggle Collider Bounds";
|
||||
}
|
||||
|
||||
if (materialIconOn == null)
|
||||
{
|
||||
materialIconOn = new GUIContent(EditorGUIUtility.IconContent("d_Material Icon"));
|
||||
materialIconOn.tooltip = "Swap Preview Mesh Material";
|
||||
}
|
||||
|
||||
if (materialIconOff == null)
|
||||
{
|
||||
materialIconOff = new GUIContent(EditorGUIUtility.IconContent("d_Material On Icon"));
|
||||
materialIconOff.tooltip = "Swap Preview Mesh Material";
|
||||
}
|
||||
|
||||
SceneAsset activeSceneAsset = AssetDatabase.LoadAssetAtPath<SceneAsset>(EditorSceneManager.GetActiveScene().path);
|
||||
if (activeSceneAsset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AssetWarehouse.OnReady(() =>
|
||||
{
|
||||
if (AssetWarehouse.Instance.EditorObjectCrateLookup.TryGetValue(activeSceneAsset, out Crate crate) && crate is LevelCrate levelCrate)
|
||||
{
|
||||
spawnerSceneAsset = AssetDatabase.LoadAssetAtPath<SceneAsset>(script.gameObject.scene.path);
|
||||
mainSceneAsset = AssetDatabase.LoadAssetAtPath<SceneAsset>(AssetDatabase.GetAssetPath(levelCrate.MainScene.EditorAsset));
|
||||
levelIsMultiScene = levelCrate.MultiScene;
|
||||
}
|
||||
|
||||
List<DataCard> awDataCards = AssetWarehouse.Instance.GetDataCards();
|
||||
if (awDataCards != null)
|
||||
{
|
||||
foreach (DataCard dataCard in awDataCards)
|
||||
{
|
||||
if (dataCard != null && dataCard is Fixture)
|
||||
{
|
||||
Fixture awFixture = (Fixture)dataCard;
|
||||
if (awFixture != null && awFixture.FixtureSpawnable != null)
|
||||
{
|
||||
if (awFixture.FixtureSpawnable.Barcode == script.spawnableCrateReference?.Barcode)
|
||||
{
|
||||
if (awFixture.StaticFixturePrefab != null && !String.IsNullOrEmpty(awFixture.StaticFixturePrefab.AssetGUID))
|
||||
{
|
||||
fixtureHasBase = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
EditorApplication.hierarchyChanged -= OnHierarchyChanged;
|
||||
EditorApplication.hierarchyChanged += OnHierarchyChanged;
|
||||
}
|
||||
|
||||
private void OnHierarchyChanged()
|
||||
{
|
||||
spawnerSceneAsset = AssetDatabase.LoadAssetAtPath<SceneAsset>(script.gameObject.scene.path);
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
EditorApplication.contextualPropertyMenu -= OnPropertyContextMenu;
|
||||
EditorApplication.hierarchyChanged -= OnHierarchyChanged;
|
||||
}
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("de672589595164d43bfb622a18720ba6");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
if (levelIsMultiScene && spawnerSceneAsset != mainSceneAsset)
|
||||
{
|
||||
EditorGUILayout.HelpBox($"{script.gameObject.name} not in persistent scene!", MessageType.Error);
|
||||
}
|
||||
};
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/Spawnables");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
Toggle useQueryToggle = tree.Q<Toggle>("useQueryToggle");
|
||||
PropertyField crateQuery = tree.Q<PropertyField>("crateQuery");
|
||||
PropertyField spawnableCrateReference = tree.Q<PropertyField>("spawnableCrateReference");
|
||||
spawnableCrateReference.RegisterValueChangeCallback(evt =>
|
||||
{
|
||||
if (ScannableReference.IsValid(script.spawnableCrateReference))
|
||||
{
|
||||
script.EditorUpdateName(true);
|
||||
}
|
||||
});
|
||||
if (serializedObject.FindProperty("policyData") == null)
|
||||
{
|
||||
tree.Q<PropertyField>("policyData").style.display = DisplayStyle.None;
|
||||
}
|
||||
|
||||
useQueryToggle.RegisterValueChangedCallback((evt) =>
|
||||
{
|
||||
useQueryToggle.style.display = DisplayStyle.None;
|
||||
spawnableCrateReference.style.display = DisplayStyle.Flex;
|
||||
});
|
||||
useQueryToggle.style.display = DisplayStyle.None;
|
||||
spawnableCrateReference.style.display = DisplayStyle.Flex;
|
||||
IMGUIContainer imguiRuntimeDebugContainer = tree.Q<IMGUIContainer>("imguiRuntimeDebugContainer");
|
||||
#if false
|
||||
#endif
|
||||
Button selectFixtureStaticButton = tree.Q<Button>("selectFixtureStaticButton");
|
||||
selectFixtureStaticButton.clickable.clicked += () =>
|
||||
{
|
||||
List<GameObject> selObjs = new List<GameObject>();
|
||||
Selection.objects = null;
|
||||
foreach (var target in targets)
|
||||
{
|
||||
CrateSpawner targetCS = (CrateSpawner)target;
|
||||
selObjs.Add(targetCS.gameObject);
|
||||
foreach (Transform gameObjectTrans in UnityEngine.Object.FindObjectsOfType<Transform>())
|
||||
{
|
||||
if (gameObjectTrans.name.ToLower().Contains("spawnpoint"))
|
||||
{
|
||||
if (Vector3.Distance(gameObjectTrans.transform.position, targetCS.transform.position) < 0.05f)
|
||||
{
|
||||
selObjs.Add(gameObjectTrans.transform.parent.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
selObjs.Add(targetCS.gameObject);
|
||||
}
|
||||
|
||||
Selection.objects = selObjs.ToArray();
|
||||
};
|
||||
Button alignFixtureToBaseButton = tree.Q<Button>("alignFixtureToBaseButton");
|
||||
alignFixtureToBaseButton.clickable.clicked += () =>
|
||||
{
|
||||
CrateSpawner targetCS = script;
|
||||
GameObject fixtureBaseParent = null;
|
||||
if (Selection.gameObjects.Length != 2)
|
||||
{
|
||||
Debug.Log($"{Selection.gameObjects.Length}, Select ONLY the CrateSpawner Fixture AND the Fixture Base GameObject, then try again");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (GameObject selObj in Selection.gameObjects)
|
||||
{
|
||||
if (selObj != script.gameObject)
|
||||
{
|
||||
fixtureBaseParent = selObj;
|
||||
}
|
||||
}
|
||||
|
||||
if (fixtureBaseParent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (Transform gameObjectTrans in fixtureBaseParent.GetComponentsInChildren<Transform>())
|
||||
{
|
||||
if (gameObjectTrans.name.ToLower().Contains("spawnpoint"))
|
||||
{
|
||||
targetCS.transform.position = gameObjectTrans.transform.position;
|
||||
targetCS.transform.rotation = gameObjectTrans.transform.rotation;
|
||||
}
|
||||
}
|
||||
};
|
||||
selectFixtureStaticButton.style.display = DisplayStyle.None;
|
||||
alignFixtureToBaseButton.style.display = DisplayStyle.None;
|
||||
if (fixtureHasBase)
|
||||
{
|
||||
selectFixtureStaticButton.style.display = DisplayStyle.Flex;
|
||||
alignFixtureToBaseButton.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
|
||||
ToolbarToggle showPreviewMeshToolbarToggle = tree.Q<ToolbarToggle>("showPreviewMeshToolbarToggle");
|
||||
Image showPreviewMeshIconImage = new Image
|
||||
{
|
||||
image = previewMeshGizmoIcon.image
|
||||
};
|
||||
showPreviewMeshToolbarToggle.Add(showPreviewMeshIconImage);
|
||||
showPreviewMeshToolbarToggle.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
CrateSpawner.showPreviewMesh = showPreviewMeshToolbarToggle.value;
|
||||
InternalEditorUtility.RepaintAllViews();
|
||||
});
|
||||
ToolbarToggle showColliderBoundsToolbarToggle = tree.Q<ToolbarToggle>("showColliderBoundsToolbarToggle");
|
||||
Image showColliderBoundsIconImage = new Image
|
||||
{
|
||||
image = colliderBoundsGizmoIcon.image
|
||||
};
|
||||
showColliderBoundsToolbarToggle.Add(showColliderBoundsIconImage);
|
||||
showColliderBoundsToolbarToggle.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
CrateSpawner.showColliderBounds = showColliderBoundsToolbarToggle.value;
|
||||
InternalEditorUtility.RepaintAllViews();
|
||||
});
|
||||
ToolbarToggle showLitMaterialPreviewToolbarToggle = tree.Q<ToolbarToggle>("showLitMaterialPreviewToolbarToggle");
|
||||
Image showLitMaterialPreviewIconOnImage = new Image
|
||||
{
|
||||
image = materialIconOn.image
|
||||
};
|
||||
Image showLitMaterialPreviewIconOffImage = new Image
|
||||
{
|
||||
image = materialIconOff.image
|
||||
};
|
||||
showLitMaterialPreviewToolbarToggle.Add(showLitMaterialPreviewIconOnImage);
|
||||
showLitMaterialPreviewToolbarToggle.Add(showLitMaterialPreviewIconOffImage);
|
||||
showLitMaterialPreviewToolbarToggle.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
CrateSpawner.showLitMaterialPreview = showLitMaterialPreviewToolbarToggle.value;
|
||||
if (CrateSpawner.showLitMaterialPreview)
|
||||
{
|
||||
showLitMaterialPreviewIconOnImage.style.display = DisplayStyle.None;
|
||||
showLitMaterialPreviewIconOffImage.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
else
|
||||
{
|
||||
showLitMaterialPreviewIconOnImage.style.display = DisplayStyle.Flex;
|
||||
showLitMaterialPreviewIconOffImage.style.display = DisplayStyle.None;
|
||||
}
|
||||
|
||||
InternalEditorUtility.RepaintAllViews();
|
||||
});
|
||||
SliderInt gizmoVisRangeSlider = tree.Q<SliderInt>("gizmoVisRangeSlider");
|
||||
gizmoVisRangeSlider.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
CrateSpawner.gizmoVisRange = gizmoVisRangeSlider.value;
|
||||
});
|
||||
showPreviewMeshToolbarToggle.SetValueWithoutNotify(CrateSpawner.showPreviewMesh);
|
||||
showColliderBoundsToolbarToggle.SetValueWithoutNotify(CrateSpawner.showColliderBounds);
|
||||
showLitMaterialPreviewToolbarToggle.SetValueWithoutNotify(CrateSpawner.showLitMaterialPreview);
|
||||
if (CrateSpawner.showLitMaterialPreview)
|
||||
{
|
||||
showLitMaterialPreviewIconOnImage.style.display = DisplayStyle.None;
|
||||
showLitMaterialPreviewIconOffImage.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
else
|
||||
{
|
||||
showLitMaterialPreviewIconOnImage.style.display = DisplayStyle.Flex;
|
||||
showLitMaterialPreviewIconOffImage.style.display = DisplayStyle.None;
|
||||
}
|
||||
|
||||
gizmoVisRangeSlider.SetValueWithoutNotify((int)CrateSpawner.gizmoVisRange);
|
||||
return tree;
|
||||
}
|
||||
|
||||
void OnPropertyContextMenu(GenericMenu menu, SerializedProperty property)
|
||||
{
|
||||
if (property.type != "CrateQuery")
|
||||
return;
|
||||
menu.AddItem(new GUIContent("Run Query"), false, () =>
|
||||
{
|
||||
foreach (var targetObject in serializedObject.targetObjects)
|
||||
{
|
||||
if (targetObject is CrateSpawner spawner)
|
||||
{
|
||||
if (spawner.useQuery)
|
||||
spawner.crateQuery.RunQuery();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/MarrowSDK/Crate Spawner", priority = 1)]
|
||||
private static void MenuCreateSpawner(MenuCommand menuCommand)
|
||||
{
|
||||
GameObject go = CrateSpawner.EditorCreateCrateSpawner();
|
||||
GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject);
|
||||
Selection.activeObject = go;
|
||||
bool overlayShown = false;
|
||||
bool overlayCollapsed = false;
|
||||
AWSpawnerOverlayToolbar.DoWithInstances(instance => overlayShown = instance.displayed);
|
||||
AWSpawnerOverlayToolbar.DoWithInstances(instance => overlayCollapsed = instance.collapsed);
|
||||
if (overlayShown == false)
|
||||
{
|
||||
if (UnityEngine.Object.FindObjectsOfType<CrateSpawner>().Length == 1)
|
||||
{
|
||||
AWSpawnerOverlayToolbar.DoWithInstances(instance => instance.displayed = true);
|
||||
AWSpawnerOverlayToolbar.DoWithInstances(instance => instance.collapsed = false);
|
||||
}
|
||||
}
|
||||
|
||||
if (overlayCollapsed == true)
|
||||
{
|
||||
if (UnityEngine.Object.FindObjectsOfType<CrateSpawner>().Length == 1)
|
||||
{
|
||||
AWSpawnerOverlayToolbar.DoWithInstances(instance => instance.collapsed = false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShowInChunkSceneWarning(CrateSpawner crateSpawner)
|
||||
{
|
||||
if (levelIsMultiScene == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SceneAsset activeSceneAsset = AssetDatabase.LoadAssetAtPath<SceneAsset>(EditorSceneManager.GetActiveScene().path);
|
||||
if (activeSceneAsset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AssetWarehouse.OnReady(() =>
|
||||
{
|
||||
if (spawnerSceneAsset == null || mainSceneAsset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (spawnerSceneAsset != mainSceneAsset && AssetDatabase.LoadAssetAtPath<SceneAsset>(crateSpawner.gameObject.scene.path) == spawnerSceneAsset)
|
||||
{
|
||||
Gizmos.color = Color.red;
|
||||
DrawGizmoHelper.DrawText($"WARNING: {crateSpawner.gameObject.name} not in persistent scene!", crateSpawner.transform.position);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.Selected)]
|
||||
static void DrawSelectedCrateSpawnerGizmo(CrateSpawner crateSpawner, GizmoType gizmoType)
|
||||
{
|
||||
ShowInChunkSceneWarning(crateSpawner);
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.NonSelected)]
|
||||
static void DrawNonSelectedCrateSpawnerGizmo(CrateSpawner crateSpawner, GizmoType gizmoType)
|
||||
{
|
||||
ShowInChunkSceneWarning(crateSpawner);
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.Pickable | GizmoType.Selected)]
|
||||
static void DrawPickableSelectedCrateSpawnerGizmo(CrateSpawner crateSpawner, GizmoType gizmoType)
|
||||
{
|
||||
ShowInChunkSceneWarning(crateSpawner);
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.Pickable | GizmoType.NonSelected)]
|
||||
static void DrawPickableNonSelectedCrateSpawnerGizmo(CrateSpawner crateSpawner, GizmoType gizmoType)
|
||||
{
|
||||
ShowInChunkSceneWarning(crateSpawner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: aca1fb984f6157d499b69d779f3442eb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,291 @@
|
|||
using System.Collections.Generic;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
using UnityEditor;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
public class CrateWizard : ScriptableWizard
|
||||
{
|
||||
public enum CrateType
|
||||
{
|
||||
SPAWNABLE_CRATE,
|
||||
LEVEL_CRATE,
|
||||
AVATAR_CRATE,
|
||||
VFX_CRATE
|
||||
}
|
||||
|
||||
public Barcode barcode = Barcode.EmptyBarcode();
|
||||
public Pallet pallet;
|
||||
public CrateType crateType;
|
||||
public string crateTitle = "";
|
||||
public Object assetReference;
|
||||
private Dictionary<System.Type, System.Type> assetTypeCache;
|
||||
private Crate tempCrate;
|
||||
private Pallet lastPallet;
|
||||
private string lastCrateTitle;
|
||||
private CrateType lastCrateType;
|
||||
private Object lastAssetRef;
|
||||
public static void CreateWizard()
|
||||
{
|
||||
CreateWizard(null);
|
||||
}
|
||||
|
||||
public static CrateWizard CreateWizard(Pallet pallet)
|
||||
{
|
||||
var wizard = ScriptableWizard.DisplayWizard<CrateWizard>("Create Crate", "Create");
|
||||
wizard.errorString = "";
|
||||
wizard.helpString = "!~~~WARNING~~~!\nTHIS IS AN OLD LEGACY WINDOW\nIt will be updated in the future for smoother crate creation workflows (like the level creation workflow)\n!~~~WARNING~~~!\n\n" + "Use this wizard to add a Crate to the Asset Warehouse. Take care naming the crate as its title will be used as part of its unique barcode, which cannot be changed once set. \n" + "\n" + "Deleting crates and pallets from the Asset Warehouse is not recommended. \n";
|
||||
foreach (var selected in Selection.objects)
|
||||
{
|
||||
if (selected != null && selected.GetType() == typeof(Pallet))
|
||||
{
|
||||
pallet = (Pallet)selected;
|
||||
}
|
||||
else if (selected != null && selected.GetType() != typeof(Pallet))
|
||||
{
|
||||
if (selected.GetType() == typeof(SceneAsset))
|
||||
{
|
||||
wizard.crateType = CrateType.LEVEL_CRATE;
|
||||
}
|
||||
else if (selected.GetType() == typeof(GameObject))
|
||||
{
|
||||
if ((selected as GameObject).GetComponent("SLZ.VRMK.Avatar"))
|
||||
{
|
||||
wizard.crateType = CrateType.AVATAR_CRATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
wizard.crateType = CrateType.SPAWNABLE_CRATE;
|
||||
}
|
||||
}
|
||||
|
||||
if (AssetDatabase.Contains(selected))
|
||||
{
|
||||
wizard.assetReference = selected;
|
||||
wizard.crateTitle = ObjectNames.NicifyVariableName(selected.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pallet == null)
|
||||
{
|
||||
var palletGuids = AssetDatabase.FindAssets("t:Pallet");
|
||||
if (palletGuids.Length > 0)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(palletGuids[0]);
|
||||
pallet = AssetDatabase.LoadAssetAtPath<Pallet>(path);
|
||||
}
|
||||
}
|
||||
|
||||
if (pallet != null)
|
||||
{
|
||||
wizard.pallet = pallet;
|
||||
}
|
||||
|
||||
wizard.OnWizardUpdate();
|
||||
return wizard;
|
||||
}
|
||||
|
||||
public System.Type GetCrateType(CrateType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CrateType.SPAWNABLE_CRATE:
|
||||
return typeof(SpawnableCrate);
|
||||
case CrateType.LEVEL_CRATE:
|
||||
return typeof(LevelCrate);
|
||||
case CrateType.AVATAR_CRATE:
|
||||
return typeof(AvatarCrate);
|
||||
case CrateType.VFX_CRATE:
|
||||
return typeof(VFXCrate);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public CrateType GetCrateType(System.Type type)
|
||||
{
|
||||
if (type == typeof(SpawnableCrate))
|
||||
{
|
||||
return CrateType.SPAWNABLE_CRATE;
|
||||
}
|
||||
else if (type == typeof(LevelCrate))
|
||||
{
|
||||
return CrateType.LEVEL_CRATE;
|
||||
}
|
||||
else if (type == typeof(AvatarCrate))
|
||||
{
|
||||
return CrateType.AVATAR_CRATE;
|
||||
}
|
||||
else if (type == typeof(VFXCrate))
|
||||
{
|
||||
return CrateType.VFX_CRATE;
|
||||
}
|
||||
|
||||
return CrateType.SPAWNABLE_CRATE;
|
||||
}
|
||||
|
||||
public System.Type GetCrateAssetType(System.Type type)
|
||||
{
|
||||
if (assetTypeCache == null)
|
||||
{
|
||||
assetTypeCache = new Dictionary<System.Type, System.Type>();
|
||||
Crate crate = ScriptableObject.CreateInstance<SpawnableCrate>();
|
||||
assetTypeCache[typeof(SpawnableCrate)] = crate.AssetType;
|
||||
crate = ScriptableObject.CreateInstance<LevelCrate>();
|
||||
assetTypeCache[typeof(LevelCrate)] = crate.AssetType;
|
||||
crate = ScriptableObject.CreateInstance<AvatarCrate>();
|
||||
assetTypeCache[typeof(AvatarCrate)] = crate.AssetType;
|
||||
crate = ScriptableObject.CreateInstance<VFXCrate>();
|
||||
assetTypeCache[typeof(VFXCrate)] = crate.AssetType;
|
||||
}
|
||||
|
||||
if (assetTypeCache.TryGetValue(type, out var assetType))
|
||||
{
|
||||
return assetType;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void OnWizardCreate()
|
||||
{
|
||||
System.Type type = GetCrateType(crateType);
|
||||
if (type != null)
|
||||
{
|
||||
string assetPath = AssetDatabase.GetAssetPath(assetReference);
|
||||
MarrowAsset crateAssetReference = null;
|
||||
if (!string.IsNullOrEmpty(assetPath))
|
||||
{
|
||||
string guid = AssetDatabase.AssetPathToGUID(assetPath);
|
||||
if (!string.IsNullOrEmpty(guid))
|
||||
{
|
||||
crateAssetReference = new MarrowAsset(guid);
|
||||
}
|
||||
}
|
||||
|
||||
if (crateAssetReference != null)
|
||||
{
|
||||
Crate crate = Crate.CreateCrate(type, pallet, crateTitle, crateAssetReference);
|
||||
string palletPath = AssetDatabase.GetAssetPath(pallet);
|
||||
palletPath = System.IO.Path.GetDirectoryName(palletPath);
|
||||
string crateAssetFilename = crate.GetAssetFilename();
|
||||
string crateAssetPath = System.IO.Path.Combine(palletPath, crateAssetFilename);
|
||||
AssetDatabase.CreateAsset(crate, crateAssetPath);
|
||||
pallet.Crates.Add(crate);
|
||||
EditorUtility.SetDirty(pallet);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
AssetWarehouseWindow.ReloadWarehouse().Forget();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Invalid Asset");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnWizardUpdate()
|
||||
{
|
||||
errorString = "";
|
||||
bool generateBarcode = false;
|
||||
bool generateCrateTitle = false;
|
||||
if (pallet == null)
|
||||
{
|
||||
errorString += "Missing Pallet!";
|
||||
}
|
||||
else if (lastPallet != pallet)
|
||||
{
|
||||
generateBarcode = true;
|
||||
}
|
||||
|
||||
if (assetReference == null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Missing Asset Reference!";
|
||||
}
|
||||
else if (!AssetDatabase.Contains(assetReference))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Invalid Asset Reference!";
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Type assetType = GetCrateAssetType(GetCrateType(crateType));
|
||||
if (assetType != assetReference.GetType())
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Asset Reference must be a " + assetType.Name + "!";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(crateTitle))
|
||||
{
|
||||
generateCrateTitle = true;
|
||||
}
|
||||
|
||||
if (lastAssetRef != assetReference)
|
||||
{
|
||||
generateCrateTitle = true;
|
||||
generateBarcode = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (generateCrateTitle)
|
||||
{
|
||||
crateTitle = ObjectNames.NicifyVariableName(assetReference.name);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(crateTitle))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Missing Title!";
|
||||
}
|
||||
else if (crateTitle != lastCrateTitle)
|
||||
{
|
||||
generateBarcode = true;
|
||||
}
|
||||
|
||||
if (crateType != lastCrateType)
|
||||
{
|
||||
generateBarcode = true;
|
||||
}
|
||||
|
||||
if (generateBarcode)
|
||||
{
|
||||
tempCrate = Crate.CreateCrate(GetCrateType(crateType), pallet, crateTitle, null);
|
||||
barcode = new Barcode(tempCrate.Barcode);
|
||||
}
|
||||
|
||||
if (!Barcode.IsValidSize(barcode))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Barcode too long! Max length is " + Barcode.MAX_SIZE;
|
||||
}
|
||||
|
||||
if (AssetWarehouse.Instance.HasCrate(barcode))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Crate already exists with that Barcode!";
|
||||
}
|
||||
|
||||
isValid = string.IsNullOrEmpty(errorString);
|
||||
lastPallet = pallet;
|
||||
lastCrateTitle = crateTitle;
|
||||
lastCrateType = crateType;
|
||||
lastAssetRef = assetReference;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 370e9504bc256974eb9d5a632daa57e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,422 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEngine;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.UIElements;
|
||||
using SLZ.Marrow;
|
||||
using Cysharp.Threading.Tasks;
|
||||
|
||||
using System.Linq;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
public class CreateCrateEditorWindow : EditorWindow
|
||||
{
|
||||
public enum CrateType
|
||||
{
|
||||
SPAWNABLE_CRATE,
|
||||
LEVEL_CRATE,
|
||||
AVATAR_CRATE,
|
||||
VFX_CRATE
|
||||
}
|
||||
|
||||
public Barcode barcode = Barcode.EmptyBarcode();
|
||||
public Pallet pallet;
|
||||
public CrateType crateType;
|
||||
public string crateTitle = "";
|
||||
public UnityEngine.Object assetReference;
|
||||
private Dictionary<System.Type, System.Type> assetTypeCache;
|
||||
private Crate tempCrate;
|
||||
public static void ShowCreateCrateWindowEditor()
|
||||
{
|
||||
EditorWindow createCrateWin = GetWindow<CreateCrateEditorWindow>();
|
||||
createCrateWin.titleContent = new GUIContent("Create Crate");
|
||||
createCrateWin.minSize = new Vector2(400, 300);
|
||||
}
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("53459f0137ff4f74d89ec29407e6100d");
|
||||
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
tree.StretchToParentSize();
|
||||
rootVisualElement.Add(tree);
|
||||
TextField barcodeField = tree.Q<TextField>("barcodeField");
|
||||
TextField crateTitleTextField = tree.Q<TextField>("crateTitleTextField");
|
||||
crateTitleTextField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
crateTitleTextField.value = MarrowSDK.SanitizeName(crateTitleTextField.value);
|
||||
crateTitle = crateTitleTextField.value;
|
||||
GenerateCrateTitleAndBarcode(barcodeField, crateTitleTextField);
|
||||
});
|
||||
ObjectField createCratePalletField = tree.Q<ObjectField>("createCratePalletField");
|
||||
createCratePalletField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
pallet = (Pallet)createCratePalletField.value;
|
||||
GenerateCrateTitleAndBarcode(barcodeField, crateTitleTextField);
|
||||
});
|
||||
ObjectField assetReferenceField = tree.Q<ObjectField>("assetReferenceField");
|
||||
assetReferenceField.allowSceneObjects = false;
|
||||
assetReferenceField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
assetReference = assetReferenceField.value;
|
||||
GenerateCrateTitleAndBarcode(barcodeField, crateTitleTextField);
|
||||
});
|
||||
EnumField crateTypeEnumField = tree.Q<EnumField>("crateTypeEnumField");
|
||||
crateTypeEnumField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
crateType = (CrateType)crateTypeEnumField.value;
|
||||
if (crateType == CrateType.SPAWNABLE_CRATE)
|
||||
{
|
||||
assetReferenceField.objectType = typeof(GameObject);
|
||||
}
|
||||
else if (crateType == CrateType.LEVEL_CRATE)
|
||||
{
|
||||
assetReferenceField.objectType = typeof(SceneAsset);
|
||||
}
|
||||
else if (crateType == CrateType.AVATAR_CRATE)
|
||||
{
|
||||
assetReferenceField.objectType = typeof(GameObject);
|
||||
}
|
||||
else if (crateType == CrateType.VFX_CRATE)
|
||||
{
|
||||
assetReferenceField.objectType = typeof(GameObject);
|
||||
}
|
||||
|
||||
GenerateCrateTitleAndBarcode(barcodeField, crateTitleTextField);
|
||||
});
|
||||
UnityEngine.UIElements.Button createCrateButton = tree.Q<UnityEngine.UIElements.Button>("createCrateButton");
|
||||
createCrateButton.clickable.clicked += () =>
|
||||
{
|
||||
if (ValidateCreateCrateInput())
|
||||
{
|
||||
System.Type type = GetCrateType(crateType);
|
||||
if (type != null)
|
||||
{
|
||||
string assetPath = AssetDatabase.GetAssetPath(assetReference);
|
||||
MarrowAsset crateAssetReference = null;
|
||||
if (!string.IsNullOrEmpty(assetPath))
|
||||
{
|
||||
string guid = AssetDatabase.AssetPathToGUID(assetPath);
|
||||
if (!string.IsNullOrEmpty(guid))
|
||||
{
|
||||
crateAssetReference = new MarrowAsset(guid);
|
||||
}
|
||||
}
|
||||
|
||||
if (crateAssetReference != null)
|
||||
{
|
||||
Crate crate = Crate.CreateCrate(type, pallet, crateTitle, crateAssetReference);
|
||||
string palletPath = AssetDatabase.GetAssetPath(pallet);
|
||||
palletPath = System.IO.Path.GetDirectoryName(palletPath);
|
||||
string crateAssetFilename = crate.GetAssetFilename();
|
||||
string crateAssetPath = System.IO.Path.Combine(palletPath, crateAssetFilename);
|
||||
AssetDatabase.CreateAsset(crate, crateAssetPath);
|
||||
pallet.Crates.Add(crate);
|
||||
EditorUtility.SetDirty(pallet);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
ReloadWarehouseAsync().Forget();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Invalid Asset");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
string errorString = "";
|
||||
if (string.IsNullOrEmpty(crateTitle))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Crate Title cannot be empty.";
|
||||
}
|
||||
|
||||
if (pallet == null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Pallet cannot be empty.";
|
||||
}
|
||||
|
||||
if (assetReference == null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Asset Reference cannot be empty.";
|
||||
}
|
||||
else if (!AssetDatabase.Contains(assetReference))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Invalid Asset Reference.";
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Type assetType = GetCrateAssetType(GetCrateType(crateType));
|
||||
if (assetType != assetReference.GetType())
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Asset Reference must be a " + assetType.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((CrateType)crateTypeEnumField.value == CrateType.AVATAR_CRATE)
|
||||
{
|
||||
if ((assetReference as GameObject).GetComponent<Avatar>() == null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Asset Reference must have an Avatar component.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Barcode.IsValidSize(barcode))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Barcode too long! Max length is " + Barcode.MAX_SIZE;
|
||||
}
|
||||
|
||||
if (AssetWarehouse.Instance.HasCrate(barcode))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Crate already exists with that Barcode!";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
EditorGUILayout.HelpBox(errorString, MessageType.Error);
|
||||
};
|
||||
SetDefaults(barcodeField, crateTitleTextField, crateTypeEnumField, createCratePalletField, assetReferenceField);
|
||||
GenerateCrateTitleAndBarcode(barcodeField, crateTitleTextField);
|
||||
}
|
||||
|
||||
private void GenerateCrateTitleAndBarcode(TextField barcodeField, TextField crateTitleTextField)
|
||||
{
|
||||
System.Type assetType = GetCrateAssetType(GetCrateType(crateType));
|
||||
if (assetReference != null && assetType == assetReference.GetType())
|
||||
{
|
||||
if (string.IsNullOrEmpty(crateTitle))
|
||||
{
|
||||
crateTitle = ObjectNames.NicifyVariableName(assetReference.name);
|
||||
crateTitleTextField.value = crateTitle;
|
||||
}
|
||||
}
|
||||
|
||||
if (pallet != null && !string.IsNullOrEmpty(crateTitle) && assetReference != null)
|
||||
{
|
||||
tempCrate = Crate.CreateCrate(GetCrateType(crateType), pallet, crateTitle, null);
|
||||
barcode = new Barcode(tempCrate.Barcode);
|
||||
barcodeField.value = barcode.ID;
|
||||
}
|
||||
else
|
||||
{
|
||||
barcode = null;
|
||||
if (pallet == null)
|
||||
{
|
||||
barcodeField.value = "INVALID - Needs Pallet";
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(crateTitle))
|
||||
{
|
||||
barcodeField.value = "INVALID - Needs Crate Title";
|
||||
}
|
||||
|
||||
if (assetReference == null)
|
||||
{
|
||||
barcodeField.value = "INVALID - Needs Asset Reference";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ValidateCreateCrateInput()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(crateTitle) && assetReference != null && pallet != null)
|
||||
{
|
||||
if (crateType == CrateType.AVATAR_CRATE && (assetReference as GameObject).GetComponent<Avatar>() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (crateType == CrateType.LEVEL_CRATE && assetReference is not SceneAsset)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SetDefaults(TextField barcodeField, TextField crateTitleTextField, EnumField crateTypeEnumField, ObjectField createCratePalletField, ObjectField assetReferenceField)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(barcode.ID))
|
||||
{
|
||||
barcodeField.value = barcode.ID;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(crateTitle))
|
||||
{
|
||||
crateTitleTextField.value = crateTitle;
|
||||
}
|
||||
else
|
||||
{
|
||||
crateTitle = crateTitleTextField.value;
|
||||
}
|
||||
|
||||
if (assetReferenceField.value == null)
|
||||
{
|
||||
assetReference = null;
|
||||
}
|
||||
|
||||
foreach (var selected in Selection.objects)
|
||||
{
|
||||
if (selected != null && selected.GetType() == typeof(Pallet))
|
||||
{
|
||||
pallet = (Pallet)selected;
|
||||
}
|
||||
else if (selected != null && selected.GetType() != typeof(Pallet))
|
||||
{
|
||||
if (selected.GetType() == typeof(SceneAsset))
|
||||
{
|
||||
crateTypeEnumField.value = CrateType.LEVEL_CRATE;
|
||||
}
|
||||
else if (selected.GetType() == typeof(GameObject))
|
||||
{
|
||||
if ((selected as GameObject).GetComponent("SLZ.VRMK.Avatar"))
|
||||
{
|
||||
crateTypeEnumField.value = CrateType.AVATAR_CRATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
crateTypeEnumField.value = CrateType.SPAWNABLE_CRATE;
|
||||
}
|
||||
}
|
||||
|
||||
if (AssetDatabase.Contains(selected))
|
||||
{
|
||||
assetReference = selected;
|
||||
crateTitle = ObjectNames.NicifyVariableName(selected.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pallet == null)
|
||||
{
|
||||
var palletGuids = AssetDatabase.FindAssets("t:Pallet");
|
||||
if (palletGuids.Length > 0)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(palletGuids[0]);
|
||||
pallet = AssetDatabase.LoadAssetAtPath<Pallet>(path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
createCratePalletField.value = pallet;
|
||||
}
|
||||
|
||||
crateType = (CrateType)crateTypeEnumField.value;
|
||||
if (crateType == CrateType.SPAWNABLE_CRATE)
|
||||
{
|
||||
assetReferenceField.objectType = typeof(GameObject);
|
||||
}
|
||||
else if (crateType == CrateType.LEVEL_CRATE)
|
||||
{
|
||||
assetReferenceField.objectType = typeof(SceneAsset);
|
||||
}
|
||||
else if (crateType == CrateType.AVATAR_CRATE)
|
||||
{
|
||||
assetReferenceField.objectType = typeof(GameObject);
|
||||
}
|
||||
else if (crateType == CrateType.VFX_CRATE)
|
||||
{
|
||||
assetReferenceField.objectType = typeof(GameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public System.Type GetCrateType(CrateType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CrateType.SPAWNABLE_CRATE:
|
||||
return typeof(SpawnableCrate);
|
||||
case CrateType.LEVEL_CRATE:
|
||||
return typeof(LevelCrate);
|
||||
case CrateType.AVATAR_CRATE:
|
||||
return typeof(AvatarCrate);
|
||||
case CrateType.VFX_CRATE:
|
||||
return typeof(VFXCrate);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public CrateType GetCrateType(System.Type type)
|
||||
{
|
||||
if (type == typeof(SpawnableCrate))
|
||||
{
|
||||
return CrateType.SPAWNABLE_CRATE;
|
||||
}
|
||||
else if (type == typeof(LevelCrate))
|
||||
{
|
||||
return CrateType.LEVEL_CRATE;
|
||||
}
|
||||
else if (type == typeof(AvatarCrate))
|
||||
{
|
||||
return CrateType.AVATAR_CRATE;
|
||||
}
|
||||
else if (type == typeof(VFXCrate))
|
||||
{
|
||||
return CrateType.VFX_CRATE;
|
||||
}
|
||||
|
||||
return CrateType.SPAWNABLE_CRATE;
|
||||
}
|
||||
|
||||
public System.Type GetCrateAssetType(System.Type type)
|
||||
{
|
||||
if (assetTypeCache == null)
|
||||
{
|
||||
assetTypeCache = new Dictionary<System.Type, System.Type>();
|
||||
Crate crate = ScriptableObject.CreateInstance<SpawnableCrate>();
|
||||
assetTypeCache[typeof(SpawnableCrate)] = crate.AssetType;
|
||||
crate = ScriptableObject.CreateInstance<LevelCrate>();
|
||||
assetTypeCache[typeof(LevelCrate)] = crate.AssetType;
|
||||
crate = ScriptableObject.CreateInstance<AvatarCrate>();
|
||||
assetTypeCache[typeof(AvatarCrate)] = crate.AssetType;
|
||||
crate = ScriptableObject.CreateInstance<VFXCrate>();
|
||||
assetTypeCache[typeof(VFXCrate)] = crate.AssetType;
|
||||
}
|
||||
|
||||
if (assetTypeCache.TryGetValue(type, out var assetType))
|
||||
{
|
||||
return assetType;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTaskVoid ReloadWarehouseAsync()
|
||||
{
|
||||
await AssetWarehouseWindow.ReloadWarehouse();
|
||||
if (AssetWarehouse.Instance.WorkingPallets.Count > 0)
|
||||
{
|
||||
Selection.activeObject = AssetWarehouse.Instance.WorkingPallets.First().Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9dee12d6d08f7c741aab75c8ee4d0694
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEngine;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using UnityEditor.UIElements;
|
||||
using SLZ.Marrow;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEditor.SceneTemplate;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
public class CreateLevelCrateEditorWindow : EditorWindow
|
||||
{
|
||||
public Barcode barcode = Barcode.EmptyBarcode();
|
||||
public Pallet pallet;
|
||||
public string levelTitle;
|
||||
public DropdownField createLevelSceneDropdown;
|
||||
public ObjectField customSceneObjectField;
|
||||
private bool validationPassed = true;
|
||||
private Crate _tempCrate;
|
||||
private Crate TempCrate
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_tempCrate == null)
|
||||
{
|
||||
_tempCrate = Crate.CreateCrate(typeof(LevelCrate), pallet, levelTitle, null);
|
||||
}
|
||||
|
||||
return _tempCrate;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ShowCreateLevelCrateWindowEditor()
|
||||
{
|
||||
string levelImagePath = MarrowSDK.GetPackagePath("Editor/Assets/Icons/Warehouse/crate-level16.png");
|
||||
Texture2D levelIconImage = EditorGUIUtility.Load(levelImagePath) as Texture2D;
|
||||
EditorWindow createLevelCrateWin = GetWindow<CreateLevelCrateEditorWindow>();
|
||||
createLevelCrateWin.titleContent = new GUIContent(" Create Level Crate");
|
||||
createLevelCrateWin.titleContent.image = levelIconImage;
|
||||
createLevelCrateWin.minSize = new Vector2(400, 210);
|
||||
}
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("f633a274391168a43a3f0fbc1c58e59b");
|
||||
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
tree.StretchToParentSize();
|
||||
rootVisualElement.Add(tree);
|
||||
TextField barcodeField = tree.Q<TextField>("barcodeField");
|
||||
TextField crateTitleTextField = tree.Q<TextField>("crateTitleTextField");
|
||||
crateTitleTextField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
crateTitleTextField.value = MarrowSDK.SanitizeName(crateTitleTextField.value);
|
||||
levelTitle = crateTitleTextField.value;
|
||||
GenerateCrateTitleAndBarcode(barcodeField, crateTitleTextField);
|
||||
});
|
||||
ObjectField createCratePalletField = tree.Q<ObjectField>("createCratePalletField");
|
||||
createCratePalletField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
pallet = (Pallet)createCratePalletField.value;
|
||||
if (createCratePalletField.value == null)
|
||||
{
|
||||
pallet = null;
|
||||
}
|
||||
|
||||
GenerateCrateTitleAndBarcode(barcodeField, crateTitleTextField);
|
||||
});
|
||||
customSceneObjectField = tree.Q<ObjectField>("customSceneObjectField");
|
||||
customSceneObjectField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
crateTitleTextField.value = evt.newValue.name;
|
||||
});
|
||||
createLevelSceneDropdown = tree.Q<DropdownField>("createLevelSceneDropdown");
|
||||
createLevelSceneDropdown.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
if (createLevelSceneDropdown.index == 0)
|
||||
{
|
||||
customSceneObjectField.style.display = DisplayStyle.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
customSceneObjectField.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
});
|
||||
Button createLevelCrateButton = tree.Q<Button>("createLevelCrateButton");
|
||||
createLevelCrateButton.clickable.clicked += () =>
|
||||
{
|
||||
if (ValidateCreateLevelCrateInput() && validationPassed)
|
||||
{
|
||||
string newScenePath = $"{MarrowSDK.GetMarrowAssetsPath("Levels", MarrowSDK.SanitizeName(levelTitle))}.unity";
|
||||
if (createLevelSceneDropdown.index == 0)
|
||||
{
|
||||
newScenePath = $"{MarrowSDK.GetMarrowAssetsPath("Levels", MarrowSDK.SanitizeName(levelTitle))}.unity";
|
||||
SceneTemplateAsset marrowSceneTemplate = AssetDatabase.LoadAssetAtPath<SceneTemplateAsset>(MarrowSDK.GetPackagePath("Editor/Assets/Scene Template/Default Marrow SceneTemplate.scenetemplate"));
|
||||
SceneTemplateService.Instantiate(marrowSceneTemplate, false, newScenePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
string customSceneObjectPath = AssetDatabase.GetAssetPath(customSceneObjectField.value);
|
||||
newScenePath = $"{customSceneObjectPath}";
|
||||
}
|
||||
|
||||
var sceneGuid = AssetDatabase.GUIDFromAssetPath(newScenePath).ToString();
|
||||
LevelCrate levelCrate = Crate.CreateCrate(typeof(LevelCrate), pallet, levelTitle, new MarrowScene(sceneGuid)) as LevelCrate;
|
||||
string palletPath = AssetDatabase.GetAssetPath(pallet);
|
||||
palletPath = System.IO.Path.GetDirectoryName(palletPath);
|
||||
string crateAssetFilename = levelCrate.GetAssetFilename();
|
||||
string crateAssetPath = System.IO.Path.Combine(palletPath, crateAssetFilename);
|
||||
AssetDatabase.CreateAsset(levelCrate, crateAssetPath);
|
||||
pallet.Crates.Add(levelCrate);
|
||||
EditorUtility.SetDirty(pallet);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
AssetWarehouseWindow.ReloadWarehouse().Forget();
|
||||
if (createLevelSceneDropdown.index != 0)
|
||||
{
|
||||
var sceneAtPath = AssetDatabase.LoadMainAssetAtPath(newScenePath);
|
||||
AssetDatabase.OpenAsset(sceneAtPath);
|
||||
}
|
||||
|
||||
this.Close();
|
||||
}
|
||||
};
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
string errorString = "";
|
||||
if (string.IsNullOrEmpty(levelTitle))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Level Crate Title cannot be empty.";
|
||||
}
|
||||
|
||||
if (pallet == null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Pallet cannot be empty.";
|
||||
}
|
||||
|
||||
if (createLevelSceneDropdown.index != 0 && customSceneObjectField.value == null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "The Custom Scene cannot be empty.";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(levelTitle) && pallet != null)
|
||||
{
|
||||
TempCrate.Pallet = pallet;
|
||||
TempCrate.Title = levelTitle;
|
||||
TempCrate.GenerateBarcode(true);
|
||||
if (AssetWarehouse.Instance.HasCrate(TempCrate.Barcode))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Level already exists with that Title.";
|
||||
}
|
||||
|
||||
if (levelTitle == "My Level Crate")
|
||||
{
|
||||
errorString += "Set the level title";
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
{
|
||||
EditorGUILayout.HelpBox(errorString, MessageType.Error);
|
||||
validationPassed = false;
|
||||
if (createLevelCrateButton.enabledSelf)
|
||||
createLevelCrateButton.SetEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
validationPassed = true;
|
||||
if (!createLevelCrateButton.enabledSelf)
|
||||
createLevelCrateButton.SetEnabled(true);
|
||||
}
|
||||
};
|
||||
SetDefaults(crateTitleTextField, createCratePalletField);
|
||||
}
|
||||
|
||||
private void GenerateCrateTitleAndBarcode(TextField barcodeField, TextField crateTitleTextField)
|
||||
{
|
||||
if (pallet != null && !string.IsNullOrEmpty(levelTitle))
|
||||
{
|
||||
TempCrate.Pallet = pallet;
|
||||
TempCrate.Title = levelTitle;
|
||||
TempCrate.GenerateBarcode(true);
|
||||
barcode = new Barcode(_tempCrate.Barcode);
|
||||
barcodeField.value = barcode.ID;
|
||||
}
|
||||
else
|
||||
{
|
||||
barcode = null;
|
||||
if (pallet == null)
|
||||
{
|
||||
barcodeField.value = "INVALID - Needs Pallet";
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(levelTitle))
|
||||
{
|
||||
barcodeField.value = "INVALID - Needs Level Title";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ValidateCreateLevelCrateInput()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(levelTitle) && pallet != null)
|
||||
{
|
||||
if (createLevelSceneDropdown.index == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (customSceneObjectField.value != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SetDefaults(TextField crateTitleTextField, ObjectField createCratePalletField)
|
||||
{
|
||||
createLevelSceneDropdown.index = 0;
|
||||
customSceneObjectField.style.display = DisplayStyle.None;
|
||||
if (!string.IsNullOrEmpty(levelTitle))
|
||||
{
|
||||
crateTitleTextField.value = levelTitle;
|
||||
}
|
||||
else
|
||||
{
|
||||
levelTitle = crateTitleTextField.value;
|
||||
}
|
||||
|
||||
foreach (var selected in Selection.objects)
|
||||
{
|
||||
if (selected != null && selected.GetType() == typeof(Pallet))
|
||||
{
|
||||
pallet = (Pallet)selected;
|
||||
}
|
||||
}
|
||||
|
||||
if (pallet == null)
|
||||
{
|
||||
var palletGuids = AssetDatabase.FindAssets("t:Pallet");
|
||||
if (palletGuids.Length > 0)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(palletGuids[0]);
|
||||
pallet = AssetDatabase.LoadAssetAtPath<Pallet>(path);
|
||||
}
|
||||
}
|
||||
|
||||
createCratePalletField.value = pallet;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 81f446fcd617a81478c2c2b682da79b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEngine;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using System.IO;
|
||||
using SLZ.Marrow;
|
||||
using Cysharp.Threading.Tasks;
|
||||
|
||||
using System.Linq;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
public class CreatePalletEditorWindow : EditorWindow
|
||||
{
|
||||
public string palletTitle = "My Pallet";
|
||||
public string palletAuthor = "Author";
|
||||
public static readonly string palletFolderName = "_Pallets";
|
||||
public static void ShowCreatePalletWindowEditor()
|
||||
{
|
||||
string palletImagePath = MarrowSDK.GetPackagePath("Editor/Assets/Icons/Warehouse/pallet16.png");
|
||||
Texture2D palletIconImage = EditorGUIUtility.Load(palletImagePath) as Texture2D;
|
||||
EditorWindow createPalletWin = GetWindow<CreatePalletEditorWindow>();
|
||||
createPalletWin.titleContent = new GUIContent(" Create Pallet");
|
||||
createPalletWin.titleContent.image = palletIconImage;
|
||||
createPalletWin.minSize = new Vector2(400, 200);
|
||||
}
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("af1a8ac6a7af0b347ba2dc089f25faf2");
|
||||
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
tree.StretchToParentSize();
|
||||
rootVisualElement.Add(tree);
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
TextField palletTitleTextField = tree.Q<TextField>("palletTitleTextField");
|
||||
palletTitleTextField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
palletTitleTextField.value = MarrowSDK.SanitizeName(palletTitleTextField.value);
|
||||
palletTitle = palletTitleTextField.value;
|
||||
});
|
||||
TextField palletAuthorTextField = tree.Q<TextField>("palletAuthorTextField");
|
||||
palletAuthorTextField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
palletAuthorTextField.value = MarrowSDK.SanitizeName(palletAuthorTextField.value);
|
||||
palletAuthor = palletAuthorTextField.value;
|
||||
});
|
||||
Button createPalletButton = tree.Q<Button>("createPalletButton");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
string errorString = "";
|
||||
if (string.IsNullOrEmpty(palletTitle))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Pallet Title cannot be empty.";
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(palletAuthor))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Pallet Author cannot be empty.";
|
||||
}
|
||||
|
||||
if (palletTitle == "My Pallet")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Set the Pallet Title";
|
||||
}
|
||||
|
||||
if (palletAuthor == "Author")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
errorString += "\n";
|
||||
errorString += "Set the Pallet Author";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(errorString))
|
||||
{
|
||||
EditorGUILayout.HelpBox(errorString, MessageType.Error);
|
||||
if (createPalletButton.enabledSelf)
|
||||
createPalletButton.SetEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!createPalletButton.enabledSelf)
|
||||
createPalletButton.SetEnabled(true);
|
||||
}
|
||||
};
|
||||
createPalletButton.clickable.clicked += () =>
|
||||
{
|
||||
if (ValidateCreatePalletInput())
|
||||
{
|
||||
Pallet pallet = Pallet.CreatePallet(palletTitle, palletAuthor);
|
||||
if (AssetWarehouse.Instance.HasPallet(pallet.Barcode))
|
||||
{
|
||||
Debug.LogError("Pallet with this barcode already exists. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(MarrowSDK.GetMarrowAssetsPath(palletFolderName, pallet.Barcode.ID)))
|
||||
{
|
||||
Directory.CreateDirectory(MarrowSDK.GetMarrowAssetsPath(palletFolderName, pallet.Barcode.ID));
|
||||
}
|
||||
|
||||
string palletAssetFileName = pallet.GetAssetFilename();
|
||||
string crateAssetPath = MarrowSDK.GetMarrowAssetsPath(palletFolderName, pallet.Barcode.ID, palletAssetFileName);
|
||||
AssetDatabase.CreateAsset(pallet, crateAssetPath);
|
||||
EditorUtility.SetDirty(pallet);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
ReloadWarehouseAsync().Forget();
|
||||
this.Close();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private bool ValidateCreatePalletInput()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(palletTitle) && !string.IsNullOrEmpty(palletAuthor))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private async UniTaskVoid ReloadWarehouseAsync()
|
||||
{
|
||||
await AssetWarehouseWindow.ReloadWarehouse();
|
||||
if (AssetWarehouse.Instance.WorkingPallets.Count > 0)
|
||||
{
|
||||
Selection.activeObject = AssetWarehouse.Instance.WorkingPallets.First().Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a7ac79fa33d76cb4e84cd099dafef3a4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
using System;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using SLZ.Marrow;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
public class DataCardCreatorEditor : EditorWindow
|
||||
{
|
||||
private VisualElement root;
|
||||
private VisualTreeAsset windowAsset;
|
||||
private DataCard dataCard;
|
||||
public Type dataCardType;
|
||||
private SerializedObject serializedObject;
|
||||
private bool validData = false;
|
||||
private bool created = false;
|
||||
public static void ShowWindow(Pallet pallet = null)
|
||||
{
|
||||
var window = GetWindow<DataCardCreatorEditor>("Create DataCard");
|
||||
window.Initialize(typeof(DataCard), pallet);
|
||||
window.Show();
|
||||
}
|
||||
|
||||
public static void ShowWindowBoneTag(Pallet pallet = null)
|
||||
{
|
||||
var window = GetWindow<DataCardCreatorEditor>("Create DataCard");
|
||||
window.Initialize(typeof(BoneTag), pallet);
|
||||
window.Show();
|
||||
}
|
||||
|
||||
public static void ShowWindowMonoDisc(Pallet pallet = null)
|
||||
{
|
||||
var window = GetWindow<DataCardCreatorEditor>("Create DataCard");
|
||||
window.Initialize(typeof(MonoDisc), pallet);
|
||||
window.Show();
|
||||
}
|
||||
|
||||
public static void ShowWindow(Type dataCardType, Pallet pallet, Action<DataCard> onCreate = null, string initialTitle = "")
|
||||
{
|
||||
if (typeof(DataCard).IsAssignableFrom(dataCardType))
|
||||
{
|
||||
var window = GetWindow<DataCardCreatorEditor>("Create DataCard");
|
||||
window.Initialize(dataCardType, pallet, initialTitle: initialTitle);
|
||||
if (onCreate != null)
|
||||
window.OnCreate += onCreate;
|
||||
window.Show();
|
||||
}
|
||||
}
|
||||
|
||||
public Action<DataCard> OnCreate;
|
||||
public void Initialize(Type dataCardTypeInput = null, Pallet pallet = null, string initialTitle = "")
|
||||
{
|
||||
dataCardType = dataCardTypeInput;
|
||||
if (dataCardType == null)
|
||||
dataCardType = typeof(MonoDisc);
|
||||
titleContent = new GUIContent($"Create {dataCardType.Name}", AssetWarehouseTreeView.GetIconForMonoScript(dataCardType));
|
||||
dataCard = ScriptableObject.CreateInstance(dataCardType) as DataCard;
|
||||
dataCard.Title = initialTitle;
|
||||
if (pallet != null)
|
||||
dataCard.Pallet = pallet;
|
||||
if (dataCard.Pallet == null)
|
||||
{
|
||||
var guids = AssetDatabase.FindAssets("t:Pallet", new[] { MarrowSDK.GetMarrowAssetsPath(PalletWizard.palletFolderName) });
|
||||
if (guids.Length > 0)
|
||||
{
|
||||
dataCard.Pallet = AssetDatabase.LoadAssetAtPath<Pallet>(AssetDatabase.GUIDToAssetPath(guids[0]));
|
||||
}
|
||||
}
|
||||
|
||||
serializedObject = new SerializedObject(dataCard);
|
||||
root.Q<ObjectField>("pallet").value = dataCard.Pallet;
|
||||
root.Q<PropertyField>("barcode").Bind(serializedObject);
|
||||
root.Q<PropertyField>("title").Bind(serializedObject);
|
||||
root.Q<PropertyField>("description").Bind(serializedObject);
|
||||
CreatePropertiesGUI(root.Q("datacardFields"));
|
||||
}
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
windowAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(AssetDatabase.GUIDToAssetPath("c23a1f389c3051f41a0b09466904bde6"));
|
||||
}
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
root = rootVisualElement;
|
||||
root.Add(windowAsset.Instantiate());
|
||||
root.Q<PropertyField>("barcode").SetEnabled(false);
|
||||
root.Q<ObjectField>("pallet").objectType = typeof(Pallet);
|
||||
root.Q<ObjectField>("pallet").RegisterValueChangedCallback(Validate);
|
||||
root.Q<ObjectField>("pallet").RegisterValueChangedCallback(PalletChangedValue);
|
||||
root.Q<PropertyField>("title").RegisterValueChangeCallback(Validate);
|
||||
root.Q<PropertyField>("title").RegisterValueChangeCallback(TitleChangedValue);
|
||||
root.Q<Button>("Create").clickable.clicked += CreateDataCardAsset;
|
||||
}
|
||||
|
||||
private void PalletChangedValue(ChangeEvent<Object> evt)
|
||||
{
|
||||
var pallet = evt.newValue as Pallet;
|
||||
dataCard.Pallet = pallet;
|
||||
GenerateBarcode();
|
||||
}
|
||||
|
||||
private void TitleChangedValue(EventBase arg)
|
||||
{
|
||||
GenerateBarcode();
|
||||
}
|
||||
|
||||
private void Validate(EventBase evt)
|
||||
{
|
||||
validData = dataCard.Pallet && !string.IsNullOrEmpty(dataCard.Title);
|
||||
root.Q<Button>("Create").SetEnabled(validData);
|
||||
}
|
||||
|
||||
private void GenerateBarcode()
|
||||
{
|
||||
if (validData)
|
||||
{
|
||||
dataCard.GenerateBarcode(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateDataCardAsset()
|
||||
{
|
||||
dataCard.Pallet.DataCards.Add(dataCard);
|
||||
EditorUtility.SetDirty(dataCard.Pallet);
|
||||
string palletPath = AssetDatabase.GetAssetPath(dataCard.Pallet);
|
||||
palletPath = System.IO.Path.GetDirectoryName(palletPath);
|
||||
string dataCardAssetFilename = dataCard.GetAssetFilename();
|
||||
string assetPath = Path.Combine(palletPath, dataCardAssetFilename);
|
||||
if (File.Exists(Path.Combine(Application.dataPath, assetPath)))
|
||||
{
|
||||
assetPath = AssetDatabase.GenerateUniqueAssetPath(assetPath);
|
||||
}
|
||||
|
||||
AssetDatabase.CreateAsset(dataCard, assetPath);
|
||||
dataCard.GeneratePackedAssets(false);
|
||||
AssetDatabase.SaveAssetIfDirty(dataCard);
|
||||
AssetDatabase.SaveAssetIfDirty(dataCard.Pallet);
|
||||
AssetDatabase.Refresh();
|
||||
if (!EditorApplication.isPlaying)
|
||||
AssetWarehouseWindow.ReloadWarehouse().Forget();
|
||||
created = true;
|
||||
OnCreate?.Invoke(dataCard);
|
||||
Close();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
OnCreate = null;
|
||||
if (!created && dataCard != null)
|
||||
{
|
||||
DestroyImmediate(dataCard);
|
||||
}
|
||||
}
|
||||
|
||||
public void CreatePropertiesGUI(VisualElement container)
|
||||
{
|
||||
HashSet<string> ignoreProperties = new HashSet<string>();
|
||||
ignoreProperties.Add("m_Script");
|
||||
ignoreProperties.Add("_barcode");
|
||||
ignoreProperties.Add("_barcodeOld");
|
||||
ignoreProperties.Add("_slimCode");
|
||||
ignoreProperties.Add("_title");
|
||||
ignoreProperties.Add("_description");
|
||||
ignoreProperties.Add("_unlockable");
|
||||
ignoreProperties.Add("_redacted");
|
||||
ignoreProperties.Add("_pallet");
|
||||
ignoreProperties.Add("_dataCardAsset");
|
||||
if (serializedObject == null)
|
||||
return;
|
||||
SerializedProperty iterator = serializedObject.GetIterator();
|
||||
if (iterator.NextVisible(true))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!ignoreProperties.Contains(iterator.propertyPath))
|
||||
{
|
||||
PropertyField child = new PropertyField(iterator);
|
||||
child.name = "PropertyField:" + iterator.propertyPath;
|
||||
container.Add((VisualElement)child);
|
||||
child.BindProperty(iterator);
|
||||
}
|
||||
}
|
||||
while (iterator.NextVisible(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 21b1b2bb83cad044492a46ba5cfdbe0b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
|
||||
using UnityEditor;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[CustomEditor(typeof(DataCard))]
|
||||
[CanEditMultipleObjects]
|
||||
public class DataCardEditor : ScannableEditor
|
||||
{
|
||||
protected DataCard dataCard = null;
|
||||
public override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
dataCard = serializedObject.targetObject as DataCard;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
serializedObject.Update();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.ObjectField("Pallet", dataCard.Pallet, typeof(Pallet), false);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e76956aa72e34191a52864d084e9814b
|
||||
timeCreated: 1673484294
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
public class DeduperTool
|
||||
{
|
||||
private const string GENERATED_DEDUPE_GROUP_NAME = "Duplicate Asset Isolation";
|
||||
private const string DEDUPE_GROUP_NAME = "Deduped";
|
||||
public enum StripOptions
|
||||
{
|
||||
None,
|
||||
Models,
|
||||
PartialAnimations
|
||||
}
|
||||
|
||||
public static AddressableAssetGroup Dedupe(string buildPath, string loadPath, StripOptions stripOptions = StripOptions.PartialAnimations)
|
||||
{
|
||||
AddressableAssetGroup dedupeGroup = null;
|
||||
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
|
||||
AddressableAssetSettings settings = AddressablesManager.Settings;
|
||||
dedupeGroup = settings.FindGroup(DEDUPE_GROUP_NAME);
|
||||
if (dedupeGroup != null)
|
||||
{
|
||||
settings.RemoveGroup(dedupeGroup);
|
||||
}
|
||||
|
||||
dedupeGroup = settings.FindGroup(GENERATED_DEDUPE_GROUP_NAME);
|
||||
if (dedupeGroup != null)
|
||||
{
|
||||
settings.RemoveGroup(dedupeGroup);
|
||||
}
|
||||
|
||||
var dedupeRule = new UnityEditor.AddressableAssets.Build.AnalyzeRules.CheckBundleDupeDependencies();
|
||||
dedupeRule.FixIssues(settings);
|
||||
dedupeGroup = settings.FindGroup(GENERATED_DEDUPE_GROUP_NAME);
|
||||
if (dedupeGroup != null)
|
||||
{
|
||||
BundledAssetGroupSchema schema = dedupeGroup.GetSchema<BundledAssetGroupSchema>();
|
||||
schema.BundleMode = BundledAssetGroupSchema.BundlePackingMode.PackSeparately;
|
||||
schema.IncludeAddressInCatalog = false;
|
||||
AddressablesManager.SetCustomBuildPath(schema, buildPath);
|
||||
AddressablesManager.SetCustomLoadPath(schema, loadPath);
|
||||
var updateSchema = dedupeGroup.GetSchema<ContentUpdateGroupSchema>();
|
||||
updateSchema.StaticContent = false;
|
||||
EditorUtility.SetDirty(schema);
|
||||
AssetDatabase.SaveAssetIfDirty(schema);
|
||||
EditorUtility.SetDirty(updateSchema);
|
||||
AssetDatabase.SaveAssetIfDirty(updateSchema);
|
||||
dedupeGroup.Name = DEDUPE_GROUP_NAME;
|
||||
dedupeGroup.name = DEDUPE_GROUP_NAME;
|
||||
EditorUtility.SetDirty(dedupeGroup);
|
||||
AssetDatabase.SaveAssetIfDirty(dedupeGroup);
|
||||
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(dedupeGroup));
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
var dedupeSchemas = dedupeGroup.Schemas.ToList();
|
||||
settings.groups.Remove(dedupeGroup);
|
||||
settings.SetDirty(AddressableAssetSettings.ModificationEvent.GroupRemoved, dedupeGroup, true, true);
|
||||
RegenerateGUID(dedupeGroup, out var metaGuid);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
dedupeGroup = settings.FindGroup(DEDUPE_GROUP_NAME);
|
||||
AddressablesManager.GroupGuidField.SetValue(dedupeGroup, metaGuid);
|
||||
EditorUtility.SetDirty(dedupeGroup);
|
||||
AssetDatabase.SaveAssetIfDirty(dedupeGroup);
|
||||
dedupeGroup = settings.FindGroup(DEDUPE_GROUP_NAME);
|
||||
foreach (var dedupeSchema in dedupeSchemas)
|
||||
{
|
||||
dedupeGroup.Schemas.Remove(dedupeSchema);
|
||||
settings.SetDirty(AddressableAssetSettings.ModificationEvent.GroupSchemaRemoved, dedupeSchema, true, true);
|
||||
}
|
||||
|
||||
foreach (var dedupeSchema in dedupeSchemas)
|
||||
{
|
||||
var loadedSchema = RegenerateGUID(dedupeSchema, out _, true);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
dedupeGroup.AddSchema(loadedSchema, true);
|
||||
}
|
||||
|
||||
dedupeGroup.SetDirty(AddressableAssetSettings.ModificationEvent.GroupAdded, dedupeGroup, true, true);
|
||||
EditorUtility.SetDirty(dedupeGroup);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
T RegenerateGUID<T>(T assetObject, out string newGuid, bool reimport = false)
|
||||
where T : UnityEngine.Object
|
||||
{
|
||||
string assetPath = AssetDatabase.GetAssetPath(assetObject);
|
||||
var md5 = System.Security.Cryptography.MD5.Create();
|
||||
var hash = md5.ComputeHash(System.Text.Encoding.Default.GetBytes(assetPath));
|
||||
string metaGuid = new Guid(hash).ToString().Replace("-", "");
|
||||
newGuid = metaGuid;
|
||||
string metaPath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetPath);
|
||||
string yamlContent = System.IO.File.ReadAllText(metaPath);
|
||||
string replacedContent = Regex.Replace(yamlContent, @"guid:\s*(\w+)", "guid: " + metaGuid);
|
||||
System.IO.File.WriteAllText(metaPath, replacedContent);
|
||||
if (reimport)
|
||||
AssetDatabase.ImportAsset(assetPath);
|
||||
return AssetDatabase.LoadAssetAtPath<T>(assetPath);
|
||||
}
|
||||
|
||||
EditorUtility.SetDirty(dedupeGroup);
|
||||
List<string> addedAddresses = new List<string>();
|
||||
foreach (var entry in dedupeGroup.entries)
|
||||
{
|
||||
if (entry.MainAsset != null)
|
||||
{
|
||||
string name = entry.MainAsset.name;
|
||||
if (entry.MainAsset is Shader)
|
||||
{
|
||||
string path = AssetDatabase.GetAssetPath(entry.MainAsset);
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
name = System.IO.Path.GetFileNameWithoutExtension(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
name = entry.MainAsset.name.Substring(name.LastIndexOf("/") + 1, name.Length - name.LastIndexOf("/") - 1);
|
||||
}
|
||||
}
|
||||
|
||||
string address = entry.MainAsset.GetType().Name + "/" + name;
|
||||
if (addedAddresses.Contains(address))
|
||||
{
|
||||
address += "--" + entry.guid.Substring(0, 8);
|
||||
}
|
||||
|
||||
entry.SetAddress(address);
|
||||
addedAddresses.Add(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Deduper: BAD entry in dedupe group! " + entry.address);
|
||||
entry.SetAddress("NULL/DELETEME");
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log("Deduper: Created Dedupe Group with " + dedupeGroup.entries.Count + " assets: " + string.Format("{0:hh\\:mm\\:ss}", timer.Elapsed));
|
||||
if (stripOptions != StripOptions.None)
|
||||
{
|
||||
List<AddressableAssetEntry> strippers = new List<AddressableAssetEntry>();
|
||||
foreach (var entry in dedupeGroup.entries)
|
||||
{
|
||||
bool strip = stripOptions.Equals(StripOptions.Models) && (entry.AssetPath.EndsWith(".fbx") || entry.AssetPath.EndsWith(".obj"));
|
||||
if (stripOptions.Equals(StripOptions.PartialAnimations) && entry.AssetPath.Contains("@") && (entry.AssetPath.EndsWith(".fbx") || entry.AssetPath.EndsWith(".obj")))
|
||||
{
|
||||
strip = true;
|
||||
}
|
||||
|
||||
if (strip)
|
||||
{
|
||||
strippers.Add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var entry in strippers)
|
||||
{
|
||||
dedupeGroup.RemoveAssetEntry(entry);
|
||||
}
|
||||
|
||||
string strippedAssets = "";
|
||||
foreach (var entry in strippers)
|
||||
{
|
||||
string extension = System.IO.Path.GetExtension(entry.AssetPath);
|
||||
strippedAssets += "[" + entry.MainAssetType.Name + (!string.IsNullOrEmpty(extension) ? "/" + extension.Replace(".", "") : "") + "] " + entry.MainAsset.name + " (" + entry.AssetPath + ") \n";
|
||||
}
|
||||
|
||||
Debug.Log("Deduper: Stripped " + strippers.Count + " Assets: \n" + strippedAssets);
|
||||
if (strippers.Count > 0)
|
||||
Debug.Log("Deduper: Stripped Dedupe Group now has " + dedupeGroup.entries.Count + " assets");
|
||||
}
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("Deduper: Finished dedupe! Took " + string.Format("{0:hh\\:mm\\:ss}", timer.Elapsed));
|
||||
return dedupeGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a8f5eb4b98f2d9545bf7fd2bcb788df6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,371 @@
|
|||
using SLZ.Marrow;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
using Quaternion = UnityEngine.Quaternion;
|
||||
using Vector2 = UnityEngine.Vector2;
|
||||
using Vector3 = UnityEngine.Vector3;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[CustomPreview(typeof(EntityPose))]
|
||||
public class EntityPosePreview : ObjectPreview
|
||||
{
|
||||
protected Editor assetEditor = null;
|
||||
protected bool hasAssetPreview = false;
|
||||
protected PreviewRenderUtility previewRender = null;
|
||||
protected Barcode previewTargetBarcode = null;
|
||||
protected Texture previewTexture = null;
|
||||
protected GameObject previewGameObject = null;
|
||||
protected Bounds previewBounds = default;
|
||||
protected int previewMeshTriangles = 0;
|
||||
protected int fullTris = 0;
|
||||
protected int previewMeshVerts = 0;
|
||||
protected int fullVerts = 0;
|
||||
protected Vector2 m_PreviewDir = new Vector2(120, -20);
|
||||
protected Rect prevRect = default;
|
||||
protected bool showPreviewMesh = true;
|
||||
protected bool showColliderBounds = true;
|
||||
public override void Initialize(Object[] targets)
|
||||
{
|
||||
base.Initialize(targets);
|
||||
ClearCachedAssets();
|
||||
}
|
||||
|
||||
public override bool HasPreviewGUI()
|
||||
{
|
||||
if (m_Targets.Length > 1)
|
||||
return false;
|
||||
var entityPose = (EntityPose)target;
|
||||
return entityPose != null && entityPose.PosePreviewMesh != null && !string.IsNullOrEmpty(entityPose.PosePreviewMesh.AssetGUID);
|
||||
}
|
||||
|
||||
public override void OnInteractivePreviewGUI(Rect r, GUIStyle background)
|
||||
{
|
||||
EntityPose entityPose = (EntityPose)target;
|
||||
if (entityPose != null)
|
||||
{
|
||||
var direction = Drag2D(m_PreviewDir, r);
|
||||
if (direction != m_PreviewDir)
|
||||
{
|
||||
m_PreviewDir = direction;
|
||||
ClearCachedTexture();
|
||||
}
|
||||
|
||||
var barStyle = new GUIStyle();
|
||||
barStyle.alignment = TextAnchor.MiddleLeft;
|
||||
using (new GUILayout.HorizontalScope(barStyle))
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
GUILayout.Button(EditorGUIUtility.IconContent("refresh"), GUILayout.ExpandWidth(false));
|
||||
showPreviewMesh = GUILayout.Toggle(showPreviewMesh, "Preview Mesh", GUILayout.ExpandWidth(false));
|
||||
showColliderBounds = GUILayout.Toggle(showColliderBounds, "Collider Bounds", GUILayout.ExpandWidth(false));
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.LabelField("Preview Mesh Triangles", GUI.skin.box, GUILayout.ExpandWidth(false));
|
||||
EditorGUILayout.LabelField($"{previewMeshTriangles.ToString()}/{fullTris.ToString()}", GUI.skin.box, GUILayout.ExpandWidth(false));
|
||||
EditorGUILayout.LabelField("Vertices", GUI.skin.box, GUILayout.ExpandWidth(false));
|
||||
EditorGUILayout.LabelField($"{previewMeshVerts.ToString()}/{fullVerts.ToString()}", GUI.skin.box, GUILayout.ExpandWidth(false));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
ClearCachedAssets();
|
||||
}
|
||||
}
|
||||
|
||||
if ((r.width < 5f && r.height < 5f))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (prevRect != r)
|
||||
{
|
||||
prevRect = r;
|
||||
ClearCachedTexture();
|
||||
}
|
||||
|
||||
if (entityPose.Barcode != previewTargetBarcode)
|
||||
{
|
||||
ClearCachedAssets();
|
||||
}
|
||||
|
||||
if (previewTexture == null)
|
||||
{
|
||||
CaptureRenderPreview(entityPose, r, background);
|
||||
}
|
||||
|
||||
if (previewTexture != null)
|
||||
{
|
||||
GUI.DrawTexture(r, previewTexture, ScaleMode.StretchToFill, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int sliderHash = "Slider".GetHashCode();
|
||||
public static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
|
||||
{
|
||||
int id = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
|
||||
Event evt = Event.current;
|
||||
switch (evt.GetTypeForControl(id))
|
||||
{
|
||||
case EventType.MouseDown:
|
||||
if (position.Contains(evt.mousePosition) && position.width > 50)
|
||||
{
|
||||
GUIUtility.hotControl = id;
|
||||
evt.Use();
|
||||
EditorGUIUtility.SetWantsMouseJumping(1);
|
||||
}
|
||||
|
||||
break;
|
||||
case EventType.MouseDrag:
|
||||
if (GUIUtility.hotControl == id)
|
||||
{
|
||||
scrollPosition -= evt.delta * (evt.shift ? 3 : 1) / Mathf.Min(position.width, position.height) * 140.0f;
|
||||
evt.Use();
|
||||
GUI.changed = true;
|
||||
}
|
||||
|
||||
break;
|
||||
case EventType.MouseUp:
|
||||
if (GUIUtility.hotControl == id)
|
||||
GUIUtility.hotControl = 0;
|
||||
EditorGUIUtility.SetWantsMouseJumping(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return scrollPosition;
|
||||
}
|
||||
|
||||
private void CaptureRenderPreview(EntityPose entityPose, Rect r, GUIStyle background)
|
||||
{
|
||||
if (previewRender == null)
|
||||
{
|
||||
SetupPreviewRender(entityPose, r, background);
|
||||
}
|
||||
|
||||
previewTexture = CreatePreviewTexture(r);
|
||||
}
|
||||
|
||||
private RenderTexture CreatePreviewTexture(Rect r)
|
||||
{
|
||||
float halfSize = Mathf.Max(previewBounds.extents.magnitude, 0.0001f);
|
||||
float distance = halfSize * 3.8f;
|
||||
Quaternion rot = Quaternion.Euler(-m_PreviewDir.y, -m_PreviewDir.x, 0);
|
||||
Vector3 pos = previewBounds.center - rot * (Vector3.forward * distance);
|
||||
previewRender.camera.transform.position = pos;
|
||||
previewRender.camera.transform.rotation = rot;
|
||||
previewRender.BeginPreview(new Rect(r), GUIStyle.none);
|
||||
previewRender.Render(true);
|
||||
var renderTexture = (RenderTexture)previewRender.EndPreview();
|
||||
renderTexture.name = "CrateEditorPreview RenderTexture";
|
||||
return renderTexture;
|
||||
}
|
||||
|
||||
private void SetupPreviewRender(EntityPose entityPose, Rect r, GUIStyle background)
|
||||
{
|
||||
ClearCachedAssets();
|
||||
previewRender = new PreviewRenderUtility(true);
|
||||
System.GC.SuppressFinalize(previewRender);
|
||||
previewBounds = entityPose.ColliderBounds;
|
||||
if (previewBounds.extents == Vector3.zero)
|
||||
previewBounds = new Bounds(Vector3.zero, Vector3.one);
|
||||
fullTris = -1;
|
||||
fullVerts = -1;
|
||||
previewTargetBarcode = entityPose.Barcode;
|
||||
previewRender.lights[0].transform.localEulerAngles = new Vector3(30, 30, 0);
|
||||
previewRender.lights[0].intensity = 2;
|
||||
previewRender.ambientColor = new Color(.1f, .1f, .1f, 0);
|
||||
SetupPreviewRenderGameObjects();
|
||||
float halfSize = Mathf.Max(previewBounds.extents.magnitude, 0.0001f);
|
||||
float distance = halfSize * 3.8f;
|
||||
var camera = previewRender.camera;
|
||||
camera.nearClipPlane = 0.001f;
|
||||
camera.farClipPlane = 1000;
|
||||
camera.fieldOfView = 30f;
|
||||
SetupPreviewRenderBoundBox(entityPose.ColliderBounds);
|
||||
MarrowAssetT<Mesh> previewMeshAsset = entityPose.PosePreviewMesh;
|
||||
Mesh previewMesh = null;
|
||||
if (previewMeshAsset != null && previewMeshAsset.EditorAsset != null)
|
||||
{
|
||||
previewMesh = previewMeshAsset.EditorAsset;
|
||||
previewBounds = previewMesh.bounds;
|
||||
if (previewMesh != null)
|
||||
{
|
||||
previewMeshTriangles = previewMesh.triangles.Length;
|
||||
previewMeshVerts = previewMesh.vertexCount;
|
||||
SetupPreviewRenderMainMesh(previewMesh);
|
||||
}
|
||||
}
|
||||
else if (previewMeshAsset != null)
|
||||
{
|
||||
QueueEditorUpdateLoop.StartEditorUpdateLoop();
|
||||
if (!string.IsNullOrEmpty(previewMeshAsset.AssetGUID))
|
||||
{
|
||||
previewMeshAsset.LoadAsset(loadedMesh =>
|
||||
{
|
||||
if (previewRender != null && loadedMesh != null)
|
||||
{
|
||||
previewMesh = loadedMesh;
|
||||
previewBounds = loadedMesh.bounds;
|
||||
if (previewMesh.isReadable)
|
||||
{
|
||||
previewMeshTriangles = previewMesh.triangles.Length;
|
||||
previewMeshVerts = previewMesh.vertexCount;
|
||||
}
|
||||
|
||||
float halfSize = Mathf.Max(previewBounds.extents.magnitude, 0.0001f);
|
||||
float distance = halfSize * 3.8f;
|
||||
var camera = previewRender.camera;
|
||||
camera.nearClipPlane = 0.001f;
|
||||
camera.farClipPlane = 1000;
|
||||
camera.fieldOfView = 30f;
|
||||
SetupPreviewRenderMainMesh(previewMesh);
|
||||
ClearCachedTexture();
|
||||
}
|
||||
|
||||
QueueEditorUpdateLoop.StopEditorUpdateLoop();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupPreviewRenderGameObjects()
|
||||
{
|
||||
previewGameObject = new GameObject("Preview Render GameObject");
|
||||
previewRender.AddSingleGO(previewGameObject);
|
||||
}
|
||||
|
||||
private void SetupPreviewRenderMainMesh(Mesh mesh)
|
||||
{
|
||||
var previewObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
previewObject.transform.parent = previewGameObject.transform;
|
||||
previewObject.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterial;
|
||||
previewObject.GetComponent<MeshFilter>().mesh = mesh;
|
||||
previewObject.GetComponent<MeshRenderer>().enabled = showPreviewMesh;
|
||||
}
|
||||
|
||||
private void SetupPreviewRenderBoundBox(Bounds bounds)
|
||||
{
|
||||
if (bounds.extents != Vector3.zero)
|
||||
{
|
||||
var boundGO = new GameObject("bound box");
|
||||
boundGO.transform.parent = previewGameObject.transform;
|
||||
GameObject boundGOBox;
|
||||
float width = bounds.extents.magnitude / 100f;
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center;
|
||||
boundGOBox.transform.localScale = new Vector3(width * 2f, width * 2f, width * 2f);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.forward * bounds.extents.z + Vector3.up * bounds.extents.y;
|
||||
boundGOBox.transform.localScale = new Vector3(bounds.size.x, width, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.back * bounds.extents.z + Vector3.up * bounds.extents.y;
|
||||
boundGOBox.transform.localScale = new Vector3(bounds.size.x, width, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.forward * bounds.extents.z + Vector3.down * bounds.extents.y;
|
||||
boundGOBox.transform.localScale = new Vector3(bounds.size.x, width, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.back * bounds.extents.z + Vector3.down * bounds.extents.y;
|
||||
boundGOBox.transform.localScale = new Vector3(bounds.size.x, width, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.name = "Crate Preview Bound Box";
|
||||
boundGOBox.transform.position = bounds.center + Vector3.forward * bounds.extents.z + Vector3.right * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, bounds.size.y, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.back * bounds.extents.z + Vector3.right * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, bounds.size.y, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.forward * bounds.extents.z + Vector3.left * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, bounds.size.y, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.back * bounds.extents.z + Vector3.left * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, bounds.size.y, width);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.up * bounds.extents.y + Vector3.right * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, width, bounds.size.z);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.down * bounds.extents.y + Vector3.right * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, width, bounds.size.z);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.up * bounds.extents.y + Vector3.left * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, width, bounds.size.z);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
boundGOBox = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
boundGOBox.transform.position = bounds.center + Vector3.down * bounds.extents.y + Vector3.left * bounds.extents.x;
|
||||
boundGOBox.transform.localScale = new Vector3(width, width, bounds.size.z);
|
||||
boundGOBox.GetComponent<MeshRenderer>().material = MarrowSDK.VoidMaterialAlt;
|
||||
boundGOBox.GetComponent<MeshRenderer>().enabled = showColliderBounds;
|
||||
boundGOBox.transform.SetParent(boundGO.transform);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearCachedTexture()
|
||||
{
|
||||
if (previewTexture != null)
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(previewTexture);
|
||||
previewTexture = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearCachedAssets()
|
||||
{
|
||||
if (previewRender != null)
|
||||
{
|
||||
previewRender.Cleanup();
|
||||
previewRender = null;
|
||||
}
|
||||
|
||||
ClearCachedTexture();
|
||||
if (previewGameObject != null)
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(previewGameObject);
|
||||
previewGameObject = null;
|
||||
}
|
||||
|
||||
previewMeshTriangles = 0;
|
||||
fullTris = 0;
|
||||
previewMeshVerts = 0;
|
||||
fullVerts = 0;
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
base.Cleanup();
|
||||
ClearCachedAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6900d60206651c945bc4b26eaebeb024
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using SLZ.Marrow.Circuits;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[CustomEditor(typeof(EventActuator))]
|
||||
public class EventActuatorEditor : Editor
|
||||
{
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("af4573843ac09e9449f41c98b9d8524f");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
};
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/EventActuator");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a2fd0a09a28556241b0d4ea8a9176ebe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using SLZ.Marrow.Circuits;
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[CustomEditor(typeof(FlipflopCircuit))]
|
||||
public class FlipflopCircuitEditor : Editor
|
||||
{
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("85f0b6f32b6e2a04e97a9bfeb7024fa4");
|
||||
VisualTreeAsset visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
VisualElement validationFeedback = tree.Q<VisualElement>("validationFeedback");
|
||||
IMGUIContainer imguiValidationContainer = tree.Q<IMGUIContainer>("imguiValidationContainer");
|
||||
imguiValidationContainer.onGUIHandler = () =>
|
||||
{
|
||||
};
|
||||
Button marrowDocsButton = tree.Q<Button>("marrowDocsButton");
|
||||
marrowDocsButton.clickable.clicked += () =>
|
||||
{
|
||||
Application.OpenURL("https://github.com/StressLevelZero/MarrowSDK/wiki/FlipFlopCircuit");
|
||||
};
|
||||
IMGUIContainer imguiInspector = tree.Q<IMGUIContainer>("imguiInspector");
|
||||
imguiInspector.onGUIHandler = () =>
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
};
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 434dbe5990e52b740aba3afac35bc86d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,357 @@
|
|||
using UnityEditor;
|
||||
using System.Linq;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SLZ.Marrow;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
public class GameInstallDirectoryEditorWindow : EditorWindow
|
||||
{
|
||||
private List<string> foundGamePaths = new List<string>();
|
||||
private List<string> foundSearchedPaths = new List<string>();
|
||||
private bool quickSearch = false;
|
||||
public Action<string> OnCloseWindow;
|
||||
private string gameName;
|
||||
private Label foundInLocationsLabel;
|
||||
private Label foundInLocationsHeaderLabel;
|
||||
private static int winHeightAdvClosed = 310;
|
||||
private int winHeightAddedAdvOpen = 165;
|
||||
private void OnDestroy()
|
||||
{
|
||||
var gamePath = LoadGamePath();
|
||||
OnCloseWindow?.Invoke(gamePath);
|
||||
if (SDKWelcomeEditorWin.createWelcomeWin)
|
||||
{
|
||||
SDKWelcomeEditorWin.createWelcomeWin.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ShowGameInstallDirWindowEditor(Action<string> onCloseWindowCallback = null)
|
||||
{
|
||||
GameInstallDirectoryEditorWindow gameInstallDirWin = GetWindow<GameInstallDirectoryEditorWindow>();
|
||||
gameInstallDirWin.titleContent = new GUIContent("Game Installation Locator");
|
||||
gameInstallDirWin.minSize = new Vector2(770, winHeightAdvClosed);
|
||||
if (onCloseWindowCallback != null)
|
||||
gameInstallDirWin.OnCloseWindow += onCloseWindowCallback;
|
||||
}
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
string VISUALTREE_PATH = AssetDatabase.GUIDToAssetPath("55c01d9138366234088eb53daeedf9b5");
|
||||
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(VISUALTREE_PATH);
|
||||
VisualElement tree = visualTree.Instantiate();
|
||||
tree.StretchToParentSize();
|
||||
rootVisualElement.Add(tree);
|
||||
Button doneButton = tree.Q<Button>("doneButton");
|
||||
doneButton.clicked += Close;
|
||||
gameName = MarrowSDK.GAME_NAMES[0];
|
||||
foundInLocationsHeaderLabel = tree.Q<Label>("foundInLocationsHeaderLabel");
|
||||
foundInLocationsLabel = tree.Q<Label>("foundInLocationsLabel");
|
||||
VisualElement gameInstallRefreshImageContainer = tree.Q<VisualElement>("gameInstallRefreshImageContainer");
|
||||
Image gameInstallRefreshImage = new Image
|
||||
{
|
||||
image = EditorGUIUtility.Load(MarrowSDK.GetPackagePath("Editor/Assets/Icons/Warehouse/hunter-reload.png")) as Texture2D
|
||||
};
|
||||
gameInstallRefreshImageContainer.Add(gameInstallRefreshImage);
|
||||
gameInstallRefreshImage.StretchToParentSize();
|
||||
Label instructionsLabel = tree.Q<Label>("instructionsLabel");
|
||||
instructionsLabel.text = instructionsLabel.text.Replace("game install location", gameName + " install location");
|
||||
instructionsLabel.text = instructionsLabel.text.Replace("game Content Pallet", gameName + " Content Pallet");
|
||||
LoadGamePath();
|
||||
Foldout advancedOptionsFoldout = tree.Q<Foldout>("advancedOptionsFoldout");
|
||||
advancedOptionsFoldout.text = advancedOptionsFoldout.text.Insert(advancedOptionsFoldout.text.IndexOf(" game install"), " " + gameName);
|
||||
advancedOptionsFoldout.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
Rect windowRect = position;
|
||||
if (advancedOptionsFoldout.value)
|
||||
{
|
||||
if (windowRect.height != (winHeightAdvClosed + winHeightAddedAdvOpen))
|
||||
{
|
||||
windowRect.height = winHeightAdvClosed + winHeightAddedAdvOpen;
|
||||
position = windowRect;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (windowRect.height != winHeightAdvClosed)
|
||||
{
|
||||
windowRect.height = winHeightAdvClosed;
|
||||
position = windowRect;
|
||||
}
|
||||
}
|
||||
});
|
||||
VisualElement multipleFoundInstructionsContainer = tree.Q<VisualElement>("multipleFoundInstructionsContainer");
|
||||
multipleFoundInstructionsContainer.style.display = DisplayStyle.None;
|
||||
ListView foundLocationsListView = tree.Q<ListView>("foundLocationsListView");
|
||||
foundLocationsListView.itemsSource = foundGamePaths;
|
||||
Func<VisualElement> makeItem = () =>
|
||||
{
|
||||
VisualElement element = new VisualElement();
|
||||
element.style.flexDirection = FlexDirection.Row;
|
||||
element.style.paddingLeft = EditorGUIUtility.singleLineHeight;
|
||||
Label pathLabel = new Label();
|
||||
pathLabel.name = "RowPathLabel";
|
||||
pathLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
|
||||
pathLabel.style.fontSize = 12;
|
||||
element.Add(pathLabel);
|
||||
return element;
|
||||
};
|
||||
Action<VisualElement, int> bindItem = (e, i) =>
|
||||
{
|
||||
Label pathLabel = e.Q<Label>("RowPathLabel");
|
||||
string foundPath = foundGamePaths[i];
|
||||
if (!String.IsNullOrEmpty(foundPath))
|
||||
{
|
||||
pathLabel.text = foundPath.Replace("\\", "/");
|
||||
}
|
||||
else
|
||||
{
|
||||
pathLabel.text = "Unknown or Inaccessible Path";
|
||||
}
|
||||
};
|
||||
foundLocationsListView.onSelectionChange += objects =>
|
||||
{
|
||||
if (objects.Any())
|
||||
{
|
||||
SetGamePath(foundGamePaths[foundLocationsListView.selectedIndex]);
|
||||
LoadGamePath();
|
||||
foundLocationsListView.Focus();
|
||||
}
|
||||
};
|
||||
foundLocationsListView.bindItem = bindItem;
|
||||
foundLocationsListView.makeItem = makeItem;
|
||||
Button searchGameFolderButton = tree.Q<Button>("searchGameFolderButton");
|
||||
searchGameFolderButton.text = $"Auto-Find {gameName}";
|
||||
searchGameFolderButton.clickable.clicked += () =>
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Perform exhaustive search?", "The Auto-Find process methodically searches all fixed hard drives looking for " + gameName + " install locations. This may take several minutes.", "Search", "Cancel"))
|
||||
{
|
||||
FindGameOnClick();
|
||||
if (foundSearchedPaths.Count == 1)
|
||||
{
|
||||
if (!foundGamePaths.Contains(foundSearchedPaths[0]))
|
||||
{
|
||||
foundGamePaths.Add(foundSearchedPaths[0]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var foundPath in foundSearchedPaths)
|
||||
{
|
||||
if (!foundGamePaths.Contains(foundPath))
|
||||
{
|
||||
foundGamePaths.Add(foundPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foundLocationsListView?.Rebuild();
|
||||
if (foundGamePaths.Count == 1)
|
||||
{
|
||||
foundLocationsListView.selectedIndex = 0;
|
||||
SetGamePath(foundGamePaths[0]);
|
||||
LoadGamePath();
|
||||
}
|
||||
|
||||
if (foundGamePaths.Count > 1)
|
||||
{
|
||||
multipleFoundInstructionsContainer.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
else
|
||||
{
|
||||
multipleFoundInstructionsContainer.style.display = DisplayStyle.None;
|
||||
}
|
||||
}
|
||||
};
|
||||
Button searchGameManualButton = tree.Q<Button>("searchGameManualButton");
|
||||
searchGameManualButton.clickable.clicked += () =>
|
||||
{
|
||||
DirectoryInfo defaultSteamPath = new DirectoryInfo("C:/Program Files (x86)/Steam/steamapps/common/");
|
||||
var manualGameInstall = EditorUtility.OpenFolderPanel($"Locate {gameName} Install", defaultSteamPath.FullName, "");
|
||||
if (!String.IsNullOrEmpty(manualGameInstall))
|
||||
{
|
||||
DirectoryInfo manualDir = new DirectoryInfo(manualGameInstall);
|
||||
if (manualDir.FullName.ToLower().Contains($"{gameName.ToLower()}") && (!manualDir.FullName.ToLower().Contains($"{gameName.ToLower()}_steam_windows64_data") && !manualDir.FullName.ToLower().Contains($"{gameName.ToLower()}_oculus_windows64_data")))
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(manualDir.FullName, $"{gameName}_Oculus_Windows64_Data")))
|
||||
{
|
||||
manualDir = new DirectoryInfo(Path.Combine(manualDir.FullName, $"{gameName}_Oculus_Windows64_Data"));
|
||||
}
|
||||
else if (Directory.Exists(Path.Combine(manualDir.FullName, $"{gameName}_Steam_Windows64_Data")))
|
||||
{
|
||||
manualDir = new DirectoryInfo(Path.Combine(manualDir.FullName, $"{gameName}_Steam_Windows64_Data"));
|
||||
}
|
||||
}
|
||||
|
||||
if (manualDir.FullName.Contains($"{gameName}_Steam_Windows64_Data") || manualDir.FullName.Contains($"{gameName}_Oculus_Windows64_Data"))
|
||||
{
|
||||
if (!foundGamePaths.Contains(manualDir.FullName))
|
||||
{
|
||||
foundGamePaths.Add(manualDir.FullName);
|
||||
foundLocationsListView?.Rebuild();
|
||||
}
|
||||
|
||||
foundLocationsListView.selectedIndex = foundGamePaths.IndexOf(manualDir.FullName);
|
||||
foundLocationsListView.Focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"Selected folder did not contain a {gameName} installation.");
|
||||
}
|
||||
}
|
||||
};
|
||||
DirectoryInfo gamePathOculus = new DirectoryInfo($"C:/Program Files/Oculus/Software/Software/stress-level-zero-inc-bonelab/{gameName}_Oculus_Windows64_Data");
|
||||
DirectoryInfo gamePathSteam = new DirectoryInfo($"C:/Program Files (x86)/Steam/steamapps/common/{gameName}/{gameName}_Steam_Windows64_Data");
|
||||
DirectoryInfo gamePathSteam2 = new DirectoryInfo($"D:/SteamLibrary/steamapps/common/{gameName}/{gameName}_Steam_Windows64_Data");
|
||||
DirectoryInfo gamePathSteam3 = new DirectoryInfo($"D:/Games/SteamLibrary/steamapps/common/{gameName}/{gameName}_Steam_Windows64_Data");
|
||||
foundGamePaths.Clear();
|
||||
var gamePath = LoadGamePath();
|
||||
if (!string.IsNullOrEmpty(gamePath) && Directory.Exists(gamePath))
|
||||
{
|
||||
DirectoryInfo currentValidPath = new DirectoryInfo(gamePath);
|
||||
foundGamePaths.Add(currentValidPath.FullName);
|
||||
foundLocationsListView.selectedIndex = 0;
|
||||
foundLocationsListView.Focus();
|
||||
}
|
||||
|
||||
if (Directory.Exists(gamePathOculus.FullName) && !foundGamePaths.Contains(gamePathOculus.FullName))
|
||||
{
|
||||
foundGamePaths.Add(gamePathOculus.FullName);
|
||||
}
|
||||
|
||||
if (Directory.Exists(gamePathSteam.FullName) && !foundGamePaths.Contains(gamePathSteam.FullName))
|
||||
{
|
||||
foundGamePaths.Add(gamePathSteam.FullName);
|
||||
}
|
||||
|
||||
if (Directory.Exists(gamePathSteam2.FullName) && !foundGamePaths.Contains(gamePathSteam2.FullName))
|
||||
{
|
||||
foundGamePaths.Add(gamePathSteam2.FullName);
|
||||
}
|
||||
|
||||
if (Directory.Exists(gamePathSteam3.FullName) && !foundGamePaths.Contains(gamePathSteam3.FullName))
|
||||
{
|
||||
foundGamePaths.Add(gamePathSteam3.FullName);
|
||||
}
|
||||
|
||||
foundLocationsListView?.Rebuild();
|
||||
if (foundGamePaths.Count == 1)
|
||||
{
|
||||
foundLocationsListView.selectedIndex = 0;
|
||||
foundLocationsListView.Focus();
|
||||
}
|
||||
|
||||
if (foundGamePaths.Count > 1)
|
||||
{
|
||||
multipleFoundInstructionsContainer.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
else
|
||||
{
|
||||
multipleFoundInstructionsContainer.style.display = DisplayStyle.None;
|
||||
}
|
||||
|
||||
if (foundGamePaths.Count > 1 && string.IsNullOrEmpty(gamePath) && Directory.Exists(foundGamePaths[0]))
|
||||
{
|
||||
SetGamePath(foundGamePaths[0]);
|
||||
LoadGamePath();
|
||||
}
|
||||
}
|
||||
|
||||
private void FindGameOnClick()
|
||||
{
|
||||
string gameName = MarrowSDK.GAME_NAMES[0];
|
||||
foundSearchedPaths.Clear();
|
||||
float progressBarStatus = 0f;
|
||||
int driveCount = 0;
|
||||
EditorUtility.DisplayCancelableProgressBar("Finding " + gameName + " Location", $"This may take a while...", progressBarStatus);
|
||||
foreach (DriveInfo drive in DriveInfo.GetDrives())
|
||||
{
|
||||
driveCount++;
|
||||
if (quickSearch && foundSearchedPaths.Count > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (drive.IsReady && drive.DriveType == DriveType.Fixed)
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] searchQueries =
|
||||
{
|
||||
$"{gameName}_Oculus_Windows64_Data",
|
||||
$"{gameName}_Steam_Windows64_Data"};
|
||||
string searchRoot = drive.Name;
|
||||
var directories = SearchDirectories(searchRoot, searchQueries);
|
||||
foreach (var foundDir in directories)
|
||||
{
|
||||
foundSearchedPaths.Add(foundDir);
|
||||
if (quickSearch && foundSearchedPaths.Count > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
progressBarStatus = driveCount / DriveInfo.GetDrives().Length;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<string> SearchDirectories(string path, string[] searchPatterns)
|
||||
{
|
||||
return searchPatterns.AsParallel().SelectMany(searchPattern => Directory.EnumerateDirectories(path, searchPattern, new EnumerationOptions { IgnoreInaccessible = true, RecurseSubdirectories = true }));
|
||||
}
|
||||
|
||||
private string LoadGamePath()
|
||||
{
|
||||
SDKProjectPreferences.LoadFromFile();
|
||||
var gameInstallPath = string.Empty;
|
||||
if (SDKProjectPreferences.MarrowGameInstallPaths != null && SDKProjectPreferences.MarrowGameInstallPaths.Count > 0)
|
||||
{
|
||||
gameInstallPath = SDKProjectPreferences.MarrowGameInstallPaths[0];
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(gameName))
|
||||
gameName = MarrowSDK.GAME_NAMES[0];
|
||||
if (foundInLocationsLabel != null)
|
||||
{
|
||||
foundInLocationsHeaderLabel.text = $"{gameName} Install Folder: ";
|
||||
foundInLocationsLabel.text = $"{gameInstallPath}";
|
||||
}
|
||||
|
||||
return gameInstallPath;
|
||||
}
|
||||
|
||||
private void SetGamePath(string gamePath)
|
||||
{
|
||||
gamePath = gamePath.Replace("\\", "/");
|
||||
bool changed = false;
|
||||
SDKProjectPreferences.LoadFromFile();
|
||||
if (SDKProjectPreferences.MarrowGameInstallPaths.Count <= 0)
|
||||
{
|
||||
SDKProjectPreferences.MarrowGameInstallPaths.Add(gamePath);
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SDKProjectPreferences.MarrowGameInstallPaths[0] != gamePath)
|
||||
{
|
||||
SDKProjectPreferences.MarrowGameInstallPaths[0] = gamePath;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
SDKProjectPreferences.SaveToFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f637fab1b6748b844b2fa9eaabc52093
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
|
||||
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using SLZ.Marrow.Warehouse;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace SLZ.MarrowEditor
|
||||
{
|
||||
[CustomEditor(typeof(GameObjectCrate))]
|
||||
[CanEditMultipleObjects]
|
||||
public class GameObjectCrateEditor : CrateEditor
|
||||
{
|
||||
SerializedProperty previewMeshProperty;
|
||||
SerializedProperty previewMeshCustomQualityProperty;
|
||||
SerializedProperty previewMeshQualityProperty;
|
||||
SerializedProperty previewMeshMaxLodProperty;
|
||||
SerializedProperty colliderBoundsProperty;
|
||||
private bool previewMeshOptions = false;
|
||||
protected override string AssetReferenceDisplayName
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Prefab";
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
previewMeshProperty = serializedObject.FindProperty("_previewMesh");
|
||||
previewMeshCustomQualityProperty = serializedObject.FindProperty("_customQuality");
|
||||
previewMeshQualityProperty = serializedObject.FindProperty("_previewMeshQuality");
|
||||
previewMeshMaxLodProperty = serializedObject.FindProperty("_maxLODLevel");
|
||||
colliderBoundsProperty = serializedObject.FindProperty("_colliderBounds");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUIPackedAssets()
|
||||
{
|
||||
base.OnInspectorGUIPackedAssets();
|
||||
LockedPropertyField(previewMeshProperty, false);
|
||||
previewMeshOptions = EditorGUILayout.Foldout(previewMeshOptions, "Preview Mesh Options");
|
||||
if (previewMeshOptions)
|
||||
{
|
||||
using (new EditorGUI.IndentLevelScope())
|
||||
{
|
||||
LockedPropertyField(previewMeshCustomQualityProperty, false);
|
||||
if (previewMeshCustomQualityProperty.boolValue)
|
||||
{
|
||||
LockedPropertyField(previewMeshQualityProperty, false);
|
||||
}
|
||||
|
||||
LockedPropertyField(previewMeshMaxLodProperty, false);
|
||||
}
|
||||
}
|
||||
|
||||
LockedPropertyField(colliderBoundsProperty, false);
|
||||
}
|
||||
}
|
||||
|
||||
[CustomPreview(typeof(SpawnableCrate))]
|
||||
public class GameObjectCratePreview : CratePreview
|
||||
{
|
||||
public override void Cleanup()
|
||||
{
|
||||
base.Cleanup();
|
||||
ClearCachedAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue