initial commit

This commit is contained in:
Jo 2025-01-07 02:06:59 +01:00
parent 6715289efe
commit 788c3389af
37645 changed files with 2526849 additions and 80 deletions

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 296771b4ca0d031561adfd16fb87090c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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);
}
}
}
}
}

View file

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

View file

@ -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();
}
}

View file

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

View file

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

View file

@ -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
}

View file

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

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 56be2341a9d36c77e3a56b49d0f69179
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 25e8734031b04f30902a04f5044aaea1
timeCreated: 1661110022

View file

@ -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");
}
}
}

View file

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

View file

@ -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

View file

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

View file

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

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c841e30038fe87fdf7534d72b7e592dd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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;
}
}
}
}
}

View file

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

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 950ecbc4c56a5e4aa560eb19d91c2dc2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1f24404b0ab13c01fdc326967932ab4a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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, "..")));
}
}
}
}

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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;
}
}
}
}

View file

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

View file

@ -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();
}
}
}

View file

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

View file

@ -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

View file

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

View file

@ -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();
}
}
}

View file

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

View file

@ -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);
}
}
}

View file

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

View file

@ -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;
}
}
}

View file

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

View file

@ -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);
}
}
}
}
}
}
}

View file

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

View file

@ -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();
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ce1fff46a22a492381cf2dfcc0dcb46d
timeCreated: 1673484143

View file

@ -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);
}
}
}

View file

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

View file

@ -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;
}
}
}

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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));
}
}
}
}

View file

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

View file

@ -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();
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e76956aa72e34191a52864d084e9814b
timeCreated: 1673484294

View file

@ -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;
}
}
}

View file

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

View file

@ -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();
}
}
}

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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