VanguardReMaster/client/Assets/Vanguard/Runtime/App/SceneEnvironment.cs

252 lines
10 KiB
C#

using UnityEngine;
namespace Vanguard.App
{
public enum SceneTheme
{
Login,
Lobby,
Collection,
DeckBuilder,
Battle,
}
/// <summary>
/// Простой 3D-фон для экранов: камера, свет, пол и тематические
/// примитивы. Это заготовка под будущие модели и арт; UI остаётся
/// отдельным Canvas-слоем.
/// </summary>
public static class SceneEnvironment
{
private const string RootName = "Vanguard 3D Environment";
public static void Build(SceneTheme theme)
{
if (GameObject.Find(RootName) != null)
return;
var root = new GameObject(RootName);
var palette = GetPalette(theme);
SetCamera(theme, palette);
SetLight(theme, palette);
RenderSettings.ambientLight = palette.Ambient;
RenderSettings.fog = true;
RenderSettings.fogMode = FogMode.Exponential;
RenderSettings.fogColor = palette.Background;
RenderSettings.fogDensity = 0.012f;
CreateFloor(root.transform, palette);
Decorate(theme, root.transform, palette);
}
private static void SetCamera(SceneTheme theme, ScenePalette palette)
{
var camera = Camera.main;
if (camera == null)
{
var go = new GameObject("Main Camera");
go.tag = "MainCamera";
camera = go.AddComponent<Camera>();
}
camera.clearFlags = CameraClearFlags.SolidColor;
camera.backgroundColor = palette.Background;
camera.fieldOfView = 52f;
camera.transform.position = theme == SceneTheme.Battle
? new Vector3(0f, 7.5f, -13f)
: new Vector3(0f, 3.2f, -10f);
camera.transform.rotation = theme == SceneTheme.Battle
? Quaternion.Euler(28f, 0f, 0f)
: Quaternion.Euler(12f, 0f, 0f);
}
private static void SetLight(SceneTheme theme, ScenePalette palette)
{
var light = Object.FindAnyObjectByType<Light>();
if (light == null)
{
var go = new GameObject("Directional Light");
light = go.AddComponent<Light>();
light.type = LightType.Directional;
}
light.color = palette.Light;
light.intensity = theme == SceneTheme.Battle ? 1.15f : 0.9f;
light.transform.rotation = Quaternion.Euler(48f, -32f, 0f);
light.shadows = LightShadows.Soft;
}
private static void CreateFloor(Transform root, ScenePalette palette)
{
var floor = GameObject.CreatePrimitive(PrimitiveType.Plane);
floor.name = "Floor";
floor.transform.SetParent(root, false);
floor.transform.localScale = new Vector3(4f, 1f, 4f);
floor.transform.position = new Vector3(0f, -0.02f, 2f);
Paint(floor, palette.Floor, 0f);
}
private static void Decorate(SceneTheme theme, Transform root, ScenePalette palette)
{
switch (theme)
{
case SceneTheme.Login:
Cube(root, "Column L", new Vector3(-5.5f, 2.4f, 2f), new Vector3(1f, 5f, 1f), palette.Structure);
Cube(root, "Column R", new Vector3(5.5f, 2.4f, 2f), new Vector3(1f, 5f, 1f), palette.Structure);
Cube(root, "Backdrop", new Vector3(0f, 3.2f, 8f), new Vector3(16f, 7f, 0.4f), palette.Structure);
Cube(root, "Emblem", new Vector3(0f, 3.4f, 7.7f), new Vector3(2.4f, 2.4f, 0.2f), palette.Accent, 1.6f);
break;
case SceneTheme.Lobby:
for (var i = -1; i <= 1; i += 2)
{
Cube(root, "Pillar " + i, new Vector3(i * 7f, 2.5f, 3f), new Vector3(1.2f, 5f, 1.2f), palette.Structure);
Cube(root, "Table " + i, new Vector3(i * 3.6f, 0.55f, 0.5f), new Vector3(3f, 1f, 3f), palette.Structure);
}
Cube(root, "Back Wall", new Vector3(0f, 3f, 9f), new Vector3(18f, 6f, 0.5f), palette.Structure);
Cube(root, "Lobby Light", new Vector3(0f, 5.2f, 4f), new Vector3(6f, 0.2f, 1f), palette.Accent, 1.8f);
break;
case SceneTheme.Collection:
for (var i = -2; i <= 2; i++)
{
Cube(root, "Shelf " + i, new Vector3(i * 3.2f, 1.6f, 6.5f), new Vector3(2.2f, 3.2f, 0.5f), palette.Structure);
Cube(root, "Shelf Glow " + i, new Vector3(i * 3.2f, 3.35f, 6.2f), new Vector3(2.2f, 0.1f, 0.5f), palette.Accent, 1.2f);
}
Cube(root, "Table", new Vector3(0f, 0.4f, 1.5f), new Vector3(7f, 0.8f, 4f), palette.Structure);
break;
case SceneTheme.DeckBuilder:
Cube(root, "Table", new Vector3(0f, 0.5f, 2f), new Vector3(11f, 1f, 6f), palette.Structure);
Cube(root, "Deck Stack", new Vector3(-3.8f, 1.3f, 3.2f), new Vector3(1.5f, 1.4f, 2.2f), palette.Accent, 0.8f);
Cube(root, "Mat", new Vector3(1.5f, 1.06f, 3f), new Vector3(5f, 0.08f, 3.5f), palette.Floor);
break;
case SceneTheme.Battle:
Cube(root, "Battle Table", new Vector3(0f, 0.2f, 1.5f), new Vector3(13f, 0.4f, 7f), palette.Structure);
Cube(root, "Center Line", new Vector3(0f, 0.44f, 1.5f), new Vector3(13f, 0.04f, 0.12f), palette.Accent, 1.2f);
for (var i = 0; i < 5; i++)
{
var x = (i - 2) * 2.2f;
Cube(root, "Zone " + i, new Vector3(x, 0.44f, 3.1f), new Vector3(1.8f, 0.04f, 2.2f), palette.Zone, 0.5f);
Cube(root, "Enemy Zone " + i, new Vector3(x, 0.44f, -0.1f), new Vector3(1.8f, 0.04f, 2.2f), palette.EnemyZone, 0.5f);
}
break;
}
}
private static void Cube(
Transform parent,
string name,
Vector3 position,
Vector3 scale,
Color color,
float emission = 0f)
{
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.name = name;
cube.transform.SetParent(parent, false);
cube.transform.position = position;
cube.transform.localScale = scale;
Paint(cube, color, emission);
}
private static void Paint(GameObject target, Color color, float emission)
{
var renderer = target.GetComponent<Renderer>();
if (renderer == null)
return;
var shader = Shader.Find("Universal Render Pipeline/Lit");
if (shader == null)
shader = Shader.Find("Standard");
var material = new Material(shader);
if (material.HasProperty("_BaseColor"))
material.SetColor("_BaseColor", color);
else if (material.HasProperty("_Color"))
material.color = color;
if (emission > 0f)
{
material.EnableKeyword("_EMISSION");
material.SetColor("_EmissionColor", color * emission);
}
renderer.material = material;
}
private static ScenePalette GetPalette(SceneTheme theme)
{
switch (theme)
{
case SceneTheme.Login:
return new ScenePalette(
new Color(0.015f, 0.02f, 0.045f),
new Color(0.035f, 0.045f, 0.075f),
new Color(0.10f, 0.12f, 0.18f),
new Color(0.20f, 0.42f, 0.95f),
new Color(0.75f, 0.82f, 1f),
new Color(0.04f, 0.05f, 0.09f),
new Color(0.10f, 0.20f, 0.40f),
new Color(0.40f, 0.12f, 0.10f));
case SceneTheme.Battle:
return new ScenePalette(
new Color(0.035f, 0.025f, 0.03f),
new Color(0.08f, 0.06f, 0.07f),
new Color(0.18f, 0.12f, 0.12f),
new Color(0.85f, 0.55f, 0.24f),
new Color(1f, 0.88f, 0.66f),
new Color(0.05f, 0.08f, 0.14f),
new Color(0.10f, 0.22f, 0.42f),
new Color(0.42f, 0.10f, 0.10f));
default:
return new ScenePalette(
new Color(0.02f, 0.03f, 0.055f),
new Color(0.06f, 0.075f, 0.11f),
new Color(0.12f, 0.15f, 0.20f),
new Color(0.30f, 0.55f, 0.85f),
new Color(0.82f, 0.88f, 1f),
new Color(0.08f, 0.11f, 0.17f),
new Color(0.16f, 0.30f, 0.52f),
new Color(0.38f, 0.12f, 0.12f));
}
}
private sealed class ScenePalette
{
public ScenePalette(
Color background,
Color floor,
Color structure,
Color accent,
Color light,
Color ambient,
Color zone,
Color enemyZone)
{
Background = background;
Floor = floor;
Structure = structure;
Accent = accent;
Light = light;
Ambient = ambient;
Zone = zone;
EnemyZone = enemyZone;
}
public Color Background { get; }
public Color Floor { get; }
public Color Structure { get; }
public Color Accent { get; }
public Color Light { get; }
public Color Ambient { get; }
public Color Zone { get; }
public Color EnemyZone { get; }
}
}
}