浏览代码

Add sample for window settings change. Cleanup.

Eugene Kozlov 5 年之前
父节点
当前提交
1fe5548ecc

+ 33 - 0
Source/Samples/54_WindowSettingsDemo/CMakeLists.txt

@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2008-2020 the Urho3D project.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+# Define target name
+set (TARGET_NAME 54_WindowSettingsDemo)
+
+# Define source files
+define_source_files (EXTRA_H_FILES ${COMMON_SAMPLE_H_FILES})
+
+# Setup target with resource copying
+setup_main_executable ()
+
+# Setup test cases
+setup_test ()

+ 314 - 0
Source/Samples/54_WindowSettingsDemo/WindowSettingsDemo.cpp

@@ -0,0 +1,314 @@
+//
+// Copyright (c) 2008-2020 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include <Urho3D/Core/CoreEvents.h>
+#include <Urho3D/Engine/Engine.h>
+#include <Urho3D/Graphics/Graphics.h>
+#include <Urho3D/Graphics/GraphicsEvents.h>
+#include <Urho3D/Graphics/Material.h>
+#include <Urho3D/Graphics/Model.h>
+#include <Urho3D/Graphics/Octree.h>
+#include <Urho3D/Graphics/StaticModel.h>
+#include <Urho3D/Graphics/Texture2D.h>
+#include <Urho3D/Graphics/Zone.h>
+#include <Urho3D/Input/Input.h>
+#include <Urho3D/Resource/ResourceCache.h>
+#include <Urho3D/UI/Button.h>
+#include <Urho3D/UI/CheckBox.h>
+#include <Urho3D/UI/DropDownList.h>
+#include <Urho3D/UI/LineEdit.h>
+#include <Urho3D/UI/Text.h>
+#include <Urho3D/UI/ToolTip.h>
+#include <Urho3D/UI/UI.h>
+#include <Urho3D/UI/UIEvents.h>
+#include <Urho3D/UI/Window.h>
+
+#include "WindowSettingsDemo.h"
+
+#include <Urho3D/DebugNew.h>
+
+URHO3D_DEFINE_APPLICATION_MAIN(WindowSettingsDemo)
+
+WindowSettingsDemo::WindowSettingsDemo(Context* context)
+    : Sample(context)
+    , uiRoot_(GetSubsystem<UI>()->GetRoot())
+{
+}
+
+void WindowSettingsDemo::Start()
+{
+    // Execute base class startup
+    Sample::Start();
+
+    // Enable OS cursor
+    GetSubsystem<Input>()->SetMouseVisible(true);
+
+    // Load XML file containing default UI style sheet
+    auto* cache = GetSubsystem<ResourceCache>();
+    auto* style = cache->GetResource<XMLFile>("UI/DefaultStyle.xml");
+
+    // Set the loaded style as default style
+    uiRoot_->SetDefaultStyle(style);
+
+    // Create window with settings.
+    InitSettings();
+    SynchronizeSettings();
+    SubscribeToEvent(E_SCREENMODE,
+        [this](StringHash /*eventType*/, const VariantMap& /*eventData*/)
+    {
+        SynchronizeSettings();
+    });
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
+
+    // Create scene
+    CreateScene();
+
+    // Setup viewport
+    auto* renderer = GetSubsystem<Renderer>();
+    SharedPtr<Viewport> viewport(new Viewport(context_, scene_, cameraNode_->GetComponent<Camera>()));
+    renderer->SetViewport(0, viewport);
+}
+
+void WindowSettingsDemo::CreateScene()
+{
+    auto* cache = GetSubsystem<ResourceCache>();
+
+    scene_ = new Scene(context_);
+    scene_->CreateComponent<Octree>();
+
+    auto* zone = scene_->CreateComponent<Zone>();
+    zone->SetAmbientColor(Color::WHITE);
+
+    // Create 3D object
+    Node* objectNode = scene_->CreateChild("Object");
+    objectNode->SetRotation(Quaternion(45.0f, 45.0f, 45.0f));
+    auto* objectModel = objectNode->CreateComponent<StaticModel>();
+    objectModel->SetModel(cache->GetResource<Model>("Models/Box.mdl"));
+    objectModel->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml"));
+
+    // Create camera
+    cameraNode_ = scene_->CreateChild("Camera");
+    cameraNode_->CreateComponent<Camera>();
+    cameraNode_->SetPosition(Vector3(0.0f, 0.0f, -4.0f));
+
+    // Rotate object
+    SubscribeToEvent(scene_, E_SCENEUPDATE,
+        [objectNode](StringHash /*eventType*/, VariantMap& eventData)
+    {
+        const float timeStep = eventData[SceneUpdate::P_TIMESTEP].GetFloat();
+        objectNode->Rotate(Quaternion(0.0f, 20.0f * timeStep, 0.0f), TS_WORLD);
+    });
+}
+
+void WindowSettingsDemo::InitSettings()
+{
+    auto* graphics = GetSubsystem<Graphics>();
+
+    // Create the Window and add it to the UI's root node
+    window_ = uiRoot_->CreateChild<Window>("Window");
+
+    // Set Window size and layout settings
+    window_->SetPosition(128, 128);
+    window_->SetMinWidth(300);
+    window_->SetLayout(LM_VERTICAL, 6, IntRect(6, 6, 6, 6));
+    window_->SetMovable(true);
+    window_->SetStyleAuto();
+
+    // Create the Window title Text
+    auto* windowTitle = window_->CreateChild<Text>("WindowTitle");
+    windowTitle->SetText("Window Settings");
+    windowTitle->SetStyleAuto();
+
+    // Create monitor selector
+    monitorControl_ = window_->CreateChild<DropDownList>("Monitor");
+    monitorControl_->SetMinHeight(24);
+    monitorControl_->SetStyleAuto();
+    for (int i = 0; i < graphics->GetMonitorCount(); ++i)
+    {
+        auto* text = MakeShared<Text>(context_);
+        text->SetText(ToString("Monitor %d", i));
+        text->SetMinWidth(CeilToInt(text->GetRowWidth(0) + 10));
+        monitorControl_->AddItem(text);
+        text->SetStyleAuto();
+    }
+
+    // Create resolution selector
+    resolutionControl_ = window_->CreateChild<DropDownList>("Resolution");
+    resolutionControl_->SetMinHeight(24);
+    resolutionControl_->SetStyleAuto();
+
+    auto* resolutionPlaceholder = MakeShared<Text>(context_);
+    resolutionPlaceholder->SetText("[Cannot fill list of resolutions]");
+    resolutionPlaceholder->SetMinWidth(CeilToInt(resolutionPlaceholder->GetRowWidth(0) + 10));
+    resolutionControl_->AddItem(resolutionPlaceholder);
+    resolutionPlaceholder->SetStyleAuto();
+
+    // Create fullscreen controller
+    auto* fullscreenFrame = window_->CreateChild<UIElement>("Fullscreen Frame");
+    fullscreenFrame->SetMinHeight(24);
+    fullscreenFrame->SetLayout(LM_HORIZONTAL, 6);
+
+    fullscreenControl_ = fullscreenFrame->CreateChild<CheckBox>("Fullscreen Control");
+    fullscreenControl_->SetStyleAuto();
+
+    auto* fullscreenText = fullscreenFrame->CreateChild<Text>("Fullscreen Label");
+    fullscreenText->SetText("Fullscreen");
+    fullscreenText->SetMinWidth(CeilToInt(fullscreenText->GetRowWidth(0) + 10));
+    fullscreenText->SetStyleAuto();
+
+    // Create borderless controller
+    auto* borderlessFrame = window_->CreateChild<UIElement>("Borderless Frame");
+    borderlessFrame->SetMinHeight(24);
+    borderlessFrame->SetLayout(LM_HORIZONTAL, 6);
+
+    borderlessControl_ = borderlessFrame->CreateChild<CheckBox>("Borderless Control");
+    borderlessControl_->SetStyleAuto();
+
+    auto* borderlessText = borderlessFrame->CreateChild<Text>("Borderless Label");
+    borderlessText->SetText("Borderless");
+    borderlessText->SetMinWidth(CeilToInt(borderlessText->GetRowWidth(0) + 10));
+    borderlessText->SetStyleAuto();
+
+    // Create resizable controller
+    auto* resizableFrame = window_->CreateChild<UIElement>("Resizable Frame");
+    resizableFrame->SetMinHeight(24);
+    resizableFrame->SetLayout(LM_HORIZONTAL, 6);
+
+    resizableControl_ = resizableFrame->CreateChild<CheckBox>("Resizable Control");
+    resizableControl_->SetStyleAuto();
+
+    auto* resizableText = resizableFrame->CreateChild<Text>("Resizable Label");
+    resizableText->SetText("Resizable");
+    resizableText->SetMinWidth(CeilToInt(resizableText->GetRowWidth(0) + 10));
+    resizableText->SetStyleAuto();
+
+    // Create resizable controller
+    auto* vsyncFrame = window_->CreateChild<UIElement>("V-Sync Frame");
+    vsyncFrame->SetMinHeight(24);
+    vsyncFrame->SetLayout(LM_HORIZONTAL, 6);
+
+    vsyncControl_ = vsyncFrame->CreateChild<CheckBox>("V-Sync Control");
+    vsyncControl_->SetStyleAuto();
+
+    auto* vsyncText = vsyncFrame->CreateChild<Text>("V-Sync Label");
+    vsyncText->SetText("V-Sync");
+    vsyncText->SetMinWidth(CeilToInt(vsyncText->GetRowWidth(0) + 10));
+    vsyncText->SetStyleAuto();
+
+    // Create multi-sample controller from 1 (= 2^0) to 16 (= 2^4)
+    multiSampleControl_ = window_->CreateChild<DropDownList>("Multi-Sample Control");
+    multiSampleControl_->SetMinHeight(24);
+    multiSampleControl_->SetStyleAuto();
+    for (int i = 0; i <= 4; ++i)
+    {
+        auto* text = MakeShared<Text>(context_);
+        text->SetText(i == 0 ? "No MSAA" : ToString("MSAA x%d", 1 << i));
+        text->SetMinWidth(CeilToInt(text->GetRowWidth(0) + 10));
+        multiSampleControl_->AddItem(text);
+        text->SetStyleAuto();
+    }
+
+    // Create "Apply" button
+    auto* applyButton = window_->CreateChild<Button>("Apply");
+    applyButton->SetLayout(LM_HORIZONTAL, 6, IntRect(6, 6, 6, 6));
+    applyButton->SetStyleAuto();
+
+    auto* applyButtonText = applyButton->CreateChild<Text>("Apply Text");
+    applyButtonText->SetAlignment(HA_CENTER, VA_CENTER);
+    applyButtonText->SetText("Apply");
+    applyButtonText->SetStyleAuto();
+
+    applyButton->SetFixedWidth(CeilToInt(applyButtonText->GetRowWidth(0) + 20));
+    applyButton->SetFixedHeight(30);
+
+    // Apply settings when "Apply" button is clicked
+    SubscribeToEvent(applyButton, E_RELEASED,
+        [this, graphics](StringHash /*eventType*/, const VariantMap& /*eventData*/)
+    {
+        const unsigned monitor = monitorControl_->GetSelection();
+        if (monitor == M_MAX_UNSIGNED)
+            return;
+
+        const auto& resolutions = graphics->GetResolutions(monitor);
+        const unsigned selectedResolution = resolutionControl_->GetSelection();
+        if (selectedResolution >= resolutions.Size())
+            return;
+
+        const bool fullscreen = fullscreenControl_->IsChecked();
+        const bool borderless = borderlessControl_->IsChecked();
+        const bool resizable = resizableControl_->IsChecked();
+        const bool vsync = vsyncControl_->IsChecked();
+
+        const unsigned multiSampleSelection = multiSampleControl_->GetSelection();
+        const int multiSample = multiSampleSelection == M_MAX_UNSIGNED ? 1 : static_cast<int>(1 << multiSampleSelection);
+
+        // TODO: Expose these options too?
+        const bool highDPI = graphics->GetHighDPI();
+        const bool tripleBuffer = graphics->GetTripleBuffer();
+
+        const int width = resolutions[selectedResolution].x_;
+        const int height = resolutions[selectedResolution].y_;
+        const int refreshRate = resolutions[selectedResolution].z_;
+        graphics->SetMode(width, height, fullscreen, borderless, resizable, highDPI, vsync, tripleBuffer, multiSample, monitor, refreshRate);
+    });
+}
+
+void WindowSettingsDemo::SynchronizeSettings()
+{
+    auto* graphics = GetSubsystem<Graphics>();
+
+    // Synchronize monitor
+    const unsigned currentMonitor = graphics->GetMonitor();
+    monitorControl_->SetSelection(currentMonitor);
+
+    // Synchronize resolution list
+    resolutionControl_->RemoveAllItems();
+    const auto& resolutions = graphics->GetResolutions(currentMonitor);
+    for (const IntVector3& resolutions : resolutions)
+    {
+        auto resolutionEntry = MakeShared<Text>(context_);
+        resolutionEntry->SetText(ToString("%dx%d, %d Hz", resolutions.x_, resolutions.y_, resolutions.z_));
+        resolutionEntry->SetMinWidth(CeilToInt(resolutionEntry->GetRowWidth(0) + 10));
+        resolutionControl_->AddItem(resolutionEntry);
+        resolutionEntry->SetStyleAuto();
+    }
+
+    // Synchronize selected resolution
+    const unsigned currentResolution = graphics->FindBestResolutionIndex(currentMonitor,
+        graphics->GetWidth(), graphics->GetHeight(), graphics->GetRefreshRate());
+    resolutionControl_->SetSelection(currentResolution);
+
+    // Synchronize fullscreen and borderless flags
+    fullscreenControl_->SetChecked(graphics->GetFullscreen());
+    borderlessControl_->SetChecked(graphics->GetBorderless());
+    resizableControl_->SetChecked(graphics->GetResizable());
+    vsyncControl_->SetChecked(graphics->GetVSync());
+
+    // Synchronize MSAA
+    for (unsigned i = 0; i <= 4; ++i)
+    {
+        if (graphics->GetMultiSample() == static_cast<int>(1 << i))
+            multiSampleControl_->SetSelection(i);
+    }
+}

+ 87 - 0
Source/Samples/54_WindowSettingsDemo/WindowSettingsDemo.h

@@ -0,0 +1,87 @@
+//
+// Copyright (c) 2008-2020 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "Sample.h"
+
+namespace Urho3D
+{
+
+class Window;
+class DropDownList;
+class CheckBox;
+
+}
+
+/// Demo application for dynamic window settings change.
+class WindowSettingsDemo : public Sample
+{
+    URHO3D_OBJECT(WindowSettingsDemo, Sample);
+
+public:
+    /// Construct.
+    explicit WindowSettingsDemo(Context* context);
+
+    /// Setup after engine initialization and before running the main loop.
+    void Start() override;
+
+protected:
+    /// Return XML patch instructions for screen joystick layout for a specific sample app, if any.
+    String GetScreenJoystickPatchString() const override { return
+        "<patch>"
+        "    <add sel=\"/element/element[./attribute[@name='Name' and @value='Hat0']]\">"
+        "        <attribute name=\"Is Visible\" value=\"false\" />"
+        "    </add>"
+        "</patch>";
+    }
+
+private:
+    /// Construct the scene content.
+    void CreateScene();
+    /// Create window with settings.
+    void InitSettings();
+    /// Synchronize settings with current state of the engine.
+    void SynchronizeSettings();
+
+    /// The Window.
+    Window* window_{};
+    /// The UI's root UIElement.
+    UIElement* uiRoot_{};
+
+    /// Monitor control.
+    DropDownList* monitorControl_{};
+    /// Resolution control.
+    DropDownList* resolutionControl_{};
+    /// Fullscreen control.
+    CheckBox* fullscreenControl_{};
+    /// Borderless flag control.
+    CheckBox* borderlessControl_{};
+    /// Resizable flag control.
+    CheckBox* resizableControl_{};
+    /// V-sync flag control.
+    CheckBox* vsyncControl_{};
+    /// MSAA control.
+    DropDownList* multiSampleControl_{};
+};
+
+

+ 2 - 2
Source/Urho3D/Graphics/Graphics.cpp

@@ -276,7 +276,7 @@ PODVector<IntVector3> Graphics::GetResolutions(int monitor) const
     return ret;
 }
 
-unsigned Graphics::FindBestResolution(int monitor, int width, int height, int refreshRate) const
+unsigned Graphics::FindBestResolutionIndex(int monitor, int width, int height, int refreshRate) const
 {
     const PODVector<IntVector3> resolutions = GetResolutions(monitor);
     if (resolutions.Empty())
@@ -549,7 +549,7 @@ void Graphics::AdjustScreenMode(int& newWidth, int& newHeight, ScreenModeParams&
         const PODVector<IntVector3> resolutions = GetResolutions(params.monitor_);
         if (!resolutions.Empty())
         {
-            const unsigned bestResolution = FindBestResolution(params.monitor_,
+            const unsigned bestResolution = FindBestResolutionIndex(params.monitor_,
                 newWidth, newHeight, params.refreshRate_);
             newWidth = resolutions[bestResolution].x_;
             newHeight = resolutions[bestResolution].y_;

+ 2 - 2
Source/Urho3D/Graphics/Graphics.h

@@ -350,7 +350,7 @@ public:
     /// Return screen mode parameters.
     const ScreenModeParams& GetScreenModeParams() const { return screenParams_; }
 
-    /// Return multisample mode (1 = no multisampling.)
+    /// Return multisample mode (1 = no multisampling).
     int GetMultiSample() const { return screenParams_.multiSample_; }
 
     /// Return window size in pixels.
@@ -440,7 +440,7 @@ public:
     /// Return supported fullscreen resolutions (third component is refreshRate). Will be empty if listing the resolutions is not supported on the platform (e.g. Web).
     PODVector<IntVector3> GetResolutions(int monitor) const;
     /// Return index of the best resolution for requested width, height and refresh rate.
-    unsigned FindBestResolution(int monitor, int width, int height, int refreshRate) const;
+    unsigned FindBestResolutionIndex(int monitor, int width, int height, int refreshRate) const;
     /// Return supported multisampling levels.
     PODVector<int> GetMultiSampleLevels() const;
     /// Return the desktop resolution.