diff --git a/Content/Documentation/ScriptingAPI-Documentation.md b/Content/Documentation/ScriptingAPI-Documentation.md index 5cb5fc45b..ffcd1b3c8 100644 --- a/Content/Documentation/ScriptingAPI-Documentation.md +++ b/Content/Documentation/ScriptingAPI-Documentation.md @@ -404,6 +404,7 @@ A four component floating point vector. Provides efficient calculations with SIM - Lerp(Vector v1,v2, float t) : Vector result - QuaternionMultiply(Vector v1,v2) : Vector result - QuaternionFromRollPitchYaw(Vector rotXYZ) : Vector result +- QuaternionToRollPitchYaw(Vector quaternion) : Vector result - QuaternionSlerp(Vector v1,v2, float t) : Vector result ### Matrix diff --git a/Editor/App_Windows.cpp b/Editor/App_Windows.cpp index 4e079e527..ae032a8f6 100644 --- a/Editor/App_Windows.cpp +++ b/Editor/App_Windows.cpp @@ -133,6 +133,14 @@ public: CoreApplication::Resuming({ this, &ViewProvider::OnResuming }); uwp_copy_assets(); + + //wi::Timer timer; + //if (editor.config.Open("config.ini")) + //{ + // editor.allow_hdr = editor.config.GetBool("allow_hdr"); + + // wi::backlog::post("config.ini loaded in " + std::to_string(timer.elapsed_milliseconds()) + " milliseconds\n"); + //} } void Uninitialize() noexcept @@ -171,7 +179,7 @@ public: m_logicalWidth = window.Bounds().Width; m_logicalHeight = window.Bounds().Height; - main.SetWindow(&window); + editor.SetWindow(&window); } void Load(winrt::hstring const&) noexcept @@ -184,7 +192,7 @@ public: { if (m_visible) { - main.Run(); + editor.Run(); CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); } @@ -218,7 +226,7 @@ protected: void OnWindowSizeChanged(CoreWindow const& sender, WindowSizeChangedEventArgs const& /*args*/) { - main.SetWindow(&sender); + editor.SetWindow(&sender); } void OnVisibilityChanged(CoreWindow const& /*sender*/, VisibilityChangedEventArgs const& args) @@ -262,7 +270,7 @@ protected: void OnDpiChanged(DisplayInformation const& sender, IInspectable const& /*args*/) { - main.SetWindow(&CoreWindow::GetForCurrentThread()); + editor.SetWindow(&CoreWindow::GetForCurrentThread()); } void OnDisplayContentsInvalidated(DisplayInformation const& /*sender*/, IInspectable const& /*args*/) @@ -275,7 +283,7 @@ private: float m_DPI = 96; float m_logicalWidth = 800; float m_logicalHeight = 600; - Editor main; + Editor editor; inline int ConvertDipsToPixels(float dips) const noexcept { diff --git a/Editor/CameraWindow.cpp b/Editor/CameraWindow.cpp index 464e41d87..d607393ac 100644 --- a/Editor/CameraWindow.cpp +++ b/Editor/CameraWindow.cpp @@ -46,10 +46,16 @@ void CameraWindow::Create(EditorComponent* _editor) float step = hei + 2; float wid = 120; + ResetCam(); + farPlaneSlider.Create(100, 10000, 5000, 100000, "Far Plane: "); farPlaneSlider.SetTooltip("Controls the camera's far clip plane, geometry farther than this will be clipped."); farPlaneSlider.SetSize(XMFLOAT2(wid, hei)); farPlaneSlider.SetPos(XMFLOAT2(x, y)); + if (editor->main->config.GetSection("camera").Has("far")) + { + editor->GetCurrentEditorScene().camera.zFarP = editor->main->config.GetSection("camera").GetFloat("far"); + } farPlaneSlider.SetValue(editor->GetCurrentEditorScene().camera.zFarP); farPlaneSlider.OnSlide([&](wi::gui::EventArgs args) { Scene& scene = editor->GetCurrentScene(); @@ -57,6 +63,8 @@ void CameraWindow::Create(EditorComponent* _editor) camera.zFarP = args.fValue; camera.UpdateCamera(); camera.SetDirty(); + editor->main->config.GetSection("camera").Set("far", args.fValue); + editor->main->config.Commit(); }); AddWidget(&farPlaneSlider); @@ -64,6 +72,10 @@ void CameraWindow::Create(EditorComponent* _editor) nearPlaneSlider.SetTooltip("Controls the camera's near clip plane, geometry closer than this will be clipped."); nearPlaneSlider.SetSize(XMFLOAT2(wid, hei)); nearPlaneSlider.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("camera").Has("near")) + { + editor->GetCurrentEditorScene().camera.zNearP = editor->main->config.GetSection("camera").GetFloat("near"); + } nearPlaneSlider.SetValue(editor->GetCurrentEditorScene().camera.zNearP); nearPlaneSlider.OnSlide([&](wi::gui::EventArgs args) { Scene& scene = editor->GetCurrentScene(); @@ -71,6 +83,8 @@ void CameraWindow::Create(EditorComponent* _editor) camera.zNearP = args.fValue; camera.UpdateCamera(); camera.SetDirty(); + editor->main->config.GetSection("camera").Set("near", args.fValue); + editor->main->config.Commit(); }); AddWidget(&nearPlaneSlider); @@ -78,12 +92,19 @@ void CameraWindow::Create(EditorComponent* _editor) fovSlider.SetTooltip("Controls the camera's top-down field of view (in degrees)"); fovSlider.SetSize(XMFLOAT2(wid, hei)); fovSlider.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("camera").Has("fov")) + { + editor->GetCurrentEditorScene().camera.fov = editor->main->config.GetSection("camera").GetFloat("fov") / 180.f * XM_PI; + } + fovSlider.SetValue(editor->GetCurrentEditorScene().camera.fov / XM_PI * 180.f); fovSlider.OnSlide([&](wi::gui::EventArgs args) { Scene& scene = editor->GetCurrentScene(); CameraComponent& camera = editor->GetCurrentEditorScene().camera; camera.fov = args.fValue / 180.f * XM_PI; camera.UpdateCamera(); camera.SetDirty(); + editor->main->config.GetSection("camera").Set("fov", args.fValue); + editor->main->config.Commit(); }); AddWidget(&fovSlider); @@ -142,16 +163,40 @@ void CameraWindow::Create(EditorComponent* _editor) movespeedSlider.Create(1, 100, 10, 10000, "Movement Speed: "); movespeedSlider.SetSize(XMFLOAT2(wid, hei)); movespeedSlider.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("camera").Has("move_speed")) + { + movespeedSlider.SetValue(editor->main->config.GetSection("camera").GetFloat("move_speed")); + } + movespeedSlider.OnSlide([=](wi::gui::EventArgs args) { + editor->main->config.GetSection("camera").Set("move_speed", args.fValue); + editor->main->config.Commit(); + }); AddWidget(&movespeedSlider); accelerationSlider.Create(0.01f, 1, 0.18f, 10000, "Acceleration: "); accelerationSlider.SetSize(XMFLOAT2(wid, hei)); accelerationSlider.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("camera").Has("acceleration")) + { + accelerationSlider.SetValue(editor->main->config.GetSection("camera").GetFloat("acceleration")); + } + accelerationSlider.OnSlide([=](wi::gui::EventArgs args) { + editor->main->config.GetSection("camera").Set("acceleration", args.fValue); + editor->main->config.Commit(); + }); AddWidget(&accelerationSlider); rotationspeedSlider.Create(0.1f, 2, 1, 10000, "Rotation Speed: "); rotationspeedSlider.SetSize(XMFLOAT2(wid, hei)); rotationspeedSlider.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("camera").Has("rotation_speed")) + { + rotationspeedSlider.SetValue(editor->main->config.GetSection("camera").GetFloat("rotation_speed")); + } + rotationspeedSlider.OnSlide([=](wi::gui::EventArgs args) { + editor->main->config.GetSection("camera").Set("rotation_speed", args.fValue); + editor->main->config.Commit(); + }); AddWidget(&rotationspeedSlider); resetButton.Create("Reset Camera"); @@ -159,6 +204,12 @@ void CameraWindow::Create(EditorComponent* _editor) resetButton.SetPos(XMFLOAT2(x, y += step)); resetButton.OnClick([&](wi::gui::EventArgs args) { ResetCam(); + + CameraComponent& camera = editor->GetCurrentEditorScene().camera; + editor->main->config.GetSection("camera").Set("near", camera.zNearP); + editor->main->config.GetSection("camera").Set("far", camera.zFarP); + editor->main->config.GetSection("camera").Set("fov", camera.fov / XM_PI * 180.f); + editor->main->config.Commit(); }); AddWidget(&resetButton); @@ -166,6 +217,11 @@ void CameraWindow::Create(EditorComponent* _editor) fpsCheckBox.SetSize(XMFLOAT2(hei, hei)); fpsCheckBox.SetPos(XMFLOAT2(x, y += step)); fpsCheckBox.SetCheck(true); + fpsCheckBox.SetCheck(editor->main->config.GetSection("camera").GetBool("fps")); + fpsCheckBox.OnClick([&](wi::gui::EventArgs args) { + editor->main->config.GetSection("camera").Set("fps", args.bValue); + editor->main->config.Commit(); + }); AddWidget(&fpsCheckBox); diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index 1a0a0586f..3278f6d3a 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -443,9 +443,7 @@ void EditorComponent::Load() ss += "-------\n"; ss += "You can find sample scenes in the Content/models directory. Try to load one.\n"; ss += "You can also import models from .OBJ, .GLTF, .GLB, .VRM files.\n"; -#ifndef PLATFORM_UWP ss += "You can find a program configuration file at Editor/config.ini\n"; -#endif // PLATFORM_UWP ss += "You can find sample LUA scripts in the Content/scripts directory. Try to load one.\n"; ss += "You can find a startup script at Editor/startup.lua (this will be executed on program start, if exists)\n"; ss += "\nFor questions, bug reports, feedback, requests, please open an issue at:\n"; @@ -476,7 +474,27 @@ void EditorComponent::Load() componentsWnd.Create(this); GetGUI().AddWidget(&componentsWnd); - optionsWnd.themeCombo.SetSelected(0); + std::string theme = main->config.GetSection("options").GetText("theme"); + if(theme.empty()) + { + optionsWnd.themeCombo.SetSelected(0); + } + else if (!theme.compare("Dark")) + { + optionsWnd.themeCombo.SetSelected(0); + } + else if (!theme.compare("Bright")) + { + optionsWnd.themeCombo.SetSelected(1); + } + else if (!theme.compare("Soft")) + { + optionsWnd.themeCombo.SetSelected(2); + } + else if (!theme.compare("Hacking")) + { + optionsWnd.themeCombo.SetSelected(3); + } static wi::eventhandler::Handle handle = wi::eventhandler::Subscribe(TerrainGenerator::EVENT_THEME_RESET, [=](uint64_t) { optionsWnd.themeCombo.SetSelected(optionsWnd.themeCombo.GetSelected()); diff --git a/Editor/Editor.h b/Editor/Editor.h index 62be42feb..990074974 100644 --- a/Editor/Editor.h +++ b/Editor/Editor.h @@ -171,6 +171,7 @@ class Editor : public wi::Application public: EditorComponent renderComponent; EditorLoadingScreen loader; + wi::config::File config; void Initialize() override; }; diff --git a/Editor/Editor_UWP.vcxproj b/Editor/Editor_UWP.vcxproj index 21fab2a9e..7d98a3262 100644 --- a/Editor/Editor_UWP.vcxproj +++ b/Editor/Editor_UWP.vcxproj @@ -150,6 +150,10 @@ + + true + true + diff --git a/Editor/Editor_UWP.vcxproj.filters b/Editor/Editor_UWP.vcxproj.filters index a6218e95d..abc655120 100644 --- a/Editor/Editor_UWP.vcxproj.filters +++ b/Editor/Editor_UWP.vcxproj.filters @@ -37,5 +37,6 @@ + \ No newline at end of file diff --git a/Editor/GraphicsWindow.cpp b/Editor/GraphicsWindow.cpp index 2c707503e..f999ea21b 100644 --- a/Editor/GraphicsWindow.cpp +++ b/Editor/GraphicsWindow.cpp @@ -27,9 +27,17 @@ void GraphicsWindow::Create(EditorComponent* _editor) vsyncCheckBox.SetScriptTip("SetVSyncEnabled(opt bool enabled)"); vsyncCheckBox.SetPos(XMFLOAT2(x, y)); vsyncCheckBox.SetSize(XMFLOAT2(itemheight, itemheight)); - vsyncCheckBox.SetCheck(editor->main->swapChain.desc.vsync); + if (editor->main->config.GetSection("graphics").Has("vsync")) + { + vsyncCheckBox.SetCheck(editor->main->config.GetSection("graphics").GetBool("vsync")); + } + else + { + vsyncCheckBox.SetCheck(editor->main->swapChain.desc.vsync); + } vsyncCheckBox.OnClick([=](wi::gui::EventArgs args) { - wi::eventhandler::SetVSync(args.bValue); + editor->main->config.GetSection("graphics").Set("vsync", args.bValue); + editor->main->config.Commit(); }); AddWidget(&vsyncCheckBox); @@ -44,13 +52,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) resolutionScaleSlider.SetTooltip("Adjust the internal rendering resolution."); resolutionScaleSlider.SetSize(XMFLOAT2(wid, itemheight)); resolutionScaleSlider.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("graphics").Has("resolution_scale")) + { + editor->resolutionScale = editor->main->config.GetSection("graphics").GetFloat("resolution_scale"); + } resolutionScaleSlider.OnSlide([=](wi::gui::EventArgs args) { - if (editor->resolutionScale != args.fValue) - { - editor->renderPath->resolutionScale = args.fValue; - editor->resolutionScale = args.fValue; - editor->ResizeBuffers(); - } + editor->resolutionScale = args.fValue; + editor->main->config.GetSection("graphics").Set("resolution_scale", args.fValue); + editor->main->config.Commit(); }); AddWidget(&resolutionScaleSlider); @@ -86,16 +95,25 @@ void GraphicsWindow::Create(EditorComponent* _editor) occlusionCullingCheckBox.SetScriptTip("SetOcclusionCullingEnabled(bool enabled)"); occlusionCullingCheckBox.SetPos(XMFLOAT2(x, y += step)); occlusionCullingCheckBox.SetSize(XMFLOAT2(itemheight, itemheight)); - occlusionCullingCheckBox.OnClick([](wi::gui::EventArgs args) { + occlusionCullingCheckBox.OnClick([=](wi::gui::EventArgs args) { wi::renderer::SetOcclusionCullingEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("occlusion_culling", args.bValue); + editor->main->config.Commit(); }); - occlusionCullingCheckBox.SetCheck(wi::renderer::GetOcclusionCullingEnabled()); + if (editor->main->config.GetSection("graphics").Has("occlusion_culling")) + { + wi::renderer::SetOcclusionCullingEnabled(editor->main->config.GetSection("graphics").GetBool("occlusion_culling")); + } AddWidget(&occlusionCullingCheckBox); visibilityComputeShadingCheckBox.Create("Visibility Compute Shading: "); visibilityComputeShadingCheckBox.SetTooltip("Visibility Compute Shading (experimental)\nThis will shade the scene in compute shaders instead of pixel shaders\nThis has a higher initial performance cost, but it will be faster in high polygon scenes.\nIt is not compatible with MSAA and tessellation."); visibilityComputeShadingCheckBox.SetPos(XMFLOAT2(x, y += step)); visibilityComputeShadingCheckBox.SetSize(XMFLOAT2(itemheight, itemheight)); + if (editor->main->config.GetSection("graphics").Has("visibility_compute_shading")) + { + editor->renderPath->visibility_shading_in_compute = editor->main->config.GetSection("graphics").GetBool("visibility_compute_shading"); + } visibilityComputeShadingCheckBox.OnClick([=](wi::gui::EventArgs args) { if (args.bValue) { @@ -105,6 +123,8 @@ void GraphicsWindow::Create(EditorComponent* _editor) { editor->renderPath->visibility_shading_in_compute = false; } + editor->main->config.GetSection("graphics").Set("visibility_compute_shading", args.bValue); + editor->main->config.Commit(); }); AddWidget(&visibilityComputeShadingCheckBox); @@ -112,9 +132,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) GIBoostSlider.SetTooltip("Adjust the strength of GI.\nNote that values other than 1.0 will cause mismatch with path tracing reference!"); GIBoostSlider.SetSize(XMFLOAT2(wid, itemheight)); GIBoostSlider.SetPos(XMFLOAT2(x, y += step)); - GIBoostSlider.SetValue(wi::renderer::GetGIBoost()); + if (editor->main->config.GetSection("graphics").Has("gi_boost")) + { + wi::renderer::SetGIBoost(editor->main->config.GetSection("graphics").GetFloat("gi_boost")); + } GIBoostSlider.OnSlide([=](wi::gui::EventArgs args) { wi::renderer::SetGIBoost(args.fValue); + editor->main->config.GetSection("graphics").Set("gi_boost", args.fValue); + editor->main->config.Commit(); }); AddWidget(&GIBoostSlider); @@ -351,10 +376,16 @@ void GraphicsWindow::Create(EditorComponent* _editor) tessellationCheckBox.SetTooltip("Enable tessellation feature. You also need to specify a tessellation factor for individual objects."); tessellationCheckBox.SetPos(XMFLOAT2(x, y += step)); tessellationCheckBox.SetSize(XMFLOAT2(itemheight, itemheight)); + if (editor->main->config.GetSection("graphics").Has("tessellation")) + { + wi::renderer::SetTessellationEnabled(editor->main->config.GetSection("graphics").GetBool("tessellation")); + } + tessellationCheckBox.SetCheck(wi::renderer::GetTessellationEnabled()); tessellationCheckBox.OnClick([=](wi::gui::EventArgs args) { wi::renderer::SetTessellationEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("tessellation", args.bValue); + editor->main->config.Commit(); }); - tessellationCheckBox.SetCheck(wi::renderer::GetTessellationEnabled()); AddWidget(&tessellationCheckBox); tessellationCheckBox.SetEnabled(wi::graphics::GetDevice()->CheckCapability(wi::graphics::GraphicsDeviceCapability::TESSELLATION)); @@ -372,9 +403,15 @@ void GraphicsWindow::Create(EditorComponent* _editor) transparentShadowsCheckBox.SetTooltip("Enables color tinted shadows and refraction caustics effects for transparent objects and water."); transparentShadowsCheckBox.SetPos(XMFLOAT2(x, y += step)); transparentShadowsCheckBox.SetSize(XMFLOAT2(itemheight, itemheight)); + if (editor->main->config.GetSection("graphics").Has("transparent_shadows")) + { + wi::renderer::SetTransparentShadowsEnabled(editor->main->config.GetSection("graphics").GetBool("transparent_shadows")); + } transparentShadowsCheckBox.SetCheck(wi::renderer::GetTransparentShadowsEnabled()); transparentShadowsCheckBox.OnClick([=](wi::gui::EventArgs args) { wi::renderer::SetTransparentShadowsEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("transparent_shadows", args.bValue); + editor->main->config.Commit(); }); AddWidget(&transparentShadowsCheckBox); @@ -441,8 +478,17 @@ void GraphicsWindow::Create(EditorComponent* _editor) default: break; } + editor->main->config.GetSection("graphics").Set("shadow_resolution_2d", args.iValue); + editor->main->config.Commit(); }); - shadowProps2DComboBox.SetSelected(4); + if (editor->main->config.GetSection("graphics").Has("shadow_resolution_2d")) + { + shadowProps2DComboBox.SetSelected(editor->main->config.GetSection("graphics").GetInt("shadow_resolution_2d")); + } + else + { + shadowProps2DComboBox.SetSelected(4); + } shadowProps2DComboBox.SetTooltip("Choose a shadow quality preset for 2D shadow maps (spotlights, directional lights)...\nThis specifies the maximum shadow resolution for these light types, but that can dynamically change unless they are set to a fixed resolution individually."); shadowProps2DComboBox.SetScriptTip("SetShadowProps2D(int resolution, int count, int softShadowQuality)"); AddWidget(&shadowProps2DComboBox); @@ -480,8 +526,17 @@ void GraphicsWindow::Create(EditorComponent* _editor) default: break; } + editor->main->config.GetSection("graphics").Set("shadow_resolution_cube", args.iValue); + editor->main->config.Commit(); }); - shadowPropsCubeComboBox.SetSelected(2); + if (editor->main->config.GetSection("graphics").Has("shadow_resolution_cube")) + { + shadowPropsCubeComboBox.SetSelected(editor->main->config.GetSection("graphics").GetInt("shadow_resolution_cube")); + } + else + { + shadowPropsCubeComboBox.SetSelected(2); + } shadowPropsCubeComboBox.SetTooltip("Choose a shadow quality preset for cube shadow maps (pointlights, area lights)...\nThis specifies the maximum shadow resolution for these light types, but that can dynamically change unless they are set to a fixed resolution individually."); shadowPropsCubeComboBox.SetScriptTip("SetShadowPropsCube(int resolution, int count)"); AddWidget(&shadowPropsCubeComboBox); @@ -493,9 +548,13 @@ void GraphicsWindow::Create(EditorComponent* _editor) MSAAComboBox.AddItem("2", 2); MSAAComboBox.AddItem("4", 4); MSAAComboBox.AddItem("8", 8); + if (editor->main->config.GetSection("graphics").Has("msaa")) + { + MSAAComboBox.SetSelectedWithoutCallback(editor->main->config.GetSection("graphics").GetInt("msaa")); + } MSAAComboBox.OnSelect([=](wi::gui::EventArgs args) { - editor->renderPath->setMSAASampleCount((uint32_t)args.userdata); - editor->ResizeBuffers(); + editor->main->config.GetSection("graphics").Set("msaa", args.iValue); + editor->main->config.Commit(); }); MSAAComboBox.SetTooltip("Multisampling Anti Aliasing quality. "); AddWidget(&MSAAComboBox); @@ -504,10 +563,16 @@ void GraphicsWindow::Create(EditorComponent* _editor) temporalAACheckBox.SetTooltip("Toggle Temporal Anti Aliasing. It is a supersampling techique which is performed across multiple frames."); temporalAACheckBox.SetPos(XMFLOAT2(x, y += step)); temporalAACheckBox.SetSize(XMFLOAT2(itemheight, itemheight)); - temporalAACheckBox.OnClick([](wi::gui::EventArgs args) { - wi::renderer::SetTemporalAAEnabled(args.bValue); - }); + if (editor->main->config.GetSection("graphics").Has("temporal_anti_aliasing")) + { + wi::renderer::SetTemporalAAEnabled(editor->main->config.GetSection("graphics").GetBool("temporal_anti_aliasing")); + } temporalAACheckBox.SetCheck(wi::renderer::GetTemporalAAEnabled()); + temporalAACheckBox.OnClick([=](wi::gui::EventArgs args) { + wi::renderer::SetTemporalAAEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("temporal_anti_aliasing", args.bValue); + editor->main->config.Commit(); + }); AddWidget(&temporalAACheckBox); temporalAADebugCheckBox.Create("DEBUGJitter: "); @@ -551,8 +616,17 @@ void GraphicsWindow::Create(EditorComponent* _editor) wi::renderer::ModifyObjectSampler(desc); + editor->main->config.GetSection("graphics").Set("texture_quality", args.iValue); + editor->main->config.Commit(); }); - textureQualityComboBox.SetSelected(3); + if (editor->main->config.GetSection("graphics").Has("texture_quality")) + { + textureQualityComboBox.SetSelected(editor->main->config.GetSection("graphics").GetInt("texture_quality")); + } + else + { + textureQualityComboBox.SetSelected(3); + } textureQualityComboBox.SetTooltip("Choose a texture sampling method for material textures."); AddWidget(&textureQualityComboBox); @@ -560,10 +634,13 @@ void GraphicsWindow::Create(EditorComponent* _editor) mipLodBiasSlider.SetTooltip("Bias the rendered mip map level of the material textures."); mipLodBiasSlider.SetSize(XMFLOAT2(wid, itemheight)); mipLodBiasSlider.SetPos(XMFLOAT2(x, y += step)); + mipLodBiasSlider.SetValue(editor->main->config.GetSection("graphics").GetFloat("mip_lod_bias")); mipLodBiasSlider.OnSlide([&](wi::gui::EventArgs args) { wi::graphics::SamplerDesc desc = wi::renderer::GetSampler(wi::enums::SAMPLER_OBJECTSHADER)->GetDesc(); desc.mip_lod_bias = wi::math::Clamp(args.fValue, -15.9f, 15.9f); wi::renderer::ModifyObjectSampler(desc); + editor->main->config.GetSection("graphics").Set("mip_lod_bias", args.fValue); + editor->main->config.Commit(); }); AddWidget(&mipLodBiasSlider); @@ -571,9 +648,15 @@ void GraphicsWindow::Create(EditorComponent* _editor) raytraceBounceCountSlider.SetTooltip("How many light bounces to compute when doing these ray tracing effects:\n- Path tracing\n- Lightmap baking"); raytraceBounceCountSlider.SetSize(XMFLOAT2(wid, itemheight)); raytraceBounceCountSlider.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("graphics").Has("raytracing_bounce_count")) + { + wi::renderer::SetRaytraceBounceCount(editor->main->config.GetSection("graphics").GetInt("raytracing_bounce_count")); + } raytraceBounceCountSlider.SetValue((float)wi::renderer::GetRaytraceBounceCount()); raytraceBounceCountSlider.OnSlide([&](wi::gui::EventArgs args) { wi::renderer::SetRaytraceBounceCount((uint32_t)args.iValue); + editor->main->config.GetSection("graphics").Set("raytracing_bounces", args.iValue); + editor->main->config.Commit(); }); AddWidget(&raytraceBounceCountSlider); @@ -624,8 +707,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) exposureSlider.SetScriptTip("RenderPath3D::SetExposure(float value)"); exposureSlider.SetSize(XMFLOAT2(wid, hei)); exposureSlider.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("graphics").Has("tonemap_exposure")) + { + editor->renderPath->setExposure(editor->main->config.GetSection("graphics").GetFloat("tonemap_exposure")); + } exposureSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setExposure(args.fValue); + editor->main->config.GetSection("graphics").Set("tonemap_exposure", args.fValue); + editor->main->config.Commit(); }); AddWidget(&exposureSlider); @@ -634,8 +723,11 @@ void GraphicsWindow::Create(EditorComponent* _editor) lensFlareCheckBox.SetScriptTip("RenderPath3D::SetLensFlareEnabled(bool value)"); lensFlareCheckBox.SetSize(XMFLOAT2(hei, hei)); lensFlareCheckBox.SetPos(XMFLOAT2(x, y += step)); + editor->renderPath->setLensFlareEnabled(editor->main->config.GetSection("graphics").GetBool("lensflare")); lensFlareCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setLensFlareEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("lensflare", args.bValue); + editor->main->config.Commit(); }); AddWidget(&lensFlareCheckBox); @@ -644,8 +736,11 @@ void GraphicsWindow::Create(EditorComponent* _editor) lightShaftsCheckBox.SetScriptTip("RenderPath3D::SetLightShaftsEnabled(bool value)"); lightShaftsCheckBox.SetSize(XMFLOAT2(hei, hei)); lightShaftsCheckBox.SetPos(XMFLOAT2(x, y += step)); + editor->renderPath->setLightShaftsEnabled(editor->main->config.GetSection("graphics").GetBool("lightshafts")); lightShaftsCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setLightShaftsEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("lightshafts", args.bValue); + editor->main->config.Commit(); }); AddWidget(&lightShaftsCheckBox); @@ -653,14 +748,21 @@ void GraphicsWindow::Create(EditorComponent* _editor) lightShaftsStrengthStrengthSlider.SetTooltip("Set light shaft strength."); lightShaftsStrengthStrengthSlider.SetSize(XMFLOAT2(mod_wid, hei)); lightShaftsStrengthStrengthSlider.SetPos(XMFLOAT2(x + 100, y)); + if (editor->main->config.GetSection("graphics").GetBool("lightshafts_strength")) + { + editor->renderPath->setLightShaftsStrength(editor->main->config.GetSection("graphics").GetFloat("lightshafts_strength")); + } lightShaftsStrengthStrengthSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setLightShaftsStrength(args.fValue); + editor->main->config.GetSection("graphics").Set("lightshafts_strength", args.fValue); + editor->main->config.Commit(); }); AddWidget(&lightShaftsStrengthStrengthSlider); aoComboBox.Create("AO: "); aoComboBox.SetTooltip("Choose Ambient Occlusion type. RTAO is only available if hardware supports ray tracing"); aoComboBox.SetScriptTip("RenderPath3D::SetAO(int value)"); + int ao = editor->main->config.GetSection("graphics").GetInt("ambient_occlusion"); aoComboBox.SetSize(XMFLOAT2(wid, hei)); aoComboBox.SetPos(XMFLOAT2(x, y += step)); aoComboBox.AddItem("Disabled"); @@ -670,40 +772,32 @@ void GraphicsWindow::Create(EditorComponent* _editor) if (wi::graphics::GetDevice()->CheckCapability(GraphicsDeviceCapability::RAYTRACING)) { aoComboBox.AddItem("RTAO"); + ao = std::min(ao, 4); + } + else + { + ao = std::min(ao, 3); } aoComboBox.OnSelect([=](wi::gui::EventArgs args) { editor->renderPath->setAO((wi::RenderPath3D::AO)args.iValue); - - switch (editor->renderPath->getAO()) - { - case wi::RenderPath3D::AO_SSAO: - aoRangeSlider.SetEnabled(true); - aoRangeSlider.SetValue(2.0f); - aoSampleCountSlider.SetEnabled(true); - aoSampleCountSlider.SetValue(9.0f); - break; - case wi::RenderPath3D::AO_RTAO: - aoRangeSlider.SetEnabled(true); - aoRangeSlider.SetValue(10.0f); - aoSampleCountSlider.SetEnabled(false); - break; - default: - aoRangeSlider.SetEnabled(false); - aoSampleCountSlider.SetEnabled(false); - break; - } - - editor->renderPath->setAORange(aoRangeSlider.GetValue()); - editor->renderPath->setAOSampleCount((uint32_t)aoSampleCountSlider.GetValue()); + editor->main->config.GetSection("graphics").Set("ambient_occlusion", args.iValue); + editor->main->config.Commit(); }); + aoComboBox.SetSelected(ao); AddWidget(&aoComboBox); aoPowerSlider.Create(0.25f, 8.0f, 2, 1000, "Power: "); aoPowerSlider.SetTooltip("Set SSAO Power. Higher values produce darker, more pronounced effect"); aoPowerSlider.SetSize(XMFLOAT2(mod_wid, hei)); aoPowerSlider.SetPos(XMFLOAT2(x + 100, y += step)); + if (editor->main->config.GetSection("graphics").GetBool("ambient_occlusion_power")) + { + editor->renderPath->setAOPower(editor->main->config.GetSection("graphics").GetFloat("ambient_occlusion_power")); + } aoPowerSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setAOPower(args.fValue); + editor->main->config.GetSection("graphics").Set("ambient_occlusion_power", args.fValue); + editor->main->config.Commit(); }); AddWidget(&aoPowerSlider); @@ -711,8 +805,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) aoRangeSlider.SetTooltip("Set AO ray length. Only for SSAO and RTAO"); aoRangeSlider.SetSize(XMFLOAT2(mod_wid, hei)); aoRangeSlider.SetPos(XMFLOAT2(x + 100, y += step)); + if (editor->main->config.GetSection("graphics").GetBool("ambient_occlusion_range")) + { + editor->renderPath->setAORange(editor->main->config.GetSection("graphics").GetFloat("ambient_occlusion_range")); + } aoRangeSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setAORange(args.fValue); + editor->main->config.GetSection("graphics").Set("ambient_occlusion_range", args.fValue); + editor->main->config.Commit(); }); AddWidget(&aoRangeSlider); @@ -730,8 +830,11 @@ void GraphicsWindow::Create(EditorComponent* _editor) ssrCheckBox.SetScriptTip("RenderPath3D::SetSSREnabled(bool value)"); ssrCheckBox.SetSize(XMFLOAT2(hei, hei)); ssrCheckBox.SetPos(XMFLOAT2(x, y += step)); + editor->renderPath->setSSREnabled(editor->main->config.GetSection("graphics").GetBool("screen_space_reflections")); ssrCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setSSREnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("screen_space_reflections", args.bValue); + editor->main->config.Commit(); }); AddWidget(&ssrCheckBox); @@ -740,8 +843,11 @@ void GraphicsWindow::Create(EditorComponent* _editor) raytracedReflectionsCheckBox.SetScriptTip("RenderPath3D::SetRaytracedReflectionsEnabled(bool value)"); raytracedReflectionsCheckBox.SetSize(XMFLOAT2(hei, hei)); raytracedReflectionsCheckBox.SetPos(XMFLOAT2(x + 140, y)); + editor->renderPath->setRaytracedReflectionsEnabled(editor->main->config.GetSection("graphics").GetBool("raytraced_reflections")); raytracedReflectionsCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setRaytracedReflectionsEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("raytraced_reflections", args.bValue); + editor->main->config.Commit(); }); AddWidget(&raytracedReflectionsCheckBox); raytracedReflectionsCheckBox.SetEnabled(wi::graphics::GetDevice()->CheckCapability(GraphicsDeviceCapability::RAYTRACING)); @@ -750,9 +856,11 @@ void GraphicsWindow::Create(EditorComponent* _editor) screenSpaceShadowsCheckBox.SetTooltip("Enable screen space contact shadows. This can add small shadows details to shadow maps in screen space."); screenSpaceShadowsCheckBox.SetSize(XMFLOAT2(hei, hei)); screenSpaceShadowsCheckBox.SetPos(XMFLOAT2(x, y += step)); - screenSpaceShadowsCheckBox.SetCheck(wi::renderer::GetScreenSpaceShadowsEnabled()); + wi::renderer::SetScreenSpaceShadowsEnabled(editor->main->config.GetSection("graphics").GetBool("screen_space_shadows")); screenSpaceShadowsCheckBox.OnClick([=](wi::gui::EventArgs args) { wi::renderer::SetScreenSpaceShadowsEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("screen_space_shadows", args.bValue); + editor->main->config.Commit(); }); AddWidget(&screenSpaceShadowsCheckBox); @@ -760,8 +868,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) screenSpaceShadowsRangeSlider.SetTooltip("Range of contact shadows"); screenSpaceShadowsRangeSlider.SetSize(XMFLOAT2(mod_wid, hei)); screenSpaceShadowsRangeSlider.SetPos(XMFLOAT2(x + 100, y)); + if (editor->main->config.GetSection("graphics").Has("screen_space_shadows_range")) + { + editor->renderPath->setScreenSpaceShadowRange(editor->main->config.GetSection("graphics").GetFloat("screen_space_shadows_range")); + } screenSpaceShadowsRangeSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setScreenSpaceShadowRange(args.fValue); + editor->main->config.GetSection("graphics").Set("screen_space_shadows_range", args.fValue); + editor->main->config.Commit(); }); AddWidget(&screenSpaceShadowsRangeSlider); @@ -769,8 +883,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) screenSpaceShadowsStepCountSlider.SetTooltip("Sample count of contact shadows. Higher values are better quality but slower."); screenSpaceShadowsStepCountSlider.SetSize(XMFLOAT2(mod_wid, hei)); screenSpaceShadowsStepCountSlider.SetPos(XMFLOAT2(x + 100, y += step)); + if (editor->main->config.GetSection("graphics").Has("screen_space_shadows_samples")) + { + editor->renderPath->setScreenSpaceShadowSampleCount(editor->main->config.GetSection("graphics").GetInt("screen_space_shadows_samples")); + } screenSpaceShadowsStepCountSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setScreenSpaceShadowSampleCount(args.iValue); + editor->main->config.GetSection("graphics").Set("screen_space_shadows_samples", args.iValue); + editor->main->config.Commit(); }); AddWidget(&screenSpaceShadowsStepCountSlider); @@ -778,8 +898,11 @@ void GraphicsWindow::Create(EditorComponent* _editor) eyeAdaptionCheckBox.SetTooltip("Enable eye adaption for the overall screen luminance"); eyeAdaptionCheckBox.SetSize(XMFLOAT2(hei, hei)); eyeAdaptionCheckBox.SetPos(XMFLOAT2(x, y += step)); + editor->renderPath->setEyeAdaptionEnabled(editor->main->config.GetSection("graphics").GetBool("eye_adaption")); eyeAdaptionCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setEyeAdaptionEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("eye_adaption", args.bValue); + editor->main->config.Commit(); }); AddWidget(&eyeAdaptionCheckBox); @@ -787,8 +910,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) eyeAdaptionKeySlider.SetTooltip("Set the key value for eye adaption."); eyeAdaptionKeySlider.SetSize(XMFLOAT2(mod_wid, hei)); eyeAdaptionKeySlider.SetPos(XMFLOAT2(x + 100, y)); + if (editor->main->config.GetSection("graphics").Has("eye_adaption_key")) + { + editor->renderPath->setEyeAdaptionKey(editor->main->config.GetSection("graphics").GetFloat("eye_adaption_key")); + } eyeAdaptionKeySlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setEyeAdaptionKey(args.fValue); + editor->main->config.GetSection("graphics").Set("eye_adaption_key", args.fValue); + editor->main->config.Commit(); }); AddWidget(&eyeAdaptionKeySlider); @@ -796,8 +925,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) eyeAdaptionRateSlider.SetTooltip("Set the eye adaption rate (speed of adjustment)"); eyeAdaptionRateSlider.SetSize(XMFLOAT2(mod_wid, hei)); eyeAdaptionRateSlider.SetPos(XMFLOAT2(x + 100, y += step)); + if (editor->main->config.GetSection("graphics").Has("eye_adaption_rate")) + { + editor->renderPath->setEyeAdaptionRate(editor->main->config.GetSection("graphics").GetFloat("eye_adaption_rate")); + } eyeAdaptionRateSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setEyeAdaptionRate(args.fValue); + editor->main->config.GetSection("graphics").Set("eye_adaption_rate", args.fValue); + editor->main->config.Commit(); }); AddWidget(&eyeAdaptionRateSlider); @@ -806,8 +941,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) motionBlurCheckBox.SetScriptTip("RenderPath3D::SetMotionBlurEnabled(bool value)"); motionBlurCheckBox.SetSize(XMFLOAT2(hei, hei)); motionBlurCheckBox.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("graphics").Has("motion_blur")) + { + editor->renderPath->setMotionBlurEnabled(editor->main->config.GetSection("graphics").GetBool("motion_blur")); + } motionBlurCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setMotionBlurEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("motion_blur", args.bValue); + editor->main->config.Commit(); }); AddWidget(&motionBlurCheckBox); @@ -816,8 +957,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) motionBlurStrengthSlider.SetScriptTip("RenderPath3D::SetMotionBlurStrength(float value)"); motionBlurStrengthSlider.SetSize(XMFLOAT2(mod_wid, hei)); motionBlurStrengthSlider.SetPos(XMFLOAT2(x + 100, y)); + if (editor->main->config.GetSection("graphics").Has("motion_blur_strength")) + { + editor->renderPath->setMotionBlurStrength(editor->main->config.GetSection("graphics").GetFloat("motion_blur_strength")); + } motionBlurStrengthSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setMotionBlurStrength(args.fValue); + editor->main->config.GetSection("graphics").Set("motion_blur_strength", args.fValue); + editor->main->config.Commit(); }); AddWidget(&motionBlurStrengthSlider); @@ -826,8 +973,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) depthOfFieldCheckBox.SetScriptTip("RenderPath3D::SetDepthOfFieldEnabled(bool value)"); depthOfFieldCheckBox.SetSize(XMFLOAT2(hei, hei)); depthOfFieldCheckBox.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("graphics").Has("depth_of_field")) + { + editor->renderPath->setDepthOfFieldEnabled(editor->main->config.GetSection("graphics").GetBool("depth_of_field")); + } depthOfFieldCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setDepthOfFieldEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("depth_of_field", args.bValue); + editor->main->config.Commit(); }); AddWidget(&depthOfFieldCheckBox); @@ -836,8 +989,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) depthOfFieldScaleSlider.SetScriptTip("RenderPath3D::SetDepthOfFieldStrength(float value)"); depthOfFieldScaleSlider.SetSize(XMFLOAT2(mod_wid, hei)); depthOfFieldScaleSlider.SetPos(XMFLOAT2(x + 100, y)); + if (editor->main->config.GetSection("graphics").Has("depth_of_field_strength")) + { + editor->renderPath->setDepthOfFieldStrength(editor->main->config.GetSection("graphics").GetFloat("depth_of_field_strength")); + } depthOfFieldScaleSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setDepthOfFieldStrength(args.fValue); + editor->main->config.GetSection("graphics").Set("depth_of_field_strength", args.fValue); + editor->main->config.Commit(); }); AddWidget(&depthOfFieldScaleSlider); @@ -846,8 +1005,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) bloomCheckBox.SetScriptTip("RenderPath3D::SetBloomEnabled(bool value)"); bloomCheckBox.SetSize(XMFLOAT2(hei, hei)); bloomCheckBox.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("graphics").Has("bloom")) + { + editor->renderPath->setBloomEnabled(editor->main->config.GetSection("graphics").GetBool("bloom")); + } bloomCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setBloomEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("bloom", args.bValue); + editor->main->config.Commit(); }); AddWidget(&bloomCheckBox); @@ -855,8 +1020,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) bloomStrengthSlider.SetTooltip("Set bloom threshold. The values below this will not glow on the screen."); bloomStrengthSlider.SetSize(XMFLOAT2(mod_wid, hei)); bloomStrengthSlider.SetPos(XMFLOAT2(x + 100, y)); + if (editor->main->config.GetSection("graphics").Has("bloom_threshold")) + { + editor->renderPath->setBloomThreshold(editor->main->config.GetSection("graphics").GetFloat("bloom_threshold")); + } bloomStrengthSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setBloomThreshold(args.fValue); + editor->main->config.GetSection("graphics").Set("bloom_threshold", args.fValue); + editor->main->config.Commit(); }); AddWidget(&bloomStrengthSlider); @@ -865,8 +1036,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) fxaaCheckBox.SetScriptTip("RenderPath3D::SetFXAAEnabled(bool value)"); fxaaCheckBox.SetSize(XMFLOAT2(hei, hei)); fxaaCheckBox.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("graphics").Has("fxaa")) + { + editor->renderPath->setFXAAEnabled(editor->main->config.GetSection("graphics").GetBool("fxaa")); + } fxaaCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setFXAAEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("fxaa", args.bValue); + editor->main->config.Commit(); }); AddWidget(&fxaaCheckBox); @@ -874,8 +1051,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) colorGradingCheckBox.SetTooltip("Enable color grading of the final render. An additional lookup texture must be set in the Weather!"); colorGradingCheckBox.SetSize(XMFLOAT2(hei, hei)); colorGradingCheckBox.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("graphics").Has("color_grading")) + { + editor->renderPath->setColorGradingEnabled(editor->main->config.GetSection("graphics").GetBool("color_grading")); + } colorGradingCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setColorGradingEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("color_grading", args.bValue); + editor->main->config.Commit(); }); AddWidget(&colorGradingCheckBox); @@ -883,8 +1066,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) ditherCheckBox.SetTooltip("Toggle the full screen dithering effect. This helps to reduce color banding."); ditherCheckBox.SetSize(XMFLOAT2(hei, hei)); ditherCheckBox.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("graphics").Has("dithering")) + { + editor->renderPath->setDitherEnabled(editor->main->config.GetSection("graphics").GetBool("dithering")); + } ditherCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setDitherEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("dithering", args.bValue); + editor->main->config.Commit(); }); AddWidget(&ditherCheckBox); @@ -893,27 +1082,45 @@ void GraphicsWindow::Create(EditorComponent* _editor) sharpenFilterCheckBox.SetScriptTip("RenderPath3D::SetSharpenFilterEnabled(bool value)"); sharpenFilterCheckBox.SetSize(XMFLOAT2(hei, hei)); sharpenFilterCheckBox.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("graphics").Has("sharpen")) + { + editor->renderPath->setSharpenFilterEnabled(editor->main->config.GetSection("graphics").GetBool("sharpen")); + } sharpenFilterCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setSharpenFilterEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("sharpen", args.bValue); + editor->main->config.Commit(); }); AddWidget(&sharpenFilterCheckBox); - sharpenFilterAmountSlider.Create(0, 4, 1, 1000, "Amount: "); + sharpenFilterAmountSlider.Create(0, 4, 1, 1000, "Strength: "); sharpenFilterAmountSlider.SetTooltip("Set sharpness filter strength."); sharpenFilterAmountSlider.SetScriptTip("RenderPath3D::SetSharpenFilterAmount(float value)"); sharpenFilterAmountSlider.SetSize(XMFLOAT2(mod_wid, hei)); sharpenFilterAmountSlider.SetPos(XMFLOAT2(x + 100, y)); + if (editor->main->config.GetSection("graphics").Has("sharpen_strength")) + { + editor->renderPath->setSharpenFilterAmount(editor->main->config.GetSection("graphics").GetFloat("sharpen_strength")); + } sharpenFilterAmountSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setSharpenFilterAmount(args.fValue); + editor->main->config.GetSection("graphics").Set("sharpen_strength", args.fValue); + editor->main->config.Commit(); }); AddWidget(&sharpenFilterAmountSlider); outlineCheckBox.Create("Cartoon Outline: "); - outlineCheckBox.SetTooltip("Toggle the cartoon outline effect. Only those materials will be outlined that have Outline enabled."); + outlineCheckBox.SetTooltip("Toggle the cartoon outline effect. Only those materials will be outlined that have Cartoon Outline enabled."); outlineCheckBox.SetSize(XMFLOAT2(hei, hei)); outlineCheckBox.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("graphics").Has("cartoon_outline")) + { + editor->renderPath->setOutlineEnabled(editor->main->config.GetSection("graphics").GetBool("cartoon_outline")); + } outlineCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setOutlineEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("cartoon_outline", args.bValue); + editor->main->config.Commit(); }); AddWidget(&outlineCheckBox); @@ -921,8 +1128,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) outlineThresholdSlider.SetTooltip("Outline edge detection threshold. Increase if not enough otlines are detected, decrease if too many outlines are detected."); outlineThresholdSlider.SetSize(XMFLOAT2(mod_wid, hei)); outlineThresholdSlider.SetPos(XMFLOAT2(x + 100, y)); + if (editor->main->config.GetSection("graphics").Has("cartoon_outline_threshold")) + { + editor->renderPath->setOutlineThreshold(editor->main->config.GetSection("graphics").GetFloat("cartoon_outline_threshold")); + } outlineThresholdSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setOutlineThreshold(args.fValue); + editor->main->config.GetSection("graphics").Set("cartoon_outline_threshold", args.fValue); + editor->main->config.Commit(); }); AddWidget(&outlineThresholdSlider); @@ -930,8 +1143,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) outlineThicknessSlider.SetTooltip("Set outline thickness."); outlineThicknessSlider.SetSize(XMFLOAT2(mod_wid, hei)); outlineThicknessSlider.SetPos(XMFLOAT2(x + 100, y += step)); + if (editor->main->config.GetSection("graphics").Has("cartoon_outline_thickness")) + { + editor->renderPath->setOutlineThickness(editor->main->config.GetSection("graphics").GetFloat("cartoon_outline_thickness")); + } outlineThicknessSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setOutlineThickness(args.fValue); + editor->main->config.GetSection("graphics").Set("cartoon_outline_thickness", args.fValue); + editor->main->config.Commit(); }); AddWidget(&outlineThicknessSlider); @@ -939,17 +1158,29 @@ void GraphicsWindow::Create(EditorComponent* _editor) chromaticaberrationCheckBox.SetTooltip("Toggle the full screen chromatic aberration effect. This simulates lens distortion at screen edges."); chromaticaberrationCheckBox.SetSize(XMFLOAT2(hei, hei)); chromaticaberrationCheckBox.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("graphics").Has("chromatic_aberration")) + { + editor->renderPath->setChromaticAberrationEnabled(editor->main->config.GetSection("graphics").GetBool("chromatic_aberration")); + } chromaticaberrationCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setChromaticAberrationEnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("chromatic_aberration", args.bValue); + editor->main->config.Commit(); }); AddWidget(&chromaticaberrationCheckBox); - chromaticaberrationSlider.Create(0, 40, 1.0f, 1000, "Amount: "); + chromaticaberrationSlider.Create(0, 40, 1.0f, 1000, "Strength: "); chromaticaberrationSlider.SetTooltip("The lens distortion amount."); chromaticaberrationSlider.SetSize(XMFLOAT2(mod_wid, hei)); chromaticaberrationSlider.SetPos(XMFLOAT2(x + 100, y)); + if (editor->main->config.GetSection("graphics").Has("chromatic_aberration_strength")) + { + editor->renderPath->setChromaticAberrationAmount(editor->main->config.GetSection("graphics").GetFloat("chromatic_aberration_strength")); + } chromaticaberrationSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setChromaticAberrationAmount(args.fValue); + editor->main->config.GetSection("graphics").Set("chromatic_aberration_strength", args.fValue); + editor->main->config.Commit(); }); AddWidget(&chromaticaberrationSlider); @@ -957,8 +1188,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) fsrCheckBox.SetTooltip("FidelityFX FSR Upscaling. Use this only with Temporal AA or MSAA when the resolution scaling is lowered."); fsrCheckBox.SetSize(XMFLOAT2(hei, hei)); fsrCheckBox.SetPos(XMFLOAT2(x, y += step)); + if (editor->main->config.GetSection("graphics").Has("fsr")) + { + editor->renderPath->setFSREnabled(editor->main->config.GetSection("graphics").GetBool("fsr")); + } fsrCheckBox.OnClick([=](wi::gui::EventArgs args) { editor->renderPath->setFSREnabled(args.bValue); + editor->main->config.GetSection("graphics").Set("fsr", args.bValue); + editor->main->config.Commit(); }); AddWidget(&fsrCheckBox); @@ -966,8 +1203,14 @@ void GraphicsWindow::Create(EditorComponent* _editor) fsrSlider.SetTooltip("The sharpening amount to apply for FSR upscaling."); fsrSlider.SetSize(XMFLOAT2(mod_wid, hei)); fsrSlider.SetPos(XMFLOAT2(x + 100, y)); + if (editor->main->config.GetSection("graphics").Has("fsr_sharpness")) + { + editor->renderPath->setFSRSharpness(editor->main->config.GetSection("graphics").GetFloat("fsr_sharpness")); + } fsrSlider.OnSlide([=](wi::gui::EventArgs args) { editor->renderPath->setFSRSharpness(args.fValue); + editor->main->config.GetSection("graphics").Set("fsr_sharpness", args.fValue); + editor->main->config.Commit(); }); AddWidget(&fsrSlider); @@ -1153,6 +1396,21 @@ void GraphicsWindow::UpdateSwapChainFormats(wi::graphics::SwapChain* swapChain) void GraphicsWindow::Update() { + if (vsyncCheckBox.GetCheck() != editor->main->swapChain.desc.vsync) + { + wi::eventhandler::SetVSync(vsyncCheckBox.GetCheck()); + } + if (editor->resolutionScale != editor->renderPath->resolutionScale) + { + editor->renderPath->resolutionScale = editor->resolutionScale; + editor->ResizeBuffers(); + } + if (MSAAComboBox.GetItemUserData(MSAAComboBox.GetSelected()) != editor->renderPath->getMSAASampleCount()) + { + editor->renderPath->setMSAASampleCount((uint32_t)MSAAComboBox.GetItemUserData(MSAAComboBox.GetSelected())); + editor->ResizeBuffers(); + } + if (IsCollapsed()) return; @@ -1162,6 +1420,8 @@ void GraphicsWindow::Update() ddgiY.SetValue(std::to_string(scene.ddgi.grid_dimensions.y)); ddgiZ.SetValue(std::to_string(scene.ddgi.grid_dimensions.z)); + occlusionCullingCheckBox.SetCheck(wi::renderer::GetOcclusionCullingEnabled()); + GIBoostSlider.SetValue(wi::renderer::GetGIBoost()); visibilityComputeShadingCheckBox.SetCheck(editor->renderPath->visibility_shading_in_compute); resolutionScaleSlider.SetValue(editor->resolutionScale); MSAAComboBox.SetSelectedByUserdataWithoutCallback(editor->renderPath->getMSAASampleCount()); @@ -1171,10 +1431,27 @@ void GraphicsWindow::Update() lightShaftsStrengthStrengthSlider.SetValue(editor->renderPath->getLightShaftsStrength()); aoComboBox.SetSelectedWithoutCallback(editor->renderPath->getAO()); aoPowerSlider.SetValue((float)editor->renderPath->getAOPower()); - aoRangeSlider.SetValue((float)editor->renderPath->getAOPower()); - aoSampleCountSlider.SetValue((float)editor->renderPath->getAOPower()); + + aoRangeSlider.SetEnabled(false); + aoSampleCountSlider.SetEnabled(false); + switch (editor->renderPath->getAO()) + { + case wi::RenderPath3D::AO_SSAO: + aoRangeSlider.SetEnabled(true); + aoSampleCountSlider.SetEnabled(true); + break; + case wi::RenderPath3D::AO_RTAO: + aoRangeSlider.SetEnabled(true); + break; + default: + break; + } + + aoRangeSlider.SetValue((float)editor->renderPath->getAORange()); + aoSampleCountSlider.SetValue((float)editor->renderPath->getAOSampleCount()); ssrCheckBox.SetCheck(editor->renderPath->getSSREnabled()); raytracedReflectionsCheckBox.SetCheck(editor->renderPath->getRaytracedReflectionEnabled()); + screenSpaceShadowsCheckBox.SetCheck(wi::renderer::GetScreenSpaceShadowsEnabled()); screenSpaceShadowsRangeSlider.SetValue((float)editor->renderPath->getScreenSpaceShadowRange()); screenSpaceShadowsStepCountSlider.SetValue((float)editor->renderPath->getScreenSpaceShadowSampleCount()); eyeAdaptionCheckBox.SetCheck(editor->renderPath->getEyeAdaptionEnabled()); diff --git a/Editor/IconDefinitions.h b/Editor/IconDefinitions.h index 07aae2032..854228ca2 100644 --- a/Editor/IconDefinitions.h +++ b/Editor/IconDefinitions.h @@ -52,6 +52,7 @@ #define ICON_PLAY ICON_FA_PLAY #define ICON_PAUSE ICON_FA_PAUSE #define ICON_STOP ICON_FA_STOP +#define ICON_PEN ICON_FA_PEN #define ICON_DARK ICON_FA_MOON #define ICON_BRIGHT ICON_FA_SUN diff --git a/Editor/OptionsWindow.cpp b/Editor/OptionsWindow.cpp index 6542942f9..c71552acc 100644 --- a/Editor/OptionsWindow.cpp +++ b/Editor/OptionsWindow.cpp @@ -82,22 +82,38 @@ void OptionsWindow::Create(EditorComponent* _editor) versionCheckBox.Create("Version: "); versionCheckBox.SetTooltip("Toggle the engine version display text in top left corner."); + editor->main->infoDisplay.watermark = editor->main->config.GetSection("options").GetBool("version"); + versionCheckBox.SetCheck(editor->main->infoDisplay.watermark); versionCheckBox.OnClick([&](wi::gui::EventArgs args) { editor->main->infoDisplay.watermark = args.bValue; + editor->main->config.GetSection("options").Set("version", args.bValue); + editor->main->config.Commit(); }); AddWidget(&versionCheckBox); versionCheckBox.SetCheck(editor->main->infoDisplay.watermark); fpsCheckBox.Create("FPS: "); fpsCheckBox.SetTooltip("Toggle the FPS display text in top left corner."); + editor->main->infoDisplay.fpsinfo = editor->main->config.GetSection("options").GetBool("fps"); + fpsCheckBox.SetCheck(editor->main->infoDisplay.fpsinfo); fpsCheckBox.OnClick([&](wi::gui::EventArgs args) { editor->main->infoDisplay.fpsinfo = args.bValue; + editor->main->config.GetSection("options").Set("fps", args.bValue); + editor->main->config.Commit(); }); AddWidget(&fpsCheckBox); fpsCheckBox.SetCheck(editor->main->infoDisplay.fpsinfo); otherinfoCheckBox.Create("Info: "); otherinfoCheckBox.SetTooltip("Toggle advanced data in the info display text in top left corner."); + bool info = editor->main->config.GetSection("options").GetBool("info"); + editor->main->infoDisplay.heap_allocation_counter = info; + editor->main->infoDisplay.vram_usage = info; + editor->main->infoDisplay.colorspace = info; + editor->main->infoDisplay.resolution = info; + editor->main->infoDisplay.logical_size = info; + editor->main->infoDisplay.pipeline_count = info; + otherinfoCheckBox.SetCheck(info); otherinfoCheckBox.OnClick([&](wi::gui::EventArgs args) { editor->main->infoDisplay.heap_allocation_counter = args.bValue; editor->main->infoDisplay.vram_usage = args.bValue; @@ -105,6 +121,8 @@ void OptionsWindow::Create(EditorComponent* _editor) editor->main->infoDisplay.resolution = args.bValue; editor->main->infoDisplay.logical_size = args.bValue; editor->main->infoDisplay.pipeline_count = args.bValue; + editor->main->config.GetSection("options").Set("info", args.bValue); + editor->main->config.Commit(); }); AddWidget(&otherinfoCheckBox); otherinfoCheckBox.SetCheck(editor->main->infoDisplay.heap_allocation_counter); @@ -324,7 +342,6 @@ void OptionsWindow::Create(EditorComponent* _editor) AddWidget(&graphicsWnd); cameraWnd.Create(editor); - cameraWnd.ResetCam(); cameraWnd.SetCollapsed(true); AddWidget(&cameraWnd); @@ -357,6 +374,11 @@ void OptionsWindow::Create(EditorComponent* _editor) saveModeComboBox.SetTooltip("Choose whether to embed resources (textures, sounds...) in the scene file when saving, or keep them as separate files.\nThe Dump to header option will use embedding and create a C++ header file with byte data of the scene to be used with wi::Archive serialization."); saveModeComboBox.SetColor(wi::Color(50, 180, 100, 180), wi::gui::IDLE); saveModeComboBox.SetColor(wi::Color(50, 220, 140, 255), wi::gui::FOCUS); + saveModeComboBox.SetSelected(editor->main->config.GetSection("options").GetInt("save_mode")); + saveModeComboBox.OnSelect([=](wi::gui::EventArgs args) { + editor->main->config.GetSection("options").Set("save_mode", args.iValue); + editor->main->config.Commit(); + }); AddWidget(&saveModeComboBox); @@ -528,7 +550,11 @@ void OptionsWindow::Create(EditorComponent* _editor) { default: break; + case Theme::Dark: + editor->main->config.GetSection("options").Set("theme", "Dark"); + break; case Theme::Bright: + editor->main->config.GetSection("options").Set("theme", "Bright"); theme_color_idle = wi::Color(200, 210, 220, 230); theme_color_focus = wi::Color(210, 230, 255, 250); dark_point = wi::Color(180, 180, 190, 230); @@ -536,6 +562,7 @@ void OptionsWindow::Create(EditorComponent* _editor) theme.font.color = wi::Color(50, 50, 80, 255); break; case Theme::Soft: + editor->main->config.GetSection("options").Set("theme", "Soft"); theme_color_idle = wi::Color(200, 180, 190, 190); theme_color_focus = wi::Color(240, 190, 200, 230); dark_point = wi::Color(100, 80, 90, 220); @@ -543,6 +570,7 @@ void OptionsWindow::Create(EditorComponent* _editor) theme.font.color = wi::Color(255, 230, 240, 255); break; case Theme::Hacking: + editor->main->config.GetSection("options").Set("theme", "Hacking"); theme_color_idle = wi::Color(0, 0, 0, 255); theme_color_focus = wi::Color(10, 230, 30, 255); dark_point = wi::Color(0, 0, 0, 255); @@ -551,6 +579,7 @@ void OptionsWindow::Create(EditorComponent* _editor) theme.font.shadow_color = wi::Color::Shadow(); break; } + editor->main->config.Commit(); theme.tooltipImage = theme.image; theme.tooltipImage.color = theme_color_idle; diff --git a/Editor/PaintToolWindow.cpp b/Editor/PaintToolWindow.cpp index eafa20f49..986bc5d53 100644 --- a/Editor/PaintToolWindow.cpp +++ b/Editor/PaintToolWindow.cpp @@ -97,25 +97,25 @@ void PaintToolWindow::Create(EditorComponent* _editor) radiusSlider.SetPos(XMFLOAT2(x, y += step)); AddWidget(&radiusSlider); - amountSlider.Create(0, 1, 1, 10000, "Brush Amount: "); + amountSlider.Create(0, 1, 1, 10000, "Power: "); amountSlider.SetTooltip("Set the brush amount. 0 = minimum affection, 1 = maximum affection"); amountSlider.SetSize(XMFLOAT2(wid, hei)); amountSlider.SetPos(XMFLOAT2(x, y += step)); AddWidget(&amountSlider); - falloffSlider.Create(0, 16, 0, 10000, "Brush Falloff: "); - falloffSlider.SetTooltip("Set the brush power. 0 = no falloff, 1 = linear falloff, more = falloff power"); + falloffSlider.Create(0, 16, 0, 10000, "Smoothness: "); + falloffSlider.SetTooltip("Set the brush power. 0 = hard, greater values will be smoother"); falloffSlider.SetSize(XMFLOAT2(wid, hei)); falloffSlider.SetPos(XMFLOAT2(x, y += step)); AddWidget(&falloffSlider); - spacingSlider.Create(0, 500, 1, 500, "Brush Spacing: "); + spacingSlider.Create(0, 500, 1, 500, "Spacing: "); spacingSlider.SetTooltip("Brush spacing means how much brush movement (in pixels) starts a new stroke. 0 = new stroke every frame, 100 = every 100 pixel movement since last stroke will start a new stroke."); spacingSlider.SetSize(XMFLOAT2(wid, hei)); spacingSlider.SetPos(XMFLOAT2(x, y += step)); AddWidget(&spacingSlider); - rotationSlider.Create(0, 1, 0, 10000, "Brush Rotation: "); + rotationSlider.Create(0, 1, 0, 10000, "Rotation: "); rotationSlider.SetTooltip("Brush rotation randomness. This will affect the splat mode brush texture."); rotationSlider.SetSize(XMFLOAT2(wid, hei)); rotationSlider.SetPos(XMFLOAT2(x, y += step)); @@ -125,6 +125,14 @@ void PaintToolWindow::Create(EditorComponent* _editor) backfaceCheckBox.SetTooltip("Set whether to paint on backfaces of geometry or not"); backfaceCheckBox.SetSize(XMFLOAT2(hei, hei)); backfaceCheckBox.SetPos(XMFLOAT2(x - 20, y += step)); + if (editor->main->config.GetSection("paint_tool").Has("backfaces")) + { + backfaceCheckBox.SetCheck(editor->main->config.GetSection("paint_tool").GetBool("backfaces")); + } + backfaceCheckBox.OnClick([=](wi::gui::EventArgs args) { + editor->main->config.GetSection("paint_tool").Set("backfaces", args.bValue); + editor->main->config.Commit(); + }); AddWidget(&backfaceCheckBox); wireCheckBox.Create("Wireframe: "); @@ -132,13 +140,29 @@ void PaintToolWindow::Create(EditorComponent* _editor) wireCheckBox.SetSize(XMFLOAT2(hei, hei)); wireCheckBox.SetPos(XMFLOAT2(x - 20 + 100, y)); wireCheckBox.SetCheck(true); + if (editor->main->config.GetSection("paint_tool").Has("wireframe")) + { + wireCheckBox.SetCheck(editor->main->config.GetSection("paint_tool").GetBool("wireframe")); + } + wireCheckBox.OnClick([=](wi::gui::EventArgs args) { + editor->main->config.GetSection("paint_tool").Set("wireframe", args.bValue); + editor->main->config.Commit(); + }); AddWidget(&wireCheckBox); pressureCheckBox.Create("Pressure: "); pressureCheckBox.SetTooltip("Set whether to use pressure sensitivity (for example pen tablet)"); pressureCheckBox.SetSize(XMFLOAT2(hei, hei)); pressureCheckBox.SetPos(XMFLOAT2(x - 20 + 200, y)); - pressureCheckBox.SetCheck(false); + if (editor->main->config.GetSection("paint_tool").Has("pressure")) + { + pressureCheckBox.SetCheck(editor->main->config.GetSection("paint_tool").GetBool("pressure")); + } + pressureCheckBox.OnClick([=](wi::gui::EventArgs args) { + editor->main->config.GetSection("paint_tool").Set("pressure", args.bValue); + editor->main->config.Commit(); + }); + pressureCheckBox.SetCheckText(ICON_PEN); AddWidget(&pressureCheckBox); axisCombo.Create("Axis Lock: "); diff --git a/Editor/config.ini b/Editor/config.ini index 9d32b0745..8eedeb200 100644 --- a/Editor/config.ini +++ b/Editor/config.ini @@ -1,8 +1,80 @@ -enabled 0 -x 0 -y 0 -w 3840 -h 2160 -fullscreen 0 -borderless 1 -allow_hdr 1 +;This is a configuration file loaded at program start. +;The application can make changes to values at runtime, and some formatting could be lost +;Use ; or # to make comments +;Commented values will fall back to defaults + +#width = 3840 +#height = 2160 +borderless = false +fullscreen = false +allow_hdr = true #This will enable HDR display output options (if display is HDR capable) + +[options] +save_mode = 0 +theme = Dark +version = false +fps = false +info = false + +[graphics] +vsync = true +resolution_scale = 1.0 +texture_quality = 3 +mip_lod_bias = 0 +occlusion_culling = true +tessellation = true +visibility_compute_shading = false +transparent_shadows = true +temporal_anti_aliasing = false +raytracing_bounces = 3 +gi_boost = 1.0 +msaa = 0 +shadow_resolution_2d = 4 +shadow_resolution_cube = 2 +fxaa = false +bloom = true +bloom_threshold = 3 +tonemap_exposure = 1 +lightshafts = false +lightshafts_strength = 0.05f +lensflare = true +ambient_occlusion = 0 +ambient_occlusion_power = 1 +ambient_occlusion_range = 2 +screen_space_reflections = false +raytraced_reflections = false +screen_space_shadows = false +screen_space_shadows_range = 1.0 +screen_space_shadows_samples = 16 +dithering = true +color_grading = true +eye_adaption = false +eye_adaption_key = 0.1 +eye_adaption_rate = 0.5 +motion_blur = false +motion_blur_strength = 100 +depth_of_field = true +depth_of_field_strength = 10 +sharpen = false +sharpen_strength = 1 +cartoon_outline = false +cartoon_outline_thickness = 1.0 +cartoon_outline_threshold = 0.1 +chromatic_aberration = false +chromatic_aberration_strength = 10 +fsr = true +fsr_sharpness = 1.0 + +[camera] +near = 0.1 +far = 5000 +fov = 60 +move_speed = 5.5 +rotation_speed = 1 +acceleration = 0.18 +fps = true + +[paint_tool] +pressure = true +backfaces = false +wireframe = true diff --git a/Editor/main_SDL2.cpp b/Editor/main_SDL2.cpp index aeba989e9..e7405757e 100644 --- a/Editor/main_SDL2.cpp +++ b/Editor/main_SDL2.cpp @@ -117,27 +117,31 @@ int main(int argc, char *argv[]) throw sdl2::SDLError("Error creating SDL2 system"); } - int x = 0, y = 0, w = 1920, h = 1080; + int width = 1920; + int height = 1080; bool fullscreen = false; - bool borderless = false; - string voidStr = ""; - ifstream file("config.ini"); - if (file.is_open()) - { - int enabled; - file >> voidStr >> enabled; - if (enabled != 0) - { - file >> voidStr >> x >> voidStr >> y >> voidStr >> w >> voidStr >> h >> voidStr >> fullscreen >> voidStr >> borderless; - } - } - file.close(); + wi::Timer timer; + if (editor.config.Open("config.ini")) + { + if (editor.config.Has("width")) + { + width = editor.config.GetInt("width"); + height = editor.config.GetInt("height"); + } + fullscreen = editor.config.GetBool("fullscreen"); + editor.allow_hdr = editor.config.GetBool("allow_hdr"); + + wi::backlog::post("config.ini loaded in " + std::to_string(timer.elapsed_milliseconds()) + " milliseconds\n"); + } + + width = std::max(100, width); + height = std::max(100, height); sdl2::window_ptr_t window = sdl2::make_window( "Wicked Engine Editor", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - w, h, + width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); if (!window) { throw sdl2::SDLError("Error creating window"); diff --git a/Editor/main_Windows.cpp b/Editor/main_Windows.cpp index 66da1ecaf..481e81daf 100644 --- a/Editor/main_Windows.cpp +++ b/Editor/main_Windows.cpp @@ -117,44 +117,57 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // Store instance handle in our global variable - int x = CW_USEDEFAULT, y = 0, w = CW_USEDEFAULT, h = 0; + int width = CW_USEDEFAULT; + int height = 0; bool fullscreen = false; bool borderless = false; - bool allow_hdr = true; - std::string voidStr = ""; - std::ifstream file("config.ini"); - if (file.is_open()) + wi::Timer timer; + if (editor.config.Open("config.ini")) { - int enabled; - file >> voidStr >> enabled; - if (enabled != 0) + if (editor.config.Has("width")) { - file >> voidStr >> x >> voidStr >> y >> voidStr >> w >> voidStr >> h >> voidStr >> fullscreen >> voidStr >> borderless >> voidStr >> allow_hdr; - editor.allow_hdr = allow_hdr; + width = editor.config.GetInt("width"); + height = editor.config.GetInt("height"); } + fullscreen = editor.config.GetBool("fullscreen"); + borderless = editor.config.GetBool("borderless"); + editor.allow_hdr = editor.config.GetBool("allow_hdr"); + + wi::backlog::post("config.ini loaded in " + std::to_string(timer.elapsed_milliseconds()) + " milliseconds\n"); } - file.close(); HWND hWnd = NULL; - if (borderless) + if (borderless || fullscreen) { - hWnd = CreateWindowEx(WS_EX_APPWINDOW, - szWindowClass, - szTitle, - WS_POPUP, - x, y, w, h, - NULL, - NULL, - hInstance, - NULL - ); + width = std::max(100, width); + height = std::max(100, height); + + hWnd = CreateWindowEx( + WS_EX_APPWINDOW, + szWindowClass, + szTitle, + WS_POPUP, + CW_USEDEFAULT, 0, width, height, + NULL, + NULL, + hInstance, + NULL + ); } else { - hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, - x, y, w, h, NULL, NULL, hInstance, NULL); + hWnd = CreateWindow( + szWindowClass, + szTitle, + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, width, height, + NULL, + NULL, + hInstance, + NULL + ); } if (!hWnd) @@ -162,7 +175,18 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) return FALSE; } - editor.SetWindow(hWnd, fullscreen); + if (fullscreen) + { + HMONITOR monitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST); + MONITORINFO info; + info.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(monitor, &info); + width = info.rcMonitor.right - info.rcMonitor.left; + height = info.rcMonitor.bottom - info.rcMonitor.top; + MoveWindow(hWnd, 0, 0, width, height, FALSE); + } + + editor.SetWindow(hWnd); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); @@ -237,6 +261,21 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_INPUT: wi::input::rawinput::ParseMessage((void*)lParam); break; + case WM_POINTERDOWN: + case WM_POINTERUPDATE: + { + POINTER_PEN_INFO pen_info = {}; + if (GetPointerPenInfo(GET_POINTERID_WPARAM(wParam), &pen_info)) + { + ScreenToClient(hWnd, &pen_info.pointerInfo.ptPixelLocation); + const float dpiscaling = (float)GetDpiForWindow(hWnd) / 96.0f; + wi::input::Pen pen; + pen.position = XMFLOAT2(pen_info.pointerInfo.ptPixelLocation.x / dpiscaling, pen_info.pointerInfo.ptPixelLocation.y / dpiscaling); + pen.pressure = float(pen_info.pressure) / 1024.0f; + wi::input::SetPen(pen); + } + } + break; case WM_KILLFOCUS: editor.is_window_active = false; break; diff --git a/WickedEngine/CMakeLists.txt b/WickedEngine/CMakeLists.txt index 58a673ea6..6ffe9e2dc 100644 --- a/WickedEngine/CMakeLists.txt +++ b/WickedEngine/CMakeLists.txt @@ -136,6 +136,7 @@ set(HEADER_FILES wiVector.h wiVersion.h wiXInput.h + wiConfig.h ) add_library(${TARGET_NAME} ${WICKED_LIBRARY_TYPE} @@ -204,6 +205,7 @@ add_library(${TARGET_NAME} ${WICKED_LIBRARY_TYPE} wiVersion.cpp wiXInput.cpp wiShaderCompiler.cpp + wiConfig.cpp ${HEADER_FILES} ) add_library(WickedEngine ALIAS ${TARGET_NAME}) diff --git a/WickedEngine/WickedEngine.h b/WickedEngine/WickedEngine.h index eb5fe0022..e4fd77eb0 100644 --- a/WickedEngine/WickedEngine.h +++ b/WickedEngine/WickedEngine.h @@ -69,6 +69,7 @@ #include "wiUnorderedSet.h" #include "wiVector.h" #include "wiNoise.h" +#include "wiConfig.h" #ifdef _WIN32 #ifdef PLATFORM_UWP diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems b/WickedEngine/WickedEngine_SOURCE.vcxitems index f7d44bf9e..4c9631f67 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems @@ -229,6 +229,7 @@ + @@ -498,6 +499,7 @@ + diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters index d5dc08da2..21b63b779 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters @@ -1077,6 +1077,9 @@ ENGINE\Helpers + + ENGINE\Helpers + @@ -1811,6 +1814,9 @@ ENGINE\System + + ENGINE\Helpers + diff --git a/WickedEngine/wiApplication.cpp b/WickedEngine/wiApplication.cpp index 2619f546c..a9ec2ec1d 100644 --- a/WickedEngine/wiApplication.cpp +++ b/WickedEngine/wiApplication.cpp @@ -454,7 +454,7 @@ namespace wi wi::profiler::EndRange(range); // Compose } - void Application::SetWindow(wi::platform::window_type window, bool fullscreen) + void Application::SetWindow(wi::platform::window_type window) { this->window = window; diff --git a/WickedEngine/wiApplication.h b/WickedEngine/wiApplication.h index 36b70f754..b4a276b27 100644 --- a/WickedEngine/wiApplication.h +++ b/WickedEngine/wiApplication.h @@ -88,7 +88,7 @@ namespace wi virtual void Compose(wi::graphics::CommandList cmd); // You need to call this before calling Run() or Initialize() if you want to render - void SetWindow(wi::platform::window_type, bool fullscreen = false); + void SetWindow(wi::platform::window_type); struct InfoDisplayer diff --git a/WickedEngine/wiConfig.cpp b/WickedEngine/wiConfig.cpp new file mode 100644 index 000000000..1061d9b15 --- /dev/null +++ b/WickedEngine/wiConfig.cpp @@ -0,0 +1,301 @@ +#include "wiConfig.h" +#include "wiHelper.h" + +#include + +namespace wi::config +{ + bool Section::Has(const char* name) const + { + return values.find(name) != values.end(); + } + + bool Section::GetBool(const char* name) const + { + auto it = values.find(name); + if (it == values.end()) + { + return 0; + } + if (!it->second.compare("true")) + { + return true; + } + if (!it->second.compare("false")) + { + return false; + } + return std::stoi(it->second) != 0; + } + int Section::GetInt(const char* name) const + { + auto it = values.find(name); + if (it == values.end()) + { + return 0; + } + if (!it->second.compare("true")) + { + return 1; + } + if (!it->second.compare("false")) + { + return 0; + } + return std::stoi(it->second); + } + float Section::GetFloat(const char* name) const + { + auto it = values.find(name); + if (it == values.end()) + { + return 0; + } + if (!it->second.compare("true")) + { + return 1; + } + if (!it->second.compare("false")) + { + return 0; + } + return std::stof(it->second); + } + std::string Section::GetText(const char* name) const + { + auto it = values.find(name); + if (it == values.end()) + { + return ""; + } + return it->second; + } + + void Section::Set(const char* name, bool value) + { + values[name] = value ? "true" : "false"; + } + void Section::Set(const char* name, int value) + { + values[name] = std::to_string(value); + } + void Section::Set(const char* name, float value) + { + values[name] = std::to_string(value); + } + void Section::Set(const char* name, const char* value) + { + values[name] = value; + } + void Section::Set(const char* name, const std::string& value) + { + values[name] = value; + } + + bool File::Open(const char* filename) + { + this->filename = filename; // even if file couldn't be loaded, we remember the filename so it can be created on commit + wi::vector filedata; + if (!wi::helper::FileRead(filename, filedata)) + return false; + + std::string text = std::string(filedata.begin(), filedata.end()); + std::string key; + std::string value; + std::string section_label; + std::string section_id; + std::string comment; + Section* current_section = this; + enum class State + { + Key, + Value, + Section, + Comment, + } state = State::Key; + for (auto c : text) + { + switch (c) + { + case '\r': + break; + case ';': + case '#': + state = State::Comment; + comment += c; + break; + case ' ': + case '\t': + if (state == State::Value && !value.empty()) + { + value += c; + } + else if (state == State::Comment) + { + comment += c; + } + break; + case '\n': + while (!value.empty() && (value.back() == ' ' || value.back() == '\t')) + { + // trailing whitespaces from values are removed and added as comment: + comment = value.back() + comment; + value.pop_back(); + } + opened_order.emplace_back(); + opened_order.back().section_label = section_label; + section_label.clear(); + opened_order.back().section_id = section_id; + opened_order.back().comment = comment; + if (!key.empty()) + { + opened_order.back().key = key; + current_section->Set(key.c_str(), value); + } + key.clear(); + value.clear(); + comment.clear(); + state = State::Key; + break; + case '=': + if (state == State::Key) + { + state = State::Value; + } + else if (state == State::Value) + { + value += c; + } + else if (state == State::Comment) + { + comment += c; + } + break; + case '[': + if (state == State::Key) + { + state = State::Section; + section_label.clear(); + section_id.clear(); + } + else if (state == State::Value) + { + value += c; + } + else if (state == State::Comment) + { + comment += c; + } + break; + case ']': + if (state == State::Section) + { + sections[section_id] = Section(); + current_section = §ions[section_id]; + state = State::Key; + } + else if (state == State::Value) + { + value += c; + } + else if (state == State::Comment) + { + comment += c; + } + break; + default: + switch (state) + { + case State::Key: + key += c; + break; + case State::Value: + value += c; + break; + case State::Section: + section_label += c; + section_id += c; + break; + case State::Comment: + comment += c; + break; + default: + break; + } + break; + } + } + return true; + } + void File::Commit() + { + std::unordered_map> committed_values; + Section* section = this; + std::string text; + for (auto& line : opened_order) + { + if (line.section_id.empty()) + { + if (!line.key.empty()) + { + text += line.key + " = " + values[line.key]; + committed_values[section].insert(line.key); + } + } + else + { + if (!line.section_label.empty()) + { + // Commit unformatted left over values for previous section: + for (auto& it : section->values) + { + if (committed_values[section].count(it.first) == 0) + { + text += it.first + " = " + it.second + "\n"; + } + } + // Begin new section: + section = §ions[line.section_label]; + text += "[" + line.section_label + "]"; + } + if (!line.key.empty()) + { + text += line.key + " = " + sections[line.section_id].GetText(line.key.c_str()); + committed_values[section].insert(line.key); + } + } + text += line.comment + "\n"; + } + + // Commit left over unformatted sections and values: + for (auto& it : values) + { + if (committed_values[this].count(it.first) == 0) + { + text += it.first + " = " + it.second + "\n"; + } + } + for (auto& it : sections) + { + if (it.second.values.empty()) + continue; + if (committed_values.count(&it.second) == 0) + { + text += "\n[" + it.first + "]\n"; + committed_values[&it.second] = {}; + } + for (auto& it2 : it.second.values) + { + if (committed_values[&it.second].count(it2.first) == 0) + { + text += it2.first + " = " + it2.second + "\n"; + } + } + } + wi::helper::FileWrite(filename, (const uint8_t*)text.c_str(), text.length()); + } + Section& File::GetSection(const char* name) + { + return sections[name]; + } +} diff --git a/WickedEngine/wiConfig.h b/WickedEngine/wiConfig.h new file mode 100644 index 000000000..50565a0dc --- /dev/null +++ b/WickedEngine/wiConfig.h @@ -0,0 +1,56 @@ +#pragma once +#include "CommonInclude.h" + +#include +#include +#include + +namespace wi::config +{ + struct File; + struct Section + { + friend struct File; + + // Check whether the key exists: + bool Has(const char* name) const; + + // Get the associated value for the key: + bool GetBool(const char* name) const; + int GetInt(const char* name) const; + float GetFloat(const char* name) const; + std::string GetText(const char* name) const; + + // Set the associated value for the key: + void Set(const char* name, bool value); + void Set(const char* name, int value); + void Set(const char* name, float value); + void Set(const char* name, const char* value); + void Set(const char* name, const std::string& value); + + protected: + std::unordered_map values; + }; + + struct File : public Section + { + // Open a config file (.ini format) + bool Open(const char* filename); + // Write back the config file with the current keys and values + void Commit(); + // Get access to a named section. If it doesn't exist, then it will be created + Section& GetSection(const char* name); + + private: + std::string filename; + std::unordered_map sections; + struct Line + { + std::string section_label; + std::string section_id; + std::string key; + std::string comment; + }; + std::vector opened_order; + }; +} diff --git a/WickedEngine/wiGUI.cpp b/WickedEngine/wiGUI.cpp index 80ceb1079..d8270efa6 100644 --- a/WickedEngine/wiGUI.cpp +++ b/WickedEngine/wiGUI.cpp @@ -1730,10 +1730,10 @@ namespace wi::gui onSlide(args); Activate(); } - - valueInputField.SetValue(value); } + valueInputField.SetValue(value); + font.params.posY = translation.y + scale.y * 0.5f; const float knobWidth = sprites_knob[state].params.siz.x; diff --git a/WickedEngine/wiInput.cpp b/WickedEngine/wiInput.cpp index 0bdc234c1..80e003cdf 100644 --- a/WickedEngine/wiInput.cpp +++ b/WickedEngine/wiInput.cpp @@ -44,6 +44,8 @@ namespace wi::input wi::Canvas canvas; KeyboardState keyboard; MouseState mouse; + Pen pen; + bool pen_override = false; const KeyboardState& GetKeyboardState() { return keyboard; } const MouseState& GetMouseState() { return mouse; } @@ -219,6 +221,14 @@ namespace wi::input #endif + if (pen_override) + { + mouse.position = pen.position; + mouse.left_button_press = pen.pressure > 0; + mouse.pressure = pen.pressure; + pen_override = false; + } + // Check if low-level XINPUT controller is not registered for playerindex slot and register: for (int i = 0; i < wi::input::xinput::GetMaxControllerCount(); ++i) { @@ -659,6 +669,12 @@ namespace wi::input } } + void SetPen(const Pen& _pen) + { + pen = _pen; + pen_override = true; + } + const wi::vector& GetTouches() { return touches; diff --git a/WickedEngine/wiInput.h b/WickedEngine/wiInput.h index 8797a46e7..d03b37f40 100644 --- a/WickedEngine/wiInput.h +++ b/WickedEngine/wiInput.h @@ -137,6 +137,15 @@ namespace wi::input // send various feedback to the controller void SetControllerFeedback(const ControllerFeedback& data, int playerindex = 0); + // これはペンです + struct Pen + { + XMFLOAT2 position; + float pressure; + }; + // Set pen params, this will override mouse params + void SetPen(const Pen& pen); + struct Touch { enum TOUCHSTATE diff --git a/WickedEngine/wiMath_BindLua.cpp b/WickedEngine/wiMath_BindLua.cpp index b85b32da5..f0a532b69 100644 --- a/WickedEngine/wiMath_BindLua.cpp +++ b/WickedEngine/wiMath_BindLua.cpp @@ -19,7 +19,6 @@ namespace wi::lua lunamethod(Vector_BindLua, TransformCoord), lunamethod(Vector_BindLua, Length), lunamethod(Vector_BindLua, Normalize), - lunamethod(Vector_BindLua, QuaternionNormalize), lunamethod(Vector_BindLua, Add), lunamethod(Vector_BindLua, Subtract), lunamethod(Vector_BindLua, Multiply), @@ -28,9 +27,10 @@ namespace wi::lua lunamethod(Vector_BindLua, Lerp), lunamethod(Vector_BindLua, Slerp), lunamethod(Vector_BindLua, Clamp), - lunamethod(Vector_BindLua, Normalize), + lunamethod(Vector_BindLua, QuaternionNormalize), lunamethod(Vector_BindLua, QuaternionMultiply), lunamethod(Vector_BindLua, QuaternionFromRollPitchYaw), + lunamethod(Vector_BindLua, QuaternionToRollPitchYaw), { NULL, NULL } }; Luna::PropertyType Vector_BindLua::properties[] = { @@ -384,6 +384,22 @@ namespace wi::lua wi::lua::SError(L, "QuaternionFromRollPitchYaw(Vector rotXYZ) not enough arguments!"); return 0; } + int Vector_BindLua::QuaternionToRollPitchYaw(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc > 0) + { + Vector_BindLua* v1 = Luna::lightcheck(L, 1); + if (v1) + { + XMFLOAT3 xyz = wi::math::QuaternionToRollPitchYaw(*v1); + Luna::push(L, new Vector_BindLua(XMFLOAT4(xyz.x, xyz.y, xyz.z, 0))); + return 1; + } + } + wi::lua::SError(L, "QuaternionToRollPitchYaw(Vector quaternion) not enough arguments!"); + return 0; + } int Vector_BindLua::Slerp(lua_State* L) { int argc = wi::lua::SGetArgCount(L); diff --git a/WickedEngine/wiMath_BindLua.h b/WickedEngine/wiMath_BindLua.h index 187f815ee..8d17c8a54 100644 --- a/WickedEngine/wiMath_BindLua.h +++ b/WickedEngine/wiMath_BindLua.h @@ -34,7 +34,6 @@ namespace wi::lua int TransformCoord(lua_State* L); int Length(lua_State* L); int Normalize(lua_State* L); - int QuaternionNormalize(lua_State* L); int Clamp(lua_State* L); int Saturate(lua_State* L); @@ -46,8 +45,10 @@ namespace wi::lua int Lerp(lua_State* L); + int QuaternionNormalize(lua_State* L); int QuaternionMultiply(lua_State* L); int QuaternionFromRollPitchYaw(lua_State* L); + int QuaternionToRollPitchYaw(lua_State* L); int Slerp(lua_State* L); static void Bind(); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 30b67e9cf..83a766514 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 17; + const int revision = 18; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);