Start to add new ui

This commit is contained in:
N3xoX1 2025-03-19 09:30:28 +10:30
parent 5f42f66c93
commit 72708c4868
16 changed files with 315 additions and 23 deletions

3
.gitmodules vendored
View File

@ -40,3 +40,6 @@
[submodule "external/vulkan_utility_libraries"]
path = external/vulkan_utility_libraries
url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git
[submodule "external/sciterui"]
path = external/sciterui
url = https://github.com/N3xoX1/sciterui.git

View File

@ -4,6 +4,7 @@
"ModuleDirectory-x64" : "..\\..\\..\\modules\\x64"
},
"UI" : {
"LanguageDirectory" : "..\\..\\..\\lang",
"EnableModuleConfiguration" : true
}
}

1
external/sciterui vendored Submodule

@ -0,0 +1 @@
Subproject commit bb76cd6d4d213a647d18361b08b7cbbbe417bf58

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,102 @@
html
{
border: none;
background-color: #232629;
}
html[window-state="maximized"]
{
border: window-frame-width solid transparent;
}
html > header
{
width: *;
flow: horizontal;
background-color: threedface;
height: window-caption-height;
margin: 0;
}
html > header > window-caption
{
display: block;
line-height: window-caption-height;
width: *;
padding: 0 1em;
font-family: 'Segoe UI', Arial, sans-serif;
font-size: 0.9em;
font-weight: 100;
}
html > header > window-caption span
{
vertical-align: middle;
}
html > header > window-caption img
{
vertical-align: middle;
margin-right: 0.4em;
width: 1.5em;
height: 1.5em;
}
html > header > window-buttons
{
display: block;
flow: horizontal;
width: max-content;
height: *;
}
html > header > window-buttons > window-button {
behavior: clickable;
display: block;
height: *;
width: window-button-width;
foreground-size: 2em 1.5em;
foreground-repeat: no-repeat;
foreground-position: 50% 50%;
stroke-width: 0;
fill: #000000;
transition: background-color linear 100ms;
padding: 0.25em;
}
html > header > window-buttons > window-button:hover
{
background: rgba(0,0,0,0.25);
}
html > header > window-buttons > window-button[role="window-close"]
{
foreground-image: url(icon:window-close);
}
html > header > window-buttons > window-button[role="window-close"]:hover
{
background: rgb(232,17,35);
fill: #fff;
}
html > header > window-buttons > window-button[role="window-maximize"]
{
foreground-image: url(icon:window-maximize);
}
html[window-state="maximized"]
{
border-color: transparent;
}
html[window-state="maximized"] > header > window-buttons > window-button[role="window-maximize"]
{
foreground-image: url(icon:window-restore);
}
html > header > window-buttons > window-button[role="window-minimize"]
{
foreground-image: url(icon:window-minimize);
}

View File

@ -0,0 +1,13 @@
<html window-frame="solid-with-shadow" window-icon="window-icon.png" >
<head>
<link href="main_window.css" rel="stylesheet" type="text/css">
<title>NxEmu</title>
</head>
<header>
<window-caption role=window-caption><img src="window-icon-32.png" /><span>NxEmu<span></window-caption>
<window-buttons>
<window-button role="window-minimize"></window-button>
<window-button role="window-close"></window-button>
</window-buttons>
</header>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -77,6 +77,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bc_decoder", "src\3rd_party
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yuzu_video_core", "src\yuzu_video_core\yuzu_video_core.vcxproj", "{0F7CE378-7060-4B23-990B-8ED758654D81}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sciterui", "external\sciterui\src\sciterui\sciterui.vcxproj", "{847B64EE-2C78-48F9-912B-D700F2A5CB91}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -285,6 +287,14 @@ Global
{0F7CE378-7060-4B23-990B-8ED758654D81}.Release|x64.Build.0 = Release|x64
{0F7CE378-7060-4B23-990B-8ED758654D81}.Release|x86.ActiveCfg = Release|x64
{0F7CE378-7060-4B23-990B-8ED758654D81}.Release|x86.Build.0 = Release|x64
{847B64EE-2C78-48F9-912B-D700F2A5CB91}.Debug|x64.ActiveCfg = Debug|x64
{847B64EE-2C78-48F9-912B-D700F2A5CB91}.Debug|x64.Build.0 = Debug|x64
{847B64EE-2C78-48F9-912B-D700F2A5CB91}.Debug|x86.ActiveCfg = Debug|x64
{847B64EE-2C78-48F9-912B-D700F2A5CB91}.Debug|x86.Build.0 = Debug|x64
{847B64EE-2C78-48F9-912B-D700F2A5CB91}.Release|x64.ActiveCfg = Release|x64
{847B64EE-2C78-48F9-912B-D700F2A5CB91}.Release|x64.Build.0 = Release|x64
{847B64EE-2C78-48F9-912B-D700F2A5CB91}.Release|x86.ActiveCfg = Release|x64
{847B64EE-2C78-48F9-912B-D700F2A5CB91}.Release|x86.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -301,6 +311,7 @@ Global
{583146AF-EE19-454C-8646-B202C0EB82BA} = {29EE6611-75A5-4A1D-A994-33A5EBB4F765}
{3A62C094-DBDF-414A-A65E-EBDB939A81E5} = {F9F8A94D-341A-46BD-A4DA-13CC33489942}
{5CC7FDA2-67EE-4C85-90F7-291AD93C82AF} = {F9F8A94D-341A-46BD-A4DA-13CC33489942}
{847B64EE-2C78-48F9-912B-D700F2A5CB91} = {29EE6611-75A5-4A1D-A994-33A5EBB4F765}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AF860836-279D-4187-9FAF-4E2D4B9C59CF}

View File

@ -1,24 +1,44 @@
#include "settings/ui_settings.h"
#include "user_interface/main_window.h"
#include "user_interface/notification.h"
#include "user_interface/sciter_main_window.h"
#include <common/std_string.h>
#include <memory>
#include <nxemu-core/app_init.h>
#include <nxemu-core/version.h>
#include <sciter_ui.h>
#include <windows.h>
int WINAPI WinMain(_In_ HINSTANCE /*hInstance*/, _In_opt_ HINSTANCE /*hPrevInstance*/, _In_ LPSTR /*lpszArgs*/, _In_ int /*nWinMode*/)
{
if (!AppInit(&Notification::GetInstance()))
{
return 1;
}
bool Res = AppInit(&Notification::GetInstance());
std::unique_ptr<MainWindow> mainWindow = std::make_unique<MainWindow>(stdstr_f("NXEmu %s", VER_FILE_VERSION_STR).ToUTF16().c_str());
mainWindow->ShowWindow(true);
mainWindow->ProcessAllMessages();
mainWindow.reset(nullptr);
if (uiSettings.sciterUI && Res)
{
ISciterUI * sciterUI = nullptr;
if (Res && !SciterUIInit(uiSettings.languageDir, uiSettings.languageBase.c_str(), uiSettings.languageCurrent.c_str(), uiSettings.sciterConsole, sciterUI))
{
Res = false;
}
if (Res)
{
SciterMainWindow window(*sciterUI);
window.Show();
sciterUI->Run();
}
if (sciterUI != nullptr)
{
sciterUI->Shutdown();
}
}
else if (Res)
{
std::unique_ptr<MainWindow> mainWindow = std::make_unique<MainWindow>(stdstr_f("NXEmu %s", VER_FILE_VERSION_STR).ToUTF16().c_str());
mainWindow->ShowWindow(true);
mainWindow->ProcessAllMessages();
mainWindow.reset(nullptr);
}
AppCleanup();
Notification::CleanUp();
return 0;
return Res ? 0 : 1;
}

View File

@ -13,23 +13,26 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{c8659f5a-3afa-4bf0-9409-3b9819e17714}</ProjectGuid>
<RootNamespace>nxemu</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(SolutionDir)property_sheets\Platform.$(Configuration).props" />
<Import Project="$(SolutionDir)property_sheets\platform.$(Configuration).props" />
</ImportGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ItemDefinitionGroup>
<ClCompile>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)external\sciterui\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<PreBuildEvent>
<Command>IF NOT EXIST "$(SolutionDir)config\NxEmu.config" (copy "$(SolutionDir)config\NxEmu.config.development" "$(SolutionDir)config\NxEmu.config")</Command>
<Command>IF NOT EXIST "$(SolutionDir)config\NxEmu.config" (copy "$(SolutionDir)config\NxEmu.config.development" "$(SolutionDir)config\NxEmu.config")
</Command>
</PreBuildEvent>
<PostBuildEvent>
<Command>xcopy /Y /D "$(SolutionDir)external\sciterui\src\3rd_party\sciter-js-sdk-main\bin\windows.d2d\x64\sciter.dll" "$(OutDir)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
@ -38,6 +41,7 @@
<ClCompile Include="user_interface\main_window.cpp" />
<ClCompile Include="user_interface\menu_item.cpp" />
<ClCompile Include="user_interface\notification.cpp" />
<ClCompile Include="user_interface\sciter_main_window.cpp" />
<ClCompile Include="user_interface\settings\config_setting_section.cpp" />
<ClCompile Include="user_interface\settings\settings_config.cpp" />
<ClCompile Include="user_interface\settings\settings_page.cpp" />
@ -51,6 +55,7 @@
<ClInclude Include="user_interface\menu_item.h" />
<ClInclude Include="user_interface\notification.h" />
<ClInclude Include="user_interface\resource.h" />
<ClInclude Include="user_interface\sciter_main_window.h" />
<ClInclude Include="user_interface\settings\config_setting_section.h" />
<ClInclude Include="user_interface\settings\settings_config.h" />
<ClInclude Include="user_interface\settings\settings_page.h" />
@ -58,6 +63,9 @@
<ClInclude Include="user_interface\wtl_controls\modified_combo_box.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\external\sciterui\src\sciterui\sciterui.vcxproj">
<Project>{847b64ee-2c78-48f9-912b-d700f2a5cb91}</Project>
</ProjectReference>
<ProjectReference Include="..\common\common.vcxproj">
<Project>{ec81be93-8316-4db6-8a26-b13fb5b13848}</Project>
</ProjectReference>

View File

@ -72,6 +72,9 @@
<ClCompile Include="user_interface\wtl_controls\modified_combo_box.cpp">
<Filter>Source Files\user_interface\wtl_controls</Filter>
</ClCompile>
<ClCompile Include="user_interface\sciter_main_window.cpp">
<Filter>Source Files\user_interface</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="user_interface\main_window.h">
@ -107,6 +110,9 @@
<ClInclude Include="user_interface\wtl_controls\modified_combo_box.h">
<Filter>Header Files\user_interface\wtl_controls</Filter>
</ClInclude>
<ClInclude Include="user_interface\sciter_main_window.h">
<Filter>Header Files\user_interface</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="user_interface\nxemu.rc">

View File

@ -1,5 +1,6 @@
#include "ui_settings.h"
#include <common/json.h>
#include <common/path.h>
#include <nxemu-core/settings/settings.h>
namespace
@ -7,6 +8,13 @@ namespace
struct UISettingsDefaults
{
static constexpr bool enableModuleConfiguration = false;
static constexpr bool sciterUI = false;
static constexpr const char * defaultLanguageDirValue = "./lang";
static constexpr const char * defaultLanguageBaseValue = "english";
static constexpr const char * defaultLanguageCurrentValue = "english";
static constexpr bool defaultSciterConsole = false;
static Path GetDefaultLanguageDir();
};
} // namespace
@ -16,21 +24,50 @@ void LoadUISetting(void)
{
uiSettings = {};
uiSettings.enableModuleConfiguration = UISettingsDefaults::enableModuleConfiguration;
uiSettings.sciterUI = UISettingsDefaults::sciterUI;
uiSettings.languageDir = UISettingsDefaults::GetDefaultLanguageDir();
uiSettings.languageDirValue = UISettingsDefaults::defaultLanguageDirValue;
uiSettings.languageBase = UISettingsDefaults::defaultLanguageBaseValue;
uiSettings.languageCurrent = UISettingsDefaults::defaultLanguageCurrentValue;
uiSettings.sciterConsole = UISettingsDefaults::defaultSciterConsole;
JsonValue settings = Settings::GetInstance().GetSettings("UI");
JsonValue jsonSettings = Settings::GetInstance().GetSettings("UI");
const JsonValue * modConfig = settings.Find("EnableModuleConfiguration");
if (modConfig != nullptr && modConfig->isBool())
const JsonValue * node = jsonSettings.Find("EnableModuleConfiguration");
if (node != nullptr && node->isBool())
{
uiSettings.enableModuleConfiguration = modConfig->asBool();
uiSettings.enableModuleConfiguration = node->asBool();
}
const JsonValue * recentFiles = settings.Find("RecentFiles");
if (recentFiles != nullptr && recentFiles->isArray())
node = jsonSettings.Find("SciterUI");
if (node != nullptr && node->isBool())
{
for (uint32_t i = 0; i < recentFiles->size(); i++)
uiSettings.sciterUI = node->asBool();
}
node = jsonSettings.Find("LanguageDirectory");
if (node != nullptr && node->isString())
{
std::string dirValue = node->asString();
if (!dirValue.empty())
{
const JsonValue & file = (*recentFiles)[i];
uiSettings.languageDirValue = dirValue;
uiSettings.languageDir = Path(uiSettings.languageDirValue, "").DirectoryNormalize(Path(Path::MODULE_DIRECTORY));
}
}
node = jsonSettings.Find("SciterConsole");
if (node != nullptr && node->isBool())
{
uiSettings.sciterConsole = node->asBool();
}
node = jsonSettings.Find("RecentFiles");
if (node != nullptr && node->isArray())
{
for (uint32_t i = 0; i < node->size(); i++)
{
const JsonValue & file = (*node)[i];
if (file.isString())
{
uiSettings.recentFiles.push_back(file.asString());
@ -60,4 +97,11 @@ void SaveUISetting(void)
Settings & settings = Settings::GetInstance();
settings.SetSettings("UI", json);
settings.Save();
}
}
Path UISettingsDefaults::GetDefaultLanguageDir()
{
Path dir(Path::MODULE_DIRECTORY);
dir.AppendDirectory("lang");
return dir;
}

View File

@ -1,4 +1,5 @@
#pragma once
#include <common/path.h>
#include <string>
#include <vector>
@ -8,6 +9,12 @@ struct UISettings
{
Stringlist recentFiles;
bool enableModuleConfiguration;
bool sciterUI;
Path languageDir;
std::string languageDirValue;
std::string languageBase;
std::string languageCurrent;
bool sciterConsole;
};
extern UISettings uiSettings;

View File

@ -0,0 +1,45 @@
#include "sciter_main_window.h"
#include <common/std_string.h>
#include <nxemu-core/version.h>
#include <sciter_element.h>
SciterMainWindow::SciterMainWindow(ISciterUI& SciterUI) :
m_sciterUI(SciterUI),
m_renderWindow(nullptr)
{
}
bool SciterMainWindow::Show(void)
{
enum
{
WINDOW_HEIGHT = 507,
WINDOW_WIDTH = 760,
};
if (!m_sciterUI.WindowCreate(nullptr, "main_window.html", 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, m_window))
{
return false;
}
m_window->OnDestroySinkAdd(this);
m_window->CenterWindow();
stdstr_f windowTitle("NxEmu - %s", VER_FILE_VERSION_STR);
SciterElement rootElement(m_window->GetRootElement());
rootElement.Eval(stdstr_f("Window.this.caption = \"%s\";", windowTitle.c_str()).c_str());
SciterElement caption(rootElement.FindFirst("[role='window-caption'] > span"));
if (caption.IsValid())
{
caption.SetHTML((uint8_t *)windowTitle.data(), windowTitle.size());
}
return true;
}
void SciterMainWindow::OnWindowDestroy(HWINDOW /*hWnd*/)
{
m_sciterUI.Stop();
}
void * SciterMainWindow::RenderSurface(void) const
{
return m_renderWindow;
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <nxemu-core/modules/module_base.h>
#include <sciter_ui.h>
class SciterMainWindow :
public IWindowDestroySink,
public IRenderWindow
{
public:
SciterMainWindow(ISciterUI & SciterUI);
bool Show(void);
private:
SciterMainWindow(void) = delete;
SciterMainWindow(const SciterMainWindow&) = delete;
SciterMainWindow& operator=(const SciterMainWindow&) = delete;
// IWindowDestroySink
void OnWindowDestroy(HWINDOW hWnd);
// IRenderWindow
void * RenderSurface(void) const;
ISciterUI & m_sciterUI;
ISciterWindow * m_window;
void * m_renderWindow;
};