shader control
This commit is contained in:
127
apps/RenderCadenceCompositor/control/RuntimeControlCommand.cpp
Normal file
127
apps/RenderCadenceCompositor/control/RuntimeControlCommand.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
#include "RuntimeControlCommand.h"
|
||||
|
||||
namespace RenderCadenceCompositor
|
||||
{
|
||||
namespace
|
||||
{
|
||||
const JsonValue* RequireObjectField(const JsonValue& root, const char* fieldName, std::string& error)
|
||||
{
|
||||
const JsonValue* field = root.find(fieldName);
|
||||
if (!field)
|
||||
error = std::string("Request field '") + fieldName + "' is required.";
|
||||
return field;
|
||||
}
|
||||
|
||||
bool RequireStringField(const JsonValue& root, const char* fieldName, std::string& value, std::string& error)
|
||||
{
|
||||
const JsonValue* field = RequireObjectField(root, fieldName, error);
|
||||
if (!field)
|
||||
return false;
|
||||
if (!field->isString() || field->asString().empty())
|
||||
{
|
||||
error = std::string("Request field '") + fieldName + "' must be a non-empty string.";
|
||||
return false;
|
||||
}
|
||||
value = field->asString();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RequireBoolField(const JsonValue& root, const char* fieldName, bool& value, std::string& error)
|
||||
{
|
||||
const JsonValue* field = RequireObjectField(root, fieldName, error);
|
||||
if (!field)
|
||||
return false;
|
||||
if (!field->isBoolean())
|
||||
{
|
||||
error = std::string("Request field '") + fieldName + "' must be a boolean.";
|
||||
return false;
|
||||
}
|
||||
value = field->asBoolean();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RequireIntegerField(const JsonValue& root, const char* fieldName, int& value, std::string& error)
|
||||
{
|
||||
const JsonValue* field = RequireObjectField(root, fieldName, error);
|
||||
if (!field)
|
||||
return false;
|
||||
if (!field->isNumber())
|
||||
{
|
||||
error = std::string("Request field '") + fieldName + "' must be a number.";
|
||||
return false;
|
||||
}
|
||||
value = static_cast<int>(field->asNumber());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ParseRuntimeControlCommand(
|
||||
const std::string& path,
|
||||
const std::string& body,
|
||||
RuntimeControlCommand& command,
|
||||
std::string& error)
|
||||
{
|
||||
command = RuntimeControlCommand();
|
||||
|
||||
JsonValue root;
|
||||
std::string parseError;
|
||||
if (!ParseJson(body.empty() ? "{}" : body, root, parseError) || !root.isObject())
|
||||
{
|
||||
error = parseError.empty() ? "Request body must be a JSON object." : parseError;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (path == "/api/layers/add")
|
||||
{
|
||||
command.type = RuntimeControlCommandType::AddLayer;
|
||||
return RequireStringField(root, "shaderId", command.shaderId, error);
|
||||
}
|
||||
if (path == "/api/layers/remove")
|
||||
{
|
||||
command.type = RuntimeControlCommandType::RemoveLayer;
|
||||
return RequireStringField(root, "layerId", command.layerId, error);
|
||||
}
|
||||
if (path == "/api/layers/reorder")
|
||||
{
|
||||
command.type = RuntimeControlCommandType::ReorderLayer;
|
||||
return RequireStringField(root, "layerId", command.layerId, error)
|
||||
&& RequireIntegerField(root, "targetIndex", command.targetIndex, error);
|
||||
}
|
||||
if (path == "/api/layers/set-bypass")
|
||||
{
|
||||
command.type = RuntimeControlCommandType::SetLayerBypass;
|
||||
return RequireStringField(root, "layerId", command.layerId, error)
|
||||
&& RequireBoolField(root, "bypass", command.bypass, error);
|
||||
}
|
||||
if (path == "/api/layers/set-shader")
|
||||
{
|
||||
command.type = RuntimeControlCommandType::SetLayerShader;
|
||||
return RequireStringField(root, "layerId", command.layerId, error)
|
||||
&& RequireStringField(root, "shaderId", command.shaderId, error);
|
||||
}
|
||||
if (path == "/api/layers/update-parameter")
|
||||
{
|
||||
command.type = RuntimeControlCommandType::UpdateLayerParameter;
|
||||
const JsonValue* value = nullptr;
|
||||
if (!RequireStringField(root, "layerId", command.layerId, error)
|
||||
|| !RequireStringField(root, "parameterId", command.parameterId, error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
value = RequireObjectField(root, "value", error);
|
||||
if (!value)
|
||||
return false;
|
||||
command.value = *value;
|
||||
return true;
|
||||
}
|
||||
if (path == "/api/layers/reset-parameters")
|
||||
{
|
||||
command.type = RuntimeControlCommandType::ResetLayerParameters;
|
||||
return RequireStringField(root, "layerId", command.layerId, error);
|
||||
}
|
||||
|
||||
command.type = RuntimeControlCommandType::Unsupported;
|
||||
error = "Endpoint is not implemented in RenderCadenceCompositor yet.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
37
apps/RenderCadenceCompositor/control/RuntimeControlCommand.h
Normal file
37
apps/RenderCadenceCompositor/control/RuntimeControlCommand.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "RuntimeJson.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace RenderCadenceCompositor
|
||||
{
|
||||
enum class RuntimeControlCommandType
|
||||
{
|
||||
AddLayer,
|
||||
RemoveLayer,
|
||||
ReorderLayer,
|
||||
SetLayerBypass,
|
||||
SetLayerShader,
|
||||
UpdateLayerParameter,
|
||||
ResetLayerParameters,
|
||||
Unsupported
|
||||
};
|
||||
|
||||
struct RuntimeControlCommand
|
||||
{
|
||||
RuntimeControlCommandType type = RuntimeControlCommandType::Unsupported;
|
||||
std::string layerId;
|
||||
std::string shaderId;
|
||||
std::string parameterId;
|
||||
int targetIndex = 0;
|
||||
bool bypass = false;
|
||||
JsonValue value;
|
||||
};
|
||||
|
||||
bool ParseRuntimeControlCommand(
|
||||
const std::string& path,
|
||||
const std::string& body,
|
||||
RuntimeControlCommand& command,
|
||||
std::string& error);
|
||||
}
|
||||
@@ -93,6 +93,31 @@ inline void WriteDefaultParameterValue(JsonWriter& writer, const ShaderParameter
|
||||
writer.Null();
|
||||
}
|
||||
|
||||
inline void WriteParameterValue(JsonWriter& writer, const ShaderParameterDefinition& parameter, const ShaderParameterValue& value)
|
||||
{
|
||||
switch (parameter.type)
|
||||
{
|
||||
case ShaderParameterType::Boolean:
|
||||
writer.Bool(value.booleanValue);
|
||||
return;
|
||||
case ShaderParameterType::Enum:
|
||||
writer.String(value.enumValue);
|
||||
return;
|
||||
case ShaderParameterType::Text:
|
||||
writer.String(value.textValue);
|
||||
return;
|
||||
case ShaderParameterType::Trigger:
|
||||
case ShaderParameterType::Float:
|
||||
writer.Double(value.numberValues.empty() ? 0.0 : value.numberValues.front());
|
||||
return;
|
||||
case ShaderParameterType::Vec2:
|
||||
case ShaderParameterType::Color:
|
||||
WriteNumberArray(writer, value.numberValues);
|
||||
return;
|
||||
}
|
||||
writer.Null();
|
||||
}
|
||||
|
||||
inline void WriteTemporalJson(JsonWriter& writer, const TemporalSettings& temporal)
|
||||
{
|
||||
writer.BeginObject();
|
||||
@@ -122,7 +147,7 @@ inline const char* RuntimeLayerBuildStateName(RuntimeLayerBuildState state)
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
inline void WriteParameterDefinitionJson(JsonWriter& writer, const ShaderParameterDefinition& parameter)
|
||||
inline void WriteParameterDefinitionJson(JsonWriter& writer, const ShaderParameterDefinition& parameter, const ShaderParameterValue* value)
|
||||
{
|
||||
writer.BeginObject();
|
||||
writer.KeyString("id", parameter.id);
|
||||
@@ -132,7 +157,10 @@ inline void WriteParameterDefinitionJson(JsonWriter& writer, const ShaderParamet
|
||||
writer.Key("defaultValue");
|
||||
WriteDefaultParameterValue(writer, parameter);
|
||||
writer.Key("value");
|
||||
WriteDefaultParameterValue(writer, parameter);
|
||||
if (value)
|
||||
WriteParameterValue(writer, parameter, *value);
|
||||
else
|
||||
WriteDefaultParameterValue(writer, parameter);
|
||||
|
||||
if (!parameter.minNumbers.empty())
|
||||
{
|
||||
@@ -197,10 +225,10 @@ inline void WriteLayersJson(JsonWriter& writer, const RuntimeStateJsonInput& inp
|
||||
WriteFeedbackJson(writer, FeedbackSettings());
|
||||
writer.Key("parameters");
|
||||
writer.BeginArray();
|
||||
if (shaderPackage)
|
||||
for (const ShaderParameterDefinition& parameter : layer.parameterDefinitions)
|
||||
{
|
||||
for (const ShaderParameterDefinition& parameter : shaderPackage->parameters)
|
||||
WriteParameterDefinitionJson(writer, parameter);
|
||||
const auto valueIt = layer.parameterValues.find(parameter.id);
|
||||
WriteParameterDefinitionJson(writer, parameter, valueIt == layer.parameterValues.end() ? nullptr : &valueIt->second);
|
||||
}
|
||||
writer.EndArray();
|
||||
writer.EndObject();
|
||||
|
||||
@@ -286,6 +286,12 @@ HttpControlServer::HttpResponse HttpControlServer::ServePost(const HttpRequest&
|
||||
if (!IsKnownPostEndpoint(request.path))
|
||||
return TextResponse("404 Not Found", "Not Found");
|
||||
|
||||
if (mCallbacks.executePost)
|
||||
{
|
||||
const ControlActionResult result = mCallbacks.executePost(request.path, request.body);
|
||||
return JsonResponse(result.ok ? "200 OK" : "400 Bad Request", ActionResponse(result.ok, result.error));
|
||||
}
|
||||
|
||||
if (request.path == "/api/layers/add" && mCallbacks.addLayer)
|
||||
{
|
||||
const ControlActionResult result = mCallbacks.addLayer(request.body);
|
||||
|
||||
@@ -28,6 +28,7 @@ struct HttpControlServerCallbacks
|
||||
std::function<std::string()> getStateJson;
|
||||
std::function<ControlActionResult(const std::string&)> addLayer;
|
||||
std::function<ControlActionResult(const std::string&)> removeLayer;
|
||||
std::function<ControlActionResult(const std::string&, const std::string&)> executePost;
|
||||
};
|
||||
|
||||
class UniqueSocket
|
||||
|
||||
Reference in New Issue
Block a user