载入中...
搜索中...
未找到
EditorPrefab.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <map>
5#include <set>
6#include <utility>
7
8namespace eve::editor {
9namespace {
10
11ObjectId instanceObject(const std::string& instanceId, const ObjectId& source) {
12 return ObjectId(instanceId + "/" + source.value());
13}
14
15const EditorValue* field(const EditorValue& value, const char* key) {
16 const auto* object = value.getIf<EditorValue::Object>();
17 if (!object) return nullptr;
18 const auto found = object->find(key);
19 return found == object->end() ? nullptr : &found->second;
20}
21
22EditorValue transformValue(const SceneTransformValue& value) {
23 return EditorValue::Object{{"x", value.x}, {"y", value.y}, {"z", value.z},
24 {"rotationX", value.rotationX}, {"rotationY", value.rotationY},
25 {"rotationZ", value.rotationZ}, {"scaleX", value.scaleX},
26 {"scaleY", value.scaleY}, {"scaleZ", value.scaleZ}};
27}
28
29Result<SceneTransformValue> parseTransform(const EditorValue& value) {
30 const auto number = [&](const char* key) -> const double* {
31 const EditorValue* entry = field(value, key);
32 return entry ? entry->getIf<double>() : nullptr;
33 };
34 const double* x = number("x");
35 const double* y = number("y");
36 const double* z = number("z");
37 const double* rx = number("rotationX");
38 const double* ry = number("rotationY");
39 const double* rz = number("rotationZ");
40 const double* sx = number("scaleX");
41 const double* sy = number("scaleY");
42 const double* sz = number("scaleZ");
43 if (!x || !y || !z || !rx || !ry || !rz || !sx || !sy || !sz)
44 return eve::editing::failed<SceneTransformValue>(EditorStatus::Rejected,
45 RuleId("editor.prefab.invalid-transform"),
46 "Prefab transform requires complete numeric TRS fields");
47 return eve::editing::applied<SceneTransformValue>({*x, *y, *z, *rx, *ry, *rz, *sx, *sy, *sz});
48}
49
50Result<void> validatePrefab(const PrefabAssetSnapshot& prefab) {
51 if (prefab.asset.empty() || prefab.rootSourceId.empty() || prefab.objects.empty() || prefab.revision == 0)
52 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.prefab.invalid-identity"),
53 "Prefab requires asset, revision, root and objects");
54 std::set<ObjectId> ids;
55 for (const PrefabObjectRecord& object : prefab.objects)
56 if (object.sourceId.empty() || !ids.insert(object.sourceId).second)
57 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.prefab.duplicate-object"),
58 "Prefab object ids must be unique and non-empty");
59 for (const PrefabObjectRecord& object : prefab.objects)
60 if (object.nestedPrefab.empty() != (object.nestedRevision == 0))
61 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.prefab.invalid-nested-pin"),
62 "Nested prefab references require both asset and non-zero revision");
63 if (!ids.contains(prefab.rootSourceId))
64 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.prefab.root-not-found"),
65 "Prefab root does not exist");
66 for (const PrefabObjectRecord& object : prefab.objects) {
67 if (object.sourceId == prefab.rootSourceId && !object.parentSourceId.empty())
68 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.prefab.root-has-parent"),
69 "Prefab root must not have an internal parent");
70 if (object.sourceId != prefab.rootSourceId && !ids.contains(object.parentSourceId))
71 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.prefab.parent-not-found"),
72 "Prefab object references a missing parent");
73 std::set<ObjectId> ancestry;
74 const PrefabObjectRecord* cursor = &object;
75 while (!cursor->parentSourceId.empty()) {
76 if (!ancestry.insert(cursor->sourceId).second)
77 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.prefab.hierarchy-cycle"),
78 "Prefab hierarchy contains a cycle");
79 const auto parent = std::find_if(prefab.objects.begin(), prefab.objects.end(),
80 [&](const PrefabObjectRecord& candidate) {
81 return candidate.sourceId == cursor->parentSourceId;
82 });
83 if (parent == prefab.objects.end()) break;
84 cursor = &*parent;
85 }
86 if (cursor->sourceId != prefab.rootSourceId)
87 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.prefab.disconnected-object"),
88 "Every prefab object must descend from its root");
89 }
90 return eve::editing::applied<void>();
91}
92
93} // namespace
94
96 const SceneTargetBase& scene,
97 const ObjectId& root) const {
98 if (asset.empty())
99 return eve::editing::failed<PrefabAssetSnapshot>(EditorStatus::Rejected, RuleId("editor.prefab.asset-required"),
100 "Prefab asset identity is required");
101 auto rootObject = scene.sceneObject(root);
102 if (!rootObject.ok())
103 return eve::editing::failed<PrefabAssetSnapshot>(EditorStatus::NotFound, RuleId("editor.prefab.root-not-found"),
104 "Prefab capture root does not exist");
106 prefab.asset = asset;
107 prefab.rootSourceId = root;
108 std::vector<ObjectId> pending{root};
109 for (size_t index = 0; index < pending.size(); ++index) {
110 const ObjectId id = pending[index];
111 auto object = scene.sceneObject(id);
112 if (!object.ok())
113 return eve::editing::failed<PrefabAssetSnapshot>(EditorStatus::Conflict,
114 RuleId("editor.prefab.capture-diverged"),
115 "Scene hierarchy changed during prefab capture");
116 prefab.objects.push_back({id, id == root ? ObjectId{} : object.value().parent,
117 object.value().name, object.value().transform, {}, 0});
118 const auto children = scene.sceneChildren(id);
119 pending.insert(pending.end(), children.begin(), children.end());
120 }
121 return eve::editing::applied<PrefabAssetSnapshot>(std::move(prefab));
122}
123
125 const std::string& instanceId,
126 const ObjectId& parent,
127 const SceneTargetBase& scene) const {
128 if (!validatePrefab(prefab).ok() || instanceId.empty())
129 return eve::editing::failed<PrefabInstancePlan>(EditorStatus::Rejected,
130 RuleId("editor.prefab.invalid-instance"),
131 "Prefab and non-empty instance id are required");
132 if (!parent.empty() && !scene.sceneObject(parent).ok())
133 return eve::editing::failed<PrefabInstancePlan>(EditorStatus::NotFound,
134 RuleId("editor.prefab.scene-parent-not-found"),
135 "Prefab instance parent does not exist");
137 plan.instanceId = instanceId;
138 plan.sourceAsset = prefab.asset;
139 plan.sourceRevision = prefab.revision;
140 for (const PrefabObjectRecord& object : prefab.objects) {
141 const ObjectId id = instanceObject(instanceId, object.sourceId);
142 if (scene.sceneObject(id).ok())
143 return eve::editing::failed<PrefabInstancePlan>(EditorStatus::Conflict,
144 RuleId("editor.prefab.instance-id-conflict"),
145 "Prefab instance object already exists: " + id.value());
147 request.id = id;
148 request.parent = object.sourceId == prefab.rootSourceId
149 ? parent
150 : instanceObject(instanceId, object.parentSourceId);
151 request.name = object.name;
152 request.transform = object.transform;
153 auto operation = scene.makeCreate(request);
154 if (!operation.ok()) {
155 // Parents created earlier in this plan are intentionally not yet in
156 // the target, so construct the same validated operation value here.
157 DomainOperation create;
158 create.type = "scene.object.create.v1";
159 create.inverseType = "scene.object.delete.v1";
160 create.target = TargetId(scene.targetId());
161 EditorValue::Object payload{{"id", request.id.value()}, {"parent", request.parent.value()},
162 {"name", request.name}, {"transform", transformValue(request.transform)}};
163 create.payload = EditorValue(payload);
164 create.inverse = EditorValue(std::move(payload));
165 create.hasInverse = true;
166 create.affectedObjects.push_back({TargetId(scene.targetId()), request.id.value(), 0});
167 plan.operations.push_back(std::move(create));
168 } else {
169 plan.operations.push_back(std::move(operation).takeValue());
170 }
171 }
172 return eve::editing::applied<PrefabInstancePlan>(std::move(plan));
173}
174
176 const PrefabAssetSnapshot& prefab, const std::string& instanceId, const ObjectId& parent,
177 const SceneTargetBase& scene) const {
178 if (!validatePrefab(prefab).ok() || instanceId.empty())
179 return eve::editing::failed<std::vector<DomainOperation>>(
180 EditorStatus::Rejected, RuleId("editor.prefab.invalid-instance"), "Prefab and instance id are required");
181 std::vector<DomainOperation> operations;
182 for (const PrefabObjectRecord& source : prefab.objects) {
183 const ObjectId id = instanceObject(instanceId, source.sourceId);
184 auto object = scene.sceneObject(id);
185 if (!object.ok())
186 return eve::editing::failed<std::vector<DomainOperation>>(
187 EditorStatus::Conflict, RuleId("editor.prefab.instance-structure-changed"),
188 "Prefab instance object is missing: " + id.value());
189 const ObjectId wantedParent = source.sourceId == prefab.rootSourceId
190 ? parent
191 : instanceObject(instanceId, source.parentSourceId);
192 if (object.value().parent != wantedParent) {
193 auto operation = scene.makeReparent(id, wantedParent);
194 if (!operation.ok())
195 return eve::editing::failed<std::vector<DomainOperation>>(EditorStatus::Conflict,
196 RuleId("editor.prefab.revert-reparent"),
197 "Could not plan prefab reparent revert");
198 operations.push_back(std::move(operation).takeValue());
199 }
200 if (object.value().name != source.name) {
201 auto operation = scene.makeRename(id, source.name);
202 if (!operation.ok())
203 return eve::editing::failed<std::vector<DomainOperation>>(EditorStatus::Conflict,
204 RuleId("editor.prefab.revert-rename"),
205 "Could not plan prefab rename revert");
206 operations.push_back(std::move(operation).takeValue());
207 }
208 if (object.value().transform != source.transform) {
209 auto operation = scene.makeSetTransform(id, source.transform);
210 if (!operation.ok())
211 return eve::editing::failed<std::vector<DomainOperation>>(EditorStatus::Conflict,
212 RuleId("editor.prefab.revert-transform"),
213 "Could not plan prefab transform revert");
214 operations.push_back(std::move(operation).takeValue());
215 }
216 }
217 return eve::editing::applied<std::vector<DomainOperation>>(std::move(operations));
218}
219
221 const std::string& instanceId,
222 const ObjectId& parent,
223 const SceneTargetBase& scene) const {
224 if (!validatePrefab(prefab).ok() || instanceId.empty())
225 return eve::editing::failed<PrefabAssetSnapshot>(
226 EditorStatus::Rejected, RuleId("editor.prefab.invalid-instance"), "Prefab and instance id are required");
228 ++result.revision;
229 std::map<ObjectId, ObjectId> instanceToSource;
230 for (const PrefabObjectRecord& source : prefab.objects)
231 instanceToSource.emplace(instanceObject(instanceId, source.sourceId), source.sourceId);
232 for (PrefabObjectRecord& destination : result.objects) {
233 const ObjectId instance = instanceObject(instanceId, destination.sourceId);
234 auto object = scene.sceneObject(instance);
235 if (!object.ok())
236 return eve::editing::failed<PrefabAssetSnapshot>(EditorStatus::Conflict,
237 RuleId("editor.prefab.instance-structure-changed"),
238 "Prefab instance object is missing: " + instance.value());
239 destination.name = object.value().name;
240 destination.transform = object.value().transform;
241 if (destination.sourceId == prefab.rootSourceId) {
242 if (object.value().parent != parent)
243 return eve::editing::failed<PrefabAssetSnapshot>(EditorStatus::Conflict,
244 RuleId("editor.prefab.root-reparented"),
245 "Prefab root moved outside its instance parent");
246 destination.parentSourceId = ObjectId{};
247 } else {
248 const auto sourceParent = instanceToSource.find(object.value().parent);
249 if (sourceParent == instanceToSource.end())
250 return eve::editing::failed<PrefabAssetSnapshot>(EditorStatus::Conflict,
251 RuleId("editor.prefab.child-reparented-outside"),
252 "Prefab child moved outside its instance");
253 destination.parentSourceId = sourceParent->second;
254 }
255 }
256 return eve::editing::applied<PrefabAssetSnapshot>(std::move(result));
257}
258
260 const PrefabAssetSnapshot& prefab, const std::string& instanceId, const ObjectId& parent,
261 const SceneTargetBase& scene) const {
262 if (!validatePrefab(prefab).ok() || instanceId.empty())
263 return eve::editing::failed<std::vector<PrefabOverrideRecord>>(
264 EditorStatus::Rejected, RuleId("editor.prefab.invalid-instance"), "Prefab and instance id are required");
265 std::vector<PrefabOverrideRecord> result;
266 for (const PrefabObjectRecord& source : prefab.objects) {
267 const ObjectId instance = instanceObject(instanceId, source.sourceId);
268 auto object = scene.sceneObject(instance);
269 if (!object.ok()) {
270 result.push_back({instance, source.sourceId, "object", "missing"});
271 continue;
272 }
273 const ObjectId expectedParent = source.sourceId == prefab.rootSourceId
274 ? parent : instanceObject(instanceId, source.parentSourceId);
275 if (object.value().parent != expectedParent)
276 result.push_back({instance, source.sourceId, "hierarchy.parent", "modified"});
277 if (object.value().name != source.name)
278 result.push_back({instance, source.sourceId, "object.name", "modified"});
279 if (object.value().transform != source.transform)
280 result.push_back({instance, source.sourceId, "transform", "modified"});
281 }
282 std::sort(result.begin(), result.end(), [](const auto& a, const auto& b) {
283 return a.instanceObject == b.instanceObject ? a.property < b.property
284 : a.instanceObject < b.instanceObject;
285 });
286 return eve::editing::applied<std::vector<PrefabOverrideRecord>>(std::move(result));
287}
288
290 const PrefabAssetSnapshot& prefab, const PrefabResolver& resolver) const {
292 const auto diagnostic = [&](DiagnosticCode code, const char* rule, DiagnosticSeverity severity,
293 std::string message) {
295 code, RuleId(rule), severity, std::move(message)));
296 };
297 report.rootAsset = prefab.asset; report.rootRevision = prefab.revision;
298 if (!resolver || !validatePrefab(prefab).ok()) {
299 report.status = EditorStatus::Rejected;
300 diagnostic(DiagnosticCode::InvalidArgument, "editor.prefab.invalid-dependency-root",
301 DiagnosticSeverity::Error,
302 "Dependency inspection requires a valid prefab and resolver");
303 return report;
304 }
305 std::set<AssetGuid> visiting, visited;
306 std::function<bool(const PrefabAssetSnapshot&)> visit = [&](const PrefabAssetSnapshot& current) {
307 if (visiting.contains(current.asset)) {
308 diagnostic(DiagnosticCode::Conflict, "editor.prefab.dependency-cycle",
309 DiagnosticSeverity::Error,
310 "Nested prefab dependency cycle reaches: " + current.asset.value());
311 return false;
312 }
313 if (visited.contains(current.asset)) return true;
314 visiting.insert(current.asset);
315 bool valid = true;
316 for (const PrefabObjectRecord& object : current.objects) {
317 if (object.nestedPrefab.empty()) continue;
318 auto resolved = resolver(object.nestedPrefab);
319 if (!resolved.ok()) {
320 diagnostic(DiagnosticCode::NotFound, "editor.prefab.dependency-missing",
321 DiagnosticSeverity::Error,
322 "Nested prefab cannot be resolved: " + object.nestedPrefab.value());
323 valid = false; continue;
324 }
325 if (!validatePrefab(resolved.value()).ok()) {
326 diagnostic(DiagnosticCode::PreconditionViolation, "editor.prefab.dependency-invalid",
327 DiagnosticSeverity::Error,
328 "Nested prefab is invalid: " + object.nestedPrefab.value());
329 valid = false; continue;
330 }
331 if (resolved.value().revision != object.nestedRevision)
332 diagnostic(DiagnosticCode::Conflict, "editor.prefab.dependency-stale",
333 DiagnosticSeverity::Warning,
334 "Nested prefab revision pin is stale: " + object.nestedPrefab.value());
335 if (!visit(resolved.value())) valid = false;
336 }
337 visiting.erase(current.asset); visited.insert(current.asset);
338 if (current.asset != prefab.asset) report.dependencyOrder.push_back(current.asset);
339 return valid;
340 };
341 const bool valid = visit(prefab);
342 report.status = valid ? EditorStatus::Applied : EditorStatus::Rejected;
343 return report;
344}
345
347 const PrefabAssetSnapshot& prefab, const PrefabResolver& resolver) const {
348 auto dependencies = inspectDependencies(prefab, resolver);
349 if (dependencies.status != EditorStatus::Applied)
350 return eve::editing::failed<PrefabAssetSnapshot>(dependencies.status,
351 RuleId("editor.prefab.invalid-dependencies"),
352 "Nested prefab dependencies are missing, invalid or cyclic");
354 bool changed = false;
355 for (PrefabObjectRecord& object : result.objects) {
356 if (object.nestedPrefab.empty()) continue;
357 auto resolved = resolver(object.nestedPrefab);
358 if (!resolved.ok())
359 return eve::editing::failed<PrefabAssetSnapshot>(
360 resolved.code(), RuleId("editor.prefab.dependency-missing"), "Nested prefab cannot be resolved");
361 if (object.nestedRevision != resolved.value().revision) {
362 object.nestedRevision = resolved.value().revision;
363 changed = true;
364 }
365 }
366 if (changed) ++result.revision;
367 return eve::editing::applied<PrefabAssetSnapshot>(std::move(result));
368}
369
371 EditorValue::Array objects;
372 for (const PrefabObjectRecord& object : prefab.objects)
373 objects.emplace_back(EditorValue::Object{{"sourceId", object.sourceId.value()},
374 {"parentSourceId", object.parentSourceId.value()},
375 {"name", object.name},
376 {"transform", transformValue(object.transform)},
377 {"nestedPrefab", object.nestedPrefab.value()},
378 {"nestedRevision", static_cast<int64_t>(object.nestedRevision)}});
379 return EditorValue::Object{{"schemaVersion", int64_t{2}}, {"asset", prefab.asset.value()},
380 {"revision", static_cast<int64_t>(prefab.revision)},
381 {"rootSourceId", prefab.rootSourceId.value()}, {"objects", std::move(objects)}};
382}
383
384Result<PrefabAssetSnapshot> ScenePrefabService::loadSnapshot(const EditorValue& snapshot) const {
385 const EditorValue* schemaValue = field(snapshot, "schemaVersion");
386 const EditorValue* assetValue = field(snapshot, "asset");
387 const EditorValue* revisionValue = field(snapshot, "revision");
388 const EditorValue* rootValue = field(snapshot, "rootSourceId");
389 const EditorValue* objectsValue = field(snapshot, "objects");
390 const auto* schema = schemaValue ? schemaValue->getIf<int64_t>() : nullptr;
391 const auto* asset = assetValue ? assetValue->getIf<std::string>() : nullptr;
392 const auto* revision = revisionValue ? revisionValue->getIf<int64_t>() : nullptr;
393 const auto* root = rootValue ? rootValue->getIf<std::string>() : nullptr;
394 const auto* objects = objectsValue ? objectsValue->getIf<EditorValue::Array>() : nullptr;
395 if (!schema || (*schema != 1 && *schema != 2) || !asset || !revision || *revision <= 0 || !root || !objects)
396 return eve::editing::failed<PrefabAssetSnapshot>(EditorStatus::Unsupported,
397 RuleId("editor.prefab.invalid-snapshot"),
398 "Prefab snapshot schema is invalid or unsupported");
399 PrefabAssetSnapshot prefab{AssetGuid(*asset), static_cast<Revision>(*revision), ObjectId(*root), {}};
400 for (const EditorValue& value : *objects) {
401 const EditorValue* idValue = field(value, "sourceId");
402 const EditorValue* parentValue = field(value, "parentSourceId");
403 const EditorValue* nameValue = field(value, "name");
404 const EditorValue* transform = field(value, "transform");
405 const EditorValue* nestedAssetValue = field(value, "nestedPrefab");
406 const EditorValue* nestedRevisionValue = field(value, "nestedRevision");
407 const auto* id = idValue ? idValue->getIf<std::string>() : nullptr;
408 const auto* parentId = parentValue ? parentValue->getIf<std::string>() : nullptr;
409 const auto* name = nameValue ? nameValue->getIf<std::string>() : nullptr;
410 if (!id || !parentId || !name || !transform)
411 return eve::editing::failed<PrefabAssetSnapshot>(EditorStatus::Rejected,
412 RuleId("editor.prefab.invalid-object"),
413 "Prefab snapshot contains an invalid object");
414 auto parsed = parseTransform(*transform);
415 if (!parsed.ok())
416 return eve::editing::failed<PrefabAssetSnapshot>(EditorStatus::Rejected,
417 RuleId("editor.prefab.invalid-transform"),
418 "Prefab snapshot contains an invalid transform");
419 AssetGuid nestedAsset;
420 Revision nestedRevision = 0;
421 if (*schema == 2) {
422 const auto* nested = nestedAssetValue ? nestedAssetValue->getIf<std::string>() : nullptr;
423 const auto* pinned = nestedRevisionValue ? nestedRevisionValue->getIf<int64_t>() : nullptr;
424 if (!nested || !pinned || *pinned < 0)
425 return eve::editing::failed<PrefabAssetSnapshot>(
426 EditorStatus::Rejected, RuleId("editor.prefab.invalid-nested-pin"),
427 "Prefab snapshot contains an invalid nested revision pin");
428 nestedAsset = AssetGuid(*nested); nestedRevision = static_cast<Revision>(*pinned);
429 }
430 prefab.objects.push_back({ObjectId(*id), ObjectId(*parentId), *name, parsed.value(),
431 nestedAsset, nestedRevision});
432 }
433 auto valid = validatePrefab(prefab);
434 if (!valid.ok()) {
436 }
437 return eve::editing::applied<PrefabAssetSnapshot>(std::move(prefab));
438}
439
440} // namespace eve::editor
ActionParameterOperation operation
double value
Value::Object payload
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
int root
Definition AnimSmr.cpp:119
std::string prefab
std::vector< QuestEvent > pending
std::uint64_t sourceId
std::uint64_t parentId
std::string message
DiagnosticCode code
const GltfImportRequest & request
std::uint32_t key
glm::uvec4 ids
std::int32_t second
eve::ResourcePin pinned
std::int32_t parent
std::string name
bool valid
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
std::uint64_t revision
std::string id
Definition PlayHost.cpp:108
std::weak_ptr< PrimitiveScene > scene
double number
bool found
double current
std::size_t cursor
Json object
int children
Definition TreeMesh.cpp:295
std::set< std::string > visiting
uint32_t index
const UnitySourceAsset & source
Move-only operation result carrying either a value or Status.
Definition Result.h:155
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
const std::string & value() const noexcept
Returns the exact legacy or canonical compatibility spelling.
Definition Identity.h:362
bool empty() const noexcept
True when no compatibility spelling has been assigned.
Definition Identity.h:374
Deterministic owning value tree shared by authoring hosts.
std::vector< Value > Array
std::map< std::string, Value > Object
const T * getIf() const
Return an immediately borrowed typed value.
Result< PrefabAssetSnapshot > applyOverrides(const PrefabAssetSnapshot &prefab, const std::string &instanceId, const ObjectId &parent, const SceneTargetBase &scene) const
Produce a new prefab revision from one structurally compatible instance.
Result< PrefabAssetSnapshot > refreshNestedRevisions(const PrefabAssetSnapshot &prefab, const PrefabResolver &resolver) const
Refresh direct nested revision pins and bump the parent only when they changed.
PrefabDependencyReport inspectDependencies(const PrefabAssetSnapshot &prefab, const PrefabResolver &resolver) const
Resolve the complete nested dependency graph and diagnose cycles/stale pins.
Result< std::vector< PrefabOverrideRecord > > inspectOverrides(const PrefabAssetSnapshot &prefab, const std::string &instanceId, const ObjectId &parent, const SceneTargetBase &scene) const
Compare one instance with its source and return stable override badges.
Result< PrefabAssetSnapshot > capture(const AssetGuid &asset, const SceneTargetBase &scene, const ObjectId &root) const
Capture one scene subtree as a deterministic prefab asset.
Result< std::vector< DomainOperation > > revertOverrides(const PrefabAssetSnapshot &prefab, const std::string &instanceId, const ObjectId &parent, const SceneTargetBase &scene) const
Plan operations reverting one instance to its source prefab revision.
std::function< Result< PrefabAssetSnapshot >(const AssetGuid &)> PrefabResolver
Result< PrefabInstancePlan > instantiate(const PrefabAssetSnapshot &prefab, const std::string &instanceId, const ObjectId &parent, const SceneTargetBase &scene) const
Plan collision-safe creation of a prefab below one scene parent.
EditorValue snapshotValue(const PrefabAssetSnapshot &prefab) const
Convert a prefab snapshot to deterministic persisted data.
Shared in-memory scene target implementation for document/runtime adapters.
Definition SceneTarget.h:86
Result< T > failed(Status status, eve::DiagnosticCode code, RuleId rule, std::string message)
Construct a failed editing result with explicit status and diagnostic categories.
Diagnostic ruleDiagnostic(eve::DiagnosticCode code, RuleId rule, DiagnosticSeverity severity, std::string message)
Build a common diagnostic carrying an open editing rule identity.
eve::editing::Value EditorValue
Compatibility alias for the UI-independent authoring value tree.
Definition EditorValue.h:8
eve::editing::TargetId TargetId
Definition EditorIds.h:29
eve::editing::RuleId RuleId
Definition EditorIds.h:32
scene_editing::SceneTransformValue SceneTransformValue
eve::StatusCode EditorStatus
Definition EditorResult.h:8
eve::editing::Revision Revision
eve::editing::ObjectId ObjectId
Definition EditorIds.h:38
const EditorValue * field(const EditorValue &value, const char *name)
Build metadata (engine git commit, build time, third-party version).
Definition Build.cpp:16
DiagnosticCode
Stable machine-readable diagnostic codes.
Definition Diagnostic.h:47
StrongUuid< detail::AssetGuidTag > AssetGuid
Stable asset identity used by sidecars, package manifests and caches.
Definition Identity.h:273
Severity
Stable severity of a diagnostic, independent of its display text.
Definition Diagnostic.h:20
DomainOperation public API.
std::vector< ObjectRefValue > affectedObjects
Runtime-neutral prefab authoring snapshot.
std::vector< PrefabObjectRecord > objects
Nested-prefab dependency diagnostics tied to the inspected root revision.
std::vector< AssetGuid > dependencyOrder
std::vector< EditorDiagnostic > diagnostics
Stable identity mapping returned with an instantiated prefab plan.
std::vector< DomainOperation > operations
One stable scene object stored relative to a prefab root.
Request used to create a scene object in either backend.
Definition SceneTarget.h:27