From ba1688ebbfe8160c2f49d53f5e7a492a0989c339 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sun, 12 Jun 2022 18:49:19 +0300 Subject: [PATCH] initial config loading system, shadows cvar, assetmanager --- Content/Materials/SimpleMapMaterial.flax | Bin 34424 -> 34674 bytes Content/Materials/SkyMaterial.flax | Bin 30453 -> 30453 bytes Content/Materials/ViewModelMaterial.flax | Bin 6149 -> 6149 bytes Content/Materials/WeaponMaterial.flax | Bin 32740 -> 32740 bytes Content/Materials/dev/dev_128_gray.flax | Bin 814 -> 939 bytes Content/Materials/dev/dev_128_green.flax | Bin 884 -> 939 bytes .../Materials/interface/crosshairs/cross.flax | Bin 15577 -> 15577 bytes Content/Materials/missing.flax | Bin 30648 -> 30648 bytes .../GameSettings}/GameplayGlobals.flax | Bin 530 -> 570 bytes Content/config.cfg | 2 + Source/Game/AudioManager.cs | 3 +- Source/Game/Console/Config.cs | 32 +++++++++++ Source/Game/Console/ConfigParser.cs | 39 ++++++++++++++ Source/Game/Console/Console.cs | 19 +++++-- Source/Game/Console/EngineSubsystem.cs | 38 +++++++------ Source/Game/GameMode/GameModeManager.cs | 3 +- Source/Game/Level/Q3MapImporter.cs | 50 +++++++++++++----- Source/Game/Utility/AssetManager.cs | 20 +++++++ 18 files changed, 168 insertions(+), 38 deletions(-) rename Content/{ => Settings/GameSettings}/GameplayGlobals.flax (56%) create mode 100644 Content/config.cfg create mode 100644 Source/Game/Console/Config.cs create mode 100644 Source/Game/Console/ConfigParser.cs create mode 100644 Source/Game/Utility/AssetManager.cs diff --git a/Content/Materials/SimpleMapMaterial.flax b/Content/Materials/SimpleMapMaterial.flax index f4d42607c0111817df9e936755124db31951f3fd..9b396068f6f5048dc74539450aaba530a98430d6 100644 GIT binary patch delta 18020 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 diff --git a/Content/Materials/SkyMaterial.flax b/Content/Materials/SkyMaterial.flax index 14812725e0837912a178b3d44641c6b2a71e752f..46ba9d5983ea0a85af20bbeeb30213a2ee266059 100644 GIT binary patch delta 23 fcmezRmhtOb#tj=78E0(X$at5D(Q$J>OIi^Cj!z0@ delta 23 fcmezRmhtOb#tj=78K-aF$at5D(PeW#OIi^Cj#LU~ diff --git a/Content/Materials/ViewModelMaterial.flax b/Content/Materials/ViewModelMaterial.flax index fa8cf2b1f24c7445caced6be6c4569fea030a244..66db88e883da2227f6908431d701c37deaff45b3 100644 GIT binary patch delta 21 dcmZoQXf@cdfst{>=8cS(m>C^6x3D$}0RUP=2e1GD delta 21 dcmZoQXf@cdfst|g=8cS(m>FF*x3D$}0RUP_2eJSF diff --git a/Content/Materials/WeaponMaterial.flax b/Content/Materials/WeaponMaterial.flax index 50df83c70f247183c621785967a1697020cfe81e..efaaf6c972905d1e3f473eb277f42b9a110130cf 100644 GIT binary patch delta 84 zcmV-a0IUDx{{iIx0kE(E0hqI~0W<*+`yB2cTw+2*xi*0ky+5T|v-JXZ1`SlEDZ+G< q7Q_Gm0004#j|dpEkqJ5h3*8B8L#(Qq!vH%elhz760YS493(<6__8-## delta 84 zcmV-a0IUDx{{iIx0kE(E0hhC}0W<*+tW(tvaZ?#ZwOb_)ep7EMv-JXZ1`Th`JHi%K q7sLPn0004#j|dpEkqJ5h3$>rrLy6=T!kW}Vlhz760YtMC3(<6R_aG1e diff --git a/Content/Materials/dev/dev_128_gray.flax b/Content/Materials/dev/dev_128_gray.flax index c00d883085d1f25db961a595eab622bf388b086d..dcd1f2719729df8145b8857d2554f4901b2a6972 100644 GIT binary patch delta 161 zcmZ3-wwisy4#t}scWN^-vQK`>Xv)Um!oa}bGFgG?SUscn+7mP9ym{%fEAq$X^(LMh z7#aD1l7BRgX?)YTsc}c+sKyVCD;ftiE@&JF@~!~I7&sUhgtqjRS|5IF?LChzaFVBL z^-Tr_khW(U*MJId1MyUipFri8H0}bm-T{hS(qQ0WNPcz7VRoXOPk)4IP5REgGQ#YW IUog1=0RPHA{Qv*} delta 36 scmZ3@zK(6e4#t>`JGB`ZStmbbG-YeBV_;~oo2ORdP6ob2gLx>@+suQW-p0RavG008_b z#whkE*(ls7#VGhF)F{Cy&?v_!+$hv2*(d-A000uSj&(c3<2y^922qkpC41SE_W~mn b3;<*5%0Qc8K1`2THGF5ey&Mw0Ra&bI0mfk!`^&Iq*F=(dHWyVLnWcST%fSxxE|{29sq2MnRPrIsgCw diff --git a/Content/Materials/interface/crosshairs/cross.flax b/Content/Materials/interface/crosshairs/cross.flax index 2bf73be91aaf1174d628bff404912b5f704f7d63..5a104666b4754fcc7fb7dcf1ca1b05510e3fa588 100644 GIT binary patch delta 21 dcmcavd9!lE21dpin>R9gi!wTH{wsDz6##JS32guX delta 21 dcmcavd9!lE21dr|n>R9gi!!=w{wsDz6##JX32y)Z diff --git a/Content/Materials/missing.flax b/Content/Materials/missing.flax index cacfde069bb4e1176ce4768969ee9c1c6c059da2..75850b8733067d52c7698a7403dfb5706550f4e9 100644 GIT binary patch delta 23 fcmdn-o^i)}#tj=78E0(X$f(53=(za`%abAif9DDK delta 23 fcmdn-o^i)}#tj=78K-aF$f(53=(70=%abAif9whR diff --git a/Content/GameplayGlobals.flax b/Content/Settings/GameSettings/GameplayGlobals.flax similarity index 56% rename from Content/GameplayGlobals.flax rename to Content/Settings/GameSettings/GameplayGlobals.flax index c57f57054ffb18534d9490873c905663e0188387..fca84a5e77c8e080032c2c9c80e94faf258d7e37 100644 GIT binary patch delta 51 zcmbQlvWsQH4#sH{cfMw1nY@%SM3$F(Path.Combine(audioBasePath, soundName + ".flax")); if (audioClip != null) { diff --git a/Source/Game/Console/Config.cs b/Source/Game/Console/Config.cs new file mode 100644 index 0000000..eab236c --- /dev/null +++ b/Source/Game/Console/Config.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; + +namespace Game +{ + public class Config + { + private Dictionary dictionary = new Dictionary(); + + public Config() + { + } + + public string this[string key] + { + get => dictionary[key]; + set => dictionary[key] = value; + } + + public string[] GetLines() + { + string[] lines = new string[dictionary.Count]; + int lineIndex = 0; + foreach (var kvp in dictionary) + { + lines[lineIndex] = $"{kvp.Key} {kvp.Value}"; + lineIndex++; + } + + return lines; + } + } +} \ No newline at end of file diff --git a/Source/Game/Console/ConfigParser.cs b/Source/Game/Console/ConfigParser.cs new file mode 100644 index 0000000..b77d99d --- /dev/null +++ b/Source/Game/Console/ConfigParser.cs @@ -0,0 +1,39 @@ +using System.IO; + +namespace Game +{ + public class ConfigParser + { + private ConfigParser() + { + + } + + public static Config ParseFile(string path) + { + Config config = new Config(); + using FileStream file = File.OpenRead(path); + using StreamReader sr = new StreamReader(file); + + string line; + while ((line = sr.ReadLine()?.Trim()) != null) + { + if (line.StartsWith(@"//")) + continue; + + int spacePos = line.IndexOf(' '); + if (spacePos == -1) + continue; + + string key = line.Substring(0, spacePos); + string value = line.Substring(spacePos+1); + + value = value.Trim('"'); + + config[key] = value; + } + + return config; + } + } +} \ No newline at end of file diff --git a/Source/Game/Console/Console.cs b/Source/Game/Console/Console.cs index 6879961..a67b8bc 100644 --- a/Source/Game/Console/Console.cs +++ b/Source/Game/Console/Console.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Linq; using System.Reflection; using FlaxEditor; +using FlaxEngine; namespace Game { @@ -89,6 +90,12 @@ namespace Game ScriptsBuilder.ScriptsReload += Destroy; Editor.Instance.PlayModeEnd += OnEditorPlayModeChanged; #endif + + AssetManager.Init(); // TODO: move these elsewhere + AssetManager.Globals.ResetValues(); + + foreach (var line in AssetManager.Config.GetLines()) + Console.Execute(line, false, true); } public static void Destroy() @@ -108,6 +115,7 @@ namespace Game #if FLAX_EDITOR private static void OnEditorPlayModeChanged() { + //AssetManager.Globals.ResetValues(); // Clear console buffer when leaving play mode if (instance != null) Clear(); @@ -173,9 +181,9 @@ namespace Game instance.Clear(); } - public static void Execute(string str, bool bufferInput = false) + public static void Execute(string str, bool bufferInput = false, bool noOutput = false) { - instance.Execute(str, bufferInput); + instance.Execute(str, bufferInput, noOutput); } public static string GetVariable(string variableName) @@ -455,14 +463,14 @@ namespace Game consoleLines.Clear(); } - public void Execute(string str, bool bufferInput = false) + public void Execute(string str, bool bufferInput = false, bool noOutput = false) { if (bufferInput) consoleBufferHistory.Insert(0, str); str = str.Trim(); - if (ShowExecutedLines) + if (ShowExecutedLines && !noOutput) Console.Print(LinePrefix + str); string[] strs = str.Split(' '); @@ -488,7 +496,8 @@ namespace Game if (value != null) cvar.SetValue(value); - Console.Print("'" + execute + "' is '" + cvar.GetValueString() + "'"); + //if (!noOutput) + Console.Print("'" + execute + "' is '" + cvar.GetValueString() + "'"); } else { diff --git a/Source/Game/Console/EngineSubsystem.cs b/Source/Game/Console/EngineSubsystem.cs index b6d872c..8474b20 100644 --- a/Source/Game/Console/EngineSubsystem.cs +++ b/Source/Game/Console/EngineSubsystem.cs @@ -195,29 +195,17 @@ namespace Game { get { - string workDir = Directory.GetCurrentDirectory(); - string matBasePath = Path.Combine(workDir, "Content"); - string assetPath = Path.Combine(matBasePath, "GameplayGlobals.flax"); - - GameplayGlobals globals = Content.Load(assetPath); - - return ((bool)globals.GetValue("Scene Lighting") ? "1" : "0"); + return ((bool)AssetManager.Globals.GetValue("Scene Lighting") ? "1" : "0"); } set { - string workDir = Directory.GetCurrentDirectory(); - string matBasePath = Path.Combine(workDir, "Content"); - string assetPath = Path.Combine(matBasePath, "GameplayGlobals.flax"); - - GameplayGlobals globals = Content.Load(assetPath); - bool boolValue = false; if (int.TryParse(value, out int intValue)) boolValue = intValue != 0; else if (float.TryParse(value, out float valueFloat)) boolValue = valueFloat != 0f; - globals.SetValue("Scene Lighting", boolValue); + AssetManager.Globals.SetValue("Scene Lighting", boolValue); PostFxVolume postFx = Level.FindActor(); @@ -234,10 +222,26 @@ namespace Game } // TODO: disable GI + Graphics.EnableGlobalSDF = boolValue; + } + } - Light[] lights = Level.GetActors(); - foreach (Light light in lights) - light.IsActive = boolValue; + [ConsoleVariable("r_shadows")] + public static string SceneShadows + { + get + { + return ((bool)AssetManager.Globals.GetValue("Scene Shadows") ? "1" : "0"); + } + set + { + bool boolValue = false; + if (int.TryParse(value, out int intValue)) + boolValue = intValue != 0; + else if (float.TryParse(value, out float valueFloat)) + boolValue = valueFloat != 0f; + + AssetManager.Globals.SetValue("Scene Shadows", boolValue); } } diff --git a/Source/Game/GameMode/GameModeManager.cs b/Source/Game/GameMode/GameModeManager.cs index 2e57203..a2e858f 100644 --- a/Source/Game/GameMode/GameModeManager.cs +++ b/Source/Game/GameMode/GameModeManager.cs @@ -384,8 +384,7 @@ namespace Game spawned = true; - string workDir = Directory.GetCurrentDirectory(); - string prefabPath = Path.Combine(workDir, "Content", "Common"); + string prefabPath = Path.Combine(AssetManager.ContentPath, "Common"); var playerPrefab = Content.Load(Path.Combine(prefabPath, "PlayerPrefab.prefab")); if (playerPrefab == null) Console.PrintError("GameModeManager: Failed to find PlayerPrefab"); diff --git a/Source/Game/Level/Q3MapImporter.cs b/Source/Game/Level/Q3MapImporter.cs index 16c3d93..e822b25 100644 --- a/Source/Game/Level/Q3MapImporter.cs +++ b/Source/Game/Level/Q3MapImporter.cs @@ -49,6 +49,7 @@ namespace Game private Model model; private MaterialBase missingMaterial; + private bool resetLights = false; private bool dirtyLights = false; private float brightnessMultiplier_ = 0.82f; @@ -62,28 +63,28 @@ namespace Game public float BrightnessMultiplier { get => brightnessMultiplier_; - set { brightnessMultiplier_ = value; dirtyLights = true; } + set { brightnessMultiplier_ = value; resetLights = true; } } [Range(0.1f, 40f)] public float LightRadiusMultiplier { get => lightRadiusMultiplier_; - set { lightRadiusMultiplier_ = value; dirtyLights = true; } + set { lightRadiusMultiplier_ = value; resetLights = true; } } [Range(2f, 8f)] public float FallOffExponent { get => fallOffExponent_; - set { fallOffExponent_ = value; dirtyLights = true; } + set { fallOffExponent_ = value; resetLights = true; } } [Range(0.01f, 1f)] public float SaturationMultiplier { get => saturationMultiplier_; - set { saturationMultiplier_ = value; dirtyLights = true; } + set { saturationMultiplier_ = value; resetLights = true; } } @@ -249,6 +250,7 @@ namespace Game { if (worldSpawnActor != null) worldSpawnActor.HideFlags |= HideFlags.DontSave; + dirtyLights = true; } catch (Exception e) { @@ -274,9 +276,24 @@ namespace Game LoadMap(false); } + private bool lastSceneLighting = false; + private bool lastSceneShadows = false; public override void OnUpdate() { - if (dirtyLights) + bool sceneLighting = EngineSubsystem.SceneLighting == "1"; + if (lastSceneLighting != sceneLighting) + { + lastSceneLighting = sceneLighting; + dirtyLights = true; + } + bool sceneShadows = EngineSubsystem.SceneShadows == "1"; + if (lastSceneShadows != sceneShadows) + { + lastSceneShadows = sceneShadows; + dirtyLights = true; + } + + if (resetLights) { if (worldSpawnActor == null || !worldSpawnActor || root == null) return; @@ -297,6 +314,18 @@ namespace Game // break; } + resetLights = false; + } + + if (dirtyLights) + { + foreach (var light in worldSpawnActor.GetChildren()) + { + light.IsActive = sceneLighting; + if (light is PointLight pointLight) + pointLight.ShadowsStrength = sceneShadows ? 1.0f : 0.0f; + } + dirtyLights = false; } } @@ -314,7 +343,7 @@ namespace Game else { FlaxEngine.Debug.Log("Map already loaded in the scene"); - dirtyLights = false; + resetLights = false; return; } } @@ -322,8 +351,7 @@ namespace Game FlaxEngine.Debug.Log("Loading map"); { - string workDir = Directory.GetCurrentDirectory(); - string matBasePath = Path.Combine(workDir, "Content", "Materials"); + string matBasePath = Path.Combine(AssetManager.ContentPath, "Materials"); string assetPath = Path.Combine(matBasePath, "missing.flax"); missingMaterial = Content.Load(assetPath); } @@ -395,8 +423,7 @@ namespace Game if (!materials.TryGetValue(textureName, out MaterialBase brushMaterial)) { - string workDir = Directory.GetCurrentDirectory(); - string matBasePath = Path.Combine(workDir, "Content", "Materials"); + string matBasePath = Path.Combine(AssetManager.ContentPath, "Materials"); string assetPath = Path.Combine(matBasePath, textureName + ".flax"); brushMaterial = Content.Load(assetPath); if (brushMaterial != null) @@ -768,8 +795,7 @@ namespace Game childModel.Model = model; //childModel.SetMaterial(0, missingMaterial); - string workDir = Directory.GetCurrentDirectory(); - string matBasePath = Path.Combine(workDir, "Content", "Materials"); + string matBasePath = Path.Combine(AssetManager.ContentPath, "Materials"); string assetPath = Path.Combine(matBasePath, "dev/dev_128_gray" + ".flax"); var brushMaterial = Content.Load(assetPath); if (brushMaterial != null) diff --git a/Source/Game/Utility/AssetManager.cs b/Source/Game/Utility/AssetManager.cs new file mode 100644 index 0000000..33229d2 --- /dev/null +++ b/Source/Game/Utility/AssetManager.cs @@ -0,0 +1,20 @@ +using System.IO; +using FlaxEngine; + +namespace Game +{ + public static class AssetManager + { + public static string ContentPath { get; private set; } = + Path.Combine(Directory.GetCurrentDirectory(), "Content"); + + public static GameplayGlobals Globals { get; private set; } + public static Config Config { get; private set; } + + public static void Init() + { + Globals = Content.Load(Path.Combine(ContentPath, "Settings", "GameSettings", "GameplayGlobals.flax")); + Config = ConfigParser.ParseFile(Path.Combine(ContentPath, "config.cfg")); + } + } +} \ No newline at end of file