using System.Collections.Generic; using UnityEngine; namespace _Project.Scripts.LevelGenerating { // ===================================================================== // Генератор, который оформляет одну комнату после того, как построены её меши. // Специальные комнаты (лифт, старт) получают свои реализации, // обычные - универсальный ThemedRoomGenerator. // ===================================================================== public interface IRoomGenerator { bool Supports(Room room); void Generate(RoomView view, FloorData floor, RoomTheme theme); } // Универсальный генератор: материалы из темы и сетка светильников под потолком. // Позже сюда добавится расстановка предметов по правилам темы. public class ThemedRoomGenerator : IRoomGenerator { public bool Supports(Room room) => true; public void Generate(RoomView view, FloorData floor, RoomTheme theme) { if (theme == null) { Debug.LogWarning($"{view.name}: для комнаты не назначена тема"); return; } ApplyMaterial(view.FloorRenderers, theme.floorMaterial); ApplyMaterial(view.WallRenderers, theme.wallMaterial); ApplyMaterial(view.CeilingRenderers, theme.ceilingMaterial); if (theme.lightConfig != null) { CreateLights(view, theme.lightConfig); } } private static void ApplyMaterial(List renderers, Material mat) { if (mat == null) return; // остаётся материал префаба foreach (var r in renderers) r.sharedMaterial = mat; } // Сетка светильников: спавнит префаб из RoomLightConfig и применяет параметры private static void CreateLights(RoomView view, RoomLightConfig config) { Vector3 size = view.SizeMeters; Vector3 origin = view.OriginMeters; float spacing = Mathf.Max(0.5f, config.spacing); int nx = Mathf.Max(1, Mathf.CeilToInt(size.x / spacing)); int nz = Mathf.Max(1, Mathf.CeilToInt(size.z / spacing)); float y = view.Height - config.ceilingDrop; var lightsRoot = new GameObject("Lights").transform; lightsRoot.SetParent(view.transform, false); Quaternion rot = Quaternion.Euler(config.rotationOffset); for (int ix = 0; ix < nx; ix++) { for (int iz = 0; iz < nz; iz++) { Vector3 pos = origin + new Vector3( (ix + 0.5f) / nx * size.x, y, (iz + 0.5f) / nz * size.z); GameObject lightGo; if (config.lightPrefab != null) { lightGo = Object.Instantiate(config.lightPrefab, pos, rot, lightsRoot); lightGo.name = $"{config.lightPrefab.name}_{ix}_{iz}"; } else { // Запасной вариант, если префаб забыли назначить в SO lightGo = new GameObject($"FallbackLight_{ix}_{iz}"); lightGo.transform.SetParent(lightsRoot, false); lightGo.transform.SetPositionAndRotation(pos, rot); var fallbackLight = lightGo.AddComponent(); fallbackLight.type = LightType.Point; } // Если включена перезапись параметров (или сработал запасной вариант без префаба) if (config.overrideLightParameters || config.lightPrefab == null) { var lights = lightGo.GetComponentsInChildren(true); foreach (var l in lights) { l.color = config.color; l.intensity = config.intensity; l.range = config.range; l.shadows = config.shadows; } } } } } } }