First commit for private source control. Older commits available on Github.
This commit is contained in:
50
Assets/Scripts/UI/Codex/CodexCategoryButton.cs
Normal file
50
Assets/Scripts/UI/Codex/CodexCategoryButton.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using BriarQueen.Data.Identifiers;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BriarQueen.UI.Codex
|
||||
{
|
||||
public class CodexCategoryButton : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private Button _button;
|
||||
|
||||
[SerializeField]
|
||||
private Image _selectedBackground;
|
||||
|
||||
public CodexType Category { get; private set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_button != null)
|
||||
_button.onClick.AddListener(HandleClicked);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_button != null)
|
||||
_button.onClick.RemoveListener(HandleClicked);
|
||||
}
|
||||
|
||||
public event Action<CodexType> OnCategoryClicked;
|
||||
|
||||
public void Initialize(CodexType category)
|
||||
{
|
||||
Category = category;
|
||||
|
||||
SetSelected(false);
|
||||
}
|
||||
|
||||
public void SetSelected(bool selected)
|
||||
{
|
||||
if (_selectedBackground != null)
|
||||
_selectedBackground.enabled = selected;
|
||||
}
|
||||
|
||||
private void HandleClicked()
|
||||
{
|
||||
OnCategoryClicked?.Invoke(Category);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/UI/Codex/CodexCategoryButton.cs.meta
Normal file
3
Assets/Scripts/UI/Codex/CodexCategoryButton.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2cfb06e8e46d402e86eb8dc6e9f6c96e
|
||||
timeCreated: 1773684333
|
||||
263
Assets/Scripts/UI/Codex/CodexEntryButton.cs
Normal file
263
Assets/Scripts/UI/Codex/CodexEntryButton.cs
Normal file
@@ -0,0 +1,263 @@
|
||||
using System;
|
||||
using BriarQueen.Framework.Managers.Player.Data;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BriarQueen.UI.Codex
|
||||
{
|
||||
[ExecuteAlways]
|
||||
public class CodexEntryButton : MonoBehaviour
|
||||
{
|
||||
private const float MIN_WIDTH = 300f;
|
||||
private const float MAX_WIDTH = 400f;
|
||||
private const float FIXED_HEIGHT = 70f;
|
||||
|
||||
[SerializeField]
|
||||
private Button _button;
|
||||
|
||||
[SerializeField]
|
||||
private Image _buttonBackgroundImage;
|
||||
|
||||
[SerializeField]
|
||||
private Sprite _defaultSprite;
|
||||
|
||||
[SerializeField]
|
||||
private Sprite _selectedSprite;
|
||||
|
||||
[SerializeField]
|
||||
private TextMeshProUGUI _label;
|
||||
|
||||
[SerializeField]
|
||||
private float _leftPadding = 24f;
|
||||
|
||||
[SerializeField]
|
||||
private float _rightPadding = 24f;
|
||||
|
||||
[SerializeField]
|
||||
private float _extraWidthSafety = 20f;
|
||||
|
||||
[SerializeField]
|
||||
private float _autoSizeMinFontSize = 18f;
|
||||
|
||||
[SerializeField]
|
||||
private bool _debugInEditor = true;
|
||||
|
||||
private bool _defaultSpriteCachedFromImage;
|
||||
|
||||
private string _lastText;
|
||||
private float _lastWidth = -1f;
|
||||
|
||||
public CodexEntrySo Entry { get; private set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
ResolveReferences();
|
||||
CacheDefaultSpriteFromImageIfNeeded();
|
||||
AddButtonListener();
|
||||
RefreshVisuals();
|
||||
ApplyCurrentBackground(false);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void Update()
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
return;
|
||||
|
||||
if (_label == null)
|
||||
return;
|
||||
|
||||
if (_lastText != _label.text)
|
||||
RefreshVisuals();
|
||||
}
|
||||
#endif
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ResolveReferences();
|
||||
CacheDefaultSpriteFromImageIfNeeded();
|
||||
AddButtonListener();
|
||||
RefreshVisuals();
|
||||
ApplyCurrentBackground(false);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
RemoveButtonListener();
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
ResolveReferences();
|
||||
CacheDefaultSpriteFromImageIfNeeded();
|
||||
RefreshVisuals();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
ApplyCurrentBackground(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
public event Action<CodexEntrySo> OnEntryClicked;
|
||||
|
||||
public void Initialize(CodexEntrySo entry)
|
||||
{
|
||||
Entry = entry;
|
||||
|
||||
ResolveReferences();
|
||||
CacheDefaultSpriteFromImageIfNeeded();
|
||||
|
||||
if (_label != null)
|
||||
_label.text = entry != null ? entry.Title : string.Empty;
|
||||
|
||||
RefreshVisuals();
|
||||
SetSelected(false);
|
||||
}
|
||||
|
||||
public void SetSelected(bool selected)
|
||||
{
|
||||
ApplyCurrentBackground(selected);
|
||||
}
|
||||
|
||||
private void HandleClicked()
|
||||
{
|
||||
if (Entry == null)
|
||||
return;
|
||||
|
||||
OnEntryClicked?.Invoke(Entry);
|
||||
}
|
||||
|
||||
private void RefreshVisuals()
|
||||
{
|
||||
ResizeToFitLabel();
|
||||
}
|
||||
|
||||
private void ResizeToFitLabel()
|
||||
{
|
||||
if (_button == null || _label == null)
|
||||
return;
|
||||
|
||||
var buttonRect = _button.GetComponent<RectTransform>();
|
||||
var labelRect = _label.rectTransform;
|
||||
|
||||
if (buttonRect == null || labelRect == null)
|
||||
return;
|
||||
|
||||
StretchLabelToButton(labelRect);
|
||||
|
||||
_label.margin = new Vector4(_leftPadding, _label.margin.y, _rightPadding, _label.margin.w);
|
||||
_label.textWrappingMode = TextWrappingModes.NoWrap;
|
||||
_label.overflowMode = TextOverflowModes.Overflow;
|
||||
_label.enableAutoSizing = false;
|
||||
|
||||
_label.ForceMeshUpdate();
|
||||
|
||||
var preferredSize = _label.GetPreferredValues(_label.text, Mathf.Infinity, Mathf.Infinity);
|
||||
var desiredWidth = preferredSize.x + _leftPadding + _rightPadding + _extraWidthSafety;
|
||||
var targetWidth = Mathf.Clamp(desiredWidth, MIN_WIDTH, MAX_WIDTH);
|
||||
|
||||
var needsAutoSizing = desiredWidth > MAX_WIDTH;
|
||||
|
||||
if (needsAutoSizing)
|
||||
{
|
||||
_label.enableAutoSizing = true;
|
||||
_label.fontSizeMin = _autoSizeMinFontSize;
|
||||
_label.fontSizeMax = _label.fontSize;
|
||||
_label.overflowMode = TextOverflowModes.Truncate;
|
||||
}
|
||||
|
||||
buttonRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, targetWidth);
|
||||
buttonRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, FIXED_HEIGHT);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (_debugInEditor && (!Mathf.Approximately(targetWidth, _lastWidth) || _lastText != _label.text))
|
||||
Debug.Log(
|
||||
$"[CodexEntryButton] '{_label.text}'\n" +
|
||||
$"Preferred: {preferredSize.x:F1} | Desired: {desiredWidth:F1} | Final: {targetWidth:F1}\n" +
|
||||
$"AutoSize: {needsAutoSizing}",
|
||||
this);
|
||||
#endif
|
||||
|
||||
_lastText = _label.text;
|
||||
_lastWidth = targetWidth;
|
||||
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(buttonRect);
|
||||
_label.ForceMeshUpdate();
|
||||
}
|
||||
|
||||
private void StretchLabelToButton(RectTransform labelRect)
|
||||
{
|
||||
labelRect.anchorMin = new Vector2(0f, 0f);
|
||||
labelRect.anchorMax = new Vector2(1f, 1f);
|
||||
labelRect.offsetMin = Vector2.zero;
|
||||
labelRect.offsetMax = Vector2.zero;
|
||||
labelRect.pivot = new Vector2(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
private void ResolveReferences()
|
||||
{
|
||||
if (_buttonBackgroundImage == null && _button != null)
|
||||
_buttonBackgroundImage = _button.GetComponent<Image>();
|
||||
}
|
||||
|
||||
private void CacheDefaultSpriteFromImageIfNeeded()
|
||||
{
|
||||
if (_buttonBackgroundImage == null)
|
||||
return;
|
||||
|
||||
if (_defaultSprite != null)
|
||||
return;
|
||||
|
||||
if (_buttonBackgroundImage.sprite == null)
|
||||
return;
|
||||
|
||||
_defaultSprite = _buttonBackgroundImage.sprite;
|
||||
_defaultSpriteCachedFromImage = true;
|
||||
}
|
||||
|
||||
private void ApplyCurrentBackground(bool selected)
|
||||
{
|
||||
if (_buttonBackgroundImage == null)
|
||||
return;
|
||||
|
||||
Sprite targetSprite = null;
|
||||
|
||||
if (selected && _selectedSprite != null)
|
||||
targetSprite = _selectedSprite;
|
||||
else if (_defaultSprite != null)
|
||||
targetSprite = _defaultSprite;
|
||||
else if (_buttonBackgroundImage.sprite != null) targetSprite = _buttonBackgroundImage.sprite;
|
||||
|
||||
if (targetSprite != null)
|
||||
{
|
||||
_buttonBackgroundImage.enabled = true;
|
||||
_buttonBackgroundImage.sprite = targetSprite;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning(
|
||||
"[CodexEntryButton] No default background sprite is available. " +
|
||||
"Assign _defaultSprite in the inspector or ensure the Image has a sprite on the prefab.",
|
||||
this);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddButtonListener()
|
||||
{
|
||||
if (_button == null)
|
||||
return;
|
||||
|
||||
_button.onClick.RemoveListener(HandleClicked);
|
||||
_button.onClick.AddListener(HandleClicked);
|
||||
}
|
||||
|
||||
private void RemoveButtonListener()
|
||||
{
|
||||
if (_button == null)
|
||||
return;
|
||||
|
||||
_button.onClick.RemoveListener(HandleClicked);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/UI/Codex/CodexEntryButton.cs.meta
Normal file
3
Assets/Scripts/UI/Codex/CodexEntryButton.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fcb40c65f84248078513824345046145
|
||||
timeCreated: 1773684301
|
||||
179
Assets/Scripts/UI/Codex/CodexLocationButton.cs
Normal file
179
Assets/Scripts/UI/Codex/CodexLocationButton.cs
Normal file
@@ -0,0 +1,179 @@
|
||||
using System;
|
||||
using BriarQueen.Data.Identifiers;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BriarQueen.UI.Codex
|
||||
{
|
||||
[ExecuteAlways]
|
||||
public class CodexLocationButton : MonoBehaviour
|
||||
{
|
||||
private const float MIN_WIDTH = 300f;
|
||||
private const float MAX_WIDTH = 400f;
|
||||
private const float FIXED_HEIGHT = 70f;
|
||||
|
||||
[SerializeField]
|
||||
private Button _button;
|
||||
|
||||
[SerializeField]
|
||||
private TextMeshProUGUI _label;
|
||||
|
||||
[SerializeField]
|
||||
private float _leftPadding = 24f;
|
||||
|
||||
[SerializeField]
|
||||
private float _rightPadding = 24f;
|
||||
|
||||
[SerializeField]
|
||||
private float _extraWidthSafety = 20f;
|
||||
|
||||
[SerializeField]
|
||||
private float _autoSizeMinFontSize = 18f;
|
||||
|
||||
[SerializeField]
|
||||
private bool _debugInEditor = true;
|
||||
|
||||
private string _lastText;
|
||||
private float _lastWidth = -1f;
|
||||
|
||||
public Location Location { get; private set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
AddButtonListener();
|
||||
RefreshVisuals();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void Update()
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
return;
|
||||
|
||||
if (_label == null)
|
||||
return;
|
||||
|
||||
if (_lastText != _label.text)
|
||||
RefreshVisuals();
|
||||
}
|
||||
#endif
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
AddButtonListener();
|
||||
RefreshVisuals();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
RemoveButtonListener();
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
RefreshVisuals();
|
||||
}
|
||||
|
||||
public event Action<Location> OnLocationClicked;
|
||||
|
||||
public void Initialize(Location location, string displayText = null)
|
||||
{
|
||||
Location = location;
|
||||
|
||||
if (_label != null)
|
||||
_label.text = string.IsNullOrWhiteSpace(displayText) ? location.ToString() : displayText;
|
||||
|
||||
RefreshVisuals();
|
||||
}
|
||||
|
||||
private void HandleClicked()
|
||||
{
|
||||
OnLocationClicked?.Invoke(Location);
|
||||
}
|
||||
|
||||
private void RefreshVisuals()
|
||||
{
|
||||
ResizeToFitLabel();
|
||||
}
|
||||
|
||||
private void ResizeToFitLabel()
|
||||
{
|
||||
if (_button == null || _label == null)
|
||||
return;
|
||||
|
||||
var buttonRect = _button.GetComponent<RectTransform>();
|
||||
var labelRect = _label.rectTransform;
|
||||
|
||||
if (buttonRect == null || labelRect == null)
|
||||
return;
|
||||
|
||||
StretchLabelToButton(labelRect);
|
||||
|
||||
_label.margin = new Vector4(_leftPadding, _label.margin.y, _rightPadding, _label.margin.w);
|
||||
_label.textWrappingMode = TextWrappingModes.NoWrap;
|
||||
_label.overflowMode = TextOverflowModes.Overflow;
|
||||
_label.enableAutoSizing = false;
|
||||
|
||||
_label.ForceMeshUpdate();
|
||||
|
||||
var preferredSize = _label.GetPreferredValues(_label.text, Mathf.Infinity, Mathf.Infinity);
|
||||
var desiredWidth = preferredSize.x + _leftPadding + _rightPadding + _extraWidthSafety;
|
||||
var targetWidth = Mathf.Clamp(desiredWidth, MIN_WIDTH, MAX_WIDTH);
|
||||
|
||||
var needsAutoSizing = desiredWidth > MAX_WIDTH;
|
||||
|
||||
if (needsAutoSizing)
|
||||
{
|
||||
_label.enableAutoSizing = true;
|
||||
_label.fontSizeMin = _autoSizeMinFontSize;
|
||||
_label.fontSizeMax = _label.fontSize;
|
||||
_label.overflowMode = TextOverflowModes.Truncate;
|
||||
}
|
||||
|
||||
buttonRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, targetWidth);
|
||||
buttonRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, FIXED_HEIGHT);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (_debugInEditor && (!Mathf.Approximately(targetWidth, _lastWidth) || _lastText != _label.text))
|
||||
Debug.Log(
|
||||
$"[CodexLocationButton] '{_label.text}'\n" +
|
||||
$"Preferred: {preferredSize.x:F1} | Desired: {desiredWidth:F1} | Final: {targetWidth:F1}\n" +
|
||||
$"AutoSize: {needsAutoSizing}",
|
||||
this);
|
||||
#endif
|
||||
|
||||
_lastText = _label.text;
|
||||
_lastWidth = targetWidth;
|
||||
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(buttonRect);
|
||||
_label.ForceMeshUpdate();
|
||||
}
|
||||
|
||||
private void StretchLabelToButton(RectTransform labelRect)
|
||||
{
|
||||
labelRect.anchorMin = new Vector2(0f, 0f);
|
||||
labelRect.anchorMax = new Vector2(1f, 1f);
|
||||
labelRect.offsetMin = Vector2.zero;
|
||||
labelRect.offsetMax = Vector2.zero;
|
||||
labelRect.pivot = new Vector2(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
private void AddButtonListener()
|
||||
{
|
||||
if (_button == null)
|
||||
return;
|
||||
|
||||
_button.onClick.RemoveListener(HandleClicked);
|
||||
_button.onClick.AddListener(HandleClicked);
|
||||
}
|
||||
|
||||
private void RemoveButtonListener()
|
||||
{
|
||||
if (_button == null)
|
||||
return;
|
||||
|
||||
_button.onClick.RemoveListener(HandleClicked);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/UI/Codex/CodexLocationButton.cs.meta
Normal file
3
Assets/Scripts/UI/Codex/CodexLocationButton.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2ac52c1bcad4ad3bb23ad8fa61d0e04
|
||||
timeCreated: 1773685516
|
||||
1289
Assets/Scripts/UI/Codex/CodexWindow.cs
Normal file
1289
Assets/Scripts/UI/Codex/CodexWindow.cs
Normal file
File diff suppressed because it is too large
Load Diff
3
Assets/Scripts/UI/Codex/CodexWindow.cs.meta
Normal file
3
Assets/Scripts/UI/Codex/CodexWindow.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 21589b43d12d4df8b6f58a8dba281eac
|
||||
timeCreated: 1773683605
|
||||
Reference in New Issue
Block a user