You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
4.8 KiB
162 lines
4.8 KiB
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
public class GameState
|
|
{
|
|
private readonly UniQuake uq;
|
|
|
|
private GameObject worldGameObject;
|
|
|
|
private readonly Dictionary<int, Entity> entities = new Dictionary<int, Entity>();
|
|
|
|
public GameState(UniQuake uniQuake)
|
|
{
|
|
uq = uniQuake;
|
|
}
|
|
|
|
public void Destroy()
|
|
{
|
|
DestroyEntities();
|
|
DestroyWorld();
|
|
}
|
|
|
|
public void NewMap(BrushModel worldModel)
|
|
{
|
|
Destroy();
|
|
|
|
worldGameObject = new GameObject(worldModel.Name);
|
|
|
|
// The first sub-model contains all of the static geometry
|
|
var subModel = worldModel.GetSubModel(0);
|
|
var subModelGO = CreateBrushGameObject(subModel);
|
|
subModelGO.transform.SetParent(worldGameObject.transform);
|
|
}
|
|
|
|
private GameObject CreateBrushGameObject(BrushModel.SubModel subModel)
|
|
{
|
|
var subModelGO = new GameObject(subModel.Name);
|
|
|
|
// DEBUG - we'll want to instantiate prefabs for each sub-model and assign materials from a preset collection
|
|
foreach (var surfaceMesh in subModel.SurfaceMeshes)
|
|
{
|
|
var meshGO = new GameObject(surfaceMesh.Mesh.name);
|
|
meshGO.transform.SetParent(subModelGO.transform);
|
|
|
|
var mf = meshGO.AddComponent<MeshFilter>();
|
|
mf.sharedMesh = surfaceMesh.Mesh;
|
|
|
|
var material = new Material(Shader.Find("Universal Render Pipeline/Simple Lit"));
|
|
uint texNum = surfaceMesh.Texture.TextureNum;
|
|
if (uq.GameAssets.TryGetTexture(texNum, out var texture))
|
|
{
|
|
material.mainTexture = texture;
|
|
}
|
|
|
|
var mr = meshGO.AddComponent<MeshRenderer>();
|
|
mr.sharedMaterial = material;
|
|
mr.shadowCastingMode = ShadowCastingMode.Off;
|
|
mr.receiveShadows = false;
|
|
mr.lightProbeUsage = LightProbeUsage.Off;
|
|
mr.reflectionProbeUsage = ReflectionProbeUsage.Off;
|
|
}
|
|
|
|
return subModelGO;
|
|
}
|
|
|
|
private void DestroyWorld()
|
|
{
|
|
if (worldGameObject != null)
|
|
{
|
|
Object.Destroy(worldGameObject);
|
|
worldGameObject = null;
|
|
}
|
|
}
|
|
|
|
public Entity GetEntity(int entityNum)
|
|
{
|
|
entities.TryGetValue(entityNum, out var entity);
|
|
return entity;
|
|
}
|
|
|
|
private Entity GetOrCreateEntity(int entityNum)
|
|
{
|
|
if (!entities.TryGetValue(entityNum, out var entity))
|
|
{
|
|
entity = new Entity(entityNum);
|
|
entities.Add(entityNum, entity);
|
|
}
|
|
|
|
return entity;
|
|
}
|
|
|
|
public void SetEntityAliasModel(int entityNum, string modelName)
|
|
{
|
|
var entity = GetOrCreateEntity(entityNum);
|
|
|
|
if (!uq.GameAssets.TryGetAliasModel(modelName, out var aliasModel))
|
|
{
|
|
Debug.LogWarning($"Unknown alias model name: {modelName}");
|
|
return;
|
|
}
|
|
|
|
entity.SetAliasModel(aliasModel);
|
|
}
|
|
|
|
public void SetEntityBrushModel(int entityNum, string modelName)
|
|
{
|
|
var entity = GetOrCreateEntity(entityNum);
|
|
|
|
if (!uq.GameAssets.TryGetBrushModel(modelName, out var brushModel))
|
|
{
|
|
Debug.LogWarning($"Unknown brush model name: {modelName}");
|
|
return;
|
|
}
|
|
|
|
var brushModelGO = new GameObject(brushModel.Name);
|
|
for (int i = 0; i < brushModel.SubModelCount; ++i)
|
|
{
|
|
var subModelGO = CreateBrushGameObject(brushModel.GetSubModel(i));
|
|
subModelGO.transform.SetParent(brushModelGO.transform);
|
|
}
|
|
|
|
entity.SetBrushModel(brushModelGO);
|
|
}
|
|
|
|
public void SetEntityWorldModel(int entityNum, int subModelNum)
|
|
{
|
|
var entity = GetOrCreateEntity(entityNum);
|
|
|
|
if (!uq.GameAssets.TryGetWorldSubModel(subModelNum, out var subModel))
|
|
{
|
|
Debug.LogWarning($"Invalid world sub-model number: {subModelNum}");
|
|
return;
|
|
}
|
|
|
|
// TODO: these relatively complex world game objects are going to get destroyed and re-created all the time
|
|
// as the player moves through the map and moves in and out of range of these entities. This can and should
|
|
// be done more efficiently by creating the game objects only once and enabling/disabling them on demand.
|
|
var worldModelGO = CreateBrushGameObject(subModel);
|
|
entity.SetWorldModel(worldModelGO);
|
|
}
|
|
|
|
public void RemoveEntity(int entityNum)
|
|
{
|
|
if (entities.TryGetValue(entityNum, out var entity))
|
|
{
|
|
entity.Destroy();
|
|
entities.Remove(entityNum);
|
|
}
|
|
}
|
|
|
|
private void DestroyEntities()
|
|
{
|
|
foreach (var entity in entities.Values)
|
|
{
|
|
entity.Destroy();
|
|
}
|
|
|
|
entities.Clear();
|
|
}
|
|
}
|