UI updates and preroll buffer to 8 frames
Some checks failed
CI / Native Windows Build And Tests (push) Has been cancelled
CI / React UI Build (push) Has been cancelled
CI / Windows Release Package (push) Has been cancelled

This commit is contained in:
2026-05-05 20:56:53 +10:00
parent 44316b29c2
commit be315111ea
9 changed files with 763 additions and 378 deletions

View File

@@ -53,6 +53,25 @@ bool MatchesControlKey(const std::string& candidate, const std::string& key)
return candidate == key || SimplifyControlKey(candidate) == SimplifyControlKey(key);
}
bool TryParseLayerIdNumber(const std::string& layerId, uint64_t& number)
{
const std::string prefix = "layer-";
if (layerId.rfind(prefix, 0) != 0 || layerId.size() == prefix.size())
return false;
uint64_t parsed = 0;
for (std::size_t index = prefix.size(); index < layerId.size(); ++index)
{
const unsigned char ch = static_cast<unsigned char>(layerId[index]);
if (!std::isdigit(ch))
return false;
parsed = parsed * 10 + static_cast<uint64_t>(ch - '0');
}
number = parsed;
return true;
}
std::vector<double> JsonArrayToNumbers(const JsonValue& value)
{
std::vector<double> numbers;
@@ -583,6 +602,7 @@ bool RuntimeHost::Initialize(std::string& error)
return false;
if (!ScanShaderPackages(error))
return false;
NormalizePersistentLayerIdsLocked();
for (LayerPersistentState& layer : mPersistentState.layers)
{
@@ -1469,15 +1489,31 @@ bool RuntimeHost::WriteTextFile(const std::filesystem::path& path, const std::st
std::error_code fsError;
std::filesystem::create_directories(path.parent_path(), fsError);
std::ofstream output(path, std::ios::binary);
const std::filesystem::path temporaryPath = path.string() + ".tmp";
std::ofstream output(temporaryPath, std::ios::binary | std::ios::trunc);
if (!output)
{
error = "Could not write file: " + path.string();
error = "Could not write file: " + temporaryPath.string();
return false;
}
output << contents;
return output.good();
output.close();
if (!output.good())
{
error = "Could not finish writing file: " + temporaryPath.string();
return false;
}
if (!MoveFileExA(temporaryPath.string().c_str(), path.string().c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH))
{
const DWORD lastError = GetLastError();
std::filesystem::remove(temporaryPath, fsError);
error = "Could not replace file: " + path.string() + " (Win32 error " + std::to_string(lastError) + ")";
return false;
}
return true;
}
bool RuntimeHost::ResolvePaths(std::string& error)
@@ -1728,6 +1764,38 @@ bool RuntimeHost::DeserializeLayerStackLocked(const JsonValue& layersValue, std:
return true;
}
void RuntimeHost::NormalizePersistentLayerIdsLocked()
{
std::set<std::string> usedIds;
uint64_t maxLayerNumber = mNextLayerId;
for (LayerPersistentState& layer : mPersistentState.layers)
{
uint64_t layerNumber = 0;
const bool hasReusableId = !layer.id.empty() &&
usedIds.find(layer.id) == usedIds.end() &&
TryParseLayerIdNumber(layer.id, layerNumber);
if (hasReusableId)
{
usedIds.insert(layer.id);
maxLayerNumber = std::max(maxLayerNumber, layerNumber);
continue;
}
do
{
++maxLayerNumber;
layer.id = "layer-" + std::to_string(maxLayerNumber);
}
while (usedIds.find(layer.id) != usedIds.end());
usedIds.insert(layer.id);
}
mNextLayerId = maxLayerNumber;
}
std::vector<std::string> RuntimeHost::GetStackPresetNamesLocked() const
{
std::vector<std::string> presetNames;