Handbuch Scroll-Listen entfernt. Handbuch offen und tabs eingefügt. Upgrades eingefügt. "Garage" eingefügt. Anbindung eines echten Gameplaymanager möglich (theoretisch)

This commit is contained in:
2026-10-15 03:24:48 +02:00
parent dadd1fcad0
commit 5486444dde
132 changed files with 55540 additions and 4807 deletions
+28 -44
View File
@@ -19,15 +19,24 @@ namespace DepthsOfGreed.HandbookUI
[SerializeField] private GameObject[] pages;
[SerializeField] private GameObject testTowerPrefab;
[SerializeField] private HandbookTowerCatalog towerCatalog;
[Tooltip("Optional: component implementing IHandbookGameplay. Empty uses the prototype backend.")]
[SerializeField] private MonoBehaviour gameplayBackend;
[Tooltip("Wartezeit nach erfolgreichem Platzieren, bevor das Buch hochfährt.")]
[SerializeField, Min(0)] private float successfulPlacementDelay = 0.5f;
[SerializeField] private float hoverDistance = 115f;
[Header("Tab movement (Build, Statistics, Upgrades, Index)")]
[Tooltip("Distance left per closed tab. -1 automatically uses its width. Rest position is the authored RectTransform position.")]
[SerializeField] private float[] closedTabRevealDistances = { -1f, -1f, -1f, -1f };
[Tooltip("Distance up per open tab. -1 automatically uses its height.")]
[SerializeField] private float[] openTabRevealDistances = { -1f, -1f, -1f, -1f };
[Tooltip("Overlap retained when an automatically sized tab is fully revealed.")]
[SerializeField, Min(0)] private float closedTabOverlap = 10f;
[SerializeField, Min(0)] private float openTabOverlap = 25f;
[SerializeField] private float animationSpeed = 14f;
private readonly string[] titles = { "Bauen", "Statistik", "Upgrades", "Index" };
private Vector2[] closedPositions, openPositions;
private TMP_Text[] closedLabels, openLabels;
private RectTransform activeLayer;
[SerializeField] private RectTransform activeLayer;
private int selected, hoveredClosed = -1, hoveredOpen = -1;
private bool isOpen, bookHovered;
private Vector3 bookScale;
@@ -48,27 +57,19 @@ namespace DepthsOfGreed.HandbookUI
closedPositions = PrepareTabs(closedTabs, out closedLabels, false);
openPositions = PrepareTabs(openTabs, out openLabels, true);
bookScale = bookButton.transform.localScale;
var layer = new GameObject("ActiveTabLayer", typeof(RectTransform));
activeLayer = layer.GetComponent<RectTransform>();
activeLayer.SetParent(openTabsRoot.parent, false);
activeLayer.anchorMin = openTabsRoot.anchorMin;
activeLayer.anchorMax = openTabsRoot.anchorMax;
activeLayer.pivot = openTabsRoot.pivot;
activeLayer.offsetMin = openTabsRoot.offsetMin;
activeLayer.offsetMax = openTabsRoot.offsetMax;
var background = openBook.transform.Find("Background");
if (background) activeLayer.SetSiblingIndex(background.GetSiblingIndex() + 1);
bookButton.onClick.AddListener(() => Open(0));
closeButton.onClick.AddListener(Close);
AddHover(bookButton.gameObject, () => bookHovered = true, () => bookHovered = false);
buildMenu = pages[0].AddComponent<BuildMenuController>();
buildMenu = pages[0].GetComponent<BuildMenuController>();
buildMenu.Initialize(towerCatalog);
placement = gameObject.AddComponent<TestPlacementController>();
placement.Initialize(this, buildMenu, (RectTransform)openBook.transform, testTowerPrefab);
placement = gameObject.GetComponent<TestPlacementController>();
placement.Initialize(this, buildMenu, (RectTransform)openBook.transform, testTowerPrefab, gameplayBackend);
placement.SuccessfulPlacementDelay = successfulPlacementDelay;
buildMenu.Placement = placement;
indexMenu = pages[3].AddComponent<HandbookIndexController>();
indexMenu = pages[3].GetComponent<HandbookIndexController>();
indexMenu.Initialize(towerCatalog);
var upgrades = pages[2].GetComponent<HandbookUpgradesController>();
upgrades.Initialize(placement);
Close();
}
@@ -79,31 +80,9 @@ namespace DepthsOfGreed.HandbookUI
for (int i = 0; i < tabs.Length; i++)
{
int index = i;
if (!opened)
{
var marker = (RectTransform)tabs[i].transform;
marker.sizeDelta = new Vector2(marker.sizeDelta.x + 25f, marker.sizeDelta.y);
marker.anchoredPosition += Vector2.right * 25f;
}
positions[i] = ((RectTransform)tabs[i].transform).anchoredPosition;
labels[i] = tabs[i].GetComponentInChildren<TMP_Text>(true);
if (labels[i])
{
var text = labels[i];
text.text = titles[i];
text.raycastTarget = false;
text.fontSize = opened ? 20 : 18;
text.enableAutoSizing = true;
text.fontSizeMin = 14;
text.fontSizeMax = opened ? 20 : 18;
text.alignment = TextAlignmentOptions.MidlineLeft;
var rect = text.rectTransform;
rect.anchorMin = Vector2.zero;
rect.anchorMax = Vector2.one;
rect.offsetMin = new Vector2(opened ? 65 : 48, 4);
rect.offsetMax = new Vector2(-6, -4);
text.gameObject.SetActive(false);
}
if (labels[i]) labels[i].gameObject.SetActive(false);
tabs[i].onClick.AddListener(() => Open(index));
AddHover(tabs[i].gameObject,
() => { if (opened) hoveredOpen = index; else hoveredClosed = index; },
@@ -143,9 +122,7 @@ namespace DepthsOfGreed.HandbookUI
rect.SetParent(i == selected ? activeLayer : openTabsRoot, false);
}
if (index == 3 && !samePage && indexMenu) indexMenu.ResetForEntry();
if (samePage)
foreach (var scroll in pages[index].GetComponentsInChildren<ScrollRect>(true))
scroll.verticalNormalizedPosition = 1f;
if (samePage && index == 3 && indexMenu) indexMenu.ResetForEntry();
}
public void Close()
@@ -189,11 +166,18 @@ namespace DepthsOfGreed.HandbookUI
bool show = i == hovered || i == active;
var rect = (RectTransform)tabs[i].transform;
// Reveal the full marker while retaining a small overlap with the page.
float distance = Mathf.Clamp(hoverDistance, 0f, Mathf.Max(0f, positions[i].x - 10f));
var target = positions[i] + (show ? Vector2.left * distance : Vector2.zero);
bool opened = tabs == openTabs;
var distances = opened ? openTabRevealDistances : closedTabRevealDistances;
float configured = distances != null && i < distances.Length ? distances[i] : -1f;
float automatic = opened
? Mathf.Max(0f, -positions[i].y - openTabOverlap)
: Mathf.Max(0f, positions[i].x - closedTabOverlap);
float distance = configured >= 0f ? configured : automatic;
var target = positions[i] + (show ? (opened ? Vector2.up : Vector2.left) * distance : Vector2.zero);
rect.anchoredPosition = Vector2.Lerp(rect.anchoredPosition, target, blend);
if (labels[i]) labels[i].gameObject.SetActive(show);
}
}
}
}