builtin/main_context: Fix scene reference handling
parent
8ae01fc502
commit
7ebce17fbd
|
@ -21,6 +21,13 @@ namespace main_context
|
|||
struct OpaqueSceneReference;
|
||||
typedef OpaqueSceneReference* SceneReference;
|
||||
|
||||
struct SceneDeleted: public interface::Event::Private
|
||||
{
|
||||
SceneReference scene;
|
||||
|
||||
SceneDeleted(SceneReference scene): scene(scene) {}
|
||||
};
|
||||
|
||||
struct Interface
|
||||
{
|
||||
// NOTE: Do not store Urho3D::SharedPtr<>s or any other kinds of pointers
|
||||
|
@ -29,7 +36,7 @@ namespace main_context
|
|||
|
||||
virtual magic::Context* get_context() = 0;
|
||||
virtual magic::Scene* find_scene(SceneReference ref) = 0;
|
||||
virtual magic::Scene* get_scene(SceneReference ref) = 0;
|
||||
virtual magic::Scene* check_scene(SceneReference ref) = 0;
|
||||
|
||||
virtual SceneReference create_scene() = 0;
|
||||
virtual void delete_scene(SceneReference ref) = 0;
|
||||
|
|
|
@ -57,21 +57,11 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct SceneSetItem
|
||||
struct OpaqueSceneReference
|
||||
{
|
||||
SharedPtr<Scene> scene;
|
||||
void *raw_ptr = nullptr; // If scene is not set, this is used for searching
|
||||
|
||||
SceneSetItem() {}
|
||||
SceneSetItem(SharedPtr<Scene> scene): scene(scene) {}
|
||||
SceneSetItem(void *raw_ptr): raw_ptr(raw_ptr) {}
|
||||
void* get_raw_ptr() const {
|
||||
if(scene) return scene.Get();
|
||||
return raw_ptr;
|
||||
}
|
||||
bool operator>(const SceneSetItem &other) const {
|
||||
return get_raw_ptr() > other.get_raw_ptr();
|
||||
}
|
||||
OpaqueSceneReference(const SharedPtr<Scene> &scene): scene(scene) {}
|
||||
};
|
||||
|
||||
struct Module: public interface::Module, public main_context::Interface
|
||||
|
@ -82,8 +72,9 @@ struct Module: public interface::Module, public main_context::Interface
|
|||
SharedPtr<Context> m_context;
|
||||
SharedPtr<Engine> m_engine;
|
||||
|
||||
// Set of scenes as a sorted array in descending address order
|
||||
sv_<SceneSetItem> m_scenes;
|
||||
// OpaqueSceneReferences are never dropped from memory so that they stay
|
||||
// unique, but the scenes itself are dropped.
|
||||
sm_<SceneReference, up_<OpaqueSceneReference>> m_scenes;
|
||||
|
||||
sm_<Event::Type, SharedPtr<
|
||||
interface::MagicEventHandler>> m_magic_event_handlers;
|
||||
|
@ -216,25 +207,24 @@ struct Module: public interface::Module, public main_context::Interface
|
|||
|
||||
Scene* find_scene(SceneReference ref)
|
||||
{
|
||||
SceneSetItem item((void*)ref);
|
||||
auto it = std::lower_bound(m_scenes.begin(), m_scenes.end(), item,
|
||||
std::greater<SceneSetItem>());
|
||||
auto it = m_scenes.find(ref);
|
||||
if(it == m_scenes.end())
|
||||
return nullptr;
|
||||
return it->scene.Get();
|
||||
return it->second->scene.Get();
|
||||
}
|
||||
|
||||
Scene* get_scene(SceneReference ref)
|
||||
Scene* check_scene(SceneReference ref)
|
||||
{
|
||||
Scene *scene = find_scene(ref);
|
||||
if(!scene)
|
||||
throw Exception("get_scene(): Scene not found");
|
||||
throw Exception("check_scene(): Scene not found");
|
||||
return scene;
|
||||
}
|
||||
|
||||
SceneReference create_scene()
|
||||
{
|
||||
SharedPtr<Scene> scene(new Scene(m_context));
|
||||
log_d(MODULE, "create_scene() -> %p", scene.Get());
|
||||
|
||||
auto *physics = scene->CreateComponent<PhysicsWorld>(LOCAL);
|
||||
physics->SetFps(30);
|
||||
|
@ -245,24 +235,20 @@ struct Module: public interface::Module, public main_context::Interface
|
|||
scene->CreateComponent<Octree>(LOCAL);
|
||||
|
||||
// Insert into m_scenes
|
||||
SceneSetItem item(scene);
|
||||
auto it = std::lower_bound(m_scenes.begin(), m_scenes.end(), item,
|
||||
std::greater<SceneSetItem>());
|
||||
if(it == m_scenes.end())
|
||||
m_scenes.insert(it, item);
|
||||
|
||||
return (SceneReference)scene.Get();
|
||||
OpaqueSceneReference *ref = new OpaqueSceneReference(scene);
|
||||
m_scenes[ref] = std::move(up_<OpaqueSceneReference>(ref));
|
||||
return ref;
|
||||
}
|
||||
|
||||
void delete_scene(SceneReference ref)
|
||||
{
|
||||
// Erase from m_scenes
|
||||
SceneSetItem item((void*)ref);
|
||||
auto it = std::lower_bound(m_scenes.begin(), m_scenes.end(), item,
|
||||
std::greater<SceneSetItem>());
|
||||
log_d(MODULE, "delete_scene(%p)", ref);
|
||||
// Drop scene, but not the reference
|
||||
auto it = m_scenes.find(ref);
|
||||
if(it == m_scenes.end())
|
||||
throw Exception("delete_scene(): Scene not found");
|
||||
m_scenes.erase(it);
|
||||
return;
|
||||
it->second->scene.Reset();
|
||||
m_server->emit_event("main_context:scene_deleted", new SceneDeleted(ref));
|
||||
}
|
||||
|
||||
void sub_magic_event(
|
||||
|
|
|
@ -170,7 +170,7 @@ ChunkBuffer& Section::get_buffer(const pv::Vector3DInt32 &chunk_p,
|
|||
|
||||
main_context::access(server, [&](main_context::Interface *imc)
|
||||
{
|
||||
Scene *scene = imc->get_scene(m_scene_ref);
|
||||
Scene *scene = imc->check_scene(m_scene_ref);
|
||||
Node *n = scene->GetNode(node_id);
|
||||
if(!n){
|
||||
log_w(MODULE,
|
||||
|
@ -310,7 +310,12 @@ struct CInstance: public voxelworld::Instance
|
|||
void on_tick(const interface::TickEvent &event)
|
||||
{
|
||||
main_context::access(m_server, [&](main_context::Interface *imc){
|
||||
Scene *scene = imc->get_scene(m_scene_ref);
|
||||
Scene *scene = imc->find_scene(m_scene_ref);
|
||||
if(!scene){
|
||||
// Scene was deleted; hope that Module deletes us at some point
|
||||
return;
|
||||
}
|
||||
|
||||
Context *context = imc->get_context();
|
||||
|
||||
// Update node collision boxes
|
||||
|
@ -565,7 +570,7 @@ struct CInstance: public voxelworld::Instance
|
|||
void create_section(Section §ion)
|
||||
{
|
||||
main_context::access(m_server, [&](main_context::Interface *imc){
|
||||
Scene *scene = imc->get_scene(m_scene_ref);
|
||||
Scene *scene = imc->check_scene(m_scene_ref);
|
||||
auto lc = section.contained_chunks.getLowerCorner();
|
||||
auto uc = section.contained_chunks.getUpperCorner();
|
||||
for(int z = 0; z <= uc.getZ() - lc.getZ(); z++){
|
||||
|
@ -775,7 +780,7 @@ struct CInstance: public voxelworld::Instance
|
|||
commit();
|
||||
|
||||
main_context::access(m_server, [&](main_context::Interface *imc){
|
||||
Scene *scene = imc->get_scene(m_scene_ref);
|
||||
Scene *scene = imc->check_scene(m_scene_ref);
|
||||
Node *n = scene->GetNode(node_id);
|
||||
const Variant &var = n->GetVar(StringHash("buildat_voxel_data"));
|
||||
const PODVector<unsigned char> &buf = var.GetBuffer();
|
||||
|
@ -897,7 +902,7 @@ struct CInstance: public voxelworld::Instance
|
|||
*chunk_buffer.volume);
|
||||
|
||||
main_context::access(m_server, [&](main_context::Interface *imc){
|
||||
Scene *scene = imc->get_scene(m_scene_ref);
|
||||
Scene *scene = imc->check_scene(m_scene_ref);
|
||||
Context *context = scene->GetContext();
|
||||
|
||||
Node *n = scene->GetNode(node_id);
|
||||
|
@ -1050,6 +1055,7 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||
m_server->sub_event(this, Event::t("replicate:peer_joined_scene"));
|
||||
m_server->sub_event(this, Event::t("replicate:peer_left_scene"));
|
||||
m_server->sub_event(this, Event::t("client_file:files_transmitted"));
|
||||
m_server->sub_event(this, Event::t("main_context:scene_deleted"));
|
||||
/*m_server->sub_event(this, Event::t(
|
||||
"network:packet_received/voxelworld:get_section"));*/
|
||||
}
|
||||
|
@ -1066,6 +1072,8 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||
replicate::PeerLeftScene);
|
||||
EVENT_TYPEN("client_file:files_transmitted", on_files_transmitted,
|
||||
client_file::FilesTransmitted)
|
||||
EVENT_TYPEN("main_context:scene_deleted", on_scene_deleted,
|
||||
main_context::SceneDeleted);
|
||||
|
||||
for(auto &pair : m_instances){
|
||||
up_<CInstance> &instance = pair.second;
|
||||
|
@ -1104,7 +1112,7 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||
|
||||
// Remove everything managed by us from the scene
|
||||
main_context::access(m_server, [&](main_context::Interface *imc){
|
||||
Scene *scene = imc->get_scene();
|
||||
Scene *scene = imc->check_scene();
|
||||
size_t progress = 0;
|
||||
for(auto §or_pair: m_sections){
|
||||
log_v(MODULE, "Unloading nodes... %i%%",
|
||||
|
@ -1173,7 +1181,20 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||
{
|
||||
}
|
||||
|
||||
// TODO: How should nodes be filtered for replication?
|
||||
void on_scene_deleted(const main_context::SceneDeleted &event)
|
||||
{
|
||||
// Drop instance of the deleted scene (there should be only one, but
|
||||
// loop through all of them just for robustness)
|
||||
for(auto it = m_instances.begin(); it != m_instances.end(); ){
|
||||
auto current_it = it++;
|
||||
up_<CInstance> &instance = current_it->second;
|
||||
if(instance->m_scene_ref == event.scene){
|
||||
m_instances.erase(current_it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*// TODO: How should nodes be filtered for replication?
|
||||
// TODO: Generally the client wants roughly one section, but isn't
|
||||
// positioned at the middle of a section
|
||||
void on_get_section(const network::Packet &packet)
|
||||
|
@ -1186,7 +1207,7 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||
}
|
||||
log_v(MODULE, "C%i: on_get_section(): " PV3I_FORMAT,
|
||||
packet.sender, PV3I_PARAMS(section_p));
|
||||
}
|
||||
}*/
|
||||
|
||||
// Interface
|
||||
|
||||
|
|
|
@ -389,7 +389,7 @@ struct Module: public interface::Module
|
|||
{
|
||||
main_context::access(m_server, [&](main_context::Interface *imc)
|
||||
{
|
||||
Scene *scene = imc->get_scene(m_main_scene);
|
||||
Scene *scene = imc->check_scene(m_main_scene);
|
||||
Context *context = imc->get_context();
|
||||
ResourceCache *cache = context->GetSubsystem<ResourceCache>();
|
||||
|
||||
|
@ -457,7 +457,7 @@ struct Module: public interface::Module
|
|||
{
|
||||
/*main_context::access(m_server, [&](main_context::Interface *imc)
|
||||
{
|
||||
Scene *scene = imc->get_scene(m_main_scene);
|
||||
Scene *scene = imc->check_scene(m_main_scene);
|
||||
Node *n = scene->GetChild("Testbox");
|
||||
auto p = n->GetPosition();
|
||||
log_v(MODULE, "Testbox: (%f, %f, %f)", p.x_, p.y_, p.z_);
|
||||
|
@ -466,7 +466,7 @@ struct Module: public interface::Module
|
|||
if(((a++) % 150) == 0){
|
||||
main_context::access(m_server, [&](main_context::Interface *imc)
|
||||
{
|
||||
Scene *scene = imc->get_scene(m_main_scene);
|
||||
Scene *scene = imc->check_scene(m_main_scene);
|
||||
Node *n = scene->GetChild("Testbox");
|
||||
if(n){
|
||||
n->SetRotation(Quaternion(30, 60, 90));
|
||||
|
|
|
@ -74,7 +74,7 @@ struct Module: public interface::Module
|
|||
main_context::access(m_server, [&](main_context::Interface *imc){
|
||||
m_main_scene = imc->create_scene();
|
||||
|
||||
Scene *scene = imc->get_scene(m_main_scene);
|
||||
Scene *scene = imc->check_scene(m_main_scene);
|
||||
Context *context = scene->GetContext();
|
||||
ResourceCache *cache = context->GetSubsystem<ResourceCache>();
|
||||
auto *m = cache->GetResource<Material>("Materials/Stone.xml");
|
||||
|
@ -145,7 +145,7 @@ struct Module: public interface::Module
|
|||
static uint a = 0;
|
||||
if(((a++) % 100) == 0){
|
||||
main_context::access(m_server, [&](main_context::Interface *imc){
|
||||
Scene *scene = imc->get_scene(m_main_scene);
|
||||
Scene *scene = imc->check_scene(m_main_scene);
|
||||
Node *n = scene->GetChild("Box");
|
||||
n->SetPosition(Vector3(0.0f, 6.0f, 0.0f));
|
||||
n->SetRotation(Quaternion(30, 60, 90));
|
||||
|
@ -168,7 +168,7 @@ struct Module: public interface::Module
|
|||
return;
|
||||
}
|
||||
main_context::access(m_server, [&](main_context::Interface *imc){
|
||||
Scene *scene = imc->get_scene(m_main_scene);
|
||||
Scene *scene = imc->check_scene(m_main_scene);
|
||||
Node *n = scene->GetChild("Box");
|
||||
//n->Translate(Vector3(0.1f, 0, 0));
|
||||
Vector3 p = n->GetPosition();
|
||||
|
|
|
@ -66,7 +66,7 @@ struct Module: public interface::Module
|
|||
main_context::access(m_server, [&](main_context::Interface *imc){
|
||||
m_main_scene = imc->create_scene();
|
||||
|
||||
Scene *scene = imc->get_scene(m_main_scene);
|
||||
Scene *scene = imc->check_scene(m_main_scene);
|
||||
Context *context = scene->GetContext();
|
||||
ResourceCache *cache = context->GetSubsystem<ResourceCache>();
|
||||
|
||||
|
@ -124,7 +124,7 @@ struct Module: public interface::Module
|
|||
void update_scene()
|
||||
{
|
||||
main_context::access(m_server, [&](main_context::Interface *imc){
|
||||
Scene *scene = imc->get_scene(m_main_scene);
|
||||
Scene *scene = imc->check_scene(m_main_scene);
|
||||
Context *context = scene->GetContext();
|
||||
ResourceCache *cache = context->GetSubsystem<ResourceCache>();
|
||||
|
||||
|
@ -178,7 +178,7 @@ struct Module: public interface::Module
|
|||
float ry = (float)rand() / RAND_MAX * 180;
|
||||
float rz = (float)rand() / RAND_MAX * 180;
|
||||
main_context::access(m_server, [&](main_context::Interface *imc){
|
||||
Scene *scene = imc->get_scene(m_main_scene);
|
||||
Scene *scene = imc->check_scene(m_main_scene);
|
||||
Node *n = scene->GetChild("Testbox");
|
||||
n->SetRotation(Quaternion(rx, ry, rz));
|
||||
n->SetPosition(Vector3(-0.5f, 8.0f, 0.0f));
|
||||
|
|
|
@ -59,7 +59,7 @@ struct Module: public interface::Module
|
|||
main_context::access(m_server, [&](main_context::Interface *imc){
|
||||
m_main_scene = imc->create_scene();
|
||||
|
||||
Scene *scene = imc->get_scene(m_main_scene);
|
||||
Scene *scene = imc->check_scene(m_main_scene);
|
||||
Context *context = scene->GetContext();
|
||||
m_atlas_reg.reset(interface::createAtlasRegistry(context));
|
||||
{
|
||||
|
@ -134,7 +134,7 @@ struct Module: public interface::Module
|
|||
{
|
||||
main_context::access(m_server, [&](main_context::Interface *imc)
|
||||
{
|
||||
Scene *scene = imc->get_scene(m_main_scene);
|
||||
Scene *scene = imc->check_scene(m_main_scene);
|
||||
Context *context = scene->GetContext();
|
||||
ResourceCache *cache = context->GetSubsystem<ResourceCache>();
|
||||
|
||||
|
@ -201,7 +201,7 @@ struct Module: public interface::Module
|
|||
{
|
||||
main_context::access(m_server, [&](main_context::Interface *imc)
|
||||
{
|
||||
Scene *scene = imc->get_scene(m_main_scene);
|
||||
Scene *scene = imc->check_scene(m_main_scene);
|
||||
Context *context = scene->GetContext();
|
||||
ResourceCache *cache = context->GetSubsystem<ResourceCache>();
|
||||
|
||||
|
@ -260,7 +260,7 @@ struct Module: public interface::Module
|
|||
static uint a = 0;
|
||||
if(((a++) % 100) == 0){
|
||||
main_context::access(m_server, [&](main_context::Interface *imc){
|
||||
Scene *scene = imc->get_scene(m_main_scene);
|
||||
Scene *scene = imc->check_scene(m_main_scene);
|
||||
Node *n = scene->GetChild("Testbox");
|
||||
//n->SetPosition(Vector3(0.0f, 8.0f, 0.0f));
|
||||
n->SetRotation(Quaternion(30, 60, 90));
|
||||
|
|
Loading…
Reference in New Issue