329 GAIA_PROF_SCOPE(cmdbuf::commit);
332 if (m_nextTemp > 0) {
333 GAIA_PROF_SCOPE(cmdbuf::alloc);
339 m_tmpFlags.resize(m_nextTemp * 3);
342 if (m_temp2real.size() < m_nextTemp) {
343 const auto from = m_temp2real.size();
344 m_temp2real.resize(m_nextTemp);
345 GAIA_FOR2(from, m_nextTemp) m_temp2real[i] = EntityBad;
349 for (
const Op& o: m_ops) {
351 if (is_tmp(o.target)) {
352 const uint32_t ti = o.target.id();
354 if (o.type == OpType::DEL_ENTITY)
355 m_tmpFlags.
set((ti * 3) + 0,
true);
356 else if (is_rel(o.type))
357 m_tmpFlags.
set((ti * 3) + 1,
true);
360 if (is_tmp(o.other) && o.other.id() < m_tmpFlags.
size())
361 m_tmpFlags.
set((o.other.id() * 3) + 2,
true);
365 for (
const Op& o: m_ops) {
366 if (!is_tmp(o.target))
369 const uint32_t ti = o.target.id();
370 if (is_canceled_temp(ti))
373 if (o.type == OpType::ADD_ENTITY) {
374 if (m_temp2real[ti] == EntityBad)
375 m_temp2real[ti] = m_world.
add(o.target.kind());
376 }
else if (o.type == OpType::CPY_ENTITY) {
377 if (m_temp2real[ti] == EntityBad) {
378 const Entity src = resolve(o.other);
379 if (src != EntityBad)
380 m_temp2real[ti] = m_world.
copy(src);
389 GAIA_PROF_SCOPE(cmdbuf::sort);
392 core::sort(m_ops.begin(), m_ops.end(), [](
const Op& a,
const Op& b) {
393 if (a.target != b.target)
394 return a.target < b.target;
395 if (a.other != b.other)
396 return a.other < b.other;
402 Entity lastKey = EntityBad;
403 Entity lastResolved = EntityBad;
404 auto resolve_cached = [&](
Entity e) {
408 return lastResolved = resolve(e);
412 GAIA_PROF_SCOPE(cmdbuf::merges);
413 for (uint32_t p = 0; p < m_ops.size();) {
414 GAIA_PROF_SCOPE(cmdbuf::merge);
416 const Entity tgtKey = m_ops[p].target;
418 const bool tgtIsTemp = is_tmp(tgtKey);
419 const uint32_t ti = tgtIsTemp ? tgtKey.id() : 0u;
421 tgtIsTemp ? (ti < m_temp2real.size() ? m_temp2real[ti] : EntityBad) : resolve_cached(tgtKey);
425 bool hasDelEntity =
false;
426 while (q < m_ops.size() && m_ops[q].target == tgtKey) {
427 if (m_ops[q].type == OpType::DEL_ENTITY)
433 if (tgtReal == EntityBad) {
437 if (tgtIsTemp && is_canceled_temp(ti)) {
442 enum : uint8_t { F_ADD = 1 << 0, F_ADD_DATA = 1 << 1, F_SET = 1 << 2, F_DEL = 1 << 3 };
447 for (uint32_t i = p; i < q;) {
448 const Entity othKey = m_ops[i].other;
449 const Entity othReal = resolve_cached(othKey);
453 while (j < q && m_ops[j].other == othKey)
456 if (tgtReal != EntityBad) {
457 const uint32_t groupSize = j - i;
459 if (groupSize == 1) {
460 const Op& op = m_ops[i];
462 case OpType::DEL_COMPONENT:
465 case OpType::ADD_COMPONENT:
468 case OpType::ADD_COMPONENT_DATA:
471 case OpType::SET_COMPONENT: {
472 const auto& ec = m_world.m_recs.
entities[tgtReal.id()];
473 const auto row = tgtReal.kind() == EntityKind::EK_Uni ? 0U : ec.row;
474 const auto compIdx = ec.pChunk->comp_idx(othReal);
475 auto* pComponentData = (
void*)ec.pChunk->comp_ptr_mut(compIdx, 0);
478 auto serializer = ser::make_serializer(m_data);
479 serializer.seek(op.off);
481 item.load(serializer, pComponentData, row, row + 1, ec.pChunk->capacity());
490 uint32_t dataPos = 0;
492 for (uint32_t k = i; k < j; ++k) {
493 const Op& op = m_ops[k];
495 case OpType::ADD_COMPONENT:
498 case OpType::ADD_COMPONENT_DATA:
502 case OpType::SET_COMPONENT:
506 case OpType::DEL_COMPONENT:
514 const bool hasAdd = mask & F_ADD;
515 const bool hasAddData = mask & F_ADD_DATA;
516 const bool hasSet = mask & F_SET;
517 const bool hasDel = mask & F_DEL;
520 if (hasDel && (hasAdd || hasAddData)) {
527 else if (hasAddData || (hasAdd && hasSet)) {
530 const auto& ec = m_world.m_recs.
entities[tgtReal.id()];
531 const auto row = tgtReal.kind() == EntityKind::EK_Uni ? 0U : ec.row;
532 const auto compIdx = ec.pChunk->comp_idx(othReal);
533 auto* pComponentData = (
void*)ec.pChunk->comp_ptr_mut(compIdx, 0);
536 auto serializer = ser::make_serializer(m_data);
537 serializer.seek(dataPos);
539 item.load(serializer, pComponentData, row, row + 1, ec.pChunk->capacity());
547 const auto& ec = m_world.m_recs.
entities[tgtReal.id()];
548 const auto row = tgtReal.kind() == EntityKind::EK_Uni ? 0U : ec.row;
549 const auto compIdx = ec.pChunk->comp_idx(othReal);
550 auto* pComponentData = (
void*)ec.pChunk->comp_ptr_mut(compIdx, 0);
553 auto serializer = ser::make_serializer(m_data);
554 serializer.seek(dataPos);
556 item.load(serializer, pComponentData, row, row + 1, ec.pChunk->capacity());
567 m_world.
del(tgtReal);