GameDevTecnico / cubos

A still very barebones game engine focused on voxels and data-oriented programming
https://gamedevtecnico.github.io/cubos/
MIT License
83 stars 23 forks source link

Make the DataInspector a system argument with hook support #1179

Open RiscadoA opened 3 months ago

RiscadoA commented 3 months ago

Problem

Currently the inspector is a resource. What's the problem with this?

Well, imagine we want to define custom behavior for asset handles. We want asset handles to show a popup when pressed, instead of just showing its UUID. How could we do this? Well, the existing data inspector could have a hook method or something similar:

cubos.startupSystem("blabla").call([](DataInspector& inspector) {
  inspector.hook([](const Type& type, void* value) {
    if (type./* is child of AnyAsset*/)
    {
      // do something
      return true;
    }
    return false;
  });
});

Then, when calling inspector.edit/show, the method would first call all hooks, until one returns true.

The thing is, to show an asset selection popup, we need to know which assets there are! This means that the data inspector needs to access the Assets resource. Of course, we don't want to make inspector.edit/show depend specifically on Assets - why couple it with a mostly unrelated plugin? In the future other similar problems may come up with other resources too.

Solution

One solution is to pass the entire World as an argument to the inspector, and then, each hook receives the world by reference, i.e., .hook([](World& world, const Type& type, void* value) {...}). Then, inspecting would look like: inspector.edit(world, myAssetHandle).

I think having to pass the World as a reference everytime is cumbersome. So, instead, the DataInspector could become an actual system argument, which internally accesses the World.

From the POV of the user, it would just look like:

cubos.system(...).call([](DataInspector inspector) {
  inspector.edit(myAsset);
});