载入中...
搜索中...
未找到
BiomeTarget.cpp
浏览该文件的文档.
2#include <algorithm>
3#include <cmath>
4#include <set>
5#include <utility>
6namespace eve::biome_editing {
7namespace {
8const EditorValue* field(const EditorValue& v, const char* k) {
9 const auto* o = v.getIf<EditorValue::Object>();
10 if (!o) return nullptr;
11 const auto i = o->find(k);
12 return i == o->end() ? nullptr : &i->second;
13}
14EditorValue assetValue(const BiomeAssetValue& v) {
15 return EditorValue::Object{{"id", v.id.value()}, {"asset", v.asset}, {"weight", v.weight},
16 {"minScale", v.minScale}, {"maxScale", v.maxScale}, {"randomYaw", v.randomYaw}};
17}
18EditorValue layerValue(const BiomeLayerValue& v) {
20 for (const auto& x : v.assets) a.push_back(assetValue(x));
21 return EditorValue::Object{{"id", v.id.value()}, {"name", v.name},
22 {"spatial", v.spatialAsset}, {"priority", int64_t{v.priority}},
23 {"density", v.density}, {"assets", std::move(a)}};
24}
25Result<BiomeAssetValue> parseAsset(const EditorValue& v) {
26 BiomeAssetValue o;
27 const auto * id = field(v, "id"), *asset = field(v, "asset"), *yaw = field(v, "randomYaw");
28 const auto* ids = id ? id->getIf<std::string>() : nullptr;
29 const auto* assets = asset ? asset->getIf<std::string>() : nullptr;
30 const auto* yaws = yaw ? yaw->getIf<bool>() : nullptr;
31 if (!ids || ids->empty() || !assets || !yaws)
32 return eve::editing::failed<BiomeAssetValue>(EditorStatus::Rejected, RuleId("editor.biome.asset"),
33 "Biome asset identity is invalid");
34 o.id = ObjectId(*ids);
35 o.asset = *assets;
36 o.randomYaw = *yaws;
37 float* values[] = {&o.weight, &o.minScale, &o.maxScale};
38 const char* fields[] = {"weight", "minScale", "maxScale"};
39 for (int i = 0; i < 3; ++i) {
40 const auto* x = field(v, fields[i]);
41 const auto* n = x ? x->getIf<double>() : nullptr;
42 if (!n || !std::isfinite(*n))
43 return eve::editing::failed<BiomeAssetValue>(EditorStatus::Rejected, RuleId("editor.biome.asset-number"),
44 "Biome asset number is invalid");
45 *values[i] = static_cast<float>(*n);
46 }
47 return eve::editing::applied<BiomeAssetValue>(std::move(o));
48}
49Result<BiomeLayerValue> parseLayer(const EditorValue& v) {
50 BiomeLayerValue o;
51 const auto * id = field(v, "id"), *name = field(v, "name"), *spatial = field(v, "spatial"),
52 *priority = field(v, "priority"), *density = field(v, "density"), *assets = field(v, "assets");
53 const auto* ids = id ? id->getIf<std::string>() : nullptr;
54 const auto* names = name ? name->getIf<std::string>() : nullptr;
55 const auto* spatials = spatial ? spatial->getIf<std::string>() : nullptr;
56 const auto* priorities = priority ? priority->getIf<int64_t>() : nullptr;
57 const auto* densities = density ? density->getIf<double>() : nullptr;
58 const auto* a = assets ? assets->getIf<EditorValue::Array>() : nullptr;
59 if (!ids || ids->empty() || !names || !spatials || !priorities || !densities || !std::isfinite(*densities) || !a)
60 return eve::editing::failed<BiomeLayerValue>(EditorStatus::Rejected, RuleId("editor.biome.layer"),
61 "Biome layer is invalid");
62 o.id = ObjectId(*ids);
63 o.name = *names;
64 o.spatialAsset = *spatials;
65 o.priority = static_cast<int>(*priorities);
66 o.density = static_cast<float>(*densities);
67 for (const auto& x : *a) {
68 auto parsed = parseAsset(x);
69 if (!parsed.ok())
70 return eve::editing::failed<BiomeLayerValue>(EditorStatus::Rejected, RuleId("editor.biome.asset"),
71 "Biome layer contains invalid asset");
72 o.assets.push_back(std::move(parsed.value()));
73 }
74 return eve::editing::applied<BiomeLayerValue>(std::move(o));
75}
76PropertyDescriptor prop(std::string p, PropertyType t, EditorValue v, const char* c, double min = -1e9,
77 double max = 1e9) {
80 d.displayNameKey = "editor.biome." + p;
81 d.category = c;
82 d.type = t;
83 d.defaultValue = std::move(v);
84 d.flags = PropertyFlag::Runtime;
85 d.numeric.minimum = min;
86 d.numeric.maximum = max;
87 return d;
88}
89bool errors(const std::vector<EditorDiagnostic>& d) {
90 return std::any_of(d.begin(), d.end(), [](const auto& v) { return v.severity() == DiagnosticSeverity::Error; });
91}
92EditorDiagnostic diagnostic(const char* rule, DiagnosticSeverity severity, std::string message) {
94 std::move(message));
95}
96} // namespace
97BiomeDocumentTarget::BiomeDocumentTarget(std::string id) : id_(std::move(id)) {}
106 if (c == propertyCapabilityId()) return static_cast<IPropertyProvider*>(this);
108 return static_cast<IEditingSnapshotProvider*>(this);
109 return nullptr;
110}
111bool BiomeDocumentTarget::matches(const SelectionSnapshot& s) const {
112 if (s.items.empty()) return false;
113 const auto type = s.items.front().type;
114 for (const auto& i : s.items) {
115 if (i.target != TargetId(id_) || i.type != type) return false;
116 bool found = false;
117 if (type == "biome.layer")
118 found = std::any_of(layers_.begin(), layers_.end(),
119 [&](const auto& v) { return v.id.value() == i.item.value(); });
120 else if (type == "biome.asset")
121 for (const auto& l : layers_)
122 found |= std::any_of(l.assets.begin(), l.assets.end(),
123 [&](const auto& v) { return v.id.value() == i.item.value(); });
124 else
125 return false;
126 if (!found) return false;
127 }
128 return true;
129}
138 if (!s.items.empty() && s.items.front().type == "biome.asset") {
139 schema.typeId = "biome.asset";
140 schema.properties = {prop("asset.ref", PropertyType::AssetRef, "", "asset"),
141 prop("asset.weight", PropertyType::Float, 1.0, "asset", .0001, 1e9),
142 prop("asset.scale", PropertyType::Vec2, EditorValue::Array{1.0, 1.0}, "asset", .0001, 1e9),
143 prop("asset.randomYaw", PropertyType::Bool, true, "asset")};
144 schema.properties[0].assetTypeFilters = {"model3d", "prefab"};
145 } else {
146 schema.typeId = "biome.layer";
147 schema.properties = {prop("layer.spatial", PropertyType::AssetRef, "", "layer"),
148 prop("layer.priority", PropertyType::Int, int64_t{0}, "layer", -100000, 100000),
149 prop("layer.density", PropertyType::Float, 1.0, "layer", 0, 1)};
150 schema.properties[0].assetTypeFilters = {"spatial", "volume", "spline", "heightfield"};
151 }
152 return schema;
153}
155 if (!matches(s) || !schema(s).find(p)) return {};
156 std::optional<EditorValue> common;
157 for (const auto& i : s.items) {
159 if (i.type == "biome.layer") {
160 const auto& v = *std::find_if(layers_.begin(), layers_.end(),
161 [&](const auto& x) { return x.id.value() == i.item.value(); });
162 if (p == PropertyPath("layer.spatial"))
163 value = v.spatialAsset;
164 else if (p == PropertyPath("layer.priority"))
165 value = int64_t{v.priority};
166 else
167 value = v.density;
168 } else {
169 const BiomeAssetValue* v = nullptr;
170 for (const auto& l : layers_) {
171 auto f = std::find_if(l.assets.begin(), l.assets.end(),
172 [&](const auto& x) { return x.id.value() == i.item.value(); });
173 if (f != l.assets.end()) v = &*f;
174 }
175 if (p == PropertyPath("asset.ref"))
176 value = v->asset;
177 else if (p == PropertyPath("asset.weight"))
178 value = v->weight;
179 else if (p == PropertyPath("asset.scale"))
180 value = EditorValue::Array{v->minScale, v->maxScale};
181 else
182 value = v->randomYaw;
183 }
184 if (!common)
185 common = value;
186 else if (*common != value)
187 return {PropertyReadState::Mixed, {}, {}};
188 }
189 return {PropertyReadState::Value, *common, {}};
190}
191EditorValue BiomeDocumentTarget::contentValue() const {
193 for (const auto& v : layers_) layers.push_back(layerValue(v));
194 for (const auto& v : exclusions_) exclusions.push_back(v);
195 return EditorValue::Object{{"layers", std::move(layers)}, {"exclusions", std::move(exclusions)}};
196}
197Result<DomainOperation> BiomeDocumentTarget::replacement(EditorValue c, std::string p) const {
199 op.type = "biome.document.replace.v1";
200 op.inverseType = op.type;
201 op.target = TargetId(id_);
202 op.payload = std::move(c);
203 op.inverse = contentValue();
204 op.hasInverse = true;
205 if (!p.empty()) op.affectedProperties.push_back(p);
206 op.mergeKey = "biome:" + id_ + ":" + (p.empty() ? "structure" : p);
207 return eve::editing::applied<DomainOperation>(std::move(op));
208}
210 const EditorValue& value, PropertySetMode mode) const {
211 if (mode == PropertySetMode::Reset) return makeReset(s, p);
212 auto d = schema(s).find(p);
213 if (!matches(s) || !d || mode != PropertySetMode::Absolute || !validatePropertyValue(*d, value).ok())
214 return eve::editing::failed<DomainOperation>(EditorStatus::Rejected, RuleId("editor.biome.set"),
215 "Biome property edit is invalid");
216 auto c = *this;
217 for (const auto& i : s.items)
218 if (i.type == "biome.layer") {
219 auto& v = *std::find_if(c.layers_.begin(), c.layers_.end(),
220 [&](const auto& x) { return x.id.value() == i.item.value(); });
221 if (p == PropertyPath("layer.spatial"))
222 v.spatialAsset = *value.getIf<std::string>();
223 else if (p == PropertyPath("layer.priority"))
224 v.priority = static_cast<int>(*value.getIf<int64_t>());
225 else
226 v.density = static_cast<float>(*value.getIf<double>());
227 } else
228 for (auto& l : c.layers_) {
229 auto f = std::find_if(l.assets.begin(), l.assets.end(),
230 [&](const auto& x) { return x.id.value() == i.item.value(); });
231 if (f == l.assets.end()) continue;
232 if (p == PropertyPath("asset.ref"))
233 f->asset = *value.getIf<std::string>();
234 else if (p == PropertyPath("asset.weight"))
235 f->weight = static_cast<float>(*value.getIf<double>());
236 else if (p == PropertyPath("asset.scale")) {
237 const auto& a = *value.getIf<EditorValue::Array>();
238 f->minScale = static_cast<float>(*a[0].getIf<double>());
239 f->maxScale = static_cast<float>(*a[1].getIf<double>());
240 } else
241 f->randomYaw = *value.getIf<bool>();
242 }
243 if (errors(c.validate()))
244 return eve::editing::failed<DomainOperation>(EditorStatus::Rejected, RuleId("editor.biome.invalid"),
245 "Biome edit produces invalid rules");
246 return replacement(c.contentValue(), p.value());
247}
249 auto d = schema(s).find(p);
250 if (!d)
251 return eve::editing::failed<DomainOperation>(EditorStatus::Unsupported, RuleId("editor.biome.property"),
252 "Unknown Biome property");
253 return makeSet(s, p, d->defaultValue, PropertySetMode::Absolute);
254}
256 if (v.id.empty() ||
257 std::any_of(layers_.begin(), layers_.end(), [&](const auto& x) { return x.id == v.id || x.name == v.name; }))
258 return eve::editing::failed<DomainOperation>(EditorStatus::Rejected, RuleId("editor.biome.layer-id"),
259 "Biome layer ID and name must be unique");
260 auto c = *this;
261 c.layers_.push_back(v);
262 if (errors(c.validate()))
263 return eve::editing::failed<DomainOperation>(EditorStatus::Rejected, RuleId("editor.biome.layer"),
264 "Biome layer is invalid");
265 return replacement(c.contentValue());
266}
268 if (std::none_of(layers_.begin(), layers_.end(), [&](const auto& v) { return v.id == id; }))
269 return eve::editing::failed<DomainOperation>(EditorStatus::NotFound, RuleId("editor.biome.layer"),
270 "Biome layer does not exist");
271 auto c = *this;
272 std::erase_if(c.layers_, [&](const auto& v) { return v.id == id; });
273 return replacement(c.contentValue());
274}
276 const BiomeAssetValue& v) const {
277 auto c = *this;
278 auto l = std::find_if(c.layers_.begin(), c.layers_.end(), [&](const auto& x) { return x.id == layer; });
279 if (l == c.layers_.end() || v.id.empty())
280 return eve::editing::failed<DomainOperation>(EditorStatus::NotFound, RuleId("editor.biome.layer"),
281 "Biome target layer is missing");
282 for (const auto& x : c.layers_)
283 for (const auto& a : x.assets)
284 if (a.id == v.id)
285 return eve::editing::failed<DomainOperation>(EditorStatus::Rejected, RuleId("editor.biome.asset-id"),
286 "Biome asset ID must be globally unique");
287 l->assets.push_back(v);
288 if (errors(c.validate()))
289 return eve::editing::failed<DomainOperation>(EditorStatus::Rejected, RuleId("editor.biome.asset"),
290 "Biome asset is invalid");
291 return replacement(c.contentValue());
292}
294 auto c = *this;
295 bool removed = false;
296 for (auto& l : c.layers_) {
297 const auto before = l.assets.size();
298 std::erase_if(l.assets, [&](const auto& v) { return v.id == id; });
299 removed |= l.assets.size() != before;
300 }
301 if (!removed)
302 return eve::editing::failed<DomainOperation>(EditorStatus::NotFound, RuleId("editor.biome.asset"),
303 "Biome asset does not exist");
304 return replacement(c.contentValue());
305}
307 auto c = *this;
308 c.exclusions_ = std::move(v);
309 if (errors(c.validate()))
310 return eve::editing::failed<DomainOperation>(EditorStatus::Rejected, RuleId("editor.biome.exclusions"),
311 "Biome exclusions are invalid");
312 return replacement(c.contentValue(), "exclusions");
313}
314std::vector<EditorDiagnostic> BiomeDocumentTarget::validate() const {
315 std::vector<EditorDiagnostic> d;
316 if (layers_.size() > 256 || exclusions_.size() > 256)
317 d.push_back(
318 diagnostic("editor.biome.budget", DiagnosticSeverity::Error, "Biome exceeds 256 layers or exclusions"));
319 std::set<std::string> ids, names, exclusions;
320 for (const auto& e : exclusions_)
321 if (e.empty() || !exclusions.insert(e).second)
322 d.push_back(diagnostic("editor.biome.exclusion", DiagnosticSeverity::Error,
323 "Biome exclusions must be non-empty and unique"));
324 for (const auto& l : layers_) {
325 if (l.id.empty() || l.name.empty() || !ids.insert(l.id.value()).second || !names.insert(l.name).second)
326 d.push_back(diagnostic("editor.biome.layer-identity", DiagnosticSeverity::Error,
327 "Biome layer IDs and names must be unique"));
328 if (l.spatialAsset.empty())
329 d.push_back(
330 diagnostic("editor.biome.spatial", DiagnosticSeverity::Error, "Biome layer requires a spatial asset"));
331 if (l.priority < -100000 || l.priority > 100000 || !std::isfinite(l.density) || l.density < 0 || l.density > 1)
332 d.push_back(diagnostic("editor.biome.layer-range", DiagnosticSeverity::Error,
333 "Biome layer priority or density is invalid"));
334 if (l.assets.empty())
335 d.push_back(diagnostic("editor.biome.empty-layer", DiagnosticSeverity::Warning,
336 "Biome layer has no assets: " + l.name));
337 if (l.assets.size() > 4096)
338 d.push_back(
339 diagnostic("editor.biome.asset-budget", DiagnosticSeverity::Error, "Biome layer exceeds 4096 assets"));
340 for (const auto& a : l.assets) {
341 if (a.id.empty() || a.asset.empty() || !ids.insert(a.id.value()).second || !std::isfinite(a.weight) ||
342 a.weight <= 0 || !std::isfinite(a.minScale) || !std::isfinite(a.maxScale) || a.minScale <= 0 ||
343 a.maxScale < a.minScale)
344 d.push_back(diagnostic("editor.biome.asset", DiagnosticSeverity::Error,
345 "Biome asset identity, weight or scale is invalid"));
346 }
347 }
348 if (layers_.empty())
349 d.push_back(diagnostic("editor.biome.empty", DiagnosticSeverity::Warning, "Biome has no layers"));
350 return d;
351}
353 if (op.target != TargetId(id_) || op.type != "biome.document.replace.v1" ||
354 !op.payload.isWithinLimits(8, 200000, 8 * 1024 * 1024))
355 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.biome.operation"),
356 "Biome operation is invalid");
357 const auto *layers = field(op.payload, "layers"), *exclusions = field(op.payload, "exclusions");
358 const auto* la = layers ? layers->getIf<EditorValue::Array>() : nullptr;
359 const auto* ea = exclusions ? exclusions->getIf<EditorValue::Array>() : nullptr;
360 if (!la || !ea || la->size() > 256 || ea->size() > 256)
361 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.biome.payload"),
362 "Biome payload exceeds limits");
364 for (const auto& v : *la) {
365 auto parsed = parseLayer(v);
366 if (!parsed.ok())
367 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.biome.layer"),
368 "Biome layer cannot be parsed");
369 c.layers_.push_back(std::move(parsed.value()));
370 }
371 for (const auto& v : *ea) {
372 const auto* s = v.getIf<std::string>();
373 if (!s)
374 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.biome.exclusion"),
375 "Biome exclusion is invalid");
376 c.exclusions_.push_back(*s);
377 }
378 if (errors(c.validate()))
379 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.biome.invalid"),
380 "Biome document validation failed");
381 layers_ = std::move(c.layers_);
382 exclusions_ = std::move(c.exclusions_);
383 bumpRevision();
384 widenDirty(0, 0);
385 return eve::editing::applied<void>();
386}
387std::unique_ptr<IDomainOperationTarget> BiomeDocumentTarget::cloneDomainState() const {
388 return std::make_unique<BiomeDocumentTarget>(*this);
389}
390Result<void> BiomeDocumentTarget::commitDomainState(std::unique_ptr<IDomainOperationTarget> c) {
391 auto* t = dynamic_cast<BiomeDocumentTarget*>(c.get());
392 if (!t || t->id_ != id_)
393 return eve::editing::failed<void>(EditorStatus::Conflict, RuleId("editor.biome.candidate"),
394 "Biome candidate mismatch");
395 *this = *t;
396 return eve::editing::applied<void>();
397}
399 return EditorValue::Object{{"schemaVersion", int64_t{1}}, {"content", contentValue()}};
400}
402 const auto *v = field(s, "schemaVersion"), *content = field(s, "content");
403 const auto* version = v ? v->getIf<int64_t>() : nullptr;
404 if (!version || *version != 1 || !content)
405 return eve::editing::failed<void>(EditorStatus::Unsupported, RuleId("editor.biome.snapshot"),
406 "Unsupported Biome snapshot");
408 op.target = TargetId(id_);
409 op.type = "biome.document.replace.v1";
410 op.payload = *content;
411 auto result = applyDomainOperation(op);
412 if (result.ok()) clearDirtyRegion();
413 return result;
414}
415} // namespace eve::biome_editing
double value
float x
Definition AnimClip.cpp:738
eve::action::ActionSpatialBinding spatial
const std::string & s
int priority
glm::vec4 p[6]
std::map< std::string, Var > values
std::string message
glm::uvec4 ids
glm::vec3 n
Definition Grass.cpp:63
float v
std::int32_t c
std::string name
MeleePoint3 a
Definition MeleeHit.cpp:40
TileLayer * layer
float f
std::vector< std::string > fields
Definition PlayHost.cpp:111
std::string id
Definition PlayHost.cpp:108
float begin
float d
float t
bool found
int removed
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
UUID-backed identifier adapter for legacy textual boundaries.
Definition Identity.h:314
Revisioned BiomeRules asset.
Definition BiomeTarget.h:64
Result< DomainOperation > makeCreateLayer(const BiomeLayerValue &) const
Make create layer.
EditorValue snapshotValue() const override
Snapshot value.
const std::vector< std::string > & exclusions() const
Exclusions.
const std::vector< BiomeLayerValue > & layers() const
Layers.
Result< void > loadSnapshot(const EditorValue &)
Loads snapshot.
Result< DomainOperation > makeSet(const SelectionSnapshot &, const PropertyPath &, const EditorValue &, PropertySetMode) const override
Make set.
Result< DomainOperation > makeDeleteLayer(const ObjectId &) const
Make delete layer.
Result< DomainOperation > makeDeleteAsset(const ObjectId &) const
Make delete asset.
BiomeDocumentTarget(std::string id)
Biome document target.
PropertyReadResult read(const SelectionSnapshot &, const PropertyPath &) const override
Reads .
Result< DomainOperation > makeReset(const SelectionSnapshot &, const PropertyPath &) const override
Make reset.
Result< DomainOperation > makeSetExclusions(std::vector< std::string >) const
Make set exclusions.
std::unique_ptr< IDomainOperationTarget > cloneDomainState() const override
Clones domain state.
PropertySchema schema(const SelectionSnapshot &) const override
Schema.
Result< void > commitDomainState(std::unique_ptr< IDomainOperationTarget >) override
Commits domain state.
std::vector< EditorDiagnostic > validate() const
Validate.
static CapabilityId propertyCapabilityId()
Capability identity published by describe() for Inspector property editing.
Definition BiomeTarget.h:69
Result< void > applyDomainOperation(const DomainOperation &) override
Applies domain operation.
Result< DomainOperation > makeCreateAsset(const ObjectId &layer, const BiomeAssetValue &) const
Make create asset.
void * queryCapability(const CapabilityId &) override
Query Inspector property and snapshot capabilities. @ownership Borrowed from this target; callers mus...
TargetDescriptor describe() const override
Describe.
eve::Result< eve::Revision > currentRevision(const SelectionSnapshot &) const override
Current revision.
void bumpRevision()
Advance the revision without touching the dirty region.
Revision revisionValue() const noexcept
Return the revision as the shared protocol revision type.
void widenDirty()
Mark an unknown area dirty without advancing the revision.
virtual void clearDirtyRegion()=0
Clears dirty region.
Optional capability exposing a deterministic, persistence-safe editing snapshot.
static CapabilityId editingCapabilityId()
Stable capability identity shared by every editable domain target.
UI-independent property access for an immutable selection snapshot.
Dotted property path (layout.size) compared and persisted as text.
Definition EditingIds.h:78
Deterministic owning value tree shared by authoring hosts.
std::vector< Value > Array
bool isWithinLimits(size_t maxDepth, size_t maxElements, size_t maxStringBytes) const
Validate nesting, element count and approximate string byte limits.
std::map< std::string, Value > Object
const T * getIf() const
Return an immediately borrowed typed value.
editing::PropertyDescriptor PropertyDescriptor
Definition BiomeTarget.h:31
editing::TargetId TargetId
Definition BiomeTarget.h:43
editing::DomainOperation DomainOperation
Definition BiomeTarget.h:19
editing::DiagnosticSeverity DiagnosticSeverity
Definition BiomeTarget.h:18
editing::PropertyType PropertyType
Definition BiomeTarget.h:38
editing::Diagnostic EditorDiagnostic
Definition BiomeTarget.h:21
editing::PropertyPath PropertyPath
Definition BiomeTarget.h:33
editing::ObjectId ObjectId
Definition BiomeTarget.h:30
editing::RuleId RuleId
Definition BiomeTarget.h:40
editing::Value EditorValue
Definition BiomeTarget.h:24
PropertySetMode
PropertySetMode public API.
Diagnostic ruleDiagnostic(eve::DiagnosticCode code, RuleId rule, DiagnosticSeverity severity, std::string message)
Build a common diagnostic carrying an open editing rule identity.
const EditorValue * field(const EditorValue &value, const char *name)
Stable weighted asset entry in one biome layer.
Definition BiomeTarget.h:45
Stable authored biome layer referencing a spatial asset.
Definition BiomeTarget.h:51
DomainOperation public API.
PropertyReadResult public API.
EVENGINE_API_PLATFORM public API.
std::vector< PropertyDescriptor > properties
PropertyDescriptorLookup find(const PropertyPath &path) const
Finds find.
SelectionSnapshot public API.
Stable discovery metadata exposed by every editable target.