This commit is contained in:
2026-07-09 21:33:33 +02:00
commit 84a2a365f3
2364 changed files with 950134 additions and 0 deletions
@@ -0,0 +1,56 @@
using System.Linq;
using Sirenix.OdinInspector.Editor.Validation;
using UnityEngine;
using VOID.Editor.AttributeValidator;
using VOID.ScriptableObjects.Animations;
[assembly: RegisterValidator(typeof(AnimationListValidator))]
namespace VOID.Editor.AttributeValidator
{
public class ActionAnimationListValidator : ValueValidator<ActionAnimationList>
{
private static readonly string[] SimpleEvents = { "OnStart", "OnPerform", "OnEnd" };
protected override void Validate(ValidationResult result)
{
if (Value == null) return;
ValidateClipEvents(result, Value.list.clip, SimpleEvents);
}
private void ValidateClipEvents(ValidationResult result, AnimationClip clip, string[] neededEvents)
{
if (!clip) return;
var currentEvents = clip.events.Select(ev => ev.functionName).ToList();
var missingEvents = neededEvents.Except(currentEvents).ToList();
var invalidEvents = currentEvents.Except(neededEvents).ToList();
var duplicatedEvents = currentEvents.GroupBy(s => s).Where(g => g.Count() > 1).Select(g => g.Key).ToList();
if (missingEvents.Count > 0)
{
var missingEventsText = string.Join(" ", missingEvents.Select(str => $"<u>{str}</u>"));
result
.AddError($"<u>{clip.name}</u> is missing required events: " + missingEventsText)
.SetSelectionObject(clip);
}
if (invalidEvents.Count > 0)
{
var invalidEventsText = string.Join(" ", invalidEvents.Select(str => $"<u>{str}</u>"));
result
.AddWarning($"<u>{clip.name}</u> contain unknown events: " + invalidEventsText)
.SetSelectionObject(clip);
}
if (duplicatedEvents.Count > 0)
{
var duplicatedEventsText = string.Join(" ", duplicatedEvents.Select(str => $"<u>{str}</u>"));
result
.AddError($"<u>{clip.name}</u> contain duplicated events: " + duplicatedEventsText)
.SetSelectionObject(clip);
}
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d2d25375d33f40e0bb0cf42d99e0ef3e
timeCreated: 1719581332
@@ -0,0 +1,73 @@
using System.Linq;
using Sirenix.OdinInspector.Editor.Validation;
using UnityEngine;
using VOID.Editor.AttributeValidator;
using VOID.ScriptableObjects.Animations;
[assembly: RegisterValidator(typeof(AnimationListValidator))]
namespace VOID.Editor.AttributeValidator
{
public class AnimationListValidator : ValueValidator<ActionLoopAnimationList>
{
private static readonly string[] LoopStartEvents = { "OnStart", "OnLoopStart", "OnPerform" };
private static readonly string[] LoopEvents = {};
private static readonly string[] LoopEndEvents = { "OnLoopEnd", "OnEnd" };
protected override void Validate(ValidationResult result)
{
if (Value == null) return;
ValidateClipEvents(result, Value.list.startClip, LoopStartEvents);
ValidateClipEvents(result, Value.list.loopClip, LoopEvents);
ValidateClipEvents(result, Value.list.endClip, LoopEndEvents);
ValidateStartEndClips(result);
}
private void ValidateClipEvents(ValidationResult result, AnimationClip clip, string[] neededEvents)
{
if (!clip) return;
var currentEvents = clip.events.Select(ev => ev.functionName).ToList();
var missingEvents = neededEvents.Except(currentEvents).ToList();
var invalidEvents = currentEvents.Except(neededEvents).ToList();
var duplicatedEvents = currentEvents.GroupBy(s => s).Where(g => g.Count() > 1).Select(g => g.Key).ToList();
if (missingEvents.Count > 0)
{
var missingEventsText = string.Join(" ", missingEvents.Select(str => $"<u>{str}</u>"));
result
.AddError($"<u>{clip.name}</u> is missing required events: " + missingEventsText)
.SetSelectionObject(clip);
}
if (invalidEvents.Count > 0)
{
var invalidEventsText = string.Join(" ", invalidEvents.Select(str => $"<u>{str}</u>"));
result
.AddWarning($"<u>{clip.name}</u> contain unknown events: " + invalidEventsText)
.SetSelectionObject(clip);
}
if (duplicatedEvents.Count > 0)
{
var duplicatedEventsText = string.Join(" ", duplicatedEvents.Select(str => $"<u>{str}</u>"));
result
.AddError($"<u>{clip.name}</u> contain duplicated events: " + duplicatedEventsText)
.SetSelectionObject(clip);
}
}
private void ValidateStartEndClips(ValidationResult result)
{
if (!Value.list.startClip && !Value.list.endClip) return;
var subInfo = $"Both {nameof(Value.list.startClip)} and {nameof(Value.list.endClip)} should exists or be deleted!";
if (!Value.list.startClip)
result.AddError($"<u>{nameof(Value.list.startClip)}</u> does not exists!\n{subInfo}");
if (!Value.list.endClip)
result.AddError($"<u>{nameof(Value.list.endClip)}</u> does not exists!\n{subInfo}");
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f202a516ff864e749792bc74d6cc50b0
timeCreated: 1743195641
@@ -0,0 +1,52 @@
using Sirenix.OdinInspector.Editor.Validation;
using Sirenix.Utilities;
using UnityEngine;
using VOID.Editor.AttributeValidator;
using VOID.Generic.World;
[assembly: RegisterValidator(typeof(AreaValidator))]
namespace VOID.Editor.AttributeValidator
{
public class AreaValidator : ValueValidator<Area>
{
protected override void Validate(ValidationResult result)
{
if (Value == null) return;
// Validate only ASSET - skip scene
if (!Value.gameObject.scene.path.IsNullOrWhitespace()) return;
ValidateIsInComplexAreaPrefab(result);
ValidatePosition(result);
}
private void ValidateIsInComplexAreaPrefab(ValidationResult result)
{
if (Value.transform.root.gameObject.GetComponent<ComplexArea>() == null)
{
result.AddError(
$"{nameof(Area)} needs to be placed inside prefab with component {nameof(ComplexArea)}!"
);
}
}
private void ValidatePosition(ValidationResult result)
{
var complexArea = Value.transform.root.gameObject.GetComponent<ComplexArea>();
if (!complexArea) return;
var relativePosition = complexArea.transform.position - Value.transform.position;
var xValid = relativePosition.x % Area.Size < Vector3.kEpsilon;
var yValid = relativePosition.y % Area.Size < Vector3.kEpsilon;
var zValid = relativePosition.z % Area.Size < Vector3.kEpsilon;
if (!xValid || !yValid || !zValid)
{
result.AddError(
$"'{Value.name}' is placed in invalid position."
+ $"\nRelative position to ComplexArea is {relativePosition} and is not dividable by {Area.Size}!"
);
}
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1a486a4fce9d4fe1a3d9ca9aa04d29c5
timeCreated: 1716645645
@@ -0,0 +1,42 @@
using System.Linq;
using Sirenix.OdinInspector.Editor.Validation;
using UnityEngine;
using VOID.Editor.AttributeValidator;
using VOID.Generic;
using VOID.Generic.Triggers;
[assembly: RegisterValidator(typeof(CameraTriggerValidator))]
namespace VOID.Editor.AttributeValidator
{
public class CameraTriggerValidator : ValueValidator<ICameraTrigger>
{
private Component _component;
private GameObject _gameObject;
protected override void Validate(ValidationResult result)
{
if (Value is not Component component) return;
_component = component;
_gameObject = _component.gameObject;
ValidateLayer(result);
ValidateIsTrigger(result);
}
private void ValidateLayer(ValidationResult result)
{
if (LayerManager.CodeInMask(_component.gameObject.layer, LayerManager.Camera)) return;
result.AddError($"Layer is not <u>{nameof(LayerManager.Camera)}</u>!");
}
private void ValidateIsTrigger(ValidationResult result)
{
var isTrigger = _gameObject.GetComponents<Collider>().All(c => c.isTrigger);
if (isTrigger) return;
result.AddError("All <u>Is Trigger</u> in colliders must be set to <u>true</u>!");
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 548b1cf469c446009821a3734df0d267
timeCreated: 1731686163
@@ -0,0 +1,66 @@
using System.Linq;
using Sirenix.OdinInspector.Editor.Validation;
using Sirenix.Utilities;
using UnityEngine;
using VOID.Editor.AttributeValidator;
using VOID.Generic.World;
[assembly: RegisterValidator(typeof(ComplexAreaValidator))]
namespace VOID.Editor.AttributeValidator
{
public class ComplexAreaValidator : ValueValidator<ComplexArea>
{
protected override void Validate(ValidationResult result)
{
if (Value == null) return;
// Validate only ASSET - skip scene
if (!Value.gameObject.scene.path.IsNullOrWhitespace()) return;
ValidateIsInRootPrefab(result);
ValidatePosition(result);
ValidateIsAtLeastOneAreaDefined(result);
ValidateAreAllAreasHandled(result);
}
private void ValidateIsInRootPrefab(ValidationResult result)
{
var prefabRoot = Value.transform.root.gameObject;
if (prefabRoot != Value.gameObject)
{
result.AddError($"{nameof(ComplexArea)} is not in prefab root!");
}
}
private void ValidatePosition(ValidationResult result)
{
if (Value.gameObject.transform.localPosition != Vector3.zero)
{
result.AddError($"{nameof(ComplexArea)}'s position in prefab must be {Vector3.zero}!");
}
}
private void ValidateIsAtLeastOneAreaDefined(ValidationResult result)
{
var areas = Value.areas;
if (areas.IsNullOrEmpty())
{
result.AddError($"{nameof(ComplexArea)} does not have any {nameof(Area)} defined!");
}
}
private void ValidateAreAllAreasHandled(ValidationResult result)
{
var areas = Value.areas;
var areasInPrefab = Value.transform.root.GetComponentsInChildren<Area>().ToList();
var areasDiff = areasInPrefab.Except(areas).ToList();
if (!areasDiff.IsNullOrEmpty())
{
result.AddError($"{nameof(ComplexArea)} does not contain all {nameof(Area)} defined in this prefab!");
}
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b8f5c7642b3c44009be0fb9d35dc02b3
timeCreated: 1716642064
@@ -0,0 +1,53 @@
using Sirenix.OdinInspector.Editor.Validation;
using Sirenix.Utilities;
using VOID.Editor.AttributeValidator;
using VOID.Generic.DropTable;
using VOID.Generic.Objects.Abstract;
using VOID.Generic.Objects.Container;
using VOID.Generic.Objects.Unit;
[assembly: RegisterValidator(typeof(DropTableComponentValidator))]
namespace VOID.Editor.AttributeValidator
{
public class DropTableComponentValidator : ValueValidator<DropTableComponent>
{
protected override void Validate(ValidationResult result)
{
if (Value == null) return;
var attachedTo = Value.GetComponent<AbstractObject>();
IsPlacedWithAbstractObject(result, attachedTo);
if (attachedTo == null) return;
CanUseTriggerOnSpawn(result, attachedTo);
IsDropTableDefined(result);
}
private void IsPlacedWithAbstractObject(ValidationResult result, AbstractObject attachedTo)
{
// DropTable's GameObject also needs to have AbstractObject (or its children)
if (attachedTo != null) return;
result.AddError($"{nameof(DropTableComponent)} needs to be placed together with any <u><b>{nameof(AbstractObject)}</b></u>");
}
private void CanUseTriggerOnSpawn(ValidationResult result, AbstractObject attachedTo)
{
// OnSpawn can be used only with Unit or Container
if (Value.trigger is not DropTableTrigger.OnSpawn || attachedTo is UnitObject or ContainerObject) return;
result.AddError($"{nameof(DropTableComponent)}'s {nameof(Value.trigger)}: <u><b>{Value.trigger}</b></u> can't be used with <u><b>{attachedTo.GetType().GetNiceName()}</b></u>");
}
private void IsDropTableDefined(ValidationResult result)
{
// DropTable is required!
if (Value.dropTable != null) return;
result.AddError($"{nameof(DropTableComponent)}'s drop table is not defined!");
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0576c79013184fe3beb6fa3238f90302
timeCreated: 1717863063
@@ -0,0 +1,26 @@
using Sirenix.OdinInspector.Editor.Validation;
using Sirenix.Utilities;
using VOID.Editor.AttributeValidator;
using VOID.Generic.DynamicValue;
[assembly: RegisterValidator(typeof(DynamicFormulaValidator))]
namespace VOID.Editor.AttributeValidator
{
public class DynamicFormulaValidator : ValueValidator<DynamicFormula>
{
protected override void Validate(ValidationResult result)
{
if (Value == null) return;
ValidatePresent(result);
}
private void ValidatePresent(ValidationResult result)
{
if (!Value.dynamicValue.IsNullOrWhitespace()) return;
result.AddError("Math formula is empty!");
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1a7a4957ce3047b69d9a190f18b142c0
timeCreated: 1723921186
@@ -0,0 +1,18 @@
using Sirenix.OdinInspector.Editor.Validation;
using VOID.Editor.AttributeValidator;
using VOID.Generic.DynamicValue;
[assembly: RegisterValidator(typeof(DynamicTextValidator))]
namespace VOID.Editor.AttributeValidator
{
public class DynamicTextValidator : ValueValidator<DynamicText>
{
protected override void Validate(ValidationResult result)
{
if (Value == null) return;
// TODO: walidacja znaczników
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3cbdf6c4f9bd462dbe91d5cb533628f0
timeCreated: 1723838013
@@ -0,0 +1,37 @@
using Sirenix.OdinInspector.Editor.Validation;
using UnityEngine;
using VOID.Editor.AttributeValidator;
using VOID.Generic;
using VOID.Generic.Triggers;
[assembly: RegisterValidator(typeof(DynamicTriggerValidator))]
namespace VOID.Editor.AttributeValidator
{
public class DynamicTriggerValidator : ValueValidator<IDynamicTrigger>
{
protected override void Validate(ValidationResult result)
{
if (Value is not Component component) return;
ValidateLayer(result, component);
ValidateCollider(result, component);
}
private void ValidateLayer(ValidationResult result, Component component)
{
if (LayerManager.CodeInMask(component.gameObject.layer, LayerManager.Trigger)) return;
result.AddError(
$"This component uses <u>{nameof(IDynamicTrigger)}</u> which requires layer <u>{nameof(LayerManager.Trigger)}</u>!");
}
private void ValidateCollider(ValidationResult result, Component component)
{
if (component.GetComponentInChildren<Collider>()) return;
result.AddError(
$"This component uses <u>{nameof(IDynamicTrigger)}</u> which requires at least one <u>collider</u>!");
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: edf8c57dfd744b9ca332155888b9677d
timeCreated: 1731687244
@@ -0,0 +1,32 @@
using System.Linq;
using Sirenix.OdinInspector.Editor.Validation;
using UnityEngine;
using VOID.Editor.AttributeValidator;
using VOID.Generic;
using VOID.Generic.Triggers;
[assembly: RegisterValidator(typeof(HideCeilingTriggerValidator))]
namespace VOID.Editor.AttributeValidator
{
public class HideCeilingTriggerValidator : ValueValidator<HideCeilingTrigger>
{
protected override void Validate(ValidationResult result)
{
if (Value == null) return;
ValidateHideableLayer(result);
}
private void ValidateHideableLayer(ValidationResult result)
{
var isWrongLayer = Value.gameObjectsToHide.SelectMany(go => go.GetComponentsInChildren<Transform>())
.Select(transform => transform.gameObject.layer)
.Any(layer => layer != LayerManager.StaticHideableIndex);
if (!isWrongLayer) return;
result.AddError($"All hideable objects targeted by this components needs layer <u>{nameof(LayerManager.StaticHideable)}</u>");
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b19a84b828dc44d19acc91a3562527f6
timeCreated: 1747502208
@@ -0,0 +1,25 @@
using InfinityPBR.ModularCharacterHelper;
using Sirenix.OdinInspector.Editor.Validation;
using VOID.Editor.AttributeValidator;
[assembly: RegisterValidator(typeof(ModularCharacterValidator))]
namespace VOID.Editor.AttributeValidator
{
public class ModularCharacterValidator : ValueValidator<ModularCharacter>
{
protected override void Validate(ValidationResult result)
{
if (Value == null) return;
ValidateBoneRoot(result);
}
private void ValidateBoneRoot(ValidationResult result)
{
if (Value.targetRootBone) return;
result.AddError($"<b>{nameof(Value.targetRootBone)}</b> is required!");
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2174b4dd14e6457f91bf2752538551b6
timeCreated: 1724879981
@@ -0,0 +1,33 @@
using InfinityPBR.ModularCharacterHelper;
using Sirenix.OdinInspector.Editor.Validation;
using VOID.Editor.AttributeValidator;
[assembly: RegisterValidator(typeof(ModularPartValidator))]
namespace VOID.Editor.AttributeValidator
{
public class ModularPartValidator : ValueValidator<ModularPart>
{
protected override void Validate(ValidationResult result)
{
if (Value == null) return;
ValidateBoneRoot(result);
ValidateSkinnedRenderer(result);
}
private void ValidateBoneRoot(ValidationResult result)
{
if (Value.boneRoot) return;
result.AddError($"<b>{nameof(Value.boneRoot)}</b> is required!");
}
private void ValidateSkinnedRenderer(ValidationResult result)
{
if (Value.skinnedMeshRenderer) return;
result.AddError($"<b>{nameof(Value.skinnedMeshRenderer)}</b> is required!");
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b10c2b7729514d839a70884069ed6c0e
timeCreated: 1724870308
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3f58b0acec154c95a69320f5a8c74317
timeCreated: 1725482081
@@ -0,0 +1,40 @@
using System;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using Sirenix.OdinInspector.Editor.Validation;
using Sirenix.Utilities;
using UnityEngine;
using VOID.Editor.AttributeValidator.Objects;
using VOID.Generic.Objects.Abstract;
[assembly: RegisterValidator(typeof(AbstractObjectValidator))]
namespace VOID.Editor.AttributeValidator.Objects
{
public class AbstractObjectValidator : ValueValidator<AbstractObject>
{
protected override void Validate(ValidationResult result)
{
if (Value == null) return;
if (OdinPrefabUtility.GetPrefabKind(Value.gameObject) is not PrefabKind.Regular) return;
IsComponentOrderValid(result);
}
private void IsComponentOrderValid(ValidationResult result)
{
var components = Value.gameObject.GetComponents<Component>();
var abstractObjectIndex = Array.FindIndex(components, component => component is AbstractObject);
// *Object is first (or right after Transform)
if (abstractObjectIndex <= 1) return;
result.AddError($"{Value.GetType().GetNiceName()} should be first component (right after Transform)")
.WithFix(() =>
{
for (var i = 0; i < abstractObjectIndex - 1; i++)
UnityEditorInternal.ComponentUtility.MoveComponentUp(components[abstractObjectIndex]);
});
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d353447115784aa3806a3b1582e00469
timeCreated: 1744384089
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using Sirenix.OdinInspector.Editor.Validation;
using Sirenix.Utilities;
using UnityEngine;
using VOID.Editor.AttributeValidator.Objects;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Usable;
[assembly: RegisterValidator(typeof(ItemObjectDataValidator))]
namespace VOID.Editor.AttributeValidator.Objects
{
public class ItemObjectDataValidator : ValueValidator<ItemObjectData>
{
protected override void Validate(ValidationResult result)
{
if (Value == null) return;
if (Property.Parent.ValueEntry.WeakSmartValue is not ItemObject itemObject) return;
if (OdinPrefabUtility.GetPrefabKind(itemObject.gameObject) is not PrefabKind.Regular) return;
IsStackableValid(result);
}
private void IsStackableValid(ValidationResult result)
{
var allowedTypes = new List<Type> { typeof(ItemObject), typeof(UsableObject) };
if (!Value.stackable || allowedTypes.Contains(Property.ParentType)) return;
var allowedTypeNames = string.Join(", ", allowedTypes.Select(t => t.GetNiceName()).ToList());
result.AddError($"Stackable can be TRUE only for objects of type: {allowedTypeNames}")
.WithFix(() => Value.stackable = false);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 665bab4b4bfc4f829cb3b4738084cdde
timeCreated: 1744214861
@@ -0,0 +1,34 @@
using System;
using System.Linq;
using Sirenix.OdinInspector.Editor.Validation;
using VOID.Editor.AttributeValidator.Objects;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Unit;
[assembly: RegisterValidator(typeof(UnitObjectEquipmentValidator))]
namespace VOID.Editor.AttributeValidator.Objects
{
public class UnitObjectEquipmentValidator : ValueValidator<UnitObjectEquipment>
{
protected override void Validate(ValidationResult result)
{
if (Value == null) return;
AreValidWearablesPlaced(result);
}
private void AreValidWearablesPlaced(ValidationResult result)
{
foreach (var slotType in Enum.GetValues(typeof(EquipmentSlotType)).Cast<EquipmentSlotType>())
{
var wearable = Value.GetEquipped(slotType);
if (wearable == null) return;
// Wrong type of wearable placed in this slot
if (Value.CanEquipInSlot(slotType, wearable) == false)
result.AddError($"<u><b>{wearable.name}</b></u> can't be placed in <u><b>{slotType}</b></u> slot!");
}
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: edb7019ba7024f92b3aad84d20f3431b
timeCreated: 1718794692
@@ -0,0 +1,15 @@
using Sirenix.OdinInspector.Editor.Validation;
using VOID.Editor.AttributeValidator;
[assembly: RegisterValidator(typeof(SceneReferenceValidator))]
namespace VOID.Editor.AttributeValidator
{
public class SceneReferenceValidator : ValueValidator<SceneReference>
{
protected override void Validate(ValidationResult result)
{
if (ValueEntry.SmartValue == "") result.AddError(Property.NiceName + " is required");
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0c3223426e38404fb5bea6a8db202522
timeCreated: 1730239681