/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * 0 A.D. is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 0 A.D. If not, see . */ #include "precompiled.h" #include "MessageHandler.h" #include "../CommandProc.h" #include "graphics/LightEnv.h" #include "graphics/Terrain.h" #include "maths/MathUtil.h" #include "ps/CStr.h" #include "ps/Game.h" #include "ps/World.h" #include "renderer/PostprocManager.h" #include "renderer/Renderer.h" #include "renderer/SceneRenderer.h" #include "renderer/SkyManager.h" #include "renderer/WaterManager.h" #include "simulation2/Simulation2.h" #include "simulation2/components/ICmpWaterManager.h" namespace AtlasMessage { sEnvironmentSettings GetSettings() { sEnvironmentSettings s; CmpPtr cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); ENSURE(cmpWaterManager); s.waterheight = cmpWaterManager->GetExactWaterLevel(0, 0) / (65536.f * HEIGHT_SCALE); const WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager(); s.watertype = waterManager.m_WaterType; s.waterwaviness = waterManager.m_Waviness; s.watermurkiness = waterManager.m_Murkiness; s.windangle = waterManager.m_WindAngle; // CColor colors #define COLOR(A, B) A = Color((int)(B.r*255), (int)(B.g*255), (int)(B.b*255)) COLOR(s.watercolor, waterManager.m_WaterColor); COLOR(s.watertint, waterManager.m_WaterTint); #undef COLOR float sunrotation = g_LightEnv.GetRotation(); if (sunrotation > (float)M_PI) sunrotation -= (float)M_PI*2; s.sunrotation = sunrotation; s.sunelevation = g_LightEnv.GetElevation(); s.posteffect = g_Renderer.GetPostprocManager().GetPostEffect(); s.skyset = g_Renderer.GetSceneRenderer().GetSkyManager().GetSkySet(); s.fogfactor = g_LightEnv.m_FogFactor; s.fogmax = g_LightEnv.m_FogMax; s.brightness = g_LightEnv.m_Brightness; s.contrast = g_LightEnv.m_Contrast; s.saturation = g_LightEnv.m_Saturation; s.bloom = g_LightEnv.m_Bloom; // RGBColor (CVector3D) colors #define COLOR(A, B) A = Color((int)(B.X*255), (int)(B.Y*255), (int)(B.Z*255)) s.sunoverbrightness = MaxComponent(g_LightEnv.m_SunColor); // clamp color to [0..1] before packing into u8 triplet if(s.sunoverbrightness > 1.0f) g_LightEnv.m_SunColor *= 1.0/s.sunoverbrightness; // (there's no operator/=) // no component was above 1.0, so reset scale factor (don't want to darken) else s.sunoverbrightness = 1.0f; COLOR(s.suncolor, g_LightEnv.m_SunColor); COLOR(s.ambientcolor, g_LightEnv.m_AmbientColor); COLOR(s.fogcolor, g_LightEnv.m_FogColor); #undef COLOR return s; } void SetSettings(const sEnvironmentSettings& s) { CmpPtr cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); ENSURE(cmpWaterManager); cmpWaterManager->SetWaterLevel(entity_pos_t::FromFloat(s.waterheight * (65536.f * HEIGHT_SCALE))); WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager(); waterManager.m_Waviness = s.waterwaviness; waterManager.m_Murkiness = s.watermurkiness; waterManager.m_WindAngle = s.windangle; if (waterManager.m_WaterType != *s.watertype) { waterManager.m_WaterType = *s.watertype; waterManager.ReloadWaterNormalTextures(); } #define COLOR(A, B) B = CColor(A->r/255.f, A->g/255.f, A->b/255.f, 1.f) COLOR(s.watercolor, waterManager.m_WaterColor); COLOR(s.watertint, waterManager.m_WaterTint); #undef COLOR g_LightEnv.SetRotation(s.sunrotation); g_LightEnv.SetElevation(s.sunelevation); CStrW posteffect = *s.posteffect; if (posteffect.length() == 0) posteffect = L"default"; g_Renderer.GetPostprocManager().SetPostEffect(posteffect); CStrW skySet = *s.skyset; if (skySet.length() == 0) skySet = L"default"; g_Renderer.GetSceneRenderer().GetSkyManager().SetSkySet(skySet); g_LightEnv.m_FogFactor = s.fogfactor; g_LightEnv.m_FogMax = s.fogmax; g_LightEnv.m_Brightness = s.brightness; g_LightEnv.m_Contrast = s.contrast; g_LightEnv.m_Saturation = s.saturation; g_LightEnv.m_Bloom = s.bloom; #define COLOR(A, B) B = RGBColor(A->r/255.f, A->g/255.f, A->b/255.f) COLOR(s.suncolor, g_LightEnv.m_SunColor); g_LightEnv.m_SunColor *= s.sunoverbrightness; COLOR(s.ambientcolor, g_LightEnv.m_AmbientColor); COLOR(s.fogcolor, g_LightEnv.m_FogColor); #undef COLOR cmpWaterManager->RecomputeWaterData(); } BEGIN_COMMAND(SetEnvironmentSettings) { sEnvironmentSettings m_OldSettings, m_NewSettings; void Do() { m_OldSettings = GetSettings(); m_NewSettings = msg->settings; Redo(); } void Redo() { SetSettings(m_NewSettings); } void Undo() { SetSettings(m_OldSettings); } void MergeIntoPrevious(cSetEnvironmentSettings* prev) { prev->m_NewSettings = m_NewSettings; } }; END_COMMAND(SetEnvironmentSettings) BEGIN_COMMAND(RecalculateWaterData) { void Do() { Redo(); } void Redo() { CmpPtr cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); ENSURE(cmpWaterManager); cmpWaterManager->RecomputeWaterData(); } void Undo() { Redo(); } }; END_COMMAND(RecalculateWaterData) BEGIN_COMMAND(PickWaterHeight) { entity_pos_t m_OldWaterHeight, m_NewWaterHeight; void Do() { CmpPtr cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); ENSURE(cmpWaterManager); CVector3D worldPos = msg->screenPos->GetWorldSpace(); m_OldWaterHeight = cmpWaterManager->GetWaterLevel( entity_pos_t::FromFloat(worldPos.X), entity_pos_t::FromFloat(worldPos.Z)); m_NewWaterHeight = entity_pos_t::FromFloat(worldPos.Y); SetWaterHeight(m_NewWaterHeight); } void Redo() { SetWaterHeight(m_NewWaterHeight); } void Undo() { SetWaterHeight(m_OldWaterHeight); } void SetWaterHeight(entity_pos_t height) { CmpPtr cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); ENSURE(cmpWaterManager); cmpWaterManager->SetWaterLevel(height); cmpWaterManager->RecomputeWaterData(); } }; END_COMMAND(PickWaterHeight) QUERYHANDLER(GetEnvironmentSettings) { msg->settings = GetSettings(); } QUERYHANDLER(GetSkySets) { std::vector skies = g_Renderer.GetSceneRenderer().GetSkyManager().GetSkySets(); msg->skysets = std::vector(skies.begin(), skies.end()); } QUERYHANDLER(GetPostEffects) { std::vector effects = g_Renderer.GetPostprocManager().GetPostEffects(); msg->posteffects = std::vector(effects.begin(), effects.end()); } }