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.
 
 
 
 
 

157 lines
4.5 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();
Resources.UnloadUnusedAssets();
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);
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 mr = meshGO.AddComponent<MeshRenderer>();
uq.CurrentStyle.SetupWorldModelRenderer(mr); // TODO FIXME This is wrong for brush model entities
uint texNum = surfaceMesh.Texture.TextureNum;
if (uq.GameAssets.TryGetTexture(texNum, out var texture))
{
uq.CurrentStyle.SetWorldModelTextures(mr.material, texture, null, null);
}
}
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, uq.CurrentStyle);
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();
}
}