launch a new base system for codex perception
This commit is contained in:
parent
80cf81a451
commit
d620c54be7
8
Assets/Resources/Services/Codex.meta
Normal file
8
Assets/Resources/Services/Codex.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0da99a62443b843fa898402c2a4b02c8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Resources/Services/Codex/Concepts.meta
Normal file
8
Assets/Resources/Services/Codex/Concepts.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a9a986ab47dc4b528fa8a7bcf5e7ced
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,15 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b6b70c957a7948bc8f0be6f30e791f18, type: 3}
|
||||
m_Name: Codex - Concept Library
|
||||
m_EditorClassIdentifier: Gameplay::Intrepid.Gameplay.Codex.Knowledge.CodexConceptLibrary
|
||||
concepts: []
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63a5d7be4117a4007af1ab89f0050093
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Resources/Services/Codex/Protocols.meta
Normal file
8
Assets/Resources/Services/Codex/Protocols.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 709db9526442d45a381fafe2b54ff976
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,15 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 73c8da23e167c437b9b4044376377a24, type: 3}
|
||||
m_Name: '# Codex - Pictorial Protocol Library'
|
||||
m_EditorClassIdentifier: Gameplay::Intrepid.Gameplay.Codex.Visual.PictorialProtocolLibrary
|
||||
protocols: []
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d9e05a934e384073975b2763edfba69
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,40 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b9a2dd3bc25546bfb126b9445e977c3c, type: 3}
|
||||
m_Name: pictorial-protocol.default
|
||||
m_EditorClassIdentifier: Gameplay::Intrepid.Gameplay.Codex.Visual.PictorialProtocolTag
|
||||
code: dcfda51c61c345898e10ae7aeae468ce
|
||||
localization: {fileID: 0}
|
||||
description: {fileID: 0}
|
||||
interfaceStyle:
|
||||
surfaceBase: {r: 0.02745098, g: 0.0627451, b: 0.078431375, a: 1}
|
||||
surfaceRaised: {r: 0.0627451, g: 0.1254902, b: 0.14901961, a: 1}
|
||||
surfaceDeep: {r: 0.011764706, g: 0.02745098, b: 0.03137255, a: 1}
|
||||
surfaceOverlay: {r: 0.08627451, g: 0.16862746, b: 0.2, a: 0.8}
|
||||
textPrimary: {r: 0.84705883, g: 0.96862745, b: 1, a: 1}
|
||||
textSecondary: {r: 0.56078434, g: 0.78039217, b: 0.81960785, a: 1}
|
||||
textMuted: {r: 0.32156864, g: 0.4745098, b: 0.50980395, a: 1}
|
||||
textDisabled: {r: 0.18431373, g: 0.27450982, b: 0.29803923, a: 1}
|
||||
focus: {r: 0.36862746, g: 0.92156863, b: 1, a: 1}
|
||||
selected: {r: 0.6156863, g: 1, b: 0.9019608, a: 1}
|
||||
disabled: {r: 0.23137255, g: 0.33333334, b: 0.36078432, a: 1}
|
||||
denied: {r: 1, g: 0.41568628, b: 0.2901961, a: 1}
|
||||
warning: {r: 1, g: 0.81960785, b: 0.4, a: 1}
|
||||
danger: {r: 1, g: 0.20784314, b: 0.3647059, a: 1}
|
||||
corruption: {r: 0.7058824, g: 0.36078432, b: 1, a: 1}
|
||||
life: {r: 1, g: 0.23137255, b: 0.30980393, a: 1}
|
||||
shield: {r: 0.21960784, g: 0.8509804, b: 1, a: 1}
|
||||
cadence: {r: 0.9647059, g: 0.9529412, b: 0.8235294, a: 1}
|
||||
progress: {r: 0.6156863, g: 1, b: 0.9019608, a: 1}
|
||||
lineSubtle: {r: 0.16862746, g: 0.3372549, b: 0.3764706, a: 1}
|
||||
lineActive: {r: 0.36862746, g: 0.92156863, b: 1, a: 1}
|
||||
lineCritical: {r: 1, g: 0.20784314, b: 0.3647059, a: 1}
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c3fd2d4d883248e18470247e672317a
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because one or more lines are too long
3
Assets/Scripts/Intrepid/Gameplay/Codex.meta
Normal file
3
Assets/Scripts/Intrepid/Gameplay/Codex.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d51db36b0b09472f80dfbd4d2d72088d
|
||||
timeCreated: 1783111087
|
||||
73
Assets/Scripts/Intrepid/Gameplay/Codex/CodexRuntime.cs
Normal file
73
Assets/Scripts/Intrepid/Gameplay/Codex/CodexRuntime.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Intrepid.GameManagers;
|
||||
using Intrepid.Gameplay.Codex.Knowledge;
|
||||
using Intrepid.Gameplay.Codex.Knowledge.Events;
|
||||
using Intrepid.Gameplay.Codex.Visual;
|
||||
using Intrepid.Gameplay.Codex.Visual.Events;
|
||||
using Intrepid.SimpleEvents;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex
|
||||
{
|
||||
/// <summary>
|
||||
/// Runtime owner of what the CODEX currently knows.
|
||||
/// This is intentionally separated from PDA runtime state.
|
||||
/// </summary>
|
||||
public class CodexRuntime : EventListener
|
||||
{
|
||||
[SerializeField] private CodexOntology ontology = new();
|
||||
[SerializeField] private PictorialProtocolInventory pictorialProtocols = new();
|
||||
|
||||
public CodexOntology Ontology => ontology;
|
||||
public PictorialProtocolInventory PictorialProtocols => pictorialProtocols;
|
||||
|
||||
public IReadOnlyList<CodexConceptTag> KnownConcepts => ontology.KnownConcepts;
|
||||
public IReadOnlyList<PictorialProtocolTag> KnownPictorialProtocols => pictorialProtocols.KnownProtocols;
|
||||
|
||||
public bool Knows(CodexConceptTag concept) => ontology.Knows(concept);
|
||||
public bool Knows(PictorialProtocolTag protocol) => pictorialProtocols.Knows(protocol);
|
||||
|
||||
protected override void InitializeVariables()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnBootstrap()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Subscriptions()
|
||||
{
|
||||
}
|
||||
|
||||
public void Learn(CodexConceptTag concept, bool raiseEvent = true)
|
||||
{
|
||||
if (concept.IsNull()) return;
|
||||
|
||||
if (Knows(concept)) return;
|
||||
|
||||
ontology.Learn(concept);
|
||||
|
||||
if (!raiseEvent) return;
|
||||
Proxy.Instance.EventBus.Raise(new CodexConceptLearnedEvent
|
||||
{
|
||||
Concept = concept,
|
||||
});
|
||||
}
|
||||
|
||||
public void Unlock(PictorialProtocolTag protocol, bool raiseEvent = true)
|
||||
{
|
||||
if (protocol.IsNull()) return;
|
||||
|
||||
if (Knows(protocol)) return;
|
||||
|
||||
pictorialProtocols.Unlock(protocol);
|
||||
|
||||
if (!raiseEvent) return;
|
||||
Proxy.Instance.EventBus.Raise(new PictorialProtocolUnlockedEvent
|
||||
{
|
||||
Protocol = protocol,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a91d3e76c034a31875d4a4ae36af980
|
||||
8
Assets/Scripts/Intrepid/Gameplay/Codex/Knowledge.meta
Normal file
8
Assets/Scripts/Intrepid/Gameplay/Codex/Knowledge.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e243cdc715848c6aaebd2dfd4f5f5d9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Intrepid.Utilities;
|
||||
using Sirenix.OdinInspector;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Knowledge
|
||||
{
|
||||
[Serializable]
|
||||
[CreateAssetMenu(fileName = "Codex - Concept Library", menuName = "GON/CODEX/Knowledge/Concept Library")]
|
||||
public class CodexConceptLibrary : SingletonScriptableObject<CodexConceptLibrary>
|
||||
{
|
||||
[GroupInjections, SerializeField] private List<CodexConceptTag> concepts = new();
|
||||
|
||||
public IReadOnlyList<CodexConceptTag> Concepts => concepts.Where(c => c.IsNotNull()).Distinct().ToList();
|
||||
|
||||
public bool Contains(CodexConceptTag concept)
|
||||
{
|
||||
return concept.IsNotNull() && concepts.Contains(concept);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[PropertyOrder(-10)]
|
||||
[GroupInjections, Button(ButtonSizes.Large), GUIColor(0.35f, 0.8f, .35f)]
|
||||
protected void FindAll()
|
||||
{
|
||||
concepts.Clear();
|
||||
var guids = AssetDatabase.FindAssets($"t:{nameof(CodexConceptTag)}");
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
var protocol = AssetDatabase.LoadAssetAtPath<CodexConceptTag>(path);
|
||||
concepts.Add(protocol);
|
||||
}
|
||||
EditorUtility.SetDirty(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b6b70c957a7948bc8f0be6f30e791f18
|
||||
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using Intrepid.Localization;
|
||||
using Intrepid.TagSystem;
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Knowledge
|
||||
{
|
||||
[Serializable]
|
||||
[CreateAssetMenu(fileName = "New Concept Tag", menuName = "GON/CODEX/Knowledge/Concept Tag")]
|
||||
public class CodexConceptTag : Tag
|
||||
{
|
||||
[GroupConfigurations, SerializeField] private LocalizationTag localization;
|
||||
[GroupConfigurations, SerializeField] private LocalizationTag description;
|
||||
|
||||
public LocalizationTag Localization => localization;
|
||||
public LocalizationTag Description => description;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19f2c1dad39848b8847bf424fc7605b2
|
||||
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Intrepid.Utilities;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Knowledge
|
||||
{
|
||||
[Serializable]
|
||||
[GroupConfigurations("Codex Ontology"), HideLabel]
|
||||
public class CodexOntology
|
||||
{
|
||||
[SerializeField] private List<CodexConceptTag> knownConcepts = new();
|
||||
|
||||
public IReadOnlyList<CodexConceptTag> KnownConcepts => knownConcepts.Where(c => c.IsNotNull()).Distinct().ToList();
|
||||
|
||||
public bool Knows(CodexConceptTag concept)
|
||||
{
|
||||
return concept.IsNotNull() && knownConcepts.Contains(concept);
|
||||
}
|
||||
|
||||
public bool Learn(CodexConceptTag concept)
|
||||
{
|
||||
if (concept.IsNull()) return false;
|
||||
if (knownConcepts.Contains(concept)) return false;
|
||||
knownConcepts.Add(concept);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Forget(CodexConceptTag concept)
|
||||
{
|
||||
if (concept.IsNull()) return false;
|
||||
return knownConcepts.Remove(concept);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[GroupDebug, Button(ButtonSizes.Medium)]
|
||||
private void CleanupKnownConcepts()
|
||||
{
|
||||
knownConcepts = knownConcepts.Where(c => c.IsNotNull()).Distinct().ToList();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb4eda8c15124aa38685c8c2b1ac9207
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0498589829b124127bc6c22e027ec669
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,9 @@
|
||||
using Intrepid.SimpleEvents;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Knowledge.Events
|
||||
{
|
||||
public class CodexConceptLearnedEvent : IEventBase
|
||||
{
|
||||
public CodexConceptTag Concept { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79e533105f1774b95ad5bacdd1887aff
|
||||
8
Assets/Scripts/Intrepid/Gameplay/Codex/Perception.meta
Normal file
8
Assets/Scripts/Intrepid/Gameplay/Codex/Perception.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7c13a24868ef417095514def91bb5d9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,14 @@
|
||||
namespace Intrepid.Gameplay.Codex.Perception
|
||||
{
|
||||
public readonly struct CodexInterpretationRequest
|
||||
{
|
||||
public CodexReadable Readable { get; }
|
||||
public CodexReadingState ReadingState { get; }
|
||||
|
||||
public CodexInterpretationRequest(CodexReadable readable, CodexReadingState readingState)
|
||||
{
|
||||
Readable = readable;
|
||||
ReadingState = readingState;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76e9ce38e022448d0b3c75ba5bd6e193
|
||||
@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using Intrepid.Gameplay.Codex.Knowledge;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Perception
|
||||
{
|
||||
public class CodexInterpretationResult
|
||||
{
|
||||
public CodexReadable Readable { get; set; }
|
||||
public CodexReadingState ReadingState { get; set; }
|
||||
public IReadOnlyList<CodexConceptTag> RecognizedConcepts { get; set; }
|
||||
public IReadOnlyList<CodexConceptTag> ResidueConcepts { get; set; }
|
||||
public float Confidence { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52b61255208554314b5f8d5a35d2120a
|
||||
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using Intrepid.Gameplay.Codex.Knowledge;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Perception
|
||||
{
|
||||
[Serializable]
|
||||
public class CodexManifestEntry
|
||||
{
|
||||
[SerializeField] private CodexConceptTag concept;
|
||||
[SerializeField, Range(0f, 1f)] private float weight = 1f;
|
||||
|
||||
public CodexConceptTag Concept => concept;
|
||||
public float Weight => weight;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 558dfbb5de4c54f70aa54dc15ce09cb5
|
||||
@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Perception
|
||||
{
|
||||
/// <summary>
|
||||
/// Marker for world objects that can be processed by the CODEX Reading Field.
|
||||
/// Keep this data-oriented. Gameplay interaction should live elsewhere.
|
||||
/// </summary>
|
||||
public class CodexReadable : MonoBehaviour
|
||||
{
|
||||
[GroupConfigurations, SerializeField] private string semanticId;
|
||||
[GroupConfigurations, SerializeField] private List<CodexManifestEntry> manifest = new();
|
||||
[GroupDebug, SerializeField] private CodexReadingState readingState = CodexReadingState.Unseen;
|
||||
|
||||
public string SemanticId => semanticId;
|
||||
public IReadOnlyList<CodexManifestEntry> Manifest => manifest;
|
||||
public CodexReadingState ReadingState => readingState;
|
||||
|
||||
public void SetReadingState(CodexReadingState state)
|
||||
{
|
||||
readingState = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74300c9a0423e42fa8bb8b5ea28a4ff8
|
||||
@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Intrepid.Gameplay.Codex.Knowledge;
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Perception
|
||||
{
|
||||
/// <summary>
|
||||
/// Minimal trigger-based reading field. Shape/orientation should be authored by the collider on the GameObject.
|
||||
/// Later this can become a true forward cone/frustum query.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Collider))]
|
||||
public class CodexReadingField : MonoBehaviour
|
||||
{
|
||||
[GroupConfigurations, SerializeField] private CodexRuntime knowledge;
|
||||
[GroupDebug, SerializeField] private List<CodexReadable> readablesInside = new();
|
||||
|
||||
private CodexSemanticClassifier classifier;
|
||||
|
||||
public IReadOnlyList<CodexReadable> ReadablesInside => readablesInside;
|
||||
public event Action<CodexInterpretationResult> ReadableDetected;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
classifier = new CodexSemanticClassifier(knowledge);
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
var readable = other.GetComponentInParent<CodexReadable>();
|
||||
if (readable.IsNull()) return;
|
||||
if (readablesInside.Contains(readable)) return;
|
||||
|
||||
readablesInside.Add(readable);
|
||||
readable.SetReadingState(CodexReadingState.Detected);
|
||||
|
||||
if (knowledge.IsNull()) return;
|
||||
var result = classifier.Classify(new CodexInterpretationRequest(readable, readable.ReadingState));
|
||||
ReadableDetected?.Invoke(result);
|
||||
}
|
||||
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
var readable = other.GetComponentInParent<CodexReadable>();
|
||||
if (readable.IsNull()) return;
|
||||
readablesInside.Remove(readable);
|
||||
readable.SetReadingState(CodexReadingState.Unseen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3a9bcb1c030f4d83b95174465c45dd9
|
||||
@ -0,0 +1,15 @@
|
||||
namespace Intrepid.Gameplay.Codex.Perception
|
||||
{
|
||||
public enum CodexReadingState
|
||||
{
|
||||
Unseen,
|
||||
Detected,
|
||||
Scanning,
|
||||
Known,
|
||||
Focused,
|
||||
Relevant,
|
||||
Locked,
|
||||
Reinterpreted,
|
||||
Corrupted
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22e041dc3b2d54f18b99b74a2c455061
|
||||
@ -0,0 +1,36 @@
|
||||
using System.Linq;
|
||||
using Intrepid.Gameplay.Codex.Knowledge;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Perception
|
||||
{
|
||||
/// <summary>
|
||||
/// First deterministic placeholder for the future vector/prototype classifier.
|
||||
/// Today it only separates known concepts from semantic residue.
|
||||
/// </summary>
|
||||
public class CodexSemanticClassifier
|
||||
{
|
||||
private readonly CodexRuntime knowledge;
|
||||
|
||||
public CodexSemanticClassifier(CodexRuntime knowledge)
|
||||
{
|
||||
this.knowledge = knowledge;
|
||||
}
|
||||
|
||||
public CodexInterpretationResult Classify(CodexInterpretationRequest request)
|
||||
{
|
||||
var manifest = request.Readable.Manifest.Where(e => e.Concept != null).ToList();
|
||||
var recognized = manifest.Where(e => knowledge.Knows(e.Concept)).Select(e => e.Concept).Distinct().ToList();
|
||||
var residue = manifest.Where(e => !knowledge.Knows(e.Concept)).Select(e => e.Concept).Distinct().ToList();
|
||||
var confidence = manifest.Count == 0 ? 0f : (float)recognized.Count / manifest.Count;
|
||||
|
||||
return new CodexInterpretationResult
|
||||
{
|
||||
Readable = request.Readable,
|
||||
ReadingState = request.ReadingState,
|
||||
RecognizedConcepts = recognized,
|
||||
ResidueConcepts = residue,
|
||||
Confidence = confidence
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 188e808f1aaf1470c9b6c596a4965724
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 518b37a61206f41d98dd2d4a85b008f8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,32 @@
|
||||
using Intrepid.Gameplay.Codex.Visual;
|
||||
using Intrepid.Gameplay.Codex.Visual.Events;
|
||||
using Intrepid.SimpleEvents;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Perception.Presentation
|
||||
{
|
||||
/// <summary>
|
||||
/// Tiny base for future diegetic marks. It only listens to visual changes.
|
||||
/// Specific marks can inherit and apply materials, sprites, particles or line renderers.
|
||||
/// </summary>
|
||||
public abstract class CodexWorldMarkPresenter : EventListener
|
||||
{
|
||||
protected override void InitializeVariables()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnBootstrap()
|
||||
{
|
||||
ApplyVisual(CodexVisualService.Instance.CurrentContext);
|
||||
}
|
||||
|
||||
protected override void Subscriptions()
|
||||
{
|
||||
Subscribe<CodexVisualChangedEvent>(e =>
|
||||
{
|
||||
ApplyVisual(e.Context);
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract void ApplyVisual(CodexVisualContext context);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a53fd6f73fe094a94957f1fbd7d053ec
|
||||
8
Assets/Scripts/Intrepid/Gameplay/Codex/Visual.meta
Normal file
8
Assets/Scripts/Intrepid/Gameplay/Codex/Visual.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c379a4bf2286d4cc497923ae4177cfb4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,10 @@
|
||||
namespace Intrepid.Gameplay.Codex.Visual
|
||||
{
|
||||
public enum CodexVisualChangeMode
|
||||
{
|
||||
Instant,
|
||||
Preview,
|
||||
Commit,
|
||||
CancelPreview
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f5c4907cbeb64120a1e148ea392e38f
|
||||
@ -0,0 +1,19 @@
|
||||
namespace Intrepid.Gameplay.Codex.Visual
|
||||
{
|
||||
/// <summary>
|
||||
/// Runtime-resolved visual context. Keep this immutable-ish and cheap to pass around.
|
||||
/// </summary>
|
||||
public class CodexVisualContext
|
||||
{
|
||||
public PictorialProtocolTag Protocol { get; }
|
||||
public int Version { get; }
|
||||
public bool IsPreview { get; }
|
||||
|
||||
public CodexVisualContext(PictorialProtocolTag protocol, int version, bool isPreview = false)
|
||||
{
|
||||
Protocol = protocol;
|
||||
Version = version;
|
||||
IsPreview = isPreview;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cfc6e6f636334e1f9282ac9e028c900
|
||||
@ -0,0 +1,77 @@
|
||||
using Intrepid.GameManagers;
|
||||
using Intrepid.Gameplay.Codex.Visual.Events;
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Visual
|
||||
{
|
||||
/// <summary>
|
||||
/// New visual-language entrypoint for CODEX/PDA/ActionBelt/world marks.
|
||||
/// Transitional note: this currently uses the existing Theme asset.
|
||||
/// Later Theme can be renamed/wrapped as PictorialProtocol without changing consumers much.
|
||||
/// </summary>
|
||||
public class CodexVisualService : SingletonMonoBehaviour<CodexVisualService>
|
||||
{
|
||||
[GroupConfigurations, SerializeField] private PictorialProtocolTag defaultProtocol;
|
||||
[GroupDebug, SerializeField] private PictorialProtocolTag currentProtocol;
|
||||
|
||||
private int version;
|
||||
private PictorialProtocolTag committedProtocol;
|
||||
private CodexVisualContext currentContext;
|
||||
|
||||
public PictorialProtocolTag CurrentPictorialProtocol => currentProtocol ?? defaultProtocol;
|
||||
public CodexVisualContext CurrentContext
|
||||
{
|
||||
get
|
||||
{
|
||||
currentContext ??= new CodexVisualContext(CurrentPictorialProtocol, version);
|
||||
return currentContext;
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
SingletonInstantiation(false, _ => { });
|
||||
committedProtocol = CurrentPictorialProtocol;
|
||||
currentContext = new CodexVisualContext(CurrentPictorialProtocol, version);
|
||||
}
|
||||
|
||||
public void ApplyTheme(PictorialProtocolTag protocol, CodexVisualChangeMode mode = CodexVisualChangeMode.Commit)
|
||||
{
|
||||
var nextProtocol = protocol ?? defaultProtocol;
|
||||
var previousProtocol = CurrentPictorialProtocol;
|
||||
|
||||
if (previousProtocol == nextProtocol && mode != CodexVisualChangeMode.CancelPreview) return;
|
||||
|
||||
currentProtocol = nextProtocol;
|
||||
if (CodexVisualChangeMode.Preview != mode)
|
||||
{
|
||||
committedProtocol = nextProtocol;
|
||||
}
|
||||
|
||||
currentContext = new CodexVisualContext(CurrentPictorialProtocol, ++version, mode == CodexVisualChangeMode.Preview);
|
||||
RaiseChanged(previousProtocol, CurrentPictorialProtocol, mode);
|
||||
}
|
||||
|
||||
public void PreviewTheme(PictorialProtocolTag protocol)
|
||||
{
|
||||
ApplyTheme(protocol, CodexVisualChangeMode.Preview);
|
||||
}
|
||||
|
||||
public void CancelPreview()
|
||||
{
|
||||
ApplyTheme(committedProtocol, CodexVisualChangeMode.CancelPreview);
|
||||
}
|
||||
|
||||
private void RaiseChanged(PictorialProtocolTag previousProtocol, PictorialProtocolTag nextProtocol, CodexVisualChangeMode mode)
|
||||
{
|
||||
Proxy.Instance.EventBus.Raise(new CodexVisualChangedEvent
|
||||
{
|
||||
PreviousProtocol = previousProtocol,
|
||||
CurrentProtocol = nextProtocol,
|
||||
Context = CurrentContext,
|
||||
Mode = mode
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a41317694c23246d8b43c7ffbe9205e5
|
||||
@ -0,0 +1,28 @@
|
||||
namespace Intrepid.Gameplay.Codex.Visual
|
||||
{
|
||||
/// <summary>
|
||||
/// Stable visual meanings. Concrete colors/materials come from the active pictorial protocol.
|
||||
/// This starts small on purpose and can grow as PDA, ActionBelt and diegetic marks migrate.
|
||||
/// </summary>
|
||||
public enum CodexVisualToken
|
||||
{
|
||||
SurfacePrimary,
|
||||
SurfaceSecondary,
|
||||
SurfaceDeep,
|
||||
TextPrimary,
|
||||
TextMuted,
|
||||
BorderSoft,
|
||||
BorderStrong,
|
||||
Focus,
|
||||
Selected,
|
||||
Disabled,
|
||||
Denied,
|
||||
Warning,
|
||||
Danger,
|
||||
Corruption,
|
||||
Available,
|
||||
Locked,
|
||||
Unknown,
|
||||
Reinterpreted
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa03f2923db1a44eba4d2349b7233ba1
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25ababed467874e9a84f02aec86b7c9e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,13 @@
|
||||
using Intrepid.Gameplay.Codex.Knowledge;
|
||||
using Intrepid.SimpleEvents;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Visual.Events
|
||||
{
|
||||
public class CodexVisualChangedEvent : IEventBase
|
||||
{
|
||||
public PictorialProtocolTag PreviousProtocol { get; set; }
|
||||
public PictorialProtocolTag CurrentProtocol { get; set; }
|
||||
public CodexVisualContext Context { get; set; }
|
||||
public CodexVisualChangeMode Mode { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 375fdd9b497264f9cbf50e7fbe710524
|
||||
@ -0,0 +1,9 @@
|
||||
using Intrepid.SimpleEvents;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Visual.Events
|
||||
{
|
||||
public class PictorialProtocolUnlockedEvent : IEventBase
|
||||
{
|
||||
public PictorialProtocolTag Protocol { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7abf081f4dc7f451a8273b457e6e4067
|
||||
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Intrepid.Utilities;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Visual
|
||||
{
|
||||
[Serializable]
|
||||
[GroupConfigurations("Pictorial Protocol Inventory"), HideLabel]
|
||||
public class PictorialProtocolInventory
|
||||
{
|
||||
[SerializeField] private List<PictorialProtocolTag> knownProtocols = new();
|
||||
|
||||
public IReadOnlyList<PictorialProtocolTag> KnownProtocols => knownProtocols.Where(p => p.IsNotNull()).Distinct().ToList();
|
||||
|
||||
public bool Knows(PictorialProtocolTag protocol)
|
||||
{
|
||||
return protocol.IsNotNull() && knownProtocols.Contains(protocol);
|
||||
}
|
||||
|
||||
public bool Unlock(PictorialProtocolTag protocol)
|
||||
{
|
||||
if (protocol.IsNull()) return false;
|
||||
if (knownProtocols.Contains(protocol)) return false;
|
||||
knownProtocols.Add(protocol);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Forget(PictorialProtocolTag protocol)
|
||||
{
|
||||
if (protocol.IsNull()) return false;
|
||||
return knownProtocols.Remove(protocol);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[GroupDebug, Button(ButtonSizes.Medium)]
|
||||
private void CleanupKnownProtocols()
|
||||
{
|
||||
knownProtocols = knownProtocols.Where(p => p.IsNotNull()).Distinct().ToList();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a488e1dac0ec4c01929a364477d39f27
|
||||
@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Intrepid.Utilities;
|
||||
using Sirenix.OdinInspector;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Visual
|
||||
{
|
||||
/// <summary>
|
||||
/// Catalog of all pictorial protocols available in the game.
|
||||
/// Currently uses the existing Theme asset as the concrete protocol asset.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[CreateAssetMenu(fileName = "Codex - Pictorial Protocol Library", menuName = "GON/CODEX/Visual/Pictorial Protocol Library")]
|
||||
public class PictorialProtocolLibrary : SingletonScriptableObject<PictorialProtocolLibrary>
|
||||
{
|
||||
[GroupInjections, SerializeField, ReadOnly] private List<PictorialProtocolTag> protocols;
|
||||
|
||||
public IReadOnlyList<PictorialProtocolTag> Protocols => protocols.Where(p => p.IsNotNull()).Distinct().ToList();
|
||||
|
||||
public bool Contains(PictorialProtocolTag protocol)
|
||||
{
|
||||
return protocol is not null && protocols.Contains(protocol);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[PropertyOrder(-10)]
|
||||
[GroupInjections, Button(ButtonSizes.Large), GUIColor(0.35f, 0.8f, .35f)]
|
||||
protected void FindAll()
|
||||
{
|
||||
protocols.Clear();
|
||||
var guids = AssetDatabase.FindAssets($"t:{nameof(PictorialProtocolTag)}");
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
var protocol = AssetDatabase.LoadAssetAtPath<PictorialProtocolTag>(path);
|
||||
protocols.Add(protocol);
|
||||
}
|
||||
EditorUtility.SetDirty(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73c8da23e167c437b9b4044376377a24
|
||||
@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using Intrepid.Diagnostics;
|
||||
using Intrepid.Localization;
|
||||
using Intrepid.TagSystem;
|
||||
using Intrepid.Utilities;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Codex.Visual
|
||||
{
|
||||
[Serializable]
|
||||
[CreateAssetMenu(fileName = "New Pictorial Protocol Tag", menuName = "GON/CODEX/Visual/Pictorial Protocol Tag")]
|
||||
public class PictorialProtocolTag : Tag
|
||||
{
|
||||
[GroupInjections, SerializeField] private LocalizationTag localization;
|
||||
[GroupInjections, SerializeField] private LocalizationTag description;
|
||||
[SerializeField, HideLabel, Title("Interface Style")] private PictorialProtocolInterfaceStyle interfaceStyle;
|
||||
|
||||
public LocalizationTag Localization => localization;
|
||||
public LocalizationTag Description => description;
|
||||
public PictorialProtocolInterfaceStyle InterfaceStyle => interfaceStyle;
|
||||
|
||||
// katakana
|
||||
// kanji
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class PictorialProtocolInterfaceStyle
|
||||
{
|
||||
[GroupConfigurations("Surfaces"), SerializeField] private Color surfaceBase = Color.black;
|
||||
[GroupConfigurations("Surfaces"), SerializeField] private Color surfaceRaised = Color.black;
|
||||
[GroupConfigurations("Surfaces"), SerializeField] private Color surfaceDeep = Color.black;
|
||||
[GroupConfigurations("Surfaces"), SerializeField] private Color surfaceOverlay = Color.black;
|
||||
|
||||
[GroupConfigurations("Text"), SerializeField] private Color textPrimary = Color.white;
|
||||
[GroupConfigurations("Text"), SerializeField] private Color textSecondary = Color.gray;
|
||||
[GroupConfigurations("Text"), SerializeField] private Color textMuted = Color.gray;
|
||||
[GroupConfigurations("Text"), SerializeField] private Color textDisabled = Color.gray;
|
||||
|
||||
[GroupConfigurations("Signals"), SerializeField] private Color focus = Color.white;
|
||||
[GroupConfigurations("Signals"), SerializeField] private Color selected = Color.white;
|
||||
[GroupConfigurations("Signals"), SerializeField] private Color disabled = Color.gray;
|
||||
[GroupConfigurations("Signals"), SerializeField] private Color denied = Color.red;
|
||||
[GroupConfigurations("Signals"), SerializeField] private Color warning = Color.yellow;
|
||||
[GroupConfigurations("Signals"), SerializeField] private Color danger = Color.red;
|
||||
[GroupConfigurations("Signals"), SerializeField] private Color corruption = Color.magenta;
|
||||
|
||||
[GroupConfigurations("Resources"), SerializeField] private Color life = Color.red;
|
||||
[GroupConfigurations("Resources"), SerializeField] private Color shield = Color.cyan;
|
||||
[GroupConfigurations("Resources"), SerializeField] private Color cadence = Color.white;
|
||||
[GroupConfigurations("Resources"), SerializeField] private Color progress = Color.white;
|
||||
|
||||
[GroupConfigurations("Lines"), SerializeField] private Color lineSubtle = Color.gray;
|
||||
[GroupConfigurations("Lines"), SerializeField] private Color lineActive = Color.white;
|
||||
[GroupConfigurations("Lines"), SerializeField] private Color lineCritical = Color.red;
|
||||
|
||||
public Color SurfaceBase => surfaceBase;
|
||||
public Color SurfaceRaised => surfaceRaised;
|
||||
public Color SurfaceDeep => surfaceDeep;
|
||||
public Color SurfaceOverlay => surfaceOverlay;
|
||||
|
||||
public Color TextPrimary => textPrimary;
|
||||
public Color TextSecondary => textSecondary;
|
||||
public Color TextMuted => textMuted;
|
||||
public Color TextDisabled => textDisabled;
|
||||
|
||||
public Color Focus => focus;
|
||||
public Color Selected => selected;
|
||||
public Color Disabled => disabled;
|
||||
public Color Denied => denied;
|
||||
public Color Warning => warning;
|
||||
public Color Danger => danger;
|
||||
public Color Corruption => corruption;
|
||||
|
||||
public Color Life => life;
|
||||
public Color Shield => shield;
|
||||
public Color Cadence => cadence;
|
||||
public Color Progress => progress;
|
||||
|
||||
public Color LineSubtle => lineSubtle;
|
||||
public Color LineActive => lineActive;
|
||||
public Color LineCritical => lineCritical;
|
||||
|
||||
private bool TryParseColor(string colorSchema, int nColors, out Color[] colors)
|
||||
{
|
||||
colors = null;
|
||||
if (string.IsNullOrWhiteSpace(colorSchema))
|
||||
{
|
||||
DLogger.LogWarn("Color Schema is empty.");
|
||||
return false;
|
||||
}
|
||||
var colorStrings = colorSchema.Split(',');
|
||||
if (colorStrings.Length < nColors)
|
||||
{
|
||||
DLogger.LogWarn($"Palette string must contain at least {nColors} hex colors.");
|
||||
return false;
|
||||
}
|
||||
|
||||
colors = new Color[colorStrings.Length];
|
||||
for (var i = 0; i < colorStrings.Length; i++)
|
||||
{
|
||||
if (ColorUtility.TryParseHtmlString(colorStrings[i].Trim(), out var color))
|
||||
{
|
||||
colors[i] = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
DLogger.LogWarn($"Invalid color code: {colorStrings[i]}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[GroupDebug, Button(ButtonSizes.Medium, ButtonStyle.FoldoutButton)]
|
||||
private void SetSurfaceColorSchema(string colorSchema)
|
||||
{
|
||||
if (TryParseColor(colorSchema, 4, out var colors))
|
||||
{
|
||||
surfaceBase = colors[0];
|
||||
surfaceRaised = colors[1];
|
||||
surfaceDeep = colors[2];
|
||||
surfaceOverlay = colors[3];
|
||||
}
|
||||
}
|
||||
|
||||
[GroupDebug, Button(ButtonSizes.Medium, ButtonStyle.FoldoutButton)]
|
||||
private void SetTextColorSchema(string colorSchema)
|
||||
{
|
||||
if (TryParseColor(colorSchema, 4, out var colors))
|
||||
{
|
||||
textPrimary = colors[0];
|
||||
textSecondary = colors[1];
|
||||
textMuted = colors[2];
|
||||
textDisabled = colors[3];
|
||||
}
|
||||
}
|
||||
|
||||
[GroupDebug, Button(ButtonSizes.Medium, ButtonStyle.FoldoutButton)]
|
||||
private void SetSignalsColorSchema(string colorSchema)
|
||||
{
|
||||
if (TryParseColor(colorSchema, 7, out var colors))
|
||||
{
|
||||
focus = colors[0];
|
||||
selected = colors[1];
|
||||
disabled = colors[2];
|
||||
denied = colors[3];
|
||||
warning = colors[4];
|
||||
danger = colors[5];
|
||||
corruption = colors[6];
|
||||
}
|
||||
}
|
||||
|
||||
[GroupDebug, Button(ButtonSizes.Medium, ButtonStyle.FoldoutButton)]
|
||||
private void SetResourceColorSchema(string colorSchema)
|
||||
{
|
||||
if (TryParseColor(colorSchema, 4, out var colors))
|
||||
{
|
||||
life = colors[0];
|
||||
shield = colors[1];
|
||||
cadence = colors[2];
|
||||
progress = colors[3];
|
||||
}
|
||||
}
|
||||
|
||||
[GroupDebug, Button(ButtonSizes.Medium, ButtonStyle.FoldoutButton)]
|
||||
private void SetLineColorSchema(string colorSchema)
|
||||
{
|
||||
if (TryParseColor(colorSchema, 3, out var colors))
|
||||
{
|
||||
lineSubtle = colors[0];
|
||||
lineActive = colors[1];
|
||||
lineCritical = colors[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9a2dd3bc25546bfb126b9445e977c3c
|
||||
timeCreated: 1783113533
|
||||
Loading…
x
Reference in New Issue
Block a user