Files
SixShopSimulator/Assets/Scripts/Shop/PackageDisplay.cs
T
svenm_adminandClaude Sonnet 5 9eb588e491 feat(shop): configurable package display rotation, pocoregal shelf model
Add _displayRotationEuler to Lieferkarton/ShelfSlot so package prefabs
with a non-upright export orientation can be corrected per-container
without touching PackageDisplay code. Fixes a bug where flying packages
landed with a different rotation than the resting shelf display
(PlayerCarry used the raw shelf transform instead of
ShelfSlot.GetSlotWorldRotation()).

Also adds the pocoregal shelf model (Blender export) and its materials,
places it in the Shop scene, registers ShelfSlot as a network prefab,
and rescales EmptyBox. See docs/PACKAGE_DISPLAY_SETUP.md for the
display-grid setup/troubleshooting reference.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 16:13:32 +02:00

85 lines
3.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections.Generic;
using UnityEngine;
namespace AfterHours.Shop
{
/// <summary>
/// Zeigt eine Stückzahl als einzelne Verpackungs-Prefabs unter einem
/// Wurzel-Transform an (Regalfach, Lieferkarton) ordentlich in einem
/// Raster (Spalten x Reihen) gestapelt, weitere Lagen stapeln sich nach
/// oben. Rein kosmetisch, läuft auf jedem Peer. Baut bei Mengenänderung
/// nur das Delta neu, nicht die komplette Anzeige wichtig beim
/// Stück-für-Stück-Ausschütten.
/// </summary>
public sealed class PackageDisplay
{
private readonly Transform _root;
private readonly int _columns;
private readonly int _rows;
private readonly Vector3 _spacing;
private readonly Quaternion _rotation;
private readonly List<GameObject> _instances = new();
private GameObject _prefab;
public PackageDisplay(Transform root, int columns, int rows, Vector3 spacing, Vector3 rotationEuler = default)
{
_root = root;
_columns = Mathf.Max(1, columns);
_rows = Mathf.Max(1, rows);
_spacing = spacing;
_rotation = Quaternion.Euler(rotationEuler);
}
/// <summary>Baut die Anzeige auf <paramref name="count"/> Instanzen an (gedeckelt bei maxVisible).</summary>
public void SetTarget(GameObject prefab, int count, int maxVisible)
{
if (_root == null) return;
if (prefab != _prefab)
{
Clear();
_prefab = prefab;
}
if (_prefab == null) return;
int target = Mathf.Clamp(count, 0, Mathf.Max(0, maxVisible));
while (_instances.Count < target)
{
var instance = Object.Instantiate(_prefab, _root);
instance.transform.localPosition = SlotLocalPosition(_instances.Count);
instance.transform.localRotation = _rotation;
_instances.Add(instance);
}
while (_instances.Count > target)
{
int last = _instances.Count - 1;
if (_instances[last] != null) Object.Destroy(_instances[last]);
_instances.RemoveAt(last);
}
}
/// <summary>Lokale Rasterposition für einen Index auch als Flug-Ziel genutzt (siehe PlayerCarry).</summary>
public Vector3 SlotLocalPosition(int index)
{
int perLayer = _columns * _rows;
int layer = index / perLayer;
int rem = index % perLayer;
int row = rem / _columns;
int col = rem % _columns;
return new Vector3(col * _spacing.x, layer * _spacing.y, row * _spacing.z);
}
public void Clear()
{
foreach (var instance in _instances)
if (instance != null) Object.Destroy(instance);
_instances.Clear();
_prefab = null;
}
}
}