UI: Add status text

This commit is contained in:
N3xoX1 2026-02-10 20:45:05 +10:30
parent 25d3feafd5
commit dcb59deec5
6 changed files with 188 additions and 8 deletions

View File

@ -17,6 +17,15 @@
height: 1.6rem;
}
#StatusText
{
width: *;
text-align: right;
display: inline-block;
height: 100%%;
padding: 0.2em;
}
#StatusBar #volume,
#StatusBar #renderer
{

View File

@ -29,7 +29,7 @@
</div>
</div>
</div>
<div id="StatusBar" ><span id="renderer" /><span id="volume" /></div>
<div id="StatusBar" ><span id="renderer" /><span id="volume" /><div id="StatusText" /></div>
</html>
<popup id="VolumePopup">
<div>

View File

@ -11,7 +11,21 @@ extern IModuleSettings * g_settings;
namespace
{
enum class SettingType { StringSetting, StringValue, AudioEngine, AudioMode, U8, BooleanSetting, BooleanValue, UnsignedInt, ControllerType };
enum class SettingType
{
StringSetting,
StringValue,
AudioEngine,
AudioMode,
U8,
U16,
BooleanSwitchable,
BooleanSetting,
BooleanValue,
UnsignedInt,
Float,
ControllerType
};
class OsSetting
{
@ -20,9 +34,12 @@ namespace
OsSetting(const char * id, const char * path, Settings::SwitchableSetting<Settings::AudioEngine> * val);
OsSetting(const char * id, const char * path, Settings::SwitchableSetting<Settings::AudioMode, true>* val);
OsSetting(const char * id, const char * path, Settings::SwitchableSetting<u8, true> * val);
OsSetting(const char * id, const char * path, Settings::Setting<bool, false> * val);
OsSetting(const char * id, const char * path, Settings::SwitchableSetting<u16, true> * val);
OsSetting(const char * id, const char * path, Settings::SwitchableSetting<bool> * val);
OsSetting(const char * id, const char * path, Settings::Setting<bool, false> * val);
OsSetting(const char * id, const char * path, bool * val, bool defaultValue);
OsSetting(const char * id, const char * path, int * val, int defaultValue);
OsSetting(const char * id, const char * path, float * val, float defaultValue);
OsSetting(const char * id, const char * path, uint32_t * val, uint32_t defaultValue);
OsSetting(const char * id, const char * path, std::string * val, const char * defaultValue);
OsSetting(const char * id, const char * path, InputSettings::ControllerType * val, InputSettings::ControllerType defaultValue);
@ -36,9 +53,12 @@ namespace
Settings::SwitchableSetting<Settings::AudioEngine> * audioEngine;
Settings::SwitchableSetting<Settings::AudioMode, true> * audioMode;
Settings::SwitchableSetting<u8, true> * u8;
Settings::SwitchableSetting<u16, true> * u16;
Settings::SwitchableSetting<bool> * booleanSwitchable;
Settings::Setting<bool, false> * booleanSetting;
bool * boolValue;
uint32_t * uint32Value;
float * floatValue;
std::string * stringValue;
InputSettings::ControllerType * controllerType;
} setting;
@ -46,6 +66,7 @@ namespace
{
bool boolValue;
uint32_t uint32Value;
float floatValue;
const char * sringValue;
InputSettings::ControllerType controllerType;
} defaultValue;
@ -422,12 +443,16 @@ namespace
{nullptr, "controller\\player_9\\ProfileName", &Settings::values.players.GetValue(true)[9].profile_name, ""},
{nullptr, "controller\\player_9\\Vibration\\UseSystem", &Settings::values.players.GetValue(true)[9].use_system_vibrator, false},
{NXOsSetting::AudioSinkId, "audio\\sink_id", &Settings::values.sink_id},
{ NXOsSetting::AudioSinkId, "audio\\sink_id", &Settings::values.sink_id},
{ NXOsSetting::AudioOutputDeviceId, "audio\\output_device_id", &Settings::values.audio_output_device_id },
{ NXOsSetting::AudioInputDeviceId, "audio\\input_device_id", &Settings::values.audio_input_device_id },
{ NXOsSetting::AudioMode, "audio\\mode", &Settings::values.sound_index },
{ NXOsSetting::AudioVolume, "audio\\volume", &Settings::values.volume },
{ NXOsSetting::AudioMuted, "audio\\muted", &Settings::values.audio_muted },
{ NXOsSetting::ResolutionUpFactor, "resolution\\up_factor", &Settings::values.resolution_info.up_factor, 1.0f },
{ NXOsSetting::SpeedLimit, "core\\speed_limit", &Settings::values.speed_limit },
{ NXOsSetting::UseMultiCore, "core\\use_multi_core", &Settings::values.use_multi_core },
{ NXOsSetting::UseSpeedLimit, "core\\use_speed_limit", &Settings::values.use_speed_limit },
};
template <typename T>
@ -544,6 +569,12 @@ void SetupOsSetting(void)
case SettingType::U8:
osSetting.setting.u8->SetValue(osSetting.setting.u8->GetDefault());
break;
case SettingType::U16:
osSetting.setting.u16->SetValue(osSetting.setting.u16->GetDefault());
break;
case SettingType::BooleanSwitchable:
osSetting.setting.booleanSetting->SetValue(osSetting.setting.booleanSwitchable->GetDefault());
break;
case SettingType::BooleanSetting:
osSetting.setting.booleanSetting->SetValue(osSetting.setting.booleanSetting->GetDefault());
break;
@ -553,6 +584,9 @@ void SetupOsSetting(void)
case SettingType::UnsignedInt:
*osSetting.setting.uint32Value = osSetting.defaultValue.uint32Value;
break;
case SettingType::Float:
*osSetting.setting.floatValue = osSetting.defaultValue.floatValue;
break;
case SettingType::StringValue:
*osSetting.setting.stringValue = osSetting.defaultValue.sringValue;
break;
@ -660,6 +694,14 @@ void SetupOsSetting(void)
g_settings->SetDefaultInt(osSetting.identifier, (int32_t)osSetting.setting.u8->GetDefault());
g_settings->SetInt(osSetting.identifier, (int32_t)osSetting.setting.u8->GetValue());
break;
case SettingType::U16:
g_settings->SetDefaultInt(osSetting.identifier, (int32_t)osSetting.setting.u16->GetDefault());
g_settings->SetInt(osSetting.identifier, (int32_t)osSetting.setting.u16->GetValue());
break;
case SettingType::BooleanSwitchable:
g_settings->SetDefaultBool(osSetting.identifier, osSetting.setting.booleanSwitchable->GetDefault() != 0);
g_settings->SetBool(osSetting.identifier, osSetting.setting.booleanSwitchable->GetValue() != 0);
break;
case SettingType::BooleanSetting:
g_settings->SetDefaultBool(osSetting.identifier, osSetting.setting.booleanSetting->GetDefault() != 0);
g_settings->SetBool(osSetting.identifier, osSetting.setting.booleanSetting->GetValue() != 0);
@ -668,6 +710,10 @@ void SetupOsSetting(void)
g_settings->SetDefaultBool(osSetting.identifier, osSetting.defaultValue.boolValue);
g_settings->SetBool(osSetting.identifier, *osSetting.setting.boolValue);
break;
case SettingType::Float:
g_settings->SetDefaultFloat(osSetting.identifier, osSetting.defaultValue.floatValue);
g_settings->SetFloat(osSetting.identifier, *osSetting.setting.floatValue);
break;
default:
UNIMPLEMENTED();
}
@ -777,8 +823,24 @@ namespace
{
setting.u8 = val;
}
OsSetting::OsSetting(const char* id, const char * path, Settings::Setting<bool, false> * val) :
OsSetting::OsSetting(const char * id, const char * path, Settings::SwitchableSetting<u16, true> * val) :
identifier(id),
json_path(path),
settingType(SettingType::U16)
{
setting.u16 = val;
}
OsSetting::OsSetting(const char * id, const char * path, Settings::SwitchableSetting<bool> * val) :
identifier(id),
json_path(path),
settingType(SettingType::BooleanSwitchable)
{
setting.booleanSwitchable = val;
}
OsSetting::OsSetting(const char * id, const char * path, Settings::Setting<bool, false> * val) :
identifier(id),
json_path(path),
settingType(SettingType::BooleanSetting)
@ -804,6 +866,15 @@ namespace
defaultValue.uint32Value = defaultValue_;
}
OsSetting::OsSetting(const char * id, const char * path, float * val, float defaultValue_) :
identifier(id),
json_path(path),
settingType(SettingType::Float)
{
setting.floatValue = val;
defaultValue.floatValue = defaultValue_;
}
OsSetting::OsSetting(const char * id, const char * path, uint32_t * val, uint32_t defaultValue_) :
identifier(id),
json_path(path),

View File

@ -8,5 +8,9 @@ namespace NXOsSetting
constexpr const char * AudioMode = "nxos:AudioMode";
constexpr const char * AudioVolume = "nxos:AudioVolume";
constexpr const char * AudioMuted = "nxos:AudioMuted";
constexpr const char * ResolutionUpFactor = "nxos:ResolutionUpScale";
constexpr const char * SpeedLimit = "nxos:SpeedLimit";
constexpr const char * UseMultiCore = "nxos:UseMultiCore";
constexpr const char * UseSpeedLimit = "nxos:UseSpeedLimit";
} // namespace NXOsSetting

View File

@ -46,6 +46,14 @@ SciterMainWindow::SciterMainWindow(ISciterUI & sciterUI, const char * windowTitl
settings.RegisterCallback(NXCoreSetting::GameName, SciterMainWindow::GameNameChanged, this);
settings.RegisterCallback(NXCoreSetting::DisplayedFrames, SciterMainWindow::DisplayedFramesChanged, this);
settings.RegisterCallback(NXOsSetting::AudioVolume, SciterMainWindow::SettingChanged, this);
settings.RegisterCallback(NXOsSetting::ResolutionUpFactor, SciterMainWindow::SettingChanged, this);
settings.RegisterCallback(NXOsSetting::SpeedLimit, SciterMainWindow::SettingChanged, this);
settings.RegisterCallback(NXOsSetting::UseMultiCore, SciterMainWindow::SettingChanged, this);
settings.RegisterCallback(NXOsSetting::UseSpeedLimit, SciterMainWindow::SettingChanged, this);
m_useMultiCore = settings.GetBool(NXOsSetting::UseMultiCore);
m_useSpeedLimit = settings.GetBool(NXOsSetting::UseSpeedLimit);
m_speedLimit = settings.GetBool(NXOsSetting::SpeedLimit);
}
SciterMainWindow::~SciterMainWindow()
@ -418,7 +426,68 @@ void SciterMainWindow::OnInputConfig()
m_inputConfig.reset(new InputConfig(m_sciterUI, m_modules));
m_inputConfig->Display((void*)m_window->GetHandle());
}
void SciterMainWindow::UpdateStatusBar()
{
SciterElement statusTextEl(m_rootElement.GetElementByID("StatusText"));
if (!statusTextEl.IsValid())
{
return;
}
if (!m_emulationRunning)
{
m_rootElement.SetTimer(0, (uint32_t *)TIMER_UPDATE_STATUS);
statusTextEl.SetText("");
return;
}
if (!m_modules.IsValid())
{
return;
}
IOperatingSystem & operatingSystem = m_modules.Modules().OperatingSystem();
IVideo & video = m_modules.Modules().Video();
std::string status;
const int shaders_building = video.ShadersBuilding();
if (shaders_building > 0)
{
status += stdstr_f("Building: %d shader(s)", shaders_building);
}
PerfStatsResults results = operatingSystem.GetAndResetPerfStats();
if (!status.empty())
{
status += " | ";
}
status += stdstr_f("Scale: %.0fx", m_resolutionUpFactor);
if (!m_useMultiCore)
{
status += " | ";
if (m_useSpeedLimit)
{
if (results.emulation_speed > 0.999 && results.emulation_speed < 1.01)
{
results.emulation_speed = 100.0;
}
status += stdstr_f("Speed: %.0f / %d", results.emulation_speed * 100.0, m_speedLimit);
}
else
{
status += stdstr_f("Speed: %f", results.emulation_speed * 100.0);
}
}
if (!status.empty())
{
status += " | ";
}
status += stdstr_f("Game: %.0f FPS%s", std::round(results.average_game_fps), m_useSpeedLimit ? "" : " (Unlocked)");
status += stdstr_f(" | Frame: %.2f ms", std::isnan(results.frametime) ? 0.0 : (results.frametime * 1000.0));
statusTextEl.SetText(status.c_str());
}
void SciterMainWindow::OnRecetGame(uint32_t fileIndex)
{
Stringlist & recentFiles = uiSettings.recentFiles;
@ -580,6 +649,22 @@ void SciterMainWindow::SettingChanged(const char * setting, void * userData)
{
impl->UpdateStatusbar();
}
else if (strcmp(setting, NXOsSetting::ResolutionUpFactor) == 0)
{
impl->m_resolutionUpFactor = SettingsStore::GetInstance().GetFloat(NXOsSetting::ResolutionUpFactor);
}
else if (strcmp(setting, NXOsSetting::UseMultiCore) == 0)
{
impl->m_useMultiCore = SettingsStore::GetInstance().GetBool(NXOsSetting::UseMultiCore);
}
else if (strcmp(setting, NXOsSetting::UseSpeedLimit) == 0)
{
impl->m_useSpeedLimit = SettingsStore::GetInstance().GetBool(NXOsSetting::UseSpeedLimit);
}
else if (strcmp(setting, NXOsSetting::SpeedLimit) == 0)
{
impl->m_speedLimit = SettingsStore::GetInstance().GetInt(NXOsSetting::SpeedLimit);
}
}
bool SciterMainWindow::OnTimer(SCITER_ELEMENT /*element*/, uint32_t * timerId)
@ -598,6 +683,10 @@ bool SciterMainWindow::OnTimer(SCITER_ELEMENT /*element*/, uint32_t * timerId)
{
UpdateInputDrivers();
}
else if (timerId == (uint32_t *)TIMER_UPDATE_STATUS)
{
UpdateStatusBar();
}
return true;
}
@ -620,6 +709,7 @@ bool SciterMainWindow::OnEvent(SCITER_ELEMENT /*element*/, SCITER_ELEMENT /*sour
else if (event_code == EVENT_EMULATION_RUNNING)
{
PreventOSSleep();
m_rootElement.SetTimer(500, (uint32_t *)TIMER_UPDATE_STATUS);
}
else if (event_code == EVENT_EMULATION_STOPPED)
{

View File

@ -45,7 +45,8 @@ class SciterMainWindow :
enum
{
TIMER_UPDATE_UI = 5000,
TIMER_UPDATE_INPUT = 5001,
TIMER_UPDATE_INPUT,
TIMER_UPDATE_STATUS,
};
public:
@ -85,6 +86,7 @@ private:
void OnSystemConfig();
void OnInputConfig();
void OnRecetGame(uint32_t fileIndex);
void UpdateStatusBar();
// IWindowDestroySink
void OnWindowDestroy(HWINDOW hWnd) override;
@ -129,6 +131,10 @@ private:
std::string m_windowTitle;
std::unique_ptr<SystemConfig> m_systemConfig;
std::unique_ptr<InputConfig> m_inputConfig;
float m_resolutionUpFactor;
bool m_volumePopup;
bool m_useMultiCore;
bool m_useSpeedLimit;
uint32_t m_speedLimit;
bool m_emulationRunning;
};