mirror of
https://github.com/Relintai/godot-lportal.git
synced 2024-11-11 10:52:09 +01:00
18eac7e810
To fix bug where get_global_transform doesn't work with dobs outside the tree, there is a new API
180 lines
3.9 KiB
C++
180 lines
3.9 KiB
C++
#include "ldoblist.h"
|
|
#include "lroom_manager.h"
|
|
#include "ldebug.h"
|
|
|
|
// returns whether changed room
|
|
bool LDobList::FindDOBOldAndNewRoom(LRoomManager &manager, int dob_id, const Vector3 &pos, int &old_room_id, int &new_room_id)
|
|
{
|
|
LDob &dob = GetDob(dob_id);
|
|
|
|
bool bCamera = (dob_id == manager.m_DOB_id_camera);
|
|
float slop = 0.2f;
|
|
if (bCamera)
|
|
slop = 0.0f;
|
|
else
|
|
{
|
|
// print_line("dob position : " + String(Variant(pt)));
|
|
}
|
|
|
|
// current room
|
|
old_room_id = dob.m_iRoomID;
|
|
new_room_id = old_room_id; // default
|
|
|
|
bool bChangedRoom = false;
|
|
LRoom * pCurrentRoom = 0;
|
|
|
|
if (old_room_id == -1)
|
|
bChangedRoom = true;
|
|
else
|
|
{
|
|
pCurrentRoom = manager.GetRoom(old_room_id);
|
|
|
|
// deal with the case that the DOB has moved way outside the room
|
|
if (!pCurrentRoom->m_Bound.IsPointWithin(pos, 1.0f))
|
|
bChangedRoom = true;
|
|
}
|
|
|
|
// if changed room definitely?
|
|
if (bChangedRoom)
|
|
{
|
|
// revert to expensive method (may have been teleported etc)
|
|
new_room_id = manager.FindClosestRoom(pos);
|
|
|
|
if (new_room_id != old_room_id)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
assert (pCurrentRoom);
|
|
|
|
// check each portal - has the object crossed it into the neighbouring room?
|
|
for (int p=0; p<pCurrentRoom->m_iNumPortals; p++)
|
|
{
|
|
const LPortal &port = manager.m_Portals[pCurrentRoom->m_iFirstPortal + p];
|
|
|
|
float dist = port.m_Plane.distance_to(pos);
|
|
|
|
if (dist > slop)
|
|
{
|
|
LPRINT(0, "DOB at pos " + pos + " ahead of portal " + port.get_name() + " by " + String(Variant(dist)));
|
|
|
|
new_room_id = manager.Portal_GetLinkedRoom(port).m_RoomID;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void LDobList::UpdateVisibility(LRoomManager &manager, Spatial * pDOBSpatial, int dob_id)
|
|
{
|
|
LDob &dob = GetDob(dob_id);
|
|
|
|
// get the room
|
|
LRoom * pRoom = manager.GetRoom(dob.m_iRoomID);
|
|
bool bRoomVisible = pRoom->IsVisible();
|
|
|
|
Spatial * pDOB = pDOBSpatial;
|
|
|
|
bool bDobVis = pDOB->is_visible_in_tree();
|
|
if (bDobVis != bRoomVisible)
|
|
{
|
|
//String sz = "DOB " + pDOB->get_name() + "\t";
|
|
|
|
if (bRoomVisible)
|
|
{
|
|
pDOB->show();
|
|
//sz += "coming into view";
|
|
}
|
|
else
|
|
{
|
|
pDOB->hide();
|
|
//sz += "exiting view";
|
|
}
|
|
|
|
//print_line(sz);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int LDobList::UpdateDob(LRoomManager &manager, int dob_id, const Vector3 &pos)
|
|
{
|
|
LDob &dob = GetDob(dob_id);
|
|
|
|
// get the VI for showing / hiding
|
|
Spatial * pSpat = (Spatial *) dob.GetVI();
|
|
|
|
int old_room, new_room;
|
|
|
|
if (FindDOBOldAndNewRoom(manager, dob_id, pos, old_room, new_room))
|
|
{
|
|
dob.m_iRoomID = new_room;
|
|
}
|
|
|
|
if (dob_id != manager.m_DOB_id_camera)
|
|
UpdateVisibility(manager, pSpat, dob_id);
|
|
|
|
return dob.m_iRoomID;
|
|
}
|
|
|
|
/*
|
|
// get _global_transform DOES NOT WORK when detached from scene tree (or hidden)
|
|
const Vector3 &pt = pDOB->get_global_transform().origin;
|
|
|
|
// is it the camera?
|
|
bool bCamera = pDOB->get_instance_id() == manager.m_ID_camera;
|
|
float slop = 0.2f;
|
|
if (bCamera)
|
|
slop = 0.0f;
|
|
else
|
|
{
|
|
// print_line("dob position : " + String(Variant(pt)));
|
|
}
|
|
|
|
// deal with the case that the DOB has moved way outside the room
|
|
if (!m_Bound.IsPointWithin(pt, 1.0f))
|
|
{
|
|
// revert to expensive method (may have been teleported etc)
|
|
int iRoomNum = manager.FindClosestRoom(pt);
|
|
//print_line("dob_teleport closest room " + itos(iRoomNum));
|
|
|
|
if (iRoomNum == -1)
|
|
return 0;
|
|
|
|
// could be no change of room...
|
|
if (iRoomNum == m_RoomID)
|
|
return 0;
|
|
|
|
return manager.GetRoom(iRoomNum);
|
|
}
|
|
|
|
// the camera can't have slop because we might end up front side of a door without entering the room,
|
|
// hence can't see into the room through the portal!
|
|
// if (bCamera)
|
|
// slop = 0.0f;
|
|
|
|
// check each portal - has the object crossed it into the neighbouring room?
|
|
for (int p=0; p<m_iNumPortals; p++)
|
|
{
|
|
const LPortal &port = manager.m_Portals[m_iFirstPortal + p];
|
|
|
|
float dist = port.m_Plane.distance_to(pt);
|
|
|
|
if (dist > slop)
|
|
{
|
|
LPRINT(0, "DOB at pos " + pt + " ahead of portal " + port.get_name() + " by " + String(Variant(dist)));
|
|
|
|
// we want to move into the adjoining room
|
|
return &manager.Portal_GetLinkedRoom(port);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
*/
|
|
|