feat: add ObjectRef for scene loading to not rely on runtime id's

This commit is contained in:
2026-10-18 17:15:51 +02:00
parent 94fa2bb4b2
commit d21c2ccfd7
10 changed files with 262 additions and 35 deletions
@@ -52,15 +52,16 @@ void InteractableButton::Interact(GameObject& interactor)
void InteractableButton::AddTarget(const GameObject& target)
{
if (target.GetId() == InvalidObjectId || std::ranges::find(m_Targets, target.GetId()) != m_Targets.end()) {
const ObjectRef ref(target);
if (!ref.IsSet() || std::ranges::find(m_Targets, ref) != m_Targets.end()) {
return;
}
m_Targets.push_back(target.GetId());
m_Targets.push_back(ref);
}
void InteractableButton::RemoveTarget(ObjectId target)
{
std::erase(m_Targets, target);
std::erase(m_Targets, ObjectRef(target));
}
void InteractableButton::ActivateTargets(GameObject& interactor)
@@ -70,10 +71,10 @@ void InteractableButton::ActivateTargets(GameObject& interactor)
return;
}
for (const ObjectId targetId : m_Targets) {
GameObject* target = scene->FindGameObject(targetId);
for (const ObjectRef& targetRef : m_Targets) {
GameObject* target = targetRef.Get(*scene);
if (target == nullptr) {
spdlog::warn("{} targets object {} which no longer exists", GetGameObject()->GetName(), targetId);
spdlog::warn("{} targets object {} which no longer exists", GetGameObject()->GetName(), targetRef.GetId());
continue;
}
@@ -122,7 +123,19 @@ void InteractableButton::Deserialize(const nlohmann::json& data)
m_ColorIndex = data.value("colorIndex", m_ColorIndex) % ButtonColors.size();
m_CycleColors = data.value("cycleColors", m_CycleColors);
m_PressCount = data.value("pressCount", m_PressCount);
m_Targets = data.value("targets", std::vector<ObjectId>{});
m_Targets = data.value("targets", std::vector<ObjectRef>{});
}
void InteractableButton::ResolveReferences(const ObjectMap& objects)
{
std::erase_if(m_Targets, [&](ObjectRef& target) {
const ObjectId fileId = target.GetId();
if (!target.Resolve(objects)) {
spdlog::warn("{} targets object {} which is not in the scene file, dropping it", GetGameObject()->GetName(), fileId);
return true;
}
return !target.IsSet();
});
}
void InteractableButton::ImGuiInspector()
@@ -149,8 +162,9 @@ void InteractableButton::DrawTargetsInspector()
}
std::optional<ObjectId> targetToRemove;
for (const ObjectId targetId : m_Targets) {
const GameObject* target = scene->FindGameObject(targetId);
for (const ObjectRef& targetRef : m_Targets) {
const ObjectId targetId = targetRef.GetId();
const GameObject* target = targetRef.Get(*scene);
ImGui::PushID(static_cast<int>(targetId));
if (ImGui::SmallButton("x")) {
targetToRemove = targetId;
@@ -170,7 +184,7 @@ void InteractableButton::DrawTargetsInspector()
if (ImGui::BeginCombo("##AddTarget", "Add target...")) {
for (const auto& object : scene->GetObjects()) {
const bool alreadyTargeted = object != nullptr &&
std::ranges::find(m_Targets, object->GetId()) != m_Targets.end();
std::ranges::find(m_Targets, ObjectRef(*object)) != m_Targets.end();
if (object == nullptr || object.get() == GetGameObject() || alreadyTargeted ||
object->GetComponent<Activatable>() == nullptr) {
continue;