OldBlueWater/BlueWater/Assets/Distant Lands/Cozy Weather/Contents/Scripts/Utility/Auxillary/CozyBiome.cs

498 lines
16 KiB
C#
Raw Normal View History

2023-09-13 05:07:40 +00:00
using DistantLands.Cozy.Data;
using System;
using System.Collections.Generic;
using System.Linq;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.Experimental.GraphView;
#endif
using UnityEngine;
namespace DistantLands.Cozy
{
public class CozyBiome : CozyEcosystem
{
public List<Vector3> bounds = new List<Vector3>() { new Vector3(-5, 0, 5), new Vector3(5, 0, 5), new Vector3(5, 0, -5), new Vector3(-5, 0, -5) };
public float height = 10;
public float transitionDistance = 5;
public Color displayColor = new Color(1, 1, 1, 1);
public MeshCollider trigger;
public List<CozyBiomeModule> modules = new List<CozyBiomeModule>();
public
// Start is called before the first frame update
void Start()
{
weatherSphere = CozyWeather.instance;
if (!trigger)
CheckTrigger();
if (Application.isPlaying)
{
weatherSphere.ecosystems.Add(this);
}
}
public void CheckTrigger()
{
trigger = gameObject.AddComponent<MeshCollider>();
trigger.sharedMesh = BuildZoneCollider();
trigger.convex = true;
trigger.isTrigger = true;
}
public Mesh BuildZoneCollider()
{
Mesh mesh = new Mesh();
mesh.name = $"{name} Custom Trigger Mesh";
List<Vector3> verts = new List<Vector3>();
List<int> tris = new List<int>();
foreach (Vector3 i in bounds)
{
verts.Add(i);
verts.Add(new Vector3(i.x, height, i.z));
}
for (int i = 0; i < bounds.Count; i++)
{
if (i == 0)
{
tris.Add(0);
tris.Add(verts.Count - 1);
tris.Add(verts.Count - 2);
tris.Add(0);
tris.Add(1);
tris.Add(verts.Count - 1);
}
else
{
int start = i * 2;
tris.Add(start);
tris.Add(start - 1);
tris.Add(start - 2);
tris.Add(start);
tris.Add(start + 1);
tris.Add(start - 1);
}
}
for (int i = 0; i < verts.Count - 4; i += 2)
{
tris.Add(0);
tris.Add(i + 2);
tris.Add(i + 4);
tris.Add(1);
tris.Add(i + 3);
tris.Add(i + 5);
}
mesh.SetVertices(verts);
mesh.SetTriangles(tris, 0, true);
mesh.RecalculateNormals();
return mesh;
}
private new void Update()
{
base.Update();
weight = GetWeight();
}
public float GetWeight()
{
if (!trigger)
CheckTrigger();
Vector3 closestPoint = trigger.ClosestPoint(weatherSphere.transform.position);
if (weatherSphere.transform.position == closestPoint)
{
return 1;
}
float distToClosestPoint = Vector3.Distance(weatherSphere.transform.position, closestPoint);
return 1 - (Mathf.Clamp(distToClosestPoint, 0, transitionDistance) / transitionDistance);
}
public void OnEnable()
{
AddBiome();
}
public void OnDisable()
{
RemoveBiome();
}
public void AddBiome()
{
weatherSphere.ecosystems.Add(this);
}
public void RemoveBiome()
{
weatherSphere.ecosystems.Remove(this);
}
private void OnDrawGizmos()
{
if (bounds.Count >= 3)
{
for (int i = 0; i < bounds.Count; i++)
{
Gizmos.color = new Color(displayColor.r, displayColor.g, displayColor.b, 0.3f);
Gizmos.DrawSphere(TransformToLocalSpace(bounds[i]), 0.2f);
Vector3 point = Vector3.zero;
if (i == 0)
point = bounds.Last();
else
point = bounds[i - 1];
Gizmos.color = new Color(displayColor.r, displayColor.g, displayColor.b, 1);
Gizmos.DrawLine(TransformToLocalSpace(bounds[i]), TransformToLocalSpace(point));
}
for (int i = 0; i < bounds.Count; i++)
{
Gizmos.color = new Color(displayColor.r, displayColor.g, displayColor.b, 0.5f);
Gizmos.DrawSphere(TransformToLocalSpace(bounds[i]) + Vector3.up * height, 0.2f);
Vector3 point = Vector3.zero;
if (i == 0)
point = bounds.Last();
else
point = bounds[i - 1];
Gizmos.color = new Color(displayColor.r, displayColor.g, displayColor.b, 1);
Gizmos.DrawLine(TransformToLocalSpace(bounds[i]) + Vector3.up * height, TransformToLocalSpace(point) + Vector3.up * height);
Gizmos.DrawLine(TransformToLocalSpace(bounds[i]), TransformToLocalSpace(bounds[i]) + Vector3.up * height);
Gizmos.color = new Color(displayColor.r, displayColor.g, displayColor.b, 0.3f);
Gizmos.DrawLine((TransformToLocalSpace(bounds[i]) + TransformToLocalSpace(point)) / 2,
(TransformToLocalSpace(bounds[i]) + TransformToLocalSpace(point)) / 2 + Vector3.up * height);
}
Gizmos.DrawMesh(trigger.sharedMesh, -1, transform.position, Quaternion.identity, Vector3.one);
}
}
private Vector3 TransformToLocalSpace(Vector3 pos)
{
Vector3 i = pos.x * transform.right + pos.y * transform.up + pos.z * transform.forward;
i += transform.position;
return i;
}
void Reset()
{
forecastProfile = Resources.Load("Profiles/Forecast Profiles/Complex Forecast Profile") as ForecastProfile;
currentWeather = Resources.Load("Profiles/Weather Profiles/Partly Cloudy") as WeatherProfile;
climateProfile = Resources.Load("Profiles/Climate Profiles/Default Climate") as ClimateProfile;
}
public CozyBiomeModule GetModule(Type type)
{
foreach (CozyBiomeModule j in modules)
if (j.GetType() == type)
return j;
return null;
}
public T GetModule<T>() where T : CozyBiomeModule
{
Type type = typeof(T);
foreach (CozyBiomeModule j in modules)
if (j.GetType() == type)
return j as T;
return null;
}
public void InitializeModule(Type module)
{
if (GetModule(module))
return;
CozyBiomeModule mod = (CozyBiomeModule)gameObject.AddComponent(module);
if (!mod.CheckBiome())
{
DestroyImmediate(mod);
return;
}
mod.biome = this;
mod.AddBiome();
modules.Add(mod);
}
public void RemoveModule(Type module)
{
if (!GetModule(module))
return;
CozyBiomeModule mod = modules.Find(x => x.GetType() == module);
mod.RemoveBiome();
modules.Remove(mod);
}
}
#if UNITY_EDITOR
[CanEditMultipleObjects]
[CustomEditor(typeof(CozyBiome))]
public class CozyBiomeEditor : Editor
{
protected static bool weatherFoldout;
protected static bool biomeFoldout;
protected static bool boundsFoldout;
protected static bool infoFoldout;
public CozyBiome biome;
public CozyWeather weatherSphere;
public List<Type> mods;
public List<E_BiomeModule> editors = new List<E_BiomeModule>();
public void OnEnable()
{
biome = (CozyBiome)target;
weatherSphere = CozyWeather.instance;
}
public void CacheEditors()
{
editors.Clear();
foreach (CozyBiomeModule module in biome.modules)
editors.Add(Editor.CreateEditor(module) as E_BiomeModule);
}
public override void OnInspectorGUI()
{
serializedObject.Update();
if (editors.Count != biome.modules.Count)
CacheEditors();
EditorGUI.indentLevel = 0;
GUIStyle foldoutStyle = new GUIStyle(GUI.skin.GetStyle("toolbarPopup"));
foldoutStyle.fontStyle = FontStyle.Bold;
foldoutStyle.margin = new RectOffset(30, 10, 5, 5);
weatherFoldout = EditorGUILayout.BeginFoldoutHeaderGroup(weatherFoldout, " Weather and Forecast", foldoutStyle);
EditorGUILayout.EndFoldoutHeaderGroup();
if (weatherFoldout)
{
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(serializedObject.FindProperty("weatherSelectionMode"));
EditorGUILayout.Space();
if ((CozyEcosystem.EcosystemStyle)serializedObject.FindProperty("weatherSelectionMode").intValue == CozyEcosystem.EcosystemStyle.forecast)
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("currentWeather"));
EditorGUILayout.Space();
EditorGUILayout.PropertyField(serializedObject.FindProperty("forecastProfile"));
EditorGUILayout.Space();
EditorGUI.indentLevel++;
if (serializedObject.FindProperty("forecastProfile").objectReferenceValue)
CreateEditor(serializedObject.FindProperty("forecastProfile").objectReferenceValue).OnInspectorGUI();
else
{
EditorGUILayout.HelpBox("Assign a forecast profile!", MessageType.Error);
}
EditorGUI.indentLevel--;
}
else
EditorGUILayout.PropertyField(serializedObject.FindProperty("currentWeather"));
EditorGUILayout.Space();
EditorGUI.indentLevel--;
}
biomeFoldout = EditorGUILayout.BeginFoldoutHeaderGroup(biomeFoldout, " Climate", foldoutStyle);
EditorGUILayout.EndFoldoutHeaderGroup();
if (biomeFoldout)
{
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(serializedObject.FindProperty("climateProfile"));
EditorGUILayout.Space();
EditorGUI.indentLevel++;
if (serializedObject.FindProperty("climateProfile").objectReferenceValue)
CreateEditor(serializedObject.FindProperty("climateProfile").objectReferenceValue).OnInspectorGUI();
else
{
EditorGUILayout.HelpBox("Assign a climate profile!", MessageType.Error);
}
EditorGUI.indentLevel--;
EditorGUILayout.Space();
EditorGUILayout.PropertyField(serializedObject.FindProperty("localTemperatureFilter"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("localPrecipitationFilter"));
EditorGUI.indentLevel--;
}
boundsFoldout = EditorGUILayout.BeginFoldoutHeaderGroup(boundsFoldout, " Bounds and Trigger", foldoutStyle);
EditorGUILayout.EndFoldoutHeaderGroup();
if (boundsFoldout)
{
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(serializedObject.FindProperty("bounds"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("height"));
if (EditorGUI.EndChangeCheck())
if (biome.trigger)
biome.trigger.sharedMesh = biome.BuildZoneCollider();
else
biome.CheckTrigger();
EditorGUILayout.Space();
EditorGUILayout.PropertyField(serializedObject.FindProperty("displayColor"));
EditorGUILayout.Space();
EditorGUILayout.PropertyField(serializedObject.FindProperty("transitionDistance"));
EditorGUI.indentLevel--;
}
foreach (E_BiomeModule module in editors)
module.DrawInlineUI(foldoutStyle);
infoFoldout = EditorGUILayout.BeginFoldoutHeaderGroup(infoFoldout, " Current Information", foldoutStyle);
EditorGUILayout.EndFoldoutHeaderGroup();
if (infoFoldout)
{
EditorGUI.indentLevel++;
EditorGUILayout.HelpBox("Currently it is " + Mathf.Round(biome.currentTemperature) + "F or " + Mathf.Round(biome.currentTemperatureCelsius) + "C with a precipitation chance of " + Mathf.Round(biome.currentPrecipitation) + "%.\n" +
"Temperatures will " + (biome.currentTemperature > biome.GetTemperature(false, weatherSphere.perennialProfile.ticksPerDay) ? "drop" : "rise") + " tomorrow, bringing the temprature to " + Mathf.Round(biome.GetTemperature(false, weatherSphere.perennialProfile.ticksPerDay)) + "F", MessageType.None);
EditorGUILayout.Space();
if (biome.currentForecast.Count == 0)
{
EditorGUILayout.HelpBox("No forecast information yet!", MessageType.None);
}
else
{
EditorGUILayout.HelpBox("Currently it is " + biome.weatherSphere.currentWeather.name, MessageType.None);
for (int i = 0; i < biome.currentForecast.Count; i++)
{
EditorGUILayout.HelpBox("Starting at " + biome.weatherSphere.perennialProfile.FormatTime(false, biome.currentForecast[i].startTicks) + " the weather will change to " +
biome.currentForecast[i].profile.name + " for " + Mathf.Round(biome.currentForecast[i].weatherProfileDuration) +
" ticks or unitl " + biome.weatherSphere.perennialProfile.FormatTime(false, biome.currentForecast[i].endTicks) + ".", MessageType.None, true);
EditorGUILayout.Space(2);
}
}
foreach (E_BiomeModule module in editors)
module.DrawReports();
EditorGUI.indentLevel--;
}
if (GUILayout.Button("Add Modules"))
{
if (mods == null)
mods = EditorUtilities.ResetBiomeModulesList();
if (mods.Contains(typeof(CozyBiomeModule)))
mods.Remove(typeof(CozyBiomeModule));
foreach (CozyBiomeModule a in biome.modules)
if (mods.Contains(a.GetType()))
mods.Remove(a.GetType());
BiomeModulesSearchProvider provider = ScriptableObject.CreateInstance<BiomeModulesSearchProvider>();
provider.modules = mods;
provider.biome = biome;
SearchWindow.Open(new SearchWindowContext(GUIUtility.GUIToScreenPoint(Event.current.mousePosition)), provider);
}
serializedObject.ApplyModifiedProperties();
}
}
#endif
}