diff --git a/Content/Documentation/WickedEngine-Documentation.md b/Content/Documentation/WickedEngine-Documentation.md
index 0b012fb4d..0a70cabf7 100644
--- a/Content/Documentation/WickedEngine-Documentation.md
+++ b/Content/Documentation/WickedEngine-Documentation.md
@@ -301,6 +301,8 @@ Calls Render for the active RenderPath and wakes up scripts that are waiting for
4. Compose()
Calls Compose for the active RenderPath
+Note: the splash_screen texture of the application can be created before application is initialized, in this case this texture will be shown as a full screen image (with cropping, if necessary) while the engine initialization hasn't finished. The splash_screen texture will be also created automatically if a splash_screen.png file is found in the working directory. If a splash screen is not used, then the intialization logging screen will be shown at startup.
+
### RenderPath
[[Header]](../../WickedEngine/wiRenderPath.h)
This is an empty base class that can be activated with a `Application`. It calls its Start(), Update(), FixedUpdate(), Render(), Compose(), Stop(), etc. functions as needed. Override this to perform custom gameplay or rendering logic. The RenderPath inherits from [wiCanvas](#wicanvas), and the canvas properties will be set by the [Application](#application) when the RenderPath was activated, and while the RenderPath is active.
diff --git a/Editor/GeneralWindow.cpp b/Editor/GeneralWindow.cpp
index 6082c0fa4..e4b24c41f 100644
--- a/Editor/GeneralWindow.cpp
+++ b/Editor/GeneralWindow.cpp
@@ -519,6 +519,7 @@ void GeneralWindow::Create(EditorComponent* _editor)
editor->paintToolWnd.revealTextureButton.SetColor(wi::Color::White(), wi::gui::IDLE);
editor->projectCreatorWnd.iconButton.SetColor(wi::Color::White(), wi::gui::IDLE);
editor->projectCreatorWnd.thumbnailButton.SetColor(wi::Color::White(), wi::gui::IDLE);
+ editor->projectCreatorWnd.splashScreenButton.SetColor(wi::Color::White(), wi::gui::IDLE);
editor->aboutLabel.sprites[wi::gui::FOCUS] = editor->aboutLabel.sprites[wi::gui::IDLE];
int scene_id = 0;
for (auto& editorscene : editor->scenes)
diff --git a/Editor/ProjectCreatorWindow.cpp b/Editor/ProjectCreatorWindow.cpp
index f5facd538..72ec160c4 100644
--- a/Editor/ProjectCreatorWindow.cpp
+++ b/Editor/ProjectCreatorWindow.cpp
@@ -26,6 +26,8 @@ void ProjectCreatorWindow::Create(EditorComponent* _editor)
iconButton.SetText("");
iconButton.SetDescription("Icon: ");
iconButton.SetSize(XMFLOAT2(128 * 0.5f, 128 * 0.5f));
+ iconButton.font_description.params.v_align = wi::font::WIFALIGN_BOTTOM;
+ iconButton.font_description.params.h_align = wi::font::WIFALIGN_CENTER;
iconButton.SetTooltip("The icon will be used for the executable icon.");
iconButton.OnClick([this](wi::gui::EventArgs args) {
if (iconResource.IsValid())
@@ -57,7 +59,9 @@ void ProjectCreatorWindow::Create(EditorComponent* _editor)
thumbnailButton.Create("projectThumbnail");
thumbnailButton.SetText("");
thumbnailButton.SetDescription("Thumbnail: ");
- thumbnailButton.SetSize(XMFLOAT2(480 * 0.5f, 270 * 0.5f));
+ thumbnailButton.font_description.params.v_align = wi::font::WIFALIGN_BOTTOM;
+ thumbnailButton.font_description.params.h_align = wi::font::WIFALIGN_CENTER;
+ thumbnailButton.SetSize(XMFLOAT2(480 * 0.4f, 270 * 0.4f));
thumbnailButton.SetTooltip("The thumbnail will be used for displaying the project in the editor.");
thumbnailButton.OnClick([this](wi::gui::EventArgs args) {
if (thumbnailResource.IsValid())
@@ -86,6 +90,42 @@ void ProjectCreatorWindow::Create(EditorComponent* _editor)
});
AddWidget(&thumbnailButton);
+ splashScreenButton.Create("projectSplashScreen");
+ splashScreenButton.SetText("");
+ splashScreenButton.SetDescription("Splash screen: ");
+ splashScreenButton.font_description.params.v_align = wi::font::WIFALIGN_BOTTOM;
+ splashScreenButton.font_description.params.h_align = wi::font::WIFALIGN_CENTER;
+ splashScreenButton.SetSize(XMFLOAT2(480 * 0.5f, 270 * 0.5f));
+ splashScreenButton.SetTooltip("The splash screen will be shown while the engine is initalizing.\nIf there is a splash screen, then it will replace the intialization log display.");
+ splashScreenButton.OnClick([this](wi::gui::EventArgs args) {
+ if (splashScreenResource.IsValid())
+ {
+ splashScreenResource = {};
+ splashScreenResourceCroppedPreview = {};
+ splashScreenName = {};
+ splashScreenButton.SetImage(splashScreenResourceCroppedPreview);
+ }
+ else
+ {
+ wi::helper::FileDialogParams params;
+ params.type = wi::helper::FileDialogParams::OPEN;
+ params.description = "Texture";
+ params.extensions = wi::resourcemanager::GetSupportedImageExtensions();
+ wi::helper::FileDialog(params, [this](std::string fileName) {
+ wi::eventhandler::Subscribe_Once(wi::eventhandler::EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) {
+ wi::Resource res = wi::resourcemanager::Load(fileName);
+ if (!res.IsValid())
+ return;
+ splashScreenResource = res;
+ splashScreenName = fileName;
+ splashScreenResourceCroppedPreview.SetTexture(editor->CreateThumbnail(splashScreenResource.GetTexture(), 1280, 720, true));
+ splashScreenButton.SetImage(splashScreenResourceCroppedPreview);
+ });
+ });
+ }
+ });
+ AddWidget(&splashScreenButton);
+
backlogColorPicker.Create("backlog color", wi::gui::Window::WindowControls::NONE);
backlogColorPicker.SetSize(XMFLOAT2(256, 256));
backlogColorPicker.SetPickColor(exe_customization.backlog_color);
@@ -138,7 +178,7 @@ runProcess(function()
-- set up a 3D render path, so if you load a model it will be displayed
local renderpath = RenderPath3D()
- application.SetActivePath(renderpath)
+ application.SetActivePath(renderpath, 1.0, 0, 0, 0, FadeType.CrossFade) -- 1 sec cross fade
-- set up a simple text that will dynamically change every frame
local counter = 0
@@ -147,14 +187,14 @@ runProcess(function()
-- run an endless update loop, it will run until killProcesses() is called or the application exits
while true do
- update()
+ update() -- blocks this process until next update() is signaled from Wicked Engine
-- every frame the text is positioned to the center of the screen and display the value of the frame counter
font.SetText("Hello World! Current frame counter = " .. counter)
- font.SetSize(12)
- font.SetScale(3)
- font.SetPos(Vector(GetScreenWidth() * 0.5, GetScreenHeight() * 0.5))
- font.SetAlign(WIFALIGN_CENTER, WIFALIGN_CENTER)
+ font.SetSize(12) -- the true render size of the font (larger can increase memory usage, but improves appearance)
+ font.SetScale(3) -- upscaling the font by a factor of 3 without increasing the true font resolution
+ font.SetPos(Vector(GetScreenWidth() * 0.5, GetScreenHeight() * 0.5)) -- put to center of the screen
+ font.SetAlign(WIFALIGN_CENTER, WIFALIGN_CENTER) -- horizontal and vertical text align
counter = counter + 1
@@ -182,6 +222,10 @@ end)
{
wi::helper::saveTextureToFile(thumbnailResource.GetTexture(), directory + "thumbnail.png");
}
+ if (splashScreenResource.IsValid())
+ {
+ wi::helper::saveTextureToFile(splashScreenResource.GetTexture(), directory + "splash_screen.png");
+ }
wi::unordered_set exes;
exes.insert(wi::helper::BackslashToForwardSlash(wi::helper::GetExecutablePath()));
@@ -370,7 +414,7 @@ void ProjectCreatorWindow::ResizeLayout()
layout.jump();
- layout.add_right(iconButton, thumbnailButton);
+ layout.add_right(iconButton, thumbnailButton, splashScreenButton);
layout.jump();
diff --git a/Editor/ProjectCreatorWindow.h b/Editor/ProjectCreatorWindow.h
index 9fcd4fd12..6672a759d 100644
--- a/Editor/ProjectCreatorWindow.h
+++ b/Editor/ProjectCreatorWindow.h
@@ -12,18 +12,23 @@ public:
wi::gui::TextInputField projectNameInput;
wi::gui::Button iconButton;
wi::gui::Button thumbnailButton;
+ wi::gui::Button splashScreenButton;
wi::gui::Button createButton;
- wi::Resource iconResource;
- std::string iconName;
-
wi::gui::ColorPicker backlogColorPicker;
wi::gui::ColorPicker backgroundColorPicker;
wi::gui::Button colorPreviewButton;
+ wi::Resource iconResource;
+ std::string iconName;
+
wi::Resource thumbnailResource;
std::string thumbnailName;
+ wi::Resource splashScreenResource;
+ wi::Resource splashScreenResourceCroppedPreview;
+ std::string splashScreenName;
+
void ResizeLayout() override;
};
diff --git a/WickedEngine/wiApplication.cpp b/WickedEngine/wiApplication.cpp
index fbfd4dfea..3848d6516 100644
--- a/WickedEngine/wiApplication.cpp
+++ b/WickedEngine/wiApplication.cpp
@@ -148,8 +148,54 @@ namespace wi
viewport.width = (float)swapChain.desc.width;
viewport.height = (float)swapChain.desc.height;
graphicsDevice->BindViewports(1, &viewport, cmd);
- if (wi::initializer::IsInitializeFinished(wi::initializer::INITIALIZED_SYSTEM_FONT))
+ static bool splash_screen_check = false;
+ if (!splash_screen.IsValid() && !splash_screen_check)
{
+ splash_screen_check = true;
+ std::string splash_screen_path = wi::helper::GetCurrentPath() + "/splash_screen.png";
+ if (wi::helper::FileExists(splash_screen_path))
+ {
+ wi::Resource resource = wi::resourcemanager::Load(splash_screen_path);
+ if (resource.IsValid())
+ {
+ splash_screen = resource.GetTexture();
+ }
+ }
+ }
+ if (splash_screen.IsValid())
+ {
+ if (wi::initializer::IsInitializeFinished(wi::initializer::INITIALIZED_SYSTEM_IMAGE))
+ {
+ // Draw the splash screen while engine is initializing and image renderer is ready
+ wi::image::SetCanvas(canvas);
+ wi::image::Params fx;
+ const TextureDesc& desc = splash_screen.GetDesc();
+ const float canvas_aspect = canvas.GetLogicalWidth() / canvas.GetLogicalHeight();
+ const float image_aspect = float(desc.width) / float(desc.height);
+ if (canvas_aspect > image_aspect)
+ {
+ // display aspect is wider than image:
+ fx.siz.x = canvas.GetLogicalWidth();
+ fx.siz.y = canvas.GetLogicalHeight() / image_aspect * canvas_aspect;
+ }
+ else
+ {
+ // image aspect is wider or equal to display
+ fx.siz.x = canvas.GetLogicalWidth() / canvas_aspect * image_aspect;
+ fx.siz.y = canvas.GetLogicalHeight();
+ }
+ fx.pos = XMFLOAT3(canvas.GetLogicalWidth() * 0.5f, canvas.GetLogicalHeight() * 0.5f, 0);
+ fx.pivot = XMFLOAT2(0.5f, 0.5f);
+ if (colorspace != ColorSpace::SRGB)
+ {
+ fx.enableLinearOutputMapping(9);
+ }
+ wi::image::Draw(&splash_screen, fx, cmd);
+ }
+ }
+ else if (wi::initializer::IsInitializeFinished(wi::initializer::INITIALIZED_SYSTEM_FONT))
+ {
+ // If there is no splash screen, the log is rendered while engine is initializing
ColorSpace colorspace = graphicsDevice->GetSwapChainColorSpace(&swapChain);
wi::backlog::DrawOutputText(canvas, cmd, colorspace);
}
@@ -170,6 +216,8 @@ namespace wi
return;
}
+ splash_screen = {}; // splash screen no longer needed after initialization, it is deleted
+
static bool startup_script = false;
if (!startup_script)
{
diff --git a/WickedEngine/wiApplication.h b/WickedEngine/wiApplication.h
index 13b76033c..262472f64 100644
--- a/WickedEngine/wiApplication.h
+++ b/WickedEngine/wiApplication.h
@@ -52,6 +52,7 @@ namespace wi
wi::graphics::SwapChain swapChain;
wi::Canvas canvas;
wi::platform::window_type window;
+ wi::graphics::Texture splash_screen;
// Runs the main engine loop
void Run();
diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp
index 83302e827..5824e56a0 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 = 788;
+ const int revision = 789;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);