载入中...
搜索中...
未找到
BiomeEditingCommands.cpp
浏览该文件的文档.
2
5
6#include <cmath>
7#include <cstdint>
8#include <string>
9
11namespace {
12
13const editing::Value* field(const editing::Value& value, const char* key) {
14 const auto* object = value.getIf<editing::Value::Object>();
15 if (!object) return nullptr;
16 const auto found = object->find(key);
17 return found == object->end() ? nullptr : &found->second;
18}
19
20const std::string* stringField(const editing::Value& value, const char* key) {
21 const editing::Value* entry = field(value, key);
22 return entry ? entry->getIf<std::string>() : nullptr;
23}
24
25bool readNumber(const editing::Value& value, const char* key, double& output, bool required) {
26 const editing::Value* entry = field(value, key);
27 if (!entry) return !required;
28 if (const auto* real = entry->getIf<double>()) {
29 output = *real;
30 return std::isfinite(output);
31 }
32 if (const auto* integer = entry->getIf<std::int64_t>()) {
33 output = static_cast<double>(*integer);
34 return true;
35 }
36 return false;
37}
38
39bool readInt(const editing::Value& value, const char* key, int& output, bool required) {
40 if (!field(value, key)) return !required;
41 double parsed = 0.0;
42 if (!readNumber(value, key, parsed, true) || parsed < -100000.0 || parsed > 100000.0) return false;
43 output = static_cast<int>(parsed);
44 return true;
45}
46
47bool readBool(const editing::Value& value, const char* key, bool& output, bool required) {
48 const editing::Value* entry = field(value, key);
49 if (!entry) return !required;
50 const auto* flag = entry->getIf<bool>();
51 if (!flag) return false;
52 output = *flag;
53 return true;
54}
55
56editing::Result<void> addCommand(editing::IEditingCommandRegistry& registry, const char* id, const char* displayName,
60 descriptor.ownerModule = "biome_editing";
61 descriptor.displayName = displayName;
62 descriptor.category = "Biome";
63 descriptor.automationAllowed = true;
64 return registry.registerPlannedCommand(std::move(descriptor), std::move(planner));
65}
66
68 return dynamic_cast<BiomeDocumentTarget*>(&target);
69}
70
71editing::SelectionSnapshot selectionFor(const BiomeDocumentTarget& target, const std::string& item,
72 const std::string& type) {
74 selection.channel = "biome";
77 row.target = editing::TargetId(target.targetId());
78 row.item = editing::StableId(item);
79 row.type = type;
80 selection.items.push_back(row);
81 selection.primary = row;
82 return selection;
83}
84
86 editing::Value summary) {
87 if (!operation.ok())
88 return eve::editing::failed<editing::CommandPlan>(operation.code(), editing::RuleId("biome.editing.operation"),
89 "Biome target rejected the planned edit");
91 plan.operations.push_back(std::move(operation).takeValue());
92 plan.summary = std::move(summary);
93 return eve::editing::applied<editing::CommandPlan>(std::move(plan));
94}
95
96} // namespace
97
99 auto registered = addCommand(
100 registry, "biome.layer.create.v1", "Create biome layer",
102 auto* biome = asBiome(target);
103 const std::string* id = stringField(request.payload, "id");
104 const std::string* spatial = stringField(request.payload, "spatial");
105 if (!biome || !id || id->empty() || !spatial || spatial->empty())
106 return eve::editing::failed<editing::CommandPlan>(editing::Status::Rejected,
107 editing::RuleId("biome.editing.layer-payload"),
108 "Biome layer create requires id and spatial asset");
109 const std::string* name = stringField(request.payload, "name");
112 layer.name = name && !name->empty() ? *name : *id;
113 layer.spatialAsset = *spatial;
114 layer.priority = 0;
115 layer.density = 1.f;
116 double density = 1.0;
117 if (!readInt(request.payload, "priority", layer.priority, false) ||
118 !readNumber(request.payload, "density", density, false))
119 return eve::editing::failed<editing::CommandPlan>(editing::Status::Rejected,
120 editing::RuleId("biome.editing.layer-number"),
121 "Biome layer priority and density must be numbers");
122 layer.density = static_cast<float>(density);
123 return planFrom(biome->makeCreateLayer(layer), editing::Value::Object{{"id", *id}});
124 });
125 if (!registered.ok()) return registered;
126
127 registered = addCommand(
128 registry, "biome.asset.create.v1", "Create biome asset",
130 auto* biome = asBiome(target);
131 const std::string* layer = stringField(request.payload, "layer");
132 const std::string* id = stringField(request.payload, "id");
133 const std::string* asset = stringField(request.payload, "asset");
134 if (!biome || !layer || layer->empty() || !id || id->empty() || !asset || asset->empty())
135 return eve::editing::failed<editing::CommandPlan>(editing::Status::Rejected,
136 editing::RuleId("biome.editing.asset-payload"),
137 "Biome asset create requires layer, id and asset");
138 BiomeAssetValue entry;
139 entry.id = editing::ObjectId(*id);
140 entry.asset = *asset;
141 double weight = 1.0, minScale = 1.0, maxScale = 1.0;
142 if (!readNumber(request.payload, "weight", weight, false) ||
143 !readNumber(request.payload, "minScale", minScale, false) ||
144 !readNumber(request.payload, "maxScale", maxScale, false) ||
145 !readBool(request.payload, "randomYaw", entry.randomYaw, false))
146 return eve::editing::failed<editing::CommandPlan>(editing::Status::Rejected,
147 editing::RuleId("biome.editing.asset-number"),
148 "Biome asset weight, scale and yaw must be valid");
149 entry.weight = static_cast<float>(weight);
150 entry.minScale = static_cast<float>(minScale);
151 entry.maxScale = static_cast<float>(maxScale);
152 return planFrom(biome->makeCreateAsset(editing::ObjectId(*layer), entry),
153 editing::Value::Object{{"id", *id}, {"layer", *layer}});
154 });
155 if (!registered.ok()) return registered;
156
157 return addCommand(
158 registry, "biome.property.set.v1", "Set biome property",
159 [](editing::IEditableTarget& target, const editing::CommandRequest& request) {
160 auto* biome = asBiome(target);
161 auto* properties = static_cast<editing::IPropertyProvider*>(
162 target.queryCapability(BiomeDocumentTarget::propertyCapabilityId()));
163 const std::string* item = stringField(request.payload, "item");
164 const std::string* type = stringField(request.payload, "type");
165 const std::string* path = stringField(request.payload, "path");
166 const editing::Value* value = field(request.payload, "value");
167 if (!biome || !properties || !item || item->empty() || !type || !path || !value)
168 return eve::editing::failed<editing::CommandPlan>(editing::Status::Rejected,
169 editing::RuleId("biome.editing.property-payload"),
170 "Biome property requires item, type, path and value");
171 return planFrom(properties->makeSet(selectionFor(*biome, *item, *type), editing::PropertyPath(*path),
172 *value, editing::PropertySetMode::Absolute),
173 editing::Value::Object{{"item", *item}, {"path", *path}});
174 });
175}
176
177} // namespace eve::biome_editing
LogicalId target
ActionParameterOperation operation
double value
std::string output
std::string descriptor
eve::action::ActionSpatialBinding spatial
const GltfImportRequest & request
std::uint32_t key
int biome
std::map< std::string, PropertyRule > properties
bool required
std::string name
TileLayer * layer
std::string path
Definition PlayHost.cpp:110
std::string id
Definition PlayHost.cpp:108
bool found
Move-only operation result carrying either a value or Status.
Definition Result.h:155
UUID-backed identifier adapter for legacy textual boundaries.
Definition Identity.h:314
Revisioned BiomeRules asset.
Definition BiomeTarget.h:64
IEditableTarget public API.
Lower-layer registration boundary implemented by an editor or runtime editing host.
virtual Result< void > registerPlannedCommand(EditingCommandDescriptor descriptor, EditingCommandPlanner planner)=0
Register or replace one domain-owned planned command.
Deterministic owning value tree shared by authoring hosts.
std::map< std::string, Value > Object
const T * getIf() const
Return an immediately borrowed typed value.
editing::Result< void > registerEditingCommands(editing::IEditingCommandRegistry &registry)
Register Biome-owned planned commands with a generic editing host.
StrongId< TargetIdTag > TargetId
Definition EditingIds.h:57
StrongId< ObjectIdTag > ObjectId
Definition EditingIds.h:65
std::function< Result< CommandPlan >(IEditableTarget &, const CommandRequest &)> EditingCommandPlanner
Side-effect-free planner invoked with the resolved target.
StrongId< StableIdTag > StableId
Definition EditingIds.h:64
StrongId< CommandIdTag > CommandId
Definition EditingIds.h:58
const EditorValue * field(const EditorValue &value, const char *name)
Stable authored biome layer referencing a spatial asset.
Definition BiomeTarget.h:51
CommandPlan public API.
std::vector< DomainOperation > operations
CommandRequest public API.
Domain-owned metadata for one planned editing command.
SelectionItem public API.
SelectionSnapshot public API.
std::vector< SelectionItem > items
std::optional< SelectionItem > primary
NodeType type
Definition Widget.h:16