106 lines
4.7 KiB
C#
106 lines
4.7 KiB
C#
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);
|
||
RuntimeRoomLightmapBaker.BakeRoom(view, theme.lightConfig); // <-- ЗАПЕКАЕМ СВЕТ НА ЛЕТУ!
|
||
}
|
||
}
|
||
|
||
private static void ApplyMaterial(List<Renderer> 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<Light>();
|
||
fallbackLight.type = LightType.Point;
|
||
}
|
||
|
||
// Если включена перезапись параметров (или сработал запасной вариант без префаба)
|
||
if (config.overrideLightParameters || config.lightPrefab == null)
|
||
{
|
||
var lights = lightGo.GetComponentsInChildren<Light>(true);
|
||
foreach (var l in lights)
|
||
{
|
||
l.color = config.color;
|
||
l.intensity = config.intensity;
|
||
l.range = config.range;
|
||
l.shadows = config.shadows;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} |