6486 lines
204 KiB
C++
6486 lines
204 KiB
C++
//
|
|
// name: DebugScene
|
|
// description: Debug Functions relating to the scene
|
|
#include "debug/debugscene.h"
|
|
|
|
#if !__FINAL
|
|
|
|
// rage headers
|
|
#include "crskeleton/skeleton.h"
|
|
#include "fragment/typechild.h"
|
|
#include "fragment/tune.h"
|
|
#include "grcore/debugdraw.h"
|
|
#include "grcore/stateblock.h"
|
|
#include "grprofile/timebars.h"
|
|
#include "rmcore/drawable.h"
|
|
#include "phbound/BoundBox.h"
|
|
#include "phbound/BoundBVH.h"
|
|
#include "phbound/BoundComposite.h"
|
|
#include "phbound/BoundGeom.h"
|
|
#include "phbound/BoundSphere.h"
|
|
#include "pheffects/mouseinput.h"
|
|
#include "physics/inst.h"
|
|
#include "physics/debugPlayback.h"
|
|
#include "profile/rocky.h"
|
|
#include "spatialdata/aabb.h"
|
|
#include "string/stringutil.h"
|
|
|
|
// framework headers
|
|
#include "ai/task/taskspew.h"
|
|
#include "fwscene/stores/staticboundsstore.h"
|
|
#include "fwscene/stores/txdstore.h"
|
|
#include "fwscene/search/SearchVolumes.h"
|
|
#include "fwsys/metadatastore.h"
|
|
|
|
// game headers
|
|
#include "ai/BlockingBounds.h"
|
|
#include "animation/AnimScene/AnimSceneManager.h"
|
|
#include "animation/debug/AnimViewer.h"
|
|
#include "Animation/debug/AnimPlacementTool.h"
|
|
#include "audio/ambience/ambientaudioentity.h"
|
|
#include "audio/collisionaudioentity.h"
|
|
#include "camera/CamInterface.h"
|
|
#include "camera/debug/DebugDirector.h"
|
|
#include "camera/helpers/Frame.h"
|
|
#include "camera/system/CameraManager.h"
|
|
#include "camera/viewports/ViewportManager.h"
|
|
#include "control/record.h"
|
|
#include "control/replay/replay.h"
|
|
#include "control/WaypointRecording.h"
|
|
#include "core/game.h"
|
|
#include "debug/debugglobals.h"
|
|
#include "debug/DebugScene.h"
|
|
#include "debug/DebugDraw/DebugWindow.h"
|
|
#include "debug/gtapicker.h"
|
|
#include "Debug/UiGadget/UiColorScheme.h"
|
|
#include "Debug/UiGadget/UIGadgetInspector.h"
|
|
#include "debug/textureviewer/textureviewerwindow.h"
|
|
#include "debug/UiGadget/UiGadgetBase.h"
|
|
#include "debug/vectormap.h"
|
|
#include "event/ShockingEvents.h"
|
|
#include "game/dispatch/DispatchManager.h"
|
|
#include "game/Dispatch/IncidentManager.h"
|
|
#include "ModelInfo/ModelInfo.h"
|
|
#include "ModelInfo/ModelInfo_Factories.h"
|
|
#include "modelinfo/vehiclemodelinfo.h"
|
|
#include "network/Debug/NetworkDebug.h"
|
|
#include "network/General/NetworkColours.h"
|
|
#include "network/NetworkInterface.h"
|
|
#include "network/objects/entities/NetObjPlayer.h"
|
|
#include "network/players/NetworkPlayerMgr.h"
|
|
#include "objects/CoverTuning.h"
|
|
#include "objects/Door.h"
|
|
#include "objects/DoorTuning.h"
|
|
#include "objects/object.h"
|
|
#include "Objects/DummyObject.h"
|
|
#include "objects/ProcObjects.h"
|
|
#include "pathserver/NavEdit.h"
|
|
#include "ik/IkManager.h"
|
|
#include "peds/PedCapsule.h"
|
|
#include "peds/peddebugvisualiser.h"
|
|
#include "peds/ped.h"
|
|
#include "peds/pedfactory.h"
|
|
#include "peds/pedintelligence.h"
|
|
#include "peds/PedDebugVisualiser.h"
|
|
#include "peds/PedMoveBlend/pedmoveblendonfoot.h"
|
|
#include "peds/pedpopulation.h"
|
|
#include "peds/PlayerInfo.h"
|
|
#include "peds/rendering/PedVariationDebug.h"
|
|
#include "Peds/PedIntelligence/PedAILodManager.h"
|
|
#include "pedgroup/formation.h"
|
|
#include "pedgroup/pedgroup.h"
|
|
#include "pathserver/pathserver.h"
|
|
#include "physics/GtaArchetype.h"
|
|
#include "physics/gtainst.h"
|
|
#include "physics/iterator.h"
|
|
#include "physics/physics.h"
|
|
#include "physics/WorldProbe/worldprobe.h"
|
|
#include "pickups/Pickup.h"
|
|
#include "pickups/PickupPlacement.h"
|
|
#include "renderer/occlusion.h"
|
|
#include "renderer/water.h"
|
|
#include "renderer/renderer.h"
|
|
#include "renderer/lights/lights.h"
|
|
#include "scene/animatedbuilding.h"
|
|
#include "scene/debug/SceneCostTracker.h"
|
|
#include "scene/debug/SceneIsolator.h"
|
|
#include "scene/entity.h"
|
|
#include "scene/entities/compEntity.h"
|
|
#include "scene/EntityTypes.h"
|
|
#include "scene/lod/LodDebug.h"
|
|
#include "scene/lod/LodDrawable.h"
|
|
#include "scene/entities/compEntity.h"
|
|
#include "scene/portals/InteriorGroupManager.h"
|
|
#include "scene/portals/portalInst.h"
|
|
#include "scene/RegdRefTypes.h"
|
|
#include "scene/texLod.h"
|
|
#include "scene/world/gameWorld.h"
|
|
#include "scene/world/WorldDebugHelper.h"
|
|
#include "scene/scene.h"
|
|
#include "scene/worldpoints.h"
|
|
#include "script/script.h"
|
|
#include "streaming/PrioritizedClipSetStreamer.h"
|
|
#include "streaming/streaming.h"
|
|
#include "streaming/streamingdebuggraph.h"
|
|
#include "system/AutoGPUCapture.h"
|
|
#include "system/controlmgr.h"
|
|
#include "system/timer.h"
|
|
#include "Task/Combat/CombatManager.h"
|
|
#include "task/Combat/TacticalAnalysis.h"
|
|
#include "task/Crimes/RandomEventManager.h"
|
|
#include "task/Default/Patrol/PatrolRoutes.h"
|
|
#include "task/Response/TaskFlee.h"
|
|
#include "task/Movement/Climbing/ClimbDebug.h"
|
|
#include "task/Movement/Climbing/DropDownDetector.h"
|
|
#include "task/Movement/TaskCollisionResponse.h"
|
|
#include "task/Movement/TaskParachute.h"
|
|
#include "task/Physics/NmDebug.h"
|
|
#include "task/Scenario/ScenarioDebug.h"
|
|
#include "Task/Scenario/ScenarioManager.h"
|
|
#include "Task/Scenario/Info/ScenarioInfo.h"
|
|
#include "vehicles/vehiclefactory.h"
|
|
#include "vehicles/vehiclepopulation.h"
|
|
#include "vehicles/buses.h"
|
|
#include "vehicleAi/junctions.h"
|
|
#include "vehicleAi/VehicleAILodManager.h"
|
|
#include "vehicleAi/JunctionEditor.h"
|
|
#include "vehicles/train.h"
|
|
#include "weapons/weapondebug.h"
|
|
#include "debug/debug.h"
|
|
#include "ai/debug/types/VehicleDebugInfo.h"
|
|
#include "streaming/streamingvisualize.h"
|
|
|
|
|
|
AI_OPTIMISATIONS ()
|
|
|
|
namespace rage
|
|
{
|
|
#if __PFDRAW
|
|
EXT_PFD_DECLARE_GROUP(Physics);
|
|
EXT_PFD_DECLARE_GROUP(Fragment);
|
|
#endif
|
|
}
|
|
|
|
CEntity * g_pFocusEntity = NULL;
|
|
|
|
// static CEntity *gpLookingAtEntity = NULL;
|
|
#if __BANK
|
|
// static CEntity *gpClosestToEntity = NULL;
|
|
bool CDebugScene::sm_VisualizeAutoOpenBounds = false;
|
|
bool CDebugScene::bDisplayDoorPersistentInfo = false;
|
|
#endif
|
|
#if (__DEV) || (__BANK)
|
|
bool CDebugScene::ms_bStopProcessCtrlAllEntities = false;
|
|
bool CDebugScene::ms_bStopProcessCtrlAllExceptFocus0Entity = false;
|
|
bool CDebugScene::ms_bStopProcessCtrlAllEntitiesOfFocus0Type = false;
|
|
bool CDebugScene::ms_bStopProcessCtrlAllOfFocus0TypeExceptFocus0 = false;
|
|
#endif
|
|
|
|
#if __DEV
|
|
int CDebugScene::iDisplaySceneUpdateCostStep = 0;
|
|
char CDebugScene::DisplaySceneUpdateCostStepName[16] = {0};
|
|
bool CDebugScene::bDisplaySceneUpdateCostOnVMap = false;
|
|
bool CDebugScene::bDisplaySceneUpdateCostSelectedOnly = false;
|
|
#endif // __DEV
|
|
|
|
#if __BANK
|
|
sysMessageQueue<CDebugScene::TuneWidgetData, CDebugScene::TUNE_WIDGET_QUEUE_SIZE, false> CDebugScene::sm_TuneWidgetQueue;
|
|
bool CDebugScene::bDisplayBuildingsOnVMap = false;
|
|
bool CDebugScene::bDisplaySceneScoredEntities = false;
|
|
|
|
bool CDebugScene::bDisplayVehiclesOnVMap = false;
|
|
bool CDebugScene::bDisplayVehiclesOnVMapAsActiveInactive = false;
|
|
bool CDebugScene::bDisplayVehiclesOnVMapTimesliceUpdates = false;
|
|
bool CDebugScene::bDisplayVehiclesOnVMapBasedOnOcclusion = false;
|
|
bool CDebugScene::bDisplayLinesToLocalDrivingCars = false;
|
|
bool CDebugScene::bDisplayVehiclesUsesFadeOnVMap = false;
|
|
bool CDebugScene::bDisplayVehPopFailedCreateEventsOnVMap = false;
|
|
bool CDebugScene::bDisplayVehPopCreateEventsOnVMap = false;
|
|
bool CDebugScene::bDisplayVehPopDestroyEventsOnVMap = false;
|
|
bool CDebugScene::bDisplayVehPopConversionEventsOnVMap = false;
|
|
bool CDebugScene::bDisplayVehGenLinksOnVM = false;
|
|
bool CDebugScene::bDisplayVehicleCreationPathsOnVMap = false;
|
|
bool CDebugScene::bDisplayVehicleCreationPathsInWorld = false;
|
|
bool CDebugScene::bDisplayVehicleCreationPathsCurrDensityOnVMap = false;
|
|
bool CDebugScene::bDisplayVehiclesToBeStreamedOutOnVMap = false;
|
|
bool CDebugScene::bDisplayVehicleCollisionsOnVMap = false;
|
|
|
|
bool CDebugScene::bDisplayPedsOnVMap = false;
|
|
bool CDebugScene::bDisplayPedsOnVMapAsActiveInactive = false;
|
|
bool CDebugScene::bDisplayPedsOnVMapTimesliceUpdates = false;
|
|
bool CDebugScene::bDisplaySpawnPointsRawDensityOnVMap = false;
|
|
bool CDebugScene::bDisplayPedPopulationEventsOnVMap = false;
|
|
bool CDebugScene::bDisplayPedsToBeStreamedOutOnVMap = false;
|
|
bool CDebugScene::bDisplayCandidateScenarioPointsOnVMap = false;
|
|
|
|
bool CDebugScene::bDisplayObjectsOnVMap = false;
|
|
bool CDebugScene::bDisplayPickupsOnVMap = false;
|
|
bool CDebugScene::bDisplayLineAboveObjects = false;
|
|
bool CDebugScene::bDisplayLineAboveAllEntities = false;
|
|
float CDebugScene::fEntityDebugLineLength = 1.0f;
|
|
bool CDebugScene::bDisplayDoorInfo = false;
|
|
bool CDebugScene::bDisplayNetworkGameOnVMap = false;
|
|
bool CDebugScene::bDisplayPortalInstancesOnVMap = false;
|
|
bool CDebugScene::bDisplayRemotePlayerCameras = false;
|
|
bool CDebugScene::bDisplayCarCreation = false;
|
|
bool CDebugScene::bDisplayLadderDebug = false;
|
|
bool CDebugScene::bDisplayWaterOnVMap = false;
|
|
bool CDebugScene::bDisplayCalmingWaterOnVMap = false;
|
|
bool CDebugScene::bDisplayShoreLinesOnVMap = false;
|
|
bool CDebugScene::ms_drawFocusEntitiesBoundBox = false;
|
|
bool CDebugScene::ms_drawFocusEntitiesBoundBoxOnVMap = false;
|
|
bool CDebugScene::ms_drawFocusEntitiesInfo = false;
|
|
bool CDebugScene::ms_drawFocusEntitiesCoverTuning = false;
|
|
bool CDebugScene::ms_drawFocusEntitiesSkeleton = false;
|
|
bool CDebugScene::ms_drawFocusEntitiesSkeletonNonOrthonormalities = false;
|
|
bool CDebugScene::ms_drawFocusEntitiesSkeletonNonOrthoDataOnly = false;
|
|
bool CDebugScene::ms_drawFocusEntitiesSkeletonBoneNamesAndIds = false;
|
|
bool CDebugScene::ms_drawFocusEntitiesSkeletonChannels = false;
|
|
bool CDebugScene::ms_drawFocusEntitiesSkeletonNonOrthonoMats = false;
|
|
bool CDebugScene::bDisplayDuplicateObjectsBB = false;
|
|
bool CDebugScene::bDisplayDuplicateObjectsOnVMap = false;
|
|
|
|
bool CDebugScene::bDisplayTargetingRanges = false;
|
|
bool CDebugScene::bDisplayTargetingCones = false;
|
|
bool CDebugScene::bDisplayTargetingEntities = false;
|
|
|
|
#endif
|
|
#if __DEV
|
|
|
|
bool CDebugScene::ms_bBreakOnWorldAddOfFocusEntity = false;
|
|
bool CDebugScene::ms_bBreakOnWorldRemoveOfFocusEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProcessControlOfFocusEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProcessIntelligenceOfFocusEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProcessPhysicsOfFocusEntity = false;
|
|
bool CDebugScene::ms_bBreakOnPreRenderOfFocusEntity = false;
|
|
bool CDebugScene::ms_bBreakOnUpdateAnimOfFocusEntity = false;
|
|
bool CDebugScene::ms_bBreakOnUpdateAnimAfterCameraUpdateOfFocusEntity = false;
|
|
bool CDebugScene::ms_bBreakOnRenderOfFocusEntity = false;
|
|
bool CDebugScene::ms_bBreakOnAddToDrawListOfFocusEntity = false;
|
|
bool CDebugScene::ms_bBreakOnDestroyOfFocusEntity = false;
|
|
bool CDebugScene::ms_bBreakOnCalcDesiredVelocityOfFocusEntity = false;
|
|
|
|
static char g_proximityTestPointString[256];
|
|
bool CDebugScene::ms_bBreakOnProximityOfDestroyCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfAddCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfRemoveCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfAddAndRemoveCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfAddToInteriorCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfRemoveFromInteriorCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfWorldAddCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfWorldAddCallingPed = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfTeleportCallingObject = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfTeleportCallingPed = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfTeleportCallingVehicle = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfWorldRemoveCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfProcessControlCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfProcessControlCallingPed = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfProcessPhysicsCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfPreRenderCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfUpdateAnimCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfUpdateAnimAfterCameraUpdateCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfRenderCallingEntity = false;
|
|
bool CDebugScene::ms_bBreakOnProximityOfAddToDrawListCallingEntity = false;
|
|
bool CDebugScene::ms_bDrawAttachmentExtensions = false;
|
|
bool CDebugScene::ms_bDrawAttachmentEdges = false;
|
|
bool CDebugScene::ms_bDisplayAttachmentEdgeData = false;
|
|
bool CDebugScene::ms_bDisplayUpdateRecords = false;
|
|
bool CDebugScene::ms_bDisplayAttachmentInvokingFunction = false;
|
|
bool CDebugScene::ms_bDisplayAttachmentInvokingFile = false;
|
|
bool CDebugScene::ms_bDisplayAttachmentPhysicsInfo = false;
|
|
bool CDebugScene::ms_bRenderListOfAttachmentExtensions = false;
|
|
bool CDebugScene::ms_bDisplayAttachmentEdgeType = false;
|
|
bool CDebugScene::ms_bDebugRenderAttachmentOfFocusEntitiesOnly = false;
|
|
bool CDebugScene::ms_fAttachmentNodeRelPosWorldUp = false;
|
|
float CDebugScene::ms_fAttachmentNodeEntityDist = 1.6f;
|
|
float CDebugScene::ms_fAttachmentNodeRadius = 0.15f;
|
|
bool CDebugScene::ms_bAttachFlagAutoDetachOnRagdoll = false;
|
|
bool CDebugScene::ms_bAttachFlagCollisionOn = false;
|
|
bool CDebugScene::ms_bAttachFlagDeleteWithParent = false;
|
|
bool CDebugScene::ms_bAttachFlagRotConstraint = false;
|
|
bool CDebugScene::ms_bDetachFlagActivatePhysics = false;
|
|
bool CDebugScene::ms_bDetachFlagApplyVelocity = false;
|
|
bool CDebugScene::ms_bDetachFlagNoCollisionUntilClear = false;
|
|
bool CDebugScene::ms_bDetachFlagIgnoreSafePositionCheck = false;
|
|
bool CDebugScene::ms_bEraserEnabled = false;
|
|
|
|
#endif // __DEV
|
|
|
|
#if !__FINAL
|
|
RegdEnt CDebugScene::ms_focusEntities[FOCUS_ENTITIES_MAX];
|
|
char CDebugScene::ms_focusEntity0AddressString[64] = { "None" };
|
|
#if __DEV
|
|
char CDebugScene::ms_focusEntity0ModelInfoString[64] = { "None" };
|
|
#endif // __DEV
|
|
bool CDebugScene::ms_changeSelectedEntityOnHover = false;
|
|
bool CDebugScene::ms_doClickTestsViaVectorMapInsteadViewport = false;
|
|
bool CDebugScene::ms_makeFocusEntitiesFlash = false;
|
|
bool CDebugScene::ms_lockFocusEntities = false;
|
|
bool CDebugScene::ms_logFocusEntitiesPosition = false;
|
|
bool CDebugScene::ms_clickTestForPeds = true;
|
|
bool CDebugScene::ms_clickTestForRagdolls = true;
|
|
bool CDebugScene::ms_clickTestForVehicles = true;
|
|
bool CDebugScene::ms_clickTestForObjects = true;
|
|
bool CDebugScene::ms_clickTestForWeapons = true;
|
|
bool CDebugScene::ms_clickTestForBuildingsAndMap = false;
|
|
|
|
Vector3 CDebugScene::ms_proximityTestPoint (0.0f, 0.0f, 0.0f);
|
|
float CDebugScene::ms_proximityMaxAllowableVerticalDiff = 0.0f;
|
|
float CDebugScene::ms_proximityMaxAllowableRadialDiff = 0.0f;
|
|
bool CDebugScene::ms_drawProximityArea = false;
|
|
bool CDebugScene::ms_drawProximityAreaFlashes = false;
|
|
bool CDebugScene::ms_drawProximityAreaOnVM = false;
|
|
bool CDebugScene::ms_drawProximityAreaOnVMFlashes = false;
|
|
bool CDebugScene::ms_bDisplayDebugSummary = false;
|
|
bool CDebugScene::ms_bDisplayLODCounts = false;
|
|
#endif
|
|
|
|
#if __BANK
|
|
bool CDebugScene::ms_bEnableFocusEntityDragging = false;
|
|
Vector3 CDebugScene::ms_lastFrameWorldPosition(VEC3_ZERO);
|
|
|
|
int CDebugScene::ms_lastFrameMouseX = 0;
|
|
int CDebugScene::ms_lastFrameMouseY = 0;
|
|
int CDebugScene::ms_DebugTimerMode = DTM_Off;
|
|
float CDebugScene::ms_DebugTimer = -1.0f;
|
|
|
|
atArray<datCallback> CDebugScene::ms_callbacks;
|
|
CUiGadgetInspector * CDebugScene::m_pInspectorWindow = NULL;
|
|
bool CDebugScene::m_bIsInspectorAttached = false;
|
|
|
|
s32 CAuthoringHelper::ms_AuthorMode = 0;
|
|
CUiGadgetSimpleListAndWindow* CAuthoringHelper::ms_pAuthorToolBar = NULL;
|
|
CAuthoringHelper* CAuthoringHelper::ms_SelectedAuthorHelper;
|
|
//CAuthoringHelper* CAuthoringHelper::ms_LastSelectedAuthorHelper = NULL;
|
|
float CAuthoringHelper::ms_DistanceToCamera;
|
|
atString CAuthoringHelper::m_Keyboardbuffer;
|
|
|
|
#endif //__BANK
|
|
|
|
PARAM(touchDebug, "Set this to enable the touchpad based debug inputs for focusing on peds and pausing the game.");
|
|
PARAM(touchDebugDisableConflictingInputs, "Disables conflicting inputs on d-pad, so that stuff doesnt trigger while trying to use touch debug");
|
|
PARAM(touchDebugTapTapTapOhWhyHasTheGamePaused, "Set this if you want to disable the touch with one finger and double tap pause part of it.");
|
|
PARAM(touchDebugDisableTwoTouchCommands, "Set this if you want to disable the two-touch d-pad commands.");
|
|
|
|
#if __BANK
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
// Helper function for the TUNE_GROUP_ macros...
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
bkGroup* GetOrCreateGroup(bkBank* pBankToSearchOrAddTo, const char* groupName)
|
|
{
|
|
const u32 groupNameHash = atStringHash(groupName);
|
|
bkGroup* pGroup = NULL;
|
|
{
|
|
bkWidget* pChild = pBankToSearchOrAddTo->GetChild();
|
|
while(pChild)
|
|
{
|
|
if(atStringHash(pChild->GetTitle()) == groupNameHash)
|
|
{
|
|
break;
|
|
}
|
|
pChild = pChild->GetNext();
|
|
}
|
|
if(pChild)
|
|
{
|
|
pGroup = dynamic_cast<bkGroup*>(pChild);
|
|
}
|
|
}
|
|
if(!pGroup)
|
|
{
|
|
pGroup = pBankToSearchOrAddTo->PushGroup(groupName);
|
|
Assert(pGroup);
|
|
pBankToSearchOrAddTo->PopGroup();
|
|
}
|
|
|
|
return pGroup;
|
|
}
|
|
|
|
CDebugScene::TuneWidgetData::TuneWidgetData()
|
|
: m_Type(TUNE_TYPE_INVALID)
|
|
, m_GroupName(NULL)
|
|
, m_Title(NULL)
|
|
{
|
|
memset(&m_Params, 0, sizeof(m_Params));
|
|
}
|
|
|
|
CDebugScene::TuneWidgetData::TuneWidgetData(const s32 type, const char* groupName, const char* title, void* data, const void* min, const void* max, const void* delta)
|
|
: m_Type(type)
|
|
, m_GroupName(ConstStringDuplicate(groupName))
|
|
, m_Title(ConstStringDuplicate(title))
|
|
{
|
|
switch (type)
|
|
{
|
|
case TUNE_TYPE_BOOL:
|
|
{
|
|
m_Params.m_AsBool.m_Data = static_cast<bool*>(data);
|
|
break;
|
|
}
|
|
case TUNE_TYPE_INT:
|
|
{
|
|
m_Params.m_AsInt.m_Data = static_cast<s32*>(data);
|
|
m_Params.m_AsInt.m_Min = *static_cast<const s32*>(min);
|
|
m_Params.m_AsInt.m_Max = *static_cast<const s32*>(max);
|
|
m_Params.m_AsInt.m_Delta = *static_cast<const float*>(delta);
|
|
break;
|
|
}
|
|
case TUNE_TYPE_FLOAT:
|
|
{
|
|
m_Params.m_AsFloat.m_Data = static_cast<float*>(data);
|
|
m_Params.m_AsFloat.m_Min = *static_cast<const float*>(min);
|
|
m_Params.m_AsFloat.m_Max = *static_cast<const float*>(max);
|
|
m_Params.m_AsFloat.m_Delta = *static_cast<const float*>(delta);
|
|
break;
|
|
}
|
|
case TUNE_TYPE_COLOR:
|
|
{
|
|
m_Params.m_AsColor.m_Data = static_cast<Color32*>(data);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
Assert(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDebugScene::AddWidgets(bkBank &DEV_ONLY(bank))
|
|
{
|
|
#if __DEV
|
|
bank.PushGroup("Point And Click Entity Debugging",false);
|
|
bank.AddTitle("Mouse point and click to select the Focus0 entity." );
|
|
bank.AddTitle("Control-click to add additional focus entities." );
|
|
#if !__FINAL
|
|
|
|
bank.AddToggle("Select entity under mouse (without click)", &ms_changeSelectedEntityOnHover, NullCB, "Allows selection update per frame for whatever is under the mouse cursor.");
|
|
bank.AddToggle("Do click tests On VectorMap instead of 3D", &ms_doClickTestsViaVectorMapInsteadViewport, NullCB, "Allows selecting via VectorMap instead of the 3D Viewport.");
|
|
bank.AddText("Focus Entity0 Address ('0xABCDEF12')", ms_focusEntity0AddressString, 64, false, datCallback(HandleFocusEntityTextBoxChange));
|
|
#if __DEV
|
|
bank.AddText("Focus Entity0 Model Info Name", ms_focusEntity0ModelInfoString, 64, false, datCallback(HandleFocusEntityTextBoxChange));
|
|
#endif // __DEV
|
|
bank.AddToggle("Draw Focus Entity(s) Bound Box", &ms_drawFocusEntitiesBoundBox, NullCB, "Makes the focus entities bounding box draw.");
|
|
bank.AddToggle("Draw Focus Entity(s) Bound Box On VectorMap", &ms_drawFocusEntitiesBoundBoxOnVMap, NullCB, "Makes the focus entities bounding box draw on VectorMap.");
|
|
bank.AddToggle("Draw Focus Entity(s) Info", &ms_drawFocusEntitiesInfo, NullCB, "Makes the focus entities info draw.");
|
|
bank.AddToggle("Draw Focus Entity(s) Cover Tuning", &ms_drawFocusEntitiesCoverTuning, NullCB, "Makes the focus entities cover tuning draw.");
|
|
bank.AddToggle("Draw Focus Entity(s) Skeleton", &ms_drawFocusEntitiesSkeleton, NullCB, "Draw the focus entities skeleton");
|
|
bank.AddToggle("Draw Focus Entity(s) Skeleton's Non-orthonormalities", &ms_drawFocusEntitiesSkeletonNonOrthonormalities, NullCB, "Draw the focus entities skeleton's non-orthonormalities");
|
|
bank.AddToggle("Draw Focus Entity(s) Skeleton's Non-ortho data only", &ms_drawFocusEntitiesSkeletonNonOrthoDataOnly, NullCB, "Draw the focus entities skeleton's non-ortho data only");
|
|
bank.AddToggle("Draw Focus Entity(s) Skeleton's Bone names and Ids", &ms_drawFocusEntitiesSkeletonBoneNamesAndIds, NullCB, "Draw the focus entities skeleton's bone names and Ids");
|
|
bank.AddToggle("Draw Focus Entity(s) Skeleton's Channels", &ms_drawFocusEntitiesSkeletonChannels, NullCB, "Draw the focus entities skeleton's channels");
|
|
bank.AddToggle("Draw Focus Entity(s) Skeleton's Non-ortho mats", &ms_drawFocusEntitiesSkeletonNonOrthonoMats, NullCB, "Draw the focus entities skeleton's non-ortho mats");
|
|
bank.AddToggle("Make Focus Entity(s) Flash", &ms_makeFocusEntitiesFlash, NullCB, "Makes the focus entity only draw every other frame.");
|
|
bank.AddToggle("Lock Focus Entity(s)", &ms_lockFocusEntities, NullCB, "Locks in the current focus entities so that clicking will not select new ones or de-select the current ones.");
|
|
bank.AddToggle("Print Position/Rotation On Focus Entity(s) Change", &ms_logFocusEntitiesPosition, NullCB, "Prints out additional information when selecting new focus entities.");
|
|
bank.PushGroup("What to entities to select on click",false);
|
|
bank.AddToggle("Peds", &ms_clickTestForPeds, NullCB, "Allows peds to be selectable via mouse click.");
|
|
bank.AddToggle("Ragdolls", &ms_clickTestForRagdolls, NullCB, "Allows ragdolls to be selectable via mouse click.");
|
|
bank.AddToggle("Vehicles", &ms_clickTestForVehicles, NullCB, "Allows vehicles to be selectable via mouse click.");
|
|
bank.AddToggle("Objects", &ms_clickTestForObjects, NullCB, "Allows objects to be selectable via mouse click.");
|
|
bank.AddToggle("Weapons", &ms_clickTestForWeapons, NullCB, "Allows weapons to be selectable via mouse click.");
|
|
bank.AddToggle("Buildings and Map", &ms_clickTestForBuildingsAndMap, NullCB, "Allows buildings and map to be selectable via mouse click.");
|
|
// bank.AddToggle("Select peds from inside of cars", &ms_selectPedsTypesFromInsideVehicles, NullCB, "Select peds from inside vehicles.");
|
|
bank.PopGroup();
|
|
#endif // !FINAL
|
|
bank.PushGroup("Break when the Focus0 entity has...",false);
|
|
bank.AddToggle("Destroy Called", &ms_bBreakOnDestroyOfFocusEntity, NullCB, "Causes the debugger to break in the Destroy (~) function of the focus entity");
|
|
bank.AddToggle("WorldAdd Called", &ms_bBreakOnWorldAddOfFocusEntity, NullCB, "Causes the debugger to break when CGameWorld::Add() function is called on the focus entity");
|
|
bank.AddToggle("WorldRemove Called", &ms_bBreakOnWorldRemoveOfFocusEntity, NullCB, "Causes the debugger to break when CGameWorld::Remove() function is called on the focus entity");
|
|
bank.AddToggle("ProcessControl Called", &ms_bBreakOnProcessControlOfFocusEntity, NullCB, "Causes the debugger to break in the ::ProcessControl() function of the focus entity");
|
|
bank.AddToggle("ProcessIntelligence Called", &ms_bBreakOnProcessIntelligenceOfFocusEntity, NullCB, "Causes the debugger to break in the ::ProcessIntellgence() function of the focus entity");
|
|
bank.AddToggle("ProcessPhysics Called", &ms_bBreakOnProcessPhysicsOfFocusEntity, NullCB, "Causes the debugger to break in the ::ProcessPhysics() function of the focus entity");
|
|
bank.AddToggle("PreRender Called", &ms_bBreakOnPreRenderOfFocusEntity, NullCB, "Causes the debugger to break in the ::PreRender() function of the focus entity");
|
|
bank.AddToggle("UpdateAnim Called", &ms_bBreakOnUpdateAnimOfFocusEntity, NullCB, "Causes the debugger to break in the ::UpdateAnim() function of the focus entity");
|
|
bank.AddToggle("UpdateAnimAfterCameraUpdate Called", &ms_bBreakOnUpdateAnimAfterCameraUpdateOfFocusEntity, NullCB, "Causes the debugger to break in the ::UpdateAnimAfterCameraUpdate() function of the focus entity");
|
|
bank.AddToggle("Render Called", &ms_bBreakOnRenderOfFocusEntity, NullCB, "Causes the debugger to break in the ::Render() function of the focus entity");
|
|
bank.AddToggle("AddToDrawList Called", &ms_bBreakOnAddToDrawListOfFocusEntity, NullCB, "Causes the debugger to break in the ::AddToDrawList() function of the focus entity");
|
|
bank.AddToggle("CalcDesiredVelocity Called", &ms_bBreakOnCalcDesiredVelocityOfFocusEntity, NullCB, "Causes the debugger to break in the ::CalcDesiredVelocity() function of the focus entity");
|
|
bank.PopGroup();
|
|
bank.AddToggle("Stop ProcessControl Of All Entities", &ms_bStopProcessCtrlAllEntities, NullCB, "Stops processing all entities");
|
|
bank.AddToggle("Stop ProcessControl Of Entities Except Focus0", &ms_bStopProcessCtrlAllExceptFocus0Entity, NullCB, "Stops processing all entities except the focus entity");
|
|
bank.AddToggle("Stop ProcessControl Of All Entities Of Focus0 Type", &ms_bStopProcessCtrlAllEntitiesOfFocus0Type, NullCB, "Stops processing all entities of focus type");
|
|
bank.AddToggle("Stop ProcessControl Of Entities Of Focus0 Type Except Focus0", &ms_bStopProcessCtrlAllOfFocus0TypeExceptFocus0, NullCB, "Stops processing all entities of focus type except the focus entity");
|
|
bank.PopGroup();
|
|
bank.PushGroup("Proximity Debugging",false);
|
|
bank.AddText("Proximity Point x y z", g_proximityTestPointString, sizeof(g_proximityTestPointString), false, &ChangeProximityTestPoint);
|
|
#if !__FINAL
|
|
bank.AddSlider("Max Allowable Vertical Diff", &ms_proximityMaxAllowableVerticalDiff, 0.0f, 1000.0f, 1.0f);
|
|
bank.AddSlider("Max Allowable radial Diff,", &ms_proximityMaxAllowableRadialDiff, 0.0f, 1000.0f, 1.0f);
|
|
bank.AddToggle("Draw Proximity Area", &ms_drawProximityArea, NullCB, "Draws the proximity area (in 3D)");
|
|
bank.AddToggle("Draw Proximity Area Flashes", &ms_drawProximityAreaFlashes, NullCB, "If drawn the proximity area flashes (in 3D)");
|
|
bank.AddToggle("Draw Proximity Area (On VectorMap)", &ms_drawProximityAreaOnVM, NullCB, "Draws the proximity area (on the Vector Map)");
|
|
bank.AddToggle("Draw Proximity Area On VM Flashes", &ms_drawProximityAreaOnVMFlashes, NullCB, "If drawn the proximity area flashes (on the Vector Map)");
|
|
#endif // !FINAL
|
|
bank.PushGroup("Break on proximity of...",false);
|
|
bank.AddToggle("Destroy Calling Entity", &ms_bBreakOnProximityOfDestroyCallingEntity, NullCB, "Causes the debugger to break on proximity of a Destroy (~) function calling entity");
|
|
bank.AddToggle("Add Calling Entity", &ms_bBreakOnProximityOfAddCallingEntity, NullCB, "Causes the debugger to break on proximity of a Add function calling entity");
|
|
bank.AddToggle("Remove Calling Entity", &ms_bBreakOnProximityOfRemoveCallingEntity, NullCB, "Causes the debugger to break on proximity of a Remove function calling entity");
|
|
bank.AddToggle("RemoveAndAdd Calling Entity", &ms_bBreakOnProximityOfAddAndRemoveCallingEntity, NullCB, "Causes the debugger to break on proximity of a AddAndRemove function calling entity");
|
|
bank.AddToggle("AddToInterior Calling Entity", &ms_bBreakOnProximityOfAddToInteriorCallingEntity, NullCB, "Causes the debugger to break on proximity of a AddToInterior function calling entity");
|
|
bank.AddToggle("RemoveFromInterior Calling Entity", &ms_bBreakOnProximityOfRemoveFromInteriorCallingEntity, NullCB, "Causes the debugger to break on proximity of a RemoveFromInterior function calling entity");
|
|
bank.AddToggle("WorldAdd Calling Entity", &ms_bBreakOnProximityOfWorldAddCallingEntity, NullCB, "Causes the debugger to break on proximity of the entity CGameWorld::Add() is called on");
|
|
bank.AddToggle("WorldAdd Calling Ped", &ms_bBreakOnProximityOfWorldAddCallingPed, NullCB, "Causes the debugger to break on proximity of the ped CGameWorld::Add() is called on");
|
|
bank.AddToggle("Teleport Calling Object", &ms_bBreakOnProximityOfTeleportCallingObject, NullCB, "Causes the debugger to break on proximity of the entity CGameWorld::Add() is called on");
|
|
bank.AddToggle("Teleport Calling Ped", &ms_bBreakOnProximityOfTeleportCallingPed, NullCB, "Causes the debugger to break on proximity of the ped CGameWorld::Add() is called on");
|
|
bank.AddToggle("Teleport Calling Vehicle", &ms_bBreakOnProximityOfTeleportCallingVehicle, NullCB, "Causes the debugger to break on proximity of the dummy ped CGameWorld::Add() is called on");
|
|
bank.AddToggle("WorldRemove Calling Entity", &ms_bBreakOnProximityOfWorldRemoveCallingEntity, NullCB, "Causes the debugger to break on proximity of the entity CGameWorld::Remove() is called on");
|
|
bank.AddToggle("ProcessControl Calling Entity", &ms_bBreakOnProximityOfProcessControlCallingEntity, NullCB, "Causes the debugger to break on proximity of a ::ProcessControl() function calling entity");
|
|
bank.AddToggle("ProcessControl Calling Ped", &ms_bBreakOnProximityOfProcessControlCallingPed, NullCB, "Causes the debugger to break on proximity of the ped CGameWorld::Remove() is called on");
|
|
bank.AddToggle("ProcessPhysics Calling Entity", &ms_bBreakOnProximityOfProcessPhysicsCallingEntity, NullCB, "Causes the debugger to break on proximity of a ::ProcessPhysics() function calling entity");
|
|
bank.AddToggle("PreRender Calling Entity", &ms_bBreakOnProximityOfPreRenderCallingEntity, NullCB, "Causes the debugger to break on proximity of a ::PreRender() function calling entity");
|
|
bank.AddToggle("UpdateAnim Calling Entity", &ms_bBreakOnProximityOfUpdateAnimCallingEntity, NullCB, "Causes the debugger to break on proximity of a ::UpdateAnim() function calling entity");
|
|
bank.AddToggle("UpdateAnimAfterCameraUpdate Calling Entity", &ms_bBreakOnProximityOfUpdateAnimAfterCameraUpdateCallingEntity, NullCB, "Causes the debugger to break on proximity of a ::UpdateAnimAfterCameraUpdate() function calling entity");
|
|
bank.AddToggle("Render Calling Entity", &ms_bBreakOnProximityOfRenderCallingEntity, NullCB, "Causes the debugger to break on proximity of a ::Render() function calling entity");
|
|
bank.AddToggle("AddToDrawList Calling Entity", &ms_bBreakOnProximityOfAddToDrawListCallingEntity, NullCB, "Causes the debugger to break on proximity of a ::AddToDrawList() function calling entity");
|
|
bank.PopGroup();
|
|
bank.PopGroup();
|
|
bank.PushGroup("Attach Test");
|
|
bank.AddButton("Attach focus entities",AttachFocusEntitiesTogether);
|
|
bank.AddButton("Attach focus entities physically",AttachFocusEntitiesTogetherPhysically);
|
|
bank.AddButton("Attach all focus entities to world",AttachFocusEntitiesToWorld);
|
|
bank.AddButton("Detach focus entity",DetachFocusEntity);
|
|
bank.AddButton("DELETE all focus entities",DeleteFocusEntities);
|
|
bank.AddToggle("Draw attachment nodes",&ms_bDrawAttachmentExtensions);
|
|
bank.AddToggle("Draw attachment edges",&ms_bDrawAttachmentEdges);
|
|
bank.AddToggle("Display attachment edge type",&ms_bDisplayAttachmentEdgeType);
|
|
bank.AddToggle("Display attachment edge data",&ms_bDisplayAttachmentEdgeData);
|
|
bank.AddToggle("Display update records",&ms_bDisplayUpdateRecords);
|
|
bank.AddToggle("Display attachment invoking function",&ms_bDisplayAttachmentInvokingFunction);
|
|
bank.AddToggle("Display attachment invoking file",&ms_bDisplayAttachmentInvokingFile);
|
|
bank.AddToggle("Display attachment physics info",&ms_bDisplayAttachmentPhysicsInfo);
|
|
bank.AddToggle("Render list of attachment extensions",&ms_bRenderListOfAttachmentExtensions);
|
|
bank.AddToggle("Debug render attachment of focus entities only",&ms_bDebugRenderAttachmentOfFocusEntitiesOnly);
|
|
bank.AddToggle("Attachment node relative pos world up",&ms_fAttachmentNodeRelPosWorldUp);
|
|
bank.AddSlider("Attachment node radius", &ms_fAttachmentNodeRadius, 0.01f, 100.0f, 0.01f);
|
|
bank.AddSlider("Attachment node dist from entity", &ms_fAttachmentNodeEntityDist, 0.0f, 100.0f, 0.01f);
|
|
bank.PushGroup("Attach flags",false);
|
|
bank.AddToggle("Collision on",&ms_bAttachFlagCollisionOn);
|
|
bank.AddToggle("Auto detach on ragdoll",&ms_bAttachFlagAutoDetachOnRagdoll);
|
|
bank.AddToggle("Delete with parent",&ms_bAttachFlagDeleteWithParent);
|
|
bank.AddToggle("Rot constraint",&ms_bAttachFlagRotConstraint);
|
|
bank.PopGroup();
|
|
bank.PushGroup("Detach flags",false);
|
|
bank.AddToggle("Activate physics",&ms_bDetachFlagActivatePhysics);
|
|
bank.AddToggle("Apply velocity",&ms_bDetachFlagApplyVelocity);
|
|
bank.AddToggle("No collision until clear",&ms_bDetachFlagNoCollisionUntilClear);
|
|
bank.AddToggle("Ignore safe position check",&ms_bDetachFlagIgnoreSafePositionCheck);
|
|
bank.PopGroup();
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Eraser");
|
|
bank.AddTitle("This allows point and click erasing");
|
|
bank.AddToggle("Eraser enabled", &ms_bEraserEnabled);
|
|
bank.PopGroup();
|
|
#endif // __DEV
|
|
|
|
bkBank& theTuneBank = BANKMGR.CreateBank("_TUNE_");
|
|
theTuneBank.AddTitle("Items are added here automatically by the macros");
|
|
theTuneBank.AddTitle("TUNE_BOOL, TUNE_INT, or TUNE_FLOAT and");
|
|
theTuneBank.AddTitle("TUNE_GROUP_BOOL, TUNE_GROUP_INT, or TUNE_GROUP_FLOAT.");
|
|
theTuneBank.AddTitle("Use them, love them.");
|
|
|
|
bkBank *pBank = BANKMGR.FindBank("Optimization");
|
|
#if !__FINAL
|
|
pBank->AddToggle("Debug Summary", &ms_bDisplayDebugSummary, NullCB, "Toggle the debug summary render output");
|
|
pBank->AddToggle(" Include LOD Counts in Debug Summary", &ms_bDisplayLODCounts, NullCB, "Include LOD counts in debug summary render output");
|
|
pBank->PushGroup("Entities on vectormap");
|
|
pBank->AddToggle("Display peds active/inactive", &CDebugScene::bDisplayPedsOnVMapAsActiveInactive);
|
|
pBank->AddToggle("Display vehicles active/inactive",&CDebugScene::bDisplayVehiclesOnVMapAsActiveInactive);
|
|
pBank->AddToggle("Display objects active/inactive", &CDebugScene::bDisplayObjectsOnVMap);
|
|
pBank->AddToggle("Display peds timeslice updates", &CDebugScene::bDisplayPedsOnVMapTimesliceUpdates);
|
|
pBank->AddToggle("Display vehicles timeslice updates",&CDebugScene::bDisplayVehiclesOnVMapTimesliceUpdates);
|
|
pBank->AddToggle("Display vehicles occluded",&CDebugScene::bDisplayVehiclesOnVMapBasedOnOcclusion);
|
|
pBank->AddToggle("Display local camera", &CVectorMap::m_bDisplayLocalPlayerCamera );
|
|
pBank->PopGroup();
|
|
#endif // !FINAL
|
|
// DEBUG!! -AC, Not the best place for this, but it will do for now...
|
|
FocusEntities_Clear();
|
|
// END DEBUG!!
|
|
}
|
|
|
|
bool CDebugScene::QueueTuneWidget(const TuneWidgetData& data)
|
|
{
|
|
return sm_TuneWidgetQueue.Push(data) != NULL;
|
|
}
|
|
|
|
void CDebugScene::FlushTuneWidgetQueue()
|
|
{
|
|
bkBank* bank = BANKMGR.FindBank("_TUNE_");
|
|
|
|
if (bank)
|
|
{
|
|
while (!sm_TuneWidgetQueue.IsEmpty())
|
|
{
|
|
const TuneWidgetData data = sm_TuneWidgetQueue.Pop();
|
|
|
|
bkGroup* group = NULL;
|
|
|
|
if (data.m_GroupName)
|
|
{
|
|
group = GetOrCreateGroup(bank, data.m_GroupName);
|
|
bank->SetCurrentGroup(*group);
|
|
}
|
|
|
|
switch (data.m_Type)
|
|
{
|
|
case TUNE_TYPE_BOOL:
|
|
{
|
|
bank->AddToggle(data.m_Title, data.m_Params.m_AsBool.m_Data);
|
|
break;
|
|
}
|
|
case TUNE_TYPE_INT:
|
|
{
|
|
bank->AddSlider(data.m_Title, data.m_Params.m_AsInt.m_Data, data.m_Params.m_AsInt.m_Min, data.m_Params.m_AsInt.m_Max, (s32)data.m_Params.m_AsInt.m_Delta);
|
|
break;
|
|
}
|
|
case TUNE_TYPE_FLOAT:
|
|
{
|
|
bank->AddSlider(data.m_Title, data.m_Params.m_AsFloat.m_Data, data.m_Params.m_AsFloat.m_Min, data.m_Params.m_AsFloat.m_Max, data.m_Params.m_AsFloat.m_Delta);
|
|
break;
|
|
}
|
|
case TUNE_TYPE_COLOR:
|
|
{
|
|
bank->AddColor(data.m_Title, data.m_Params.m_AsColor.m_Data);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
Assert(0);
|
|
}
|
|
}
|
|
|
|
if (group)
|
|
{
|
|
bank->UnSetCurrentGroup(*group);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif // __BANK
|
|
|
|
#if __BANK
|
|
|
|
void CDebugScene::DisableInputsForTouchDebug()
|
|
{
|
|
if (PARAM_touchDebugDisableConflictingInputs.Get())
|
|
{
|
|
CControl& rControl = CControlMgr::GetMainPlayerControl();
|
|
|
|
rControl.SetInputExclusive(INPUT_FRONTEND_UP);
|
|
rControl.SetInputExclusive(INPUT_FRONTEND_DOWN);
|
|
rControl.SetInputExclusive(INPUT_FRONTEND_LEFT);
|
|
rControl.SetInputExclusive(INPUT_FRONTEND_RIGHT);
|
|
}
|
|
}
|
|
|
|
void CDebugScene::RegisterEntityChangeCallback(datCallback callback)
|
|
{
|
|
ms_callbacks.PushAndGrow(callback);
|
|
}
|
|
|
|
#endif //__BANK
|
|
|
|
#if USE_PROFILER
|
|
const char* MEM_TYPE_TO_SIZE_STRING[] = { "Memory\\Game Virtual (Kb)",
|
|
"Memory\\Resource Virtual (Kb)",
|
|
"Memory\\Game Physical (Kb)",
|
|
"Memory\\Resource Physical (Kb)",
|
|
"Memory\\Debug Virtual (Kb)" };
|
|
|
|
const char* MEM_TYPE_TO_TOTAL_STRING[] = { "Memory\\Game Virtual [Total] (Kb)",
|
|
"Memory\\Resource Virtual [Total] (Kb)",
|
|
"Memory\\Game Physical [Total] (Kb)",
|
|
"Memory\\Resource Physical [Total] (Kb)",
|
|
"Memory\\Debug Virtual [Total] (Kb)" };
|
|
|
|
template<eMemoryType MEM_TYPE>
|
|
struct MemoryReporter
|
|
{
|
|
static void Report()
|
|
{
|
|
if (sysMemAllocator* allocator = sysMemAllocator::GetMaster().GetAllocator(MEM_TYPE))
|
|
{ \
|
|
PROFILER_TAG(MEM_TYPE_TO_SIZE_STRING[MEM_TYPE], (rage::u64)(allocator->GetMemoryUsed() >> 10));
|
|
PROFILER_TAG(MEM_TYPE_TO_TOTAL_STRING[MEM_TYPE], (rage::u64)(allocator->GetHeapSize() >> 10));
|
|
} \
|
|
}
|
|
};
|
|
|
|
struct PoolReporter
|
|
{
|
|
const Profiler::TagDescription* tags[ENTITY_TYPE_TOTAL];
|
|
PoolReporter()
|
|
{
|
|
char buffer[256];
|
|
for (int i = 0; i < ENTITY_TYPE_TOTAL; ++i)
|
|
{
|
|
sprintf_s(buffer, "EntityCount\\%s", entityTypeStr[i]);
|
|
tags[i] = Profiler::TagDescription::Create(buffer);
|
|
}
|
|
}
|
|
|
|
static void Report()
|
|
{
|
|
static PoolReporter reporter;
|
|
|
|
Profiler::Timestamp time;
|
|
time.Start();
|
|
|
|
for (int i = 0; i < ENTITY_TYPE_TOTAL; ++i)
|
|
if (const fwBasePool* pEntPool = CEntity::ms_EntityPools[i])
|
|
Profiler::AttachTag(reporter.tags[i], (u64)pEntPool->GetNoOfUsedSpaces(), time);
|
|
}
|
|
};
|
|
|
|
void CDebugScene::AttachProfilingVariables()
|
|
{
|
|
if (Profiler::IsCollectingTags())
|
|
{
|
|
PoolReporter::Report();
|
|
|
|
PROFILER_TAG("General\\Camera Position", VECTOR3_TO_VEC3V(camInterface::GetPos()));
|
|
PROFILER_TAG("General\\Camera FOV", camInterface::GetFov());
|
|
PROFILER_TAG("General\\Camera Rotation", Vec3V(camInterface::GetHeading(), camInterface::GetPitch(), camInterface::GetRoll()));
|
|
|
|
PROFILER_TAG("Frame\\Number", (rage::u64)fwTimer::GetFrameCount());
|
|
PROFILER_TAG("Frame\\GPU Number", (rage::u64)GRCDEVICE.GetFrameCounter());
|
|
PROFILER_TAG("Frame\\CPU Time (ms)", fwTimer::GetSystemTimeStep() * 1000.0f);
|
|
|
|
MemoryReporter<MEMTYPE_GAME_VIRTUAL>::Report();
|
|
MemoryReporter<MEMTYPE_RESOURCE_VIRTUAL>::Report();
|
|
MemoryReporter<MEMTYPE_GAME_PHYSICAL>::Report();
|
|
MemoryReporter<MEMTYPE_RESOURCE_PHYSICAL>::Report();
|
|
MemoryReporter<MEMTYPE_DEBUG_VIRTUAL>::Report();
|
|
}
|
|
|
|
// Outside IsCollectingTags scope check - we need to add them in any case
|
|
Profiler::AddInternalTags();
|
|
}
|
|
#endif //USE_PROFILER
|
|
|
|
|
|
void CDebugScene::ChangeProximityTestPoint()
|
|
{
|
|
#if __DEV
|
|
Vector3 vecPos(VEC3_ZERO);
|
|
int nResults = 0;
|
|
|
|
nResults = sscanf(g_proximityTestPointString, "%f %f %f", &vecPos.x, &vecPos.y, &vecPos.z);
|
|
|
|
if(nResults)
|
|
{
|
|
ms_proximityTestPoint = vecPos;
|
|
}
|
|
#endif // __DEV
|
|
}
|
|
|
|
|
|
|
|
#if __BANK
|
|
|
|
static const char* gDebugSceneInspectorEntries[CDebugScene::GADGET_NUM] =
|
|
{
|
|
"",
|
|
"Matrix-X",
|
|
"Matrix-Y",
|
|
"Matrix-Z",
|
|
"Translation",
|
|
"Scale",
|
|
"Heading",
|
|
"Entity type",
|
|
"PathServer Id",
|
|
"Mass",
|
|
"Health",
|
|
"Collision model type",
|
|
"Num 2dFx",
|
|
"Num attached lights",
|
|
"Visible",
|
|
"Fixed",
|
|
"Fixed for navigation",
|
|
"Not avoided",
|
|
"Does not provide AI cover",
|
|
"Does not provide player cover",
|
|
"Is ladder",
|
|
"Uses door physics",
|
|
"Has animation",
|
|
"Animation auto start",
|
|
"Has uv animation",
|
|
"Has spawn points",
|
|
"Generates wind audio",
|
|
"Ambient scale",
|
|
"Is prop",
|
|
"Is traffic light",
|
|
"Tint palette index",
|
|
"Climbable by AI",
|
|
"Has added lights",
|
|
"Is targettable with no los",
|
|
"Is a target priority",
|
|
"Can be targetted by player",
|
|
"Cull Small Shadows",
|
|
"Don't cast shadows",
|
|
"Render Only In Reflections",
|
|
"Don't Render In Reflections",
|
|
"Render Only In Shadow",
|
|
"Don't Render In Shadow",
|
|
"LOD Group Mask",
|
|
"LOD Flags",
|
|
"Is Used In MP",
|
|
"POPTYPE",
|
|
"Owned By",
|
|
"Replay ID",
|
|
"Replay Map Hash",
|
|
"Replay Hide Count",
|
|
};
|
|
|
|
void PopulateDebugSceneInspectorWindowCB(CUiGadgetText* pResult, u32 row, u32 col)
|
|
{
|
|
if (pResult && row < CDebugScene::GADGET_NUM)
|
|
{
|
|
char str[256];
|
|
CEntity *pEntity = static_cast<CEntity*>(g_PickerManager.GetSelectedEntity());
|
|
if (pEntity)
|
|
{
|
|
if(col==0)
|
|
{
|
|
switch(row)
|
|
{
|
|
case 0:
|
|
sprintf(str, "\"%s\"", pEntity->GetModelName());
|
|
break;
|
|
default:
|
|
sprintf(str, "%s", gDebugSceneInspectorEntries[row]);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch(row)
|
|
{
|
|
case 0:
|
|
sprintf(str, "0x%p (MI:%i)", pEntity, pEntity->GetModelIndex());
|
|
break;
|
|
|
|
case CDebugScene::GADGET_ENTITY_TYPE:
|
|
{
|
|
sprintf(str, "%i (%s)", pEntity->GetType(), GetEntityTypeStr(pEntity->GetType()) );
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_MAT_XAXIS:
|
|
{
|
|
Vector3 vRight = VEC3V_TO_VECTOR3(pEntity->GetTransform().GetRight());
|
|
sprintf(str, "%.4f, %.4f, %.4f", vRight.x, vRight.y, vRight.z);
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_MAT_YAXIS:
|
|
{
|
|
Vector3 vFwd = VEC3V_TO_VECTOR3(pEntity->GetTransform().GetForward());
|
|
sprintf(str, "%.4f, %.4f, %.4f", vFwd.x, vFwd.y, vFwd.z);
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_MAT_ZAXIS:
|
|
{
|
|
Vector3 vUp = VEC3V_TO_VECTOR3(pEntity->GetTransform().GetUp());
|
|
sprintf(str, "%.4f, %.4f, %.4f", vUp.x, vUp.y, vUp.z);
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_MAT_TRANS:
|
|
{
|
|
Vector3 vPos = VEC3V_TO_VECTOR3(pEntity->GetTransform().GetPosition());
|
|
sprintf(str, "%.4f, %.4f, %.4f", vPos.x, vPos.y, vPos.z);
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_SCALE:
|
|
{
|
|
float fScaleXY = 1.0f;
|
|
float fScaleZ = 1.0f;
|
|
|
|
//Mat34V mat = pEntity->GetNonOrthoMatrix();
|
|
//Vec3V vscale = mat.d();
|
|
//Displayf("%.2f, %.2f, %.2f", vscale.GetXf(), vscale.GetYf(), vscale.GetZf());
|
|
|
|
const fwTransform* pTransform = pEntity->GetTransformPtr();
|
|
if (pTransform->IsSimpleScaledTransform())
|
|
{
|
|
fScaleXY = ((fwSimpleScaledTransform*)pTransform)->GetScaleXY();
|
|
fScaleZ = ((fwSimpleScaledTransform*)pTransform)->GetScaleZ();
|
|
}
|
|
else if (pTransform->IsMatrixScaledTransform())
|
|
{
|
|
fScaleXY = ((fwMatrixScaledTransform*)pTransform)->GetScaleXY();
|
|
fScaleZ = ((fwMatrixScaledTransform*)pTransform)->GetScaleZ();
|
|
}
|
|
else if (pTransform->IsQuaternionScaledTransform())
|
|
{
|
|
fScaleXY = ((fwQuaternionScaledTransform*)pTransform)->GetScaleXY();
|
|
fScaleZ = ((fwQuaternionScaledTransform*)pTransform)->GetScaleZ();
|
|
}
|
|
sprintf(str, "%.4f, %.4f, %.4f", fScaleXY, fScaleXY, fScaleZ);
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_ENTITY_HEADING:
|
|
{
|
|
float rad = pEntity->GetTransform().GetHeading();
|
|
sprintf(str, "%.2f (degrees: %.2f)", rad, rad * RtoD);
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_PATHSERVER_ID:
|
|
{
|
|
if(pEntity->GetIsTypeObject())
|
|
sprintf(str, "%i", ((CObject*)pEntity)->GetPathServerDynamicObjectIndex());
|
|
else if(pEntity->GetIsTypeVehicle())
|
|
sprintf(str, "%i", ((CVehicle*)pEntity)->GetPathServerDynamicObjectIndex());
|
|
else
|
|
sprintf(str, "-");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_MASS:
|
|
{
|
|
sprintf(str, "%.2f", pEntity->GetPhysArch() ? ((CPhysical*)pEntity)->GetMass() : 0.0f);
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_PED_HEALTH:
|
|
{
|
|
if(pEntity->GetIsPhysical())
|
|
{
|
|
CPhysical *pPed = static_cast<CPhysical*>(pEntity);
|
|
sprintf(str, "%.2f", pPed->GetHealth());
|
|
}
|
|
else
|
|
{
|
|
sprintf(str, "N/A");
|
|
}
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_COLLISION_MODEL_TYPE:
|
|
{
|
|
if(pEntity->GetPhysArch() && pEntity->GetPhysArch()->GetBound())
|
|
sprintf(str, "%s", pEntity->GetPhysArch()->GetBound()->GetTypeString());
|
|
else
|
|
sprintf(str, "none");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_NUM_2D_FX:
|
|
{
|
|
sprintf(str, "%i", pEntity->GetBaseModelInfo()->GetNum2dEffects());
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_NUM_2D_FX_LIGHTS:
|
|
{
|
|
sprintf(str, "%i", pEntity->GetBaseModelInfo()->GetNum2dEffectLights());
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_VISIBLE:
|
|
{
|
|
pEntity->GetIsVisibleInfo( str, 256 );
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_FIXED:
|
|
{
|
|
sprintf(str, "%s", pEntity->IsBaseFlagSet(fwEntity::IS_FIXED) ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_FIXED_FOR_NAVIGATION:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->GetIsFixedForNavigation() ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_NOT_AVOIDED:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->GetNotAvoidedByPeds() ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_DOES_NOT_PROVIDE_AI_COVER:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->GetDoesNotProvideAICover() ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_DOES_NOT_PROVIDE_PLAYER_COVER:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->GetDoesNotProvidePlayerCover() ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_LADDER:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->GetIsLadder() ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_DOOR_PHYSICS:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->GetUsesDoorPhysics() ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_HAS_ANIM:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->GetHasAnimation() ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_ANIM_AUTO_START:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->GetAutoStartAnim() ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_HAS_UV_ANIM:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->GetHasUvAnimation() ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_HAS_SPAWN_POINTS:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->GetHasSpawnPoints() ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_GENERATES_WIND_AUDIO:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->GetGeneratesWindAudio() ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_AMBIENT_SCALE:
|
|
{
|
|
sprintf(str, "%s - %s - %s", pEntity->GetBaseModelInfo()->GetUseAmbientScale() ? "true" : "false",
|
|
pEntity->GetUseAmbientScale() ? "true" : "false",
|
|
pEntity->GetUseDynamicAmbientScale() ? "true" : "false" );
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_IS_PROP:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->GetIsProp() ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_IS_TRAFFIC_LIGHT:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->TestAttribute(MODEL_ATTRIBUTE_IS_TRAFFIC_LIGHT) ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_TINT_PALETTE_INDEX:
|
|
{
|
|
sprintf(str, "%d", pEntity->GetTintIndex());
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_CLIMBABLE_BY_AI:
|
|
{
|
|
sprintf(str, "%s", pEntity->GetBaseModelInfo()->GetIsClimbableByAI() ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_HAS_ADDED_LIGHTS:
|
|
{
|
|
sprintf(str, "%s", pEntity->m_nFlags.bLightObject ? "true" : "false");
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_IS_TARGETTABLE_WITH_NO_LOS:
|
|
{
|
|
if (pEntity->GetIsTypeObject())
|
|
{
|
|
sprintf(str, "%s", static_cast<CObject*>(pEntity)->m_nObjectFlags.bTargettableWithNoLos ? "true" : "false");
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
sprintf(str, "Unknown");
|
|
break;
|
|
}
|
|
}
|
|
case CDebugScene::GADGET_IS_A_TARGET_PRIORITY:
|
|
{
|
|
if (pEntity->GetIsTypeObject())
|
|
{
|
|
sprintf(str, "%s", static_cast<CObject*>(pEntity)->m_nObjectFlags.bIsATargetPriority ? "true" : "false");
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
sprintf(str, "Unknown");
|
|
break;
|
|
}
|
|
}
|
|
case CDebugScene::GADGET_CAN_BE_TARGETTED_BY_PLAYER:
|
|
{
|
|
if (pEntity->GetIsTypeObject())
|
|
{
|
|
sprintf(str, "%s", static_cast<CObject*>(pEntity)->m_nObjectFlags.bCanBeTargettedByPlayer ? "true" : "false");
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
sprintf(str, "Unknown");
|
|
break;
|
|
}
|
|
}
|
|
|
|
case CDebugScene::GADGET_IS_CULL_SMALL_SHADOWS:
|
|
{
|
|
sprintf(str, "%s", (pEntity->GetBaseFlags() & fwEntity::RENDER_SMALL_SHADOW) ? "false" : "true");
|
|
break;
|
|
}
|
|
|
|
case CDebugScene::GADGET_IS_DONT_CAST_SHADOWS:
|
|
{
|
|
const fwFlags16 &flags = pEntity->GetRenderPhaseVisibilityMask();
|
|
bool dontCastShadows = !flags.IsFlagSet(VIS_PHASE_MASK_CASCADE_SHADOWS) && !flags.IsFlagSet(VIS_PHASE_MASK_PARABOLOID_SHADOWS);
|
|
sprintf(str, "%s", dontCastShadows ? "true" : "false");
|
|
break;
|
|
}
|
|
|
|
case CDebugScene::GADGET_IS_RENDER_ONLY_IN_REFLECTIONS:
|
|
{
|
|
fwFlags16 &visibilityMask = pEntity->GetRenderPhaseVisibilityMask();
|
|
sprintf(str, "%s", ( visibilityMask & (u16)(~(VIS_PHASE_MASK_REFLECTIONS|VIS_PHASE_MASK_STREAMING))) ? "false" : "true" );
|
|
break;
|
|
}
|
|
|
|
case CDebugScene::GADGET_IS_DONT_RENDER_IN_REFLECTIONS:
|
|
{
|
|
fwFlags16 &visibilityMask = pEntity->GetRenderPhaseVisibilityMask();
|
|
const bool bIsRenderingInReflections = visibilityMask.AreAllFlagsSet(VIS_PHASE_MASK_REFLECTIONS);
|
|
sprintf(str, "%s", !bIsRenderingInReflections ? "true" : "false");
|
|
break;
|
|
}
|
|
|
|
case CDebugScene::GADGET_IS_RENDER_ONLY_IN_SHADOWS:
|
|
{
|
|
fwFlags16 &visibilityMask = pEntity->GetRenderPhaseVisibilityMask();
|
|
sprintf(str, "%s", (visibilityMask & (u16)(~(VIS_PHASE_MASK_SHADOWS|VIS_PHASE_MASK_STREAMING))) ? "false" : "true" );
|
|
break;
|
|
}
|
|
|
|
case CDebugScene::GADGET_IS_DONT_RENDER_IN_SHADOWS:
|
|
{
|
|
fwFlags16 &visibilityMask = pEntity->GetRenderPhaseVisibilityMask();
|
|
sprintf(str, "%s", (visibilityMask & VIS_PHASE_MASK_SHADOWS) ? "false" : "true");
|
|
break;
|
|
}
|
|
|
|
case CDebugScene::GADGET_LODGROUP_FLAGS:
|
|
{
|
|
const Drawable* pDrawable = pEntity->GetDrawable();
|
|
u32 fl00 = 0xFFFF;
|
|
u32 fl01 = 0xFFFF;
|
|
u32 fl02 = 0xFFFF;
|
|
u32 fl03 = 0xFFFF;
|
|
|
|
if( pDrawable )
|
|
{
|
|
fl00 = pDrawable->GetLodGroup().GetBucketMask(0);
|
|
fl01 = pDrawable->GetLodGroup().GetBucketMask(1);
|
|
fl02 = pDrawable->GetLodGroup().GetBucketMask(2);
|
|
fl03 = pDrawable->GetLodGroup().GetBucketMask(3);
|
|
}
|
|
|
|
sprintf(str, "%x - %x - %x - %x", fl00,fl01,fl02,fl03);
|
|
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_LODMASK_FLAGS:
|
|
{
|
|
u32 shadowFlag = (pEntity->GetPhaseLODs() >> LODDrawable::LODFLAG_SHIFT_SHADOW ) & LODDrawable::LODFLAG_MASK;
|
|
u32 reflectionFlag = (pEntity->GetPhaseLODs() >> LODDrawable::LODFLAG_SHIFT_REFLECTION ) & LODDrawable::LODFLAG_MASK;
|
|
u32 waterFlag = (pEntity->GetPhaseLODs() >> LODDrawable::LODFLAG_SHIFT_WATER ) & LODDrawable::LODFLAG_MASK;
|
|
u32 mirrorFlag = (pEntity->GetPhaseLODs() >> LODDrawable::LODFLAG_SHIFT_MIRROR ) & LODDrawable::LODFLAG_MASK;
|
|
u32 lastLODIdx = pEntity->GetLastLODIdx();
|
|
u32 AltFade = pEntity->GetUseAltFadeDistance() ? 1 : 0;
|
|
|
|
sprintf(str, "%d - %d - %x - %x - %x - %x", AltFade, lastLODIdx, shadowFlag, reflectionFlag, waterFlag, mirrorFlag);
|
|
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_IS_USED_IN_MP:
|
|
{
|
|
bool isUsedInMP = CMPObjectUsage::IsUsedInMP(pEntity);
|
|
sprintf(str, "%s", isUsedInMP ? "true" : "false");
|
|
break;
|
|
}
|
|
|
|
case CDebugScene::GADGET_IS_POPTYPE:
|
|
{
|
|
if(pEntity->GetIsPhysical())
|
|
{
|
|
CPhysical *pPhysical = static_cast<CPhysical*>(pEntity);
|
|
const char *pPopTypeName = CTheScripts::GetPopTypeName(pPhysical->PopTypeGet());
|
|
sprintf(str, "%s", pPopTypeName);
|
|
}
|
|
else
|
|
{
|
|
sprintf(str, "N/A");
|
|
}
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_OWNED_BY:
|
|
{
|
|
sprintf(str, "%d", (int)pEntity->GetOwnedBy());
|
|
break;
|
|
}
|
|
case CDebugScene::GADGET_REPLAY_ID:
|
|
{
|
|
#if GTA_REPLAY
|
|
if(pEntity->GetIsPhysical())
|
|
{
|
|
CPhysical *pPhysical = static_cast<CPhysical*>(pEntity);
|
|
sprintf(str, "0x%08X", pPhysical->GetReplayID().ToInt());
|
|
}
|
|
#endif // GTA_REPLAY
|
|
break;
|
|
}
|
|
|
|
case CDebugScene::GADGET_REPLAY_MAPHASH:
|
|
{
|
|
#if GTA_REPLAY
|
|
if(pEntity->GetIsTypeObject())
|
|
{
|
|
CObject *pObject = static_cast<CObject*>(pEntity);
|
|
if(pObject->GetRelatedDummy())
|
|
{
|
|
sprintf(str, "%u", pObject->GetRelatedDummy()->GetHash());
|
|
}
|
|
}
|
|
#endif // GTA_REPLAY
|
|
break;
|
|
}
|
|
|
|
case CDebugScene::GADGET_REPLAY_HIDECOUNT:
|
|
{
|
|
#if GTA_REPLAY
|
|
if(pEntity->GetIsTypeObject())
|
|
{
|
|
CObject *pObject = static_cast<CObject*>(pEntity);
|
|
if(pObject->GetRelatedDummy())
|
|
{
|
|
u32 hash = pObject->GetRelatedDummy()->GetHash();
|
|
CReplayID id;
|
|
FrameRef frameRef;
|
|
if(CReplayMgr::IsMapObjectExpectedToBeHidden(hash, id, frameRef))
|
|
{
|
|
sprintf(str, "0x%08X, %u:%u", id.ToInt(), frameRef.GetBlockIndex(), frameRef.GetFrame());
|
|
}
|
|
}
|
|
}
|
|
#endif // GTA_REPLAY
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
Assertf(false, "inspector gadget didn't handle case %i..", row);
|
|
sprintf(str, "???");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
pResult->SetString(str);
|
|
}
|
|
}
|
|
}
|
|
#endif // __BANK
|
|
|
|
const char *
|
|
CDebugScene::GetEntityDescription(const CEntity * pEntity)
|
|
{
|
|
switch(pEntity->GetType())
|
|
{
|
|
case ENTITY_TYPE_NOTHING:
|
|
return "Nothing";
|
|
case ENTITY_TYPE_BUILDING:
|
|
if(!pEntity->GetLodData().IsHighDetail())
|
|
return "Lod";
|
|
return "Building";
|
|
case ENTITY_TYPE_VEHICLE:
|
|
return "Vehicle";
|
|
case ENTITY_TYPE_PED:
|
|
return "Ped";
|
|
case ENTITY_TYPE_OBJECT:
|
|
return "Object";
|
|
case ENTITY_TYPE_DUMMY_OBJECT:
|
|
return "Dummy Object";
|
|
case ENTITY_TYPE_PORTAL:
|
|
return "Portal";
|
|
case ENTITY_TYPE_MLO:
|
|
return "MLO";
|
|
}
|
|
|
|
// if not handled above, get the 'official' type name ..
|
|
return GetEntityTypeStr(pEntity->GetType());
|
|
}
|
|
|
|
CEntity* CDebugScene::GetBestFilteredEntity(const FocusFilter& filter)
|
|
{
|
|
CEntity* pBestEntity = nullptr;
|
|
float bestScore = -100000.f;
|
|
const ScalarV sUpCloseDist(filter.upCloseDist);
|
|
const int iNumPeds = CPed::GetPool()->GetSize();
|
|
CPed* pLocalPlayer = CGameWorld::FindLocalPlayer();
|
|
for (int i = 0; i < iNumPeds; i++)
|
|
{
|
|
CPed* pPed = CPed::GetPool()->GetSlot(i);
|
|
const bool isAnimal = (pPed && CPedType::IsAnimalType(pPed->GetPedType()));
|
|
if (!pPed
|
|
|| FocusEntities_IsInGroup(pPed)
|
|
|| (filter.bDead != pPed->GetIsDeadOrDying())
|
|
|| (!filter.bPlayer && pPed == pLocalPlayer)
|
|
|| (!filter.bAnimal && isAnimal)
|
|
|| (!filter.bBird && pPed->GetCapsuleInfo() && pPed->GetCapsuleInfo()->IsBird())
|
|
|| (!filter.bHuman && !isAnimal && pPed != pLocalPlayer)
|
|
|| (filter.bRider && !pPed->GetVehiclePedInside())
|
|
)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const float score = filter.CalculateScore(pPed);
|
|
if (score > bestScore)
|
|
{
|
|
pBestEntity = pPed;
|
|
bestScore = score;
|
|
}
|
|
}
|
|
|
|
if (filter.bVehicle)
|
|
{
|
|
const int iNumVehicles = (int)CVehicle::GetPool()->GetSize();
|
|
for (int i = 0; i < iNumVehicles; i++)
|
|
{
|
|
CVehicle* pVehicle = CVehicle::GetPool()->GetSlot(i);
|
|
if (!pVehicle || FocusEntities_IsInGroup(pVehicle))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const float score = filter.CalculateScore(pVehicle);
|
|
if (score > bestScore)
|
|
{
|
|
pBestEntity = pVehicle;
|
|
bestScore = score;
|
|
}
|
|
}
|
|
}
|
|
return pBestEntity;
|
|
}
|
|
|
|
float CDebugScene::FocusFilter::CalculateScore(CEntity* pEntity) const
|
|
{
|
|
const Vec3V entPos(pEntity->GetTransform().GetPosition());
|
|
Vec3V toEnt(entPos - camPos);
|
|
const float dist = VEC3V_TO_VECTOR3(toEnt).Mag();
|
|
VEC3V_TO_VECTOR3(toEnt).NormalizeSafe();
|
|
const float dot = VEC3V_TO_VECTOR3(camFwd).Dot(VEC3V_TO_VECTOR3(toEnt));
|
|
const float dotScore = FPRangeClamp(dot, minDot, 1.f);
|
|
const float distScore = square(FPRamp(dist, 1.f, 120.f, 1.f, 0.f));
|
|
return dotScore + distScore;
|
|
}
|
|
|
|
void CDebugScene::FocusAddClosestAIPed(FocusFilter& filter)
|
|
{
|
|
// From the player or from in front of the camera
|
|
filter.camFwd = VECTOR3_TO_VEC3V(camInterface::GetFront());
|
|
filter.camPos = VECTOR3_TO_VEC3V(camInterface::GetPos());
|
|
if (!filter.bPlayer)
|
|
{
|
|
const Vec3V cameraFwd = filter.camFwd;
|
|
const Vec3V posCalc = VECTOR3_TO_VEC3V(CPlayerInfo::ms_cachedMainPlayerPos - camInterface::GetPos());
|
|
const float newPos = VEC3V_TO_VECTOR3(posCalc).Dot(VEC3V_TO_VECTOR3(cameraFwd));
|
|
filter.camPos += VECTOR3_TO_VEC3V(VEC3V_TO_VECTOR3(cameraFwd)* newPos);
|
|
}
|
|
if (camInterface::GetDebugDirector().IsFreeCamActive())
|
|
{
|
|
const camFrame& freeCam = camInterface::GetDebugDirector().GetFreeCamFrame();
|
|
filter.camPos = VECTOR3_TO_VEC3V(freeCam.GetPosition());
|
|
filter.camFwd = VECTOR3_TO_VEC3V(freeCam.GetFront());
|
|
}
|
|
|
|
CEntity* pEntity = GetBestFilteredEntity(filter);
|
|
if (!pEntity && filter.bPlayer)
|
|
{
|
|
pEntity = CGameWorld::FindLocalPlayer();
|
|
}
|
|
if (pEntity)
|
|
{
|
|
int index = -1;
|
|
FocusEntities_Add(pEntity, index);
|
|
#if DEBUG_DRAW
|
|
spdAABB bounds;
|
|
pEntity->GetAABB(bounds);
|
|
grcDebugDraw::BoxAxisAligned(bounds.GetMin(), bounds.GetMax(), Color_yellow, false, 30);
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
void CDebugScene::FocusEntities_Clear()
|
|
{
|
|
#if !__FINAL
|
|
for(int i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
|
|
{
|
|
FocusEntities_Set(NULL, i);
|
|
}
|
|
#endif // !__FINAL
|
|
}
|
|
bool CDebugScene::FocusEntities_IsEmpty()
|
|
{
|
|
#if !__FINAL
|
|
for(int i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
|
|
{
|
|
if(ms_focusEntities[i])
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
#endif // !__FINAL
|
|
return true;
|
|
}
|
|
CEntity* CDebugScene::FocusEntities_Get(int index)
|
|
{
|
|
if(index >= FOCUS_ENTITIES_MAX)
|
|
{
|
|
return NULL;
|
|
}
|
|
#if !__FINAL
|
|
return ms_focusEntities[index];
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
bool CDebugScene::FocusEntities_IsInGroup(const CEntity* const pEntity, int& NOTFINAL_ONLY(out_index))
|
|
{
|
|
if(!pEntity)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
#if !__FINAL
|
|
for(int i = 0; i < FOCUS_ENTITIES_MAX; ++i)
|
|
{
|
|
if(pEntity == ms_focusEntities[i])
|
|
{
|
|
out_index = i;
|
|
return true;
|
|
}
|
|
}
|
|
#endif // !__FINAL
|
|
|
|
return false;
|
|
}
|
|
bool CDebugScene::FocusEntities_IsInGroup(const CEntity* const pEntity)
|
|
{
|
|
int index = -1;
|
|
return FocusEntities_IsInGroup(pEntity, index);
|
|
}
|
|
bool CDebugScene::FocusEntities_IsNearGroup(Vec3V_In vPos, float fThreshold)
|
|
{
|
|
#if !__FINAL
|
|
const ScalarV fThresholdSq(square(fThreshold));
|
|
for(int i = 0; i < FOCUS_ENTITIES_MAX; ++i)
|
|
{
|
|
if(ms_focusEntities[i] && IsLessThanAll(DistSquared(vPos,ms_focusEntities[i]->GetTransform().GetPosition()),fThresholdSq))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
#endif // !__FINAL
|
|
return false;
|
|
}
|
|
bool CDebugScene::FocusEntities_Add(CEntity* NOTFINAL_ONLY(pEntity), int& NOTFINAL_ONLY(out_index))
|
|
{
|
|
#if !__FINAL
|
|
if(!FocusEntities_IsInGroup(pEntity, out_index))
|
|
{
|
|
for(int i = 0; i < FOCUS_ENTITIES_MAX; ++i)
|
|
{
|
|
if(!ms_focusEntities[i])
|
|
{
|
|
FocusEntities_Set(pEntity, i);
|
|
out_index = i;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
#endif // !__FINAL
|
|
|
|
return false;
|
|
}
|
|
|
|
extern char gCurrentDisplayObject[];
|
|
|
|
#if __DEV
|
|
XPARAM(displayobject);
|
|
#endif // __DEV
|
|
|
|
void CDebugScene::FocusEntities_Set(CEntity* NOTFINAL_ONLY(pEntity), int index)
|
|
{
|
|
if(index >= FOCUS_ENTITIES_MAX)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#if !__FINAL
|
|
// Make sure the old entity in this slot is visible.
|
|
if(ms_focusEntities[index])
|
|
{
|
|
if(ms_makeFocusEntitiesFlash)
|
|
{
|
|
ms_focusEntities[index]->SetIsVisibleForModule( SETISVISIBLE_MODULE_DEBUG, true );
|
|
}
|
|
}
|
|
|
|
if (index == 0)
|
|
{
|
|
aiTaskTree::ms_pFocusEntity = pEntity;
|
|
if (pEntity)
|
|
{
|
|
DR_ONLY( debugPlayback::TrackEntity(pEntity, false) );
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
bool bActualChange = (ms_focusEntities[index] != pEntity);
|
|
#endif
|
|
ms_focusEntities[index] = pEntity;
|
|
|
|
//******************************************************************
|
|
// Print out the entity's address here.
|
|
// This is because the in-game font printing doesn't work reliably
|
|
// enough in the CPedDebugVisualiser.
|
|
#if __BANK
|
|
const char * pType = "Unknown";
|
|
const char * pModelName = "Unknown";
|
|
if(pEntity)
|
|
{
|
|
pType = "Entity";
|
|
if(pEntity->GetIsTypePed()) pType = "Ped";
|
|
else if(pEntity->GetIsTypeVehicle()) pType = "Vehicle";
|
|
|
|
CBaseModelInfo* pModelInfo = pEntity->GetBaseModelInfo();
|
|
if(pModelInfo)
|
|
{
|
|
pModelName = pModelInfo->GetModelName();
|
|
}
|
|
}
|
|
|
|
#if __DEV
|
|
if (!PARAM_displayobject.Get())
|
|
{
|
|
strncpy(gCurrentDisplayObject, pModelName, STORE_NAME_LENGTH);
|
|
}
|
|
#endif
|
|
|
|
if (bActualChange)
|
|
{
|
|
Displayf("\n******************************************************************************************\n");
|
|
Displayf("Focus Changed - Type = %s. Model Name = %s. Address = 0x%p", pType, pModelName, pEntity);
|
|
if (pEntity && ms_logFocusEntitiesPosition)
|
|
{
|
|
Displayf("Focus Changed - Position = %.3f,%.3f,%.3f Roll = %.3f Pitch = %.3f Heading = %.3f", pEntity->GetTransform().GetPosition().GetXf(), pEntity->GetTransform().GetPosition().GetYf(), pEntity->GetTransform().GetPosition().GetZf(),
|
|
pEntity->GetTransform().GetRoll(), pEntity->GetTransform().GetPitch(), pEntity->GetTransform().GetHeading());
|
|
}
|
|
Displayf("\n******************************************************************************************\n");
|
|
}
|
|
#endif
|
|
|
|
OnChangeFocusEntity(index);
|
|
|
|
#if __BANK
|
|
NetworkDebug::UpdateFocusEntity(true);
|
|
#endif
|
|
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
#if !__FINAL
|
|
static const u32 atStringHashNone = ATSTRINGHASH("None", 0x1D632BA1);
|
|
#endif // !FINAL
|
|
void CDebugScene::HandleFocusEntityTextBoxChange(void)
|
|
{
|
|
#if !__FINAL
|
|
CEntity* pForceFocusEntity = NULL;
|
|
if(atStringHash(ms_focusEntity0AddressString) != atStringHashNone)
|
|
{
|
|
sscanf(ms_focusEntity0AddressString, "0x%p", &pForceFocusEntity);
|
|
}
|
|
if(pForceFocusEntity != FocusEntities_Get(0))
|
|
{
|
|
FocusEntities_Set(pForceFocusEntity, 0);
|
|
|
|
#if __DEV
|
|
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfo(pForceFocusEntity->GetModelId());
|
|
if(pModelInfo && pModelInfo->GetModelName())
|
|
{
|
|
formatf(ms_focusEntity0ModelInfoString, 64, "%s", pModelInfo->GetModelName());
|
|
}
|
|
#endif // __DEV
|
|
}
|
|
#endif // !FINAL
|
|
}
|
|
void CDebugScene::OnChangeFocusEntity(int NOTFINAL_ONLY(index))
|
|
{
|
|
#if !__FINAL
|
|
if(index != 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CEntity* pFocusEntity = FocusEntities_Get(0);
|
|
if(!pFocusEntity)
|
|
{
|
|
formatf(ms_focusEntity0AddressString, 64, "%s", "None");
|
|
|
|
DEV_ONLY( formatf(ms_focusEntity0ModelInfoString, 64, "%s", "None"); )
|
|
|
|
#if __BANK
|
|
CPedDebugVisualiserMenu::OnChangeFocusPedCB(NULL);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
formatf(ms_focusEntity0AddressString, 64, "0x%X", pFocusEntity);
|
|
#if __BANK
|
|
|
|
#if __DEV
|
|
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfo(pFocusEntity->GetModelId());
|
|
if(pModelInfo && pModelInfo->GetModelName())
|
|
{
|
|
formatf(ms_focusEntity0ModelInfoString, 64, "%s", pModelInfo->GetModelName());
|
|
}
|
|
#endif // __DEV
|
|
|
|
if(pFocusEntity->GetIsTypePed())
|
|
{
|
|
CPed* pFocusPed = static_cast<CPed*>(pFocusEntity);
|
|
CPedGroup* pGroup = pFocusPed->GetPedsGroup();
|
|
if(pGroup)
|
|
{
|
|
CPedDebugVisualiserMenu::m_iFormationComboIndex = pGroup->GetFormation()->GetFormationType();
|
|
CPedDebugVisualiserMenu::m_fFormationSpacing = pGroup->GetFormation()->GetSpacing();
|
|
}
|
|
|
|
CPedDebugVisualiserMenu::OnChangeFocusPedCB(pFocusPed);
|
|
}
|
|
else
|
|
{
|
|
CPedDebugVisualiserMenu::m_iFormationComboIndex = 0;
|
|
CPedDebugVisualiserMenu::m_fFormationSpacing = 0;
|
|
}
|
|
|
|
// Callback the list of interested systems to say there's been a change of focus entity
|
|
|
|
for (int i = 0; i < ms_callbacks.GetCount(); i++)
|
|
{
|
|
ms_callbacks[i].Call(CallbackData(pFocusEntity));
|
|
}
|
|
#endif // __BANK
|
|
aiTaskTree::ms_pFocusEntity = pFocusEntity;
|
|
}
|
|
#endif // !__FINAL
|
|
}
|
|
|
|
|
|
#if __DEV
|
|
void CDebugScene::UpdateAttachTest()
|
|
{
|
|
IF_COMMERCE_STORE_RETURN();
|
|
|
|
if(!(ms_bDrawAttachmentExtensions || ms_bDrawAttachmentEdges || ms_bDisplayAttachmentEdgeType || ms_bDisplayAttachmentEdgeData || ms_bDisplayUpdateRecords
|
|
|| ms_bRenderListOfAttachmentExtensions || ms_bDisplayAttachmentInvokingFile || ms_bDisplayAttachmentInvokingFunction || ms_bDisplayAttachmentPhysicsInfo))
|
|
{
|
|
//Avoid looping over all of the attachments if we'll render nothing
|
|
return;
|
|
}
|
|
|
|
if( ms_bDebugRenderAttachmentOfFocusEntitiesOnly )
|
|
{
|
|
for(int i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
|
|
{
|
|
if(FocusEntities_Get(i) && FocusEntities_Get(i)->GetIsPhysical())
|
|
{
|
|
fwAttachmentEntityExtension const * pAttachExt = static_cast<CPhysical*>(FocusEntities_Get(i))->GetAttachmentExtension();
|
|
|
|
if(pAttachExt)
|
|
pAttachExt->RenderDebug(ms_bDrawAttachmentExtensions, ms_bDrawAttachmentEdges, ms_bDisplayAttachmentEdgeType, ms_bDisplayAttachmentEdgeData, ms_bDisplayAttachmentInvokingFunction,
|
|
ms_bDisplayAttachmentInvokingFile, ms_bDisplayAttachmentPhysicsInfo, ms_bDisplayUpdateRecords, ms_fAttachmentNodeRadius, ms_fAttachmentNodeRelPosWorldUp, ms_fAttachmentNodeEntityDist);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int const n = fwAttachmentEntityExtension::GetPool()->GetSize();
|
|
const Vec2V attachmentListScreenPos(0.03f, 0.05f);
|
|
u32 lineNum = 0u;
|
|
|
|
for(s32 i = 0 ; i < n; i++)
|
|
{
|
|
fwAttachmentEntityExtension const * pAttachExt = fwAttachmentEntityExtension::GetPool()->GetSlot(i);
|
|
|
|
if(pAttachExt)
|
|
{
|
|
pAttachExt->RenderDebug(ms_bDrawAttachmentExtensions, ms_bDrawAttachmentEdges, ms_bDisplayAttachmentEdgeType, ms_bDisplayAttachmentEdgeData,
|
|
ms_bDisplayAttachmentInvokingFunction, ms_bDisplayAttachmentInvokingFile, ms_bDisplayAttachmentPhysicsInfo, ms_bDisplayUpdateRecords, ms_fAttachmentNodeRadius, ms_fAttachmentNodeRelPosWorldUp, ms_fAttachmentNodeEntityDist);
|
|
|
|
if(ms_bRenderListOfAttachmentExtensions && pAttachExt->GetAttachState() != ATTACH_STATE_NONE)
|
|
{
|
|
char printBuffer[1024];
|
|
snprintf(printBuffer, 1024, "%s. %s",
|
|
fwAttachmentEntityExtension::GetAttachStateString( pAttachExt->GetAttachState()), pAttachExt->DebugGetInvokingFunction() );
|
|
|
|
Vec2V lineScreenPos = attachmentListScreenPos + Vec2V(0.0f, 0.0125f * (float)lineNum++);
|
|
|
|
grcDebugDraw::Text(lineScreenPos, Color_black, printBuffer);
|
|
|
|
snprintf(printBuffer, 1024, " extension:0x%p. m_pThisEntity:0x%p(%s). m_pAttachParent:0x%p(%s)",
|
|
pAttachExt, pAttachExt->GetThisEntity(), pAttachExt->GetThisEntity()->GetArchetype()->GetModelName(),
|
|
pAttachExt->GetAttachParentForced(), pAttachExt->GetAttachParentForced() ? pAttachExt->GetAttachParentForced()->GetArchetype()->GetModelName() : "");
|
|
|
|
lineScreenPos = attachmentListScreenPos + Vec2V(0.0f, 0.0125f * (float)lineNum++);
|
|
|
|
grcDebugDraw::Text(lineScreenPos, Color_black, printBuffer);
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDebugScene::AttachFocusEntitiesTogether()
|
|
{
|
|
|
|
// Attach focus entity 0 to focus entity 1
|
|
// Will only work if both are physical
|
|
if(FocusEntities_Get(0) && FocusEntities_Get(0)->GetIsPhysical()
|
|
&& FocusEntities_Get(1) && FocusEntities_Get(1)->GetIsPhysical())
|
|
{
|
|
CPhysical* pPhys0 = static_cast<CPhysical*>(FocusEntities_Get(0));
|
|
CPhysical* pPhys1 = static_cast<CPhysical*>(FocusEntities_Get(1));
|
|
|
|
Matrix34 matRotate;
|
|
matRotate.DotTranspose(MAT34V_TO_MATRIX34(pPhys0->GetMatrix()),MAT34V_TO_MATRIX34(pPhys1->GetMatrix()));
|
|
Quaternion vPivot;
|
|
vPivot.FromMatrix34(matRotate);
|
|
|
|
u32 iAttachFlags = ATTACH_STATE_BASIC;
|
|
if(ms_bAttachFlagAutoDetachOnRagdoll)
|
|
iAttachFlags |= ATTACH_FLAG_AUTODETACH_ON_RAGDOLL;
|
|
if(ms_bAttachFlagCollisionOn)
|
|
iAttachFlags |= ATTACH_FLAG_COL_ON;
|
|
if(ms_bAttachFlagDeleteWithParent)
|
|
iAttachFlags |= ATTACH_FLAG_DELETE_WITH_PARENT;
|
|
|
|
pPhys0->AttachToPhysicalBasic(pPhys1,-1,iAttachFlags,&matRotate.d,&vPivot);
|
|
}
|
|
}
|
|
|
|
void CDebugScene::AttachFocusEntitiesTogetherPhysically()
|
|
{
|
|
|
|
// Attach focus entity 0 to focus entity 1
|
|
// Will only work if both are physical
|
|
if(FocusEntities_Get(0) && FocusEntities_Get(0)->GetIsPhysical()
|
|
&& FocusEntities_Get(1) && FocusEntities_Get(1)->GetIsPhysical())
|
|
{
|
|
CPhysical* pPhys0 = static_cast<CPhysical*>(FocusEntities_Get(0));
|
|
CPhysical* pPhys1 = static_cast<CPhysical*>(FocusEntities_Get(1));
|
|
|
|
u32 iAttachFlags = ATTACH_STATE_PHYSICAL | ATTACH_FLAG_POS_CONSTRAINT;
|
|
if(ms_bAttachFlagAutoDetachOnRagdoll)
|
|
iAttachFlags |= ATTACH_FLAG_AUTODETACH_ON_RAGDOLL;
|
|
if(ms_bAttachFlagCollisionOn)
|
|
iAttachFlags |= ATTACH_FLAG_COL_ON;
|
|
if(ms_bAttachFlagDeleteWithParent)
|
|
iAttachFlags |= ATTACH_FLAG_DELETE_WITH_PARENT;
|
|
if(ms_bAttachFlagRotConstraint)
|
|
iAttachFlags |= ATTACH_FLAG_ROT_CONSTRAINT;
|
|
|
|
pPhys0->AttachToPhysicalUsingPhysics(pPhys1,-1,-1,iAttachFlags, VEC3V_TO_VECTOR3(pPhys0->GetTransform().GetPosition()) ,0.0f);
|
|
}
|
|
}
|
|
|
|
void CDebugScene::AttachFocusEntitiesToWorld()
|
|
{
|
|
for(int i = 0; i < FOCUS_ENTITIES_MAX; i++)
|
|
{
|
|
if(FocusEntities_Get(i) && FocusEntities_Get(i)->GetIsPhysical())
|
|
{
|
|
u32 iAttachFlags = ATTACH_STATE_WORLD;
|
|
if(ms_bAttachFlagAutoDetachOnRagdoll)
|
|
iAttachFlags |= ATTACH_FLAG_AUTODETACH_ON_RAGDOLL;
|
|
if(ms_bAttachFlagCollisionOn)
|
|
iAttachFlags |= ATTACH_FLAG_COL_ON;
|
|
if(ms_bAttachFlagDeleteWithParent)
|
|
iAttachFlags |= ATTACH_FLAG_DELETE_WITH_PARENT;
|
|
|
|
Quaternion quat = QUATV_TO_QUATERNION(QuatVFromMat33V(FocusEntities_Get(i)->GetMatrix().GetMat33()));
|
|
static_cast<CPhysical*>(FocusEntities_Get(i))->AttachToWorldBasic(iAttachFlags,VEC3V_TO_VECTOR3(FocusEntities_Get(i)->GetTransform().GetPosition()),&quat);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDebugScene::DetachFocusEntity()
|
|
{
|
|
for(int i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
|
|
{
|
|
if(FocusEntities_Get(i) && FocusEntities_Get(i)->GetIsPhysical())
|
|
{
|
|
u16 iDetachFlags = 0;
|
|
if(ms_bDetachFlagActivatePhysics)
|
|
iDetachFlags |= DETACH_FLAG_ACTIVATE_PHYSICS;
|
|
if(ms_bDetachFlagApplyVelocity)
|
|
iDetachFlags |= DETACH_FLAG_APPLY_VELOCITY;
|
|
if(ms_bDetachFlagNoCollisionUntilClear)
|
|
iDetachFlags |= DETACH_FLAG_NO_COLLISION_UNTIL_CLEAR;
|
|
if(ms_bDetachFlagIgnoreSafePositionCheck)
|
|
iDetachFlags |= DETACH_FLAG_IGNORE_SAFE_POSITION_CHECK;
|
|
|
|
CPhysical* pPhysical = static_cast<CPhysical*>(FocusEntities_Get(i));
|
|
pPhysical->DetachFromParent(iDetachFlags);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDebugScene::DeleteFocusEntities()
|
|
{
|
|
for(int i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
|
|
{
|
|
if(FocusEntities_Get(i))
|
|
{
|
|
CGameWorld::RemoveEntity(FocusEntities_Get(i));
|
|
}
|
|
}
|
|
}
|
|
#endif // __DEV
|
|
|
|
|
|
//
|
|
// name: CDebugScene::RenderCollisionGeometry
|
|
// description:
|
|
void CDebugScene::RenderCollisionGeometry(void)
|
|
{
|
|
IF_COMMERCE_STORE_RETURN();
|
|
|
|
#if !__FINAL //No debug cameras in final builds.
|
|
camDebugDirector& debugDirector = camInterface::GetDebugDirector();
|
|
Vector3 vOrigin = debugDirector.IsFreeCamActive() ? debugDirector.GetFreeCamFrame().GetPosition() : CGameWorld::FindLocalPlayerCoors();
|
|
#else
|
|
Vector3 vOrigin = CGameWorld::FindLocalPlayerCoors();
|
|
#endif
|
|
|
|
phLevelNew * phLevel = CPhysics::GetLevel();
|
|
#if ENABLE_PHYSICS_LOCK
|
|
phIterator iterator(phIterator::PHITERATORLOCKTYPE_READLOCK);
|
|
#else // ENABLE_PHYSICS_LOCK
|
|
phIterator iterator;
|
|
#endif // ENABLE_PHYSICS_LOCK
|
|
|
|
// Use this option to get all objects matching the req'd state
|
|
iterator.InitCull_All();
|
|
iterator.SetStateIncludeFlags(phLevelNew::STATE_FLAG_FIXED);
|
|
|
|
u16 iIndexInLevel = phLevel->GetFirstCulledObject(iterator);
|
|
|
|
while(iIndexInLevel != phInst::INVALID_INDEX)
|
|
{
|
|
phInst * pInstance = phLevel->GetInstance(iIndexInLevel);
|
|
|
|
if(pInstance)
|
|
{
|
|
phArchetype * pArchetype = pInstance->GetArchetype();
|
|
const rage::phBound * pBound = pArchetype->GetBound();
|
|
|
|
if(pBound)
|
|
{
|
|
DrawBoundCollisionGeometry(vOrigin, pBound);
|
|
}
|
|
}
|
|
|
|
iIndexInLevel = phLevel->GetNextCulledObject(iterator);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// name: CDebugScene::DrawBoundCollisionGeometry
|
|
// description:
|
|
void CDebugScene::DrawBoundCollisionGeometry(const Vector3 & BANK_ONLY(vOrigin), const rage::phBound * BANK_ONLY(pBound))
|
|
{
|
|
#if __BANK
|
|
int iBoundType = pBound->GetType();
|
|
s32 r;
|
|
|
|
Vector3 vTriCentroid;
|
|
Vector3 vDiff;
|
|
float fDistSqr;
|
|
// static const float fOneThird = 1.0f / 3.0f;
|
|
static const float fMaxDistSqr = 30.0f * 30.0f;
|
|
int v;
|
|
|
|
switch(iBoundType)
|
|
{
|
|
// All of these exist as types and might want to draw one day
|
|
// Seems silly to just assert that they occur (in default condition below)
|
|
case phBound::CAPSULE:
|
|
USE_TAPERED_CAPSULE_ONLY(case phBound::TAPERED_CAPSULE:)
|
|
case phBound::BOX:
|
|
USE_GEOMETRY_CURVED_ONLY(case phBound::GEOMETRY_CURVED:)
|
|
USE_GRIDS_ONLY(case phBound::GRID:)
|
|
USE_RIBBONS_ONLY(case phBound::RIBBON:)
|
|
USE_SURFACES_ONLY(case phBound::SURFACE:)
|
|
case phBound::TRIANGLE:
|
|
case phBound::DISC:
|
|
case phBound::CYLINDER:
|
|
{
|
|
break;
|
|
}
|
|
case phBound::SPHERE:
|
|
{
|
|
// These spheres are just a byproduct of the export process (You can't create a
|
|
// composite simply by adding meshes). So we'll ignore them..
|
|
|
|
//rage::phBoundSphere * pSphere = (rage::phBoundSphere*)pBound;
|
|
//Color32 col(255,0,0,255);
|
|
//grcDebugDraw::Sphere(vBoundCenter.x, vBoundCenter.y, vBoundCenter.z, pSphere->GetRadius(), col);
|
|
break;
|
|
}
|
|
// all these bounds are derived from geometry
|
|
case phBound::BVH:
|
|
case phBound::GEOMETRY:
|
|
{
|
|
rage::phBoundGeometry * pGeom = (rage::phBoundGeometry*)pBound;
|
|
int iNumPolys = pGeom->GetNumPolygons();
|
|
|
|
for(int p=0; p<iNumPolys; p++)
|
|
{
|
|
const phPolygon & poly = pGeom->GetPolygon(p);
|
|
const rage::phPrimitive *curPrim = reinterpret_cast<const rage::phPrimitive *>(&poly);
|
|
// TODO -- Draw other types of bounds?
|
|
if(curPrim->GetType() == rage::PRIM_TYPE_POLYGON)
|
|
{
|
|
bool drawThis = false;
|
|
for(v=0; v<POLY_MAX_VERTICES; v++)
|
|
{
|
|
rage::phPolygon::Index vIndex0 = poly.GetVertexIndex(v);
|
|
Vector3 vert0 = VEC3V_TO_VECTOR3(pGeom->GetVertex(vIndex0));
|
|
fDistSqr = (vert0 - vOrigin).Mag2();
|
|
if(fDistSqr <= fMaxDistSqr)
|
|
{
|
|
drawThis = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(drawThis)
|
|
{
|
|
r = p * 8;
|
|
r &= 0xFF;
|
|
Color32 col(64,r,64,255);
|
|
|
|
int lastv = POLY_MAX_VERTICES-1;
|
|
for(v=0; v<POLY_MAX_VERTICES; v++)
|
|
{
|
|
rage::phPolygon::Index vIndex0 = poly.GetVertexIndex(lastv);
|
|
rage::phPolygon::Index vIndex1 = poly.GetVertexIndex(v);
|
|
Vector3 vert0 = VEC3V_TO_VECTOR3(pGeom->GetVertex(vIndex0));
|
|
Vector3 vert1 = VEC3V_TO_VECTOR3(pGeom->GetVertex(vIndex1));
|
|
grcDebugDraw::Line(vert0, vert1, col);
|
|
lastv = v;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case phBound::COMPOSITE:
|
|
{
|
|
rage::phBoundComposite * pComposite = (rage::phBoundComposite*)pBound;
|
|
int iNumBounds = pComposite->GetNumBounds();
|
|
|
|
for(int b=0; b<iNumBounds; b++)
|
|
{
|
|
phBound * pCompositeBound = pComposite->GetBound(b);
|
|
DrawBoundCollisionGeometry(vOrigin, pCompositeBound);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
Assert(0);
|
|
break;
|
|
}
|
|
}
|
|
#endif // __BANK
|
|
}
|
|
|
|
//
|
|
// name: CDebugScene::DrawEntityBoundingBox
|
|
// description: Draw a bounding box for an entity
|
|
void CDebugScene::DrawEntityBoundingBox(CEntity* pEntity, Color32 color, bool bDrawWorldAABB, bool bDrawGeometryBoxes)
|
|
{
|
|
Matrix34 matrix = MAT34V_TO_MATRIX34(pEntity->GetNonOrthoMatrix());
|
|
|
|
// Draw the bounding-box
|
|
Vector3 vMin, vMax;
|
|
if(pEntity->IsArchetypeSet())
|
|
{
|
|
if (bDrawGeometryBoxes)
|
|
{
|
|
const Drawable* pDrawable = pEntity->GetDrawable();
|
|
|
|
if (pDrawable)
|
|
{
|
|
const rmcLodGroup& group = pDrawable->GetLodGroup();
|
|
|
|
if (group.ContainsLod(LOD_HIGH))
|
|
{
|
|
const grmModel& model = group.GetLodModel0(LOD_HIGH);
|
|
const int numGeoms = model.GetGeometryCount();
|
|
|
|
if (numGeoms > 1)
|
|
{
|
|
for (int i = 0; i < numGeoms; i++)
|
|
{
|
|
const spdAABB& aabb = model.GetGeometryAABB(i);
|
|
const Vector3 vMin = VEC3V_TO_VECTOR3(aabb.GetMin());
|
|
const Vector3 vMax = VEC3V_TO_VECTOR3(aabb.GetMax());
|
|
|
|
Draw3DBoundingBox(vMin, vMax, matrix, color);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const spdAABB& aabb = model.GetModelAABB();
|
|
const Vector3 vMin = VEC3V_TO_VECTOR3(aabb.GetMin());
|
|
const Vector3 vMax = VEC3V_TO_VECTOR3(aabb.GetMax());
|
|
|
|
Draw3DBoundingBox(vMin, vMax, matrix, color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vMin = pEntity->GetBoundingBoxMin();
|
|
vMax = pEntity->GetBoundingBoxMax();
|
|
}
|
|
}
|
|
else if(pEntity->GetCurrentPhysicsInst())
|
|
{
|
|
vMin = VEC3V_TO_VECTOR3(pEntity->GetCurrentPhysicsInst()->GetArchetype()->GetBound()->GetBoundingBoxMin());
|
|
vMax = VEC3V_TO_VECTOR3(pEntity->GetCurrentPhysicsInst()->GetArchetype()->GetBound()->GetBoundingBoxMax());
|
|
}
|
|
else
|
|
return;
|
|
|
|
if (bDrawWorldAABB)
|
|
{
|
|
spdAABB temp(RCC_VEC3V(vMin), RCC_VEC3V(vMax));
|
|
temp.Transform(RCC_MAT34V(matrix));
|
|
vMin = VEC3V_TO_VECTOR3(temp.GetMin());
|
|
vMax = VEC3V_TO_VECTOR3(temp.GetMax());
|
|
matrix.Identity();
|
|
}
|
|
|
|
Draw3DBoundingBox(vMin, vMax, matrix, color);
|
|
}
|
|
|
|
|
|
//
|
|
// name: CDebugScene::Draw3DBoundingBox
|
|
// description: Draw a bounding box for an entity
|
|
void CDebugScene::Draw3DBoundingBox(const Vector3 & BANK_ONLY(vMin), const Vector3 & BANK_ONLY(vMax), const Matrix34 & BANK_ONLY(mat), Color32 BANK_ONLY(color))
|
|
{
|
|
#if __BANK
|
|
s32 v;
|
|
Vector3 vCorners[8] = {
|
|
Vector3(vMin.x, vMin.y, vMin.z), Vector3(vMax.x, vMin.y, vMin.z), Vector3(vMax.x, vMax.y, vMin.z), Vector3(vMin.x, vMax.y, vMin.z),
|
|
Vector3(vMin.x, vMin.y, vMax.z), Vector3(vMax.x, vMin.y, vMax.z), Vector3(vMax.x, vMax.y, vMax.z), Vector3(vMin.x, vMax.y, vMax.z)
|
|
};
|
|
for(v=0; v<8; v++)
|
|
mat.Transform(vCorners[v]);
|
|
|
|
for(v=0; v<4; v++)
|
|
{
|
|
grcDebugDraw::Line(vCorners[v], vCorners[(v+1)%4], color);
|
|
grcDebugDraw::Line(vCorners[v+4], vCorners[((v+1)%4)+4], color);
|
|
grcDebugDraw::Line(vCorners[v], vCorners[v+4], color);
|
|
}
|
|
#endif // __BANK
|
|
}
|
|
|
|
void CDebugScene::DrawEntitySubBounds(CEntity * pEntity, Color32 color)
|
|
{
|
|
phInst* pInst = pEntity->GetFragInst();
|
|
if(pInst==NULL)
|
|
pInst = pEntity->GetCurrentPhysicsInst();
|
|
|
|
phBound* pBound = pInst->GetArchetype()->GetBound();
|
|
Matrix34 currMat = RCC_MATRIX34(pInst->GetMatrix());
|
|
DrawSubBounds(pInst, pBound, &currMat, color);
|
|
|
|
/*
|
|
Matrix34 compoundMat;
|
|
phBound * pParentBound = pEntity->GetCurrentPhysicsInst()->GetArchetype()->GetBound();
|
|
|
|
if(pParentBound->GetType()==phBound::COMPOSITE)
|
|
{
|
|
phBoundComposite * pComposite = (phBoundComposite*)pParentBound;
|
|
int iNumComponents = pComposite->GetNumBounds();
|
|
for(int c=0; c<iNumComponents; c++)
|
|
{
|
|
const phBound * pSubBound = pComposite->GetBound(c);
|
|
const Matrix34 & subMat = pComposite->GetCurrentMatrix(c);
|
|
const Vector3 & vMin = pSubBound->GetBoundingBoxMin();
|
|
const Vector3 & vMax = pSubBound->GetBoundingBoxMax();
|
|
|
|
//compoundMat.Dot(subMat, pEntity->GetMatrix());
|
|
compoundMat.Dot(pEntity->GetMatrix(), subMat);
|
|
Draw3DBoundingBox(vMin, vMax, compoundMat, color);
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
void CDebugScene::DrawSubBounds(phInst *pInst, phBound* pBound, Matrix34* pCurrMat, Color32 color)
|
|
{
|
|
// recurse with any composite bounds
|
|
if (pBound->GetType() == phBound::COMPOSITE)
|
|
{
|
|
phBoundComposite* pBoundComposite = (phBoundComposite*)pBound;
|
|
for (s32 i=0; i<pBoundComposite->GetNumBounds(); i++)
|
|
{
|
|
// check this bound is still valid (smashable code may have removed it)
|
|
phBound* pChildBound = pBoundComposite->GetBound(i);
|
|
if (pChildBound)
|
|
{
|
|
// calc the new matrix
|
|
Matrix34 newMat = *pCurrMat;
|
|
Matrix34 thisMat = RCC_MATRIX34(pBoundComposite->GetCurrentMatrix(i));
|
|
newMat.DotFromLeft(thisMat);
|
|
|
|
// render the bound
|
|
DrawSubBounds(pInst, pChildBound, &newMat, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
const Vector3 & vMin = VEC3V_TO_VECTOR3(pBound->GetBoundingBoxMin());
|
|
const Vector3 & vMax = VEC3V_TO_VECTOR3(pBound->GetBoundingBoxMax());
|
|
|
|
Draw3DBoundingBox(vMin, vMax, *pCurrMat, color);
|
|
}
|
|
|
|
|
|
#if __DEV
|
|
void PrintBoundsInfo(phBound* pBound)
|
|
{
|
|
if(pBound==NULL)
|
|
return;
|
|
|
|
int nNumPolys = 0;
|
|
if(pBound->GetType()==phBound::GEOMETRY)
|
|
nNumPolys = ((phBoundGeometry*)pBound)->GetNumPolygons();
|
|
else if(pBound->GetType()==phBound::BVH)
|
|
nNumPolys = ((phBoundBVH*)pBound)->GetNumPolygons();
|
|
else if(pBound->GetType()==phBound::COMPOSITE)
|
|
nNumPolys = ((phBoundComposite*)pBound)->GetNumBounds();
|
|
|
|
grcDebugDraw::AddDebugOutput("Collision model type: %s, No. polys %d", pBound->GetTypeString(), nNumPolys);
|
|
|
|
// if this is a composite we want to itterate through the bounds it contains
|
|
if(pBound->GetType()==phBound::COMPOSITE)
|
|
{
|
|
phBoundComposite* pBoundComposite = (phBoundComposite*)pBound;
|
|
for(int i=0; i<pBoundComposite->GetNumBounds(); i++)
|
|
{
|
|
PrintBoundsInfo(pBoundComposite->GetBound(i));
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// name: CDebugScene::PrintInfoAboutEntity
|
|
// description:
|
|
void CDebugScene::PrintInfoAboutEntity(CEntity* pEntity)
|
|
{
|
|
CBaseModelInfo *pBMI = pEntity->GetBaseModelInfo();
|
|
if (pBMI)
|
|
{
|
|
#if DEBUG_DRAW
|
|
|
|
const Vector3 vEntityPosition = VEC3V_TO_VECTOR3(pEntity->GetTransform().GetPosition());
|
|
grcDebugDraw::AddDebugOutput(
|
|
"Looking at %s : %s (0x%x) MI:%d LOD:%d Collision:%d LevelIndex:%d Posn:%.1f,%.1f,%.1f Attr:%d",
|
|
GetEntityDescription(pEntity),
|
|
#if !__FINAL
|
|
(char*)pBMI->GetModelName(),
|
|
#else
|
|
"-",
|
|
#endif
|
|
pEntity,
|
|
pEntity->GetBaseModelInfo()->GetStreamSlot(),
|
|
(s32)pEntity->GetLodDistance(),
|
|
(pEntity->GetCurrentPhysicsInst() != NULL),
|
|
(pEntity->GetCurrentPhysicsInst() ? pEntity->GetCurrentPhysicsInst()->GetLevelIndex() : -1),
|
|
vEntityPosition.x, vEntityPosition.y, vEntityPosition.z,
|
|
pBMI->GetAttributes()
|
|
);
|
|
|
|
#endif // DEBUG_DRAW
|
|
|
|
#if __DEV
|
|
// print some info about the collision bounds
|
|
if(pEntity->GetPhysArch())
|
|
{
|
|
PrintBoundsInfo(pEntity->GetPhysArch()->GetBound());
|
|
}
|
|
#endif
|
|
|
|
if(pEntity->GetIsPhysical())
|
|
{
|
|
#if DEBUG_DRAW
|
|
CPhysical * pPhysical = (CPhysical*)pEntity;
|
|
if(pEntity->IsBaseFlagSet(fwEntity::IS_FIXED))
|
|
grcDebugDraw::AddDebugOutput("Entity is fixed");
|
|
else if(pPhysical->GetPhysArch())
|
|
grcDebugDraw::AddDebugOutput("Entity is NOT fixed, and has mass %.1f", pPhysical->GetMass());
|
|
#endif // DEBUG_DRAW
|
|
}
|
|
#if DEBUG_DRAW
|
|
u32 iPathServerID = DYNAMIC_OBJECT_INDEX_NONE;
|
|
if(pEntity->GetType() == ENTITY_TYPE_VEHICLE)
|
|
{
|
|
iPathServerID = ((CVehicle*)pEntity)->GetPathServerDynamicObjectIndex();
|
|
}
|
|
else if(pEntity->GetType() == ENTITY_TYPE_OBJECT)
|
|
{
|
|
iPathServerID = ((CObject*)pEntity)->GetPathServerDynamicObjectIndex();
|
|
}
|
|
if(iPathServerID != DYNAMIC_OBJECT_INDEX_NONE)
|
|
{
|
|
grcDebugDraw::AddDebugOutput("Entity is in PathServer (m_iPathServerDynObjId = %i)", iPathServerID);
|
|
}
|
|
if(pBMI->GetIsLadder())
|
|
{
|
|
grcDebugDraw::AddDebugOutput("Entity is a ladder object.");
|
|
}
|
|
if(pBMI->GetIsFixedForNavigation())
|
|
{
|
|
grcDebugDraw::AddDebugOutput("Entity is considered fixed for navigation purposes.");
|
|
}
|
|
if(pBMI->GetNotAvoidedByPeds())
|
|
{
|
|
grcDebugDraw::AddDebugOutput("Entity is marked as NOT AVOIDED BY PEDS.");
|
|
}
|
|
if(pBMI->GetDoesNotProvideAICover())
|
|
{
|
|
grcDebugDraw::AddDebugOutput("Entity is marked as NOT PROVIDING AI COVER.");
|
|
}
|
|
if(pBMI->TestAttribute(MODEL_ATTRIBUTE_IS_TRAFFIC_LIGHT))
|
|
{
|
|
grcDebugDraw::AddDebugOutput("Entity is marked with MODEL_ATTRIBUTE_IS_TRAFFIC_LIGHT.");
|
|
}
|
|
#endif // DEBUG_DRAW
|
|
} // if(pBMI != NULL)...
|
|
// found entity no CBaseModelInfo. It must be attached to a static bound
|
|
else
|
|
{
|
|
#if DEBUG_DRAW
|
|
#if !__FINAL
|
|
grcDebugDraw::AddDebugOutput("Static bound: %s %s", g_StaticBoundsStore.GetName(strLocalIndex(pEntity->GetIplIndex())), pEntity->GetCurrentPhysicsInst()->GetArchetype()->GetFilename());
|
|
#else
|
|
grcDebugDraw::AddDebugOutput("Static bound: %s", "-");
|
|
#endif
|
|
#endif // DEBUG_DRAW
|
|
#if __DEV
|
|
int nBoundType = pEntity->GetPhysArch()->GetBound()->GetType();
|
|
int nNumPolys = 0;
|
|
if(nBoundType==phBound::BVH)
|
|
nNumPolys = ((phBoundBVH*)pEntity->GetPhysArch()->GetBound())->GetNumPolygons();
|
|
else
|
|
Assertf(false, "Static bound is not an Octree or BVH bound!");
|
|
grcDebugDraw::AddDebugOutput("Collision model type: %s, No. polys %d", pEntity->GetPhysArch()->GetBound()->GetTypeString(), nNumPolys);
|
|
#endif // DEBUG_DRAW
|
|
}
|
|
|
|
}// end of PrintInfoAboutEntity()...
|
|
|
|
#if __BANK
|
|
void CDebugScene::PrintCoverTuningForEntity(CEntity* pEntity)
|
|
{
|
|
if( pEntity && pEntity->GetIsTypeObject() )
|
|
{
|
|
CObject* pObject = static_cast<CObject*>(pEntity);
|
|
const CBaseModelInfo* pModelInfo = pObject->GetBaseModelInfo();
|
|
if( pModelInfo )
|
|
{
|
|
const CCoverTuning& coverTuning = CCoverTuningManager::GetInstance().GetTuningForModel(pModelInfo->GetModelNameHash());
|
|
Vector3 vecPosition = VEC3V_TO_VECTOR3(pObject->GetTransform().GetPosition());
|
|
vecPosition.x = rage::Floorf(vecPosition.x + 0.5f);
|
|
vecPosition.y = rage::Floorf(vecPosition.y + 0.5f);
|
|
vecPosition.z = rage::Floorf(vecPosition.z + 0.5f);
|
|
|
|
const char* tuningName = CCoverTuningManager::GetInstance().FindNameForTuning(coverTuning);
|
|
|
|
grcDebugDraw::AddDebugOutput("Model: %s, Cover Tuning: %s", pObject->GetModelName(), tuningName);
|
|
}
|
|
}
|
|
}
|
|
#endif // __BANK
|
|
|
|
|
|
//
|
|
// name: CDebugScene::Draw3DBoundingBoxOnVMap
|
|
// description: Draw a bounding box for an entity on the vector map.
|
|
void CDebugScene::DrawEntityBoundingBoxOnVMap(CEntity* pEntity, Color32 colour)
|
|
{
|
|
// Draw the bounding-box
|
|
|
|
spdAABB localBox;
|
|
if(pEntity->IsArchetypeSet())
|
|
{
|
|
const Vec3V vMin = RCC_VEC3V(pEntity->GetBoundingBoxMin());
|
|
const Vec3V vMax = RCC_VEC3V(pEntity->GetBoundingBoxMax());
|
|
localBox.Set(vMin, vMax);
|
|
}
|
|
else if(pEntity->GetCurrentPhysicsInst())
|
|
{
|
|
const Vec3V vMin = pEntity->GetCurrentPhysicsInst()->GetArchetype()->GetBound()->GetBoundingBoxMin();
|
|
const Vec3V vMax = pEntity->GetCurrentPhysicsInst()->GetArchetype()->GetBound()->GetBoundingBoxMax();
|
|
localBox.Set(vMin, vMax);
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
spdAABB box = localBox;
|
|
box.Transform(pEntity->GetMatrix());
|
|
fwVectorMap::Draw3DBoundingBoxOnVMap(box, colour);
|
|
}
|
|
|
|
|
|
//
|
|
// name: CDebugScene::GetMouse0to1
|
|
// description: Returns where the mouse is pointing as a 2d screen vector in 0 to 1 space.
|
|
Vector2 CDebugScene::GetMouse0to1(void)
|
|
{
|
|
// Get the raw mouse position.
|
|
const float mouseScreenX = static_cast<float>(ioMouse::GetX());
|
|
const float mouseScreenY = static_cast<float>(ioMouse::GetY());
|
|
|
|
// Convert the mouse position into screen o to 1 coordinates.
|
|
const float mouseScreen0to1X = mouseScreenX / grcViewport::GetDefaultScreen()->GetWidth();
|
|
const float mouseScreen0to1Y = mouseScreenY / grcViewport::GetDefaultScreen()->GetHeight();
|
|
|
|
// Hand back the 2d screen vector in 0 to one space.
|
|
return Vector2(mouseScreen0to1X, mouseScreen0to1Y);
|
|
}
|
|
|
|
|
|
//
|
|
// name: CDebugScene::GetMouseLeftPressed
|
|
// description: Returns whether the left mouse button has been clicked this frame.
|
|
bool CDebugScene::GetMouseLeftPressed(void)
|
|
{
|
|
return (ioMouse::GetPressedButtons()&ioMouse::MOUSE_LEFT);
|
|
}
|
|
bool CDebugScene::GetMouseLeftReleased(void)
|
|
{
|
|
return (ioMouse::GetReleasedButtons()&ioMouse::MOUSE_LEFT);
|
|
}
|
|
|
|
//
|
|
// name: CDebugScene::GetMouseRightPressed
|
|
// description: Returns whether the left mouse button has been clicked this frame.
|
|
bool CDebugScene::GetMouseRightPressed(void)
|
|
{
|
|
return (ioMouse::GetPressedButtons()&ioMouse::MOUSE_RIGHT) != 0;
|
|
}
|
|
|
|
bool CDebugScene::GetMouseRightReleased(void)
|
|
{
|
|
return (ioMouse::GetReleasedButtons()&ioMouse::MOUSE_RIGHT) != 0;
|
|
}
|
|
|
|
bool CDebugScene::GetMouseMiddlePressed(void)
|
|
{
|
|
return (ioMouse::GetPressedButtons()&ioMouse::MOUSE_MIDDLE) != 0;
|
|
}
|
|
|
|
bool CDebugScene::GetMouseMiddleReleased(void)
|
|
{
|
|
return (ioMouse::GetReleasedButtons()&ioMouse::MOUSE_MIDDLE) != 0;
|
|
}
|
|
|
|
//
|
|
// name: CDebugScene::GetMousePointing
|
|
// description: Returns where the mouse is pointing
|
|
void CDebugScene::GetMousePointing( Vector3& vMouseNear, Vector3& vMouseFar, bool onVectorMap )
|
|
{
|
|
// Get where the mouse is pointing as a 2d screen vector in 0 to 1 space.
|
|
Vector2 mouseScreen0to1 = CDebugScene::GetMouse0to1();
|
|
|
|
if(onVectorMap)
|
|
{
|
|
|
|
// Convert the screen0to1 coordinates into World coordinates.
|
|
float mouseWorldX=0;
|
|
float mouseWorldY=0;
|
|
CVectorMap::ConvertPointMapToWorld(mouseScreen0to1.x, mouseScreen0to1.y, mouseWorldX, mouseWorldY);
|
|
|
|
const Vector3 clickPosWorldFlat(mouseWorldX, mouseWorldY, 0.0f);
|
|
|
|
vMouseNear.Set(clickPosWorldFlat.x, clickPosWorldFlat.y, 1000.0f);
|
|
vMouseFar.Set(clickPosWorldFlat.x, clickPosWorldFlat.y, -1000.0f);
|
|
}
|
|
else
|
|
{
|
|
// Fix for reverse transform not working with scaled window
|
|
const float viewportX = mouseScreen0to1.x * gVpMan.GetGameViewport()->GetGrcViewport().GetWidth();
|
|
const float viewportY = mouseScreen0to1.y * gVpMan.GetGameViewport()->GetGrcViewport().GetHeight();
|
|
|
|
gVpMan.GetGameViewport()->GetGrcViewport().ReverseTransform(viewportX, viewportY, (Vec3V&)vMouseNear, (Vec3V&)vMouseFar);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Name CDebugScene::GetWorldPosIn
|
|
// Returns a world point in screen space
|
|
void CDebugScene::GetScreenPosFromWorldPoint(const Vector3& vWorldPos, float& fWindowX, float& fWindowY)
|
|
{
|
|
gVpMan.GetGameViewport()->GetGrcViewport().Transform((Vec3V&)vWorldPos, fWindowX, fWindowY);
|
|
|
|
fWindowX=( fWindowX*grcViewport::GetDefaultScreen()->GetWidth() ) /gVpMan.GetGameViewport()->GetGrcViewport().GetWidth();
|
|
fWindowY=( fWindowY*grcViewport::GetDefaultScreen()->GetHeight() ) /gVpMan.GetGameViewport()->GetGrcViewport().GetHeight();
|
|
|
|
}
|
|
|
|
//
|
|
// name: CDebugScene::GetWorldPositionUnderMouse
|
|
// description: Return the world position under the mouse pointer
|
|
bool CDebugScene::GetWorldPositionFromScreenPos(float &fScreenX, float &fScreenY, Vector3& posn, s32 iOptionalFlags, Vector3* pvNormal, void **entity)
|
|
{
|
|
Vector3 vMouseNear, vMouseFar;
|
|
|
|
fScreenX=( fScreenX/grcViewport::GetDefaultScreen()->GetWidth() ) *gVpMan.GetGameViewport()->GetGrcViewport().GetWidth();
|
|
fScreenY=( fScreenY/grcViewport::GetDefaultScreen()->GetHeight() ) *gVpMan.GetGameViewport()->GetGrcViewport().GetHeight();
|
|
|
|
|
|
gVpMan.GetGameViewport()->GetGrcViewport().ReverseTransform(fScreenX, fScreenY,(Vec3V&)vMouseNear,(Vec3V&)vMouseFar);
|
|
|
|
|
|
if(iOptionalFlags == 0)
|
|
{
|
|
iOptionalFlags = ArchetypeFlags::GTA_ALL_TYPES_MOVER;
|
|
}
|
|
|
|
// check for nans in position passed in.
|
|
if(vMouseNear==vMouseNear && vMouseFar==vMouseFar)
|
|
{
|
|
WorldProbe::CShapeTestProbeDesc probeDesc;
|
|
WorldProbe::CShapeTestFixedResults<> probeResult;
|
|
probeDesc.SetResultsStructure(&probeResult);
|
|
probeDesc.SetStartAndEnd(vMouseNear, vMouseFar);
|
|
probeDesc.SetIncludeFlags(iOptionalFlags);
|
|
if(WorldProbe::GetShapeTestManager()->SubmitTest(probeDesc))
|
|
{
|
|
posn = probeResult[0].GetHitPosition();
|
|
|
|
phInst* pInst = probeResult[0].GetHitInst();
|
|
if( pInst )
|
|
{
|
|
CEntity* pEntity = CPhysics::GetEntityFromInst(pInst);
|
|
if( pEntity && entity)
|
|
*entity = pEntity;
|
|
}
|
|
|
|
if( pvNormal )
|
|
{
|
|
*pvNormal = probeResult[0].GetHitNormal();
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// name: CDebugScene::GetEntityUnderMouse
|
|
// description: Return the entity under the mouse pointer
|
|
CEntity* CDebugScene::GetEntityUnderMouse( Vector3* pvOptionalIntersectionPosition, s32* piOptionalComponent, s32 iOptionalFlags)
|
|
{
|
|
Vector3 mouseStart, mouseEnd;
|
|
GetMousePointing(mouseStart, mouseEnd, ms_doClickTestsViaVectorMapInsteadViewport);
|
|
if( ms_doClickTestsViaVectorMapInsteadViewport &&
|
|
GetMouseLeftPressed())
|
|
{
|
|
// Draw a temporal marker to show where we clicked.
|
|
const Vector3 pos((mouseStart + mouseEnd) * 0.5f);
|
|
const Color32 col(255,255,255,255);
|
|
const float finalRadius = 40.0f;
|
|
const u32 lifetime = 2000;
|
|
CVectorMap::MakeEventRipple( pos,
|
|
finalRadius,// Final radius in meters.
|
|
lifetime,// Lifetime in milliseconds.
|
|
col);
|
|
}
|
|
|
|
Vector3 StartPos;
|
|
|
|
if( iOptionalFlags == 0 )
|
|
{
|
|
iOptionalFlags = ArchetypeFlags::GTA_ALL_TYPES_MOVER | ArchetypeFlags::GTA_PROJECTILE_TYPE | ArchetypeFlags::GTA_PLANT_TYPE;
|
|
}
|
|
#if __DEV
|
|
if(!rage::FPIsFinite(mouseStart.x) || !rage::FPIsFinite(mouseStart.y) || !rage::FPIsFinite(mouseStart.z))
|
|
return NULL;
|
|
if(!rage::FPIsFinite(mouseEnd.x) || !rage::FPIsFinite(mouseEnd.y) || !rage::FPIsFinite(mouseEnd.z))
|
|
return NULL;
|
|
#endif
|
|
|
|
WorldProbe::CShapeTestProbeDesc probeDesc;
|
|
WorldProbe::CShapeTestFixedResults<> probeResult;
|
|
probeDesc.SetResultsStructure(&probeResult);
|
|
probeDesc.SetStartAndEnd(mouseStart, mouseEnd);
|
|
probeDesc.SetIncludeFlags(iOptionalFlags);
|
|
probeDesc.SetTypeFlags(TYPE_FLAGS_ALL);
|
|
if(WorldProbe::GetShapeTestManager()->SubmitTest(probeDesc))
|
|
{
|
|
if( pvOptionalIntersectionPosition )
|
|
{
|
|
*pvOptionalIntersectionPosition = probeResult[0].GetHitPosition();
|
|
}
|
|
if( piOptionalComponent )
|
|
{
|
|
*piOptionalComponent = (u16) probeResult[0].GetHitComponent();
|
|
}
|
|
return CPhysics::GetEntityFromInst(probeResult[0].GetHitInst());
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void CDebugScene::UpdateFocusEntityDragging()
|
|
{
|
|
IF_COMMERCE_STORE_RETURN();
|
|
|
|
#if __BANK
|
|
Vector3 thisFrameWorldPosition(VEC3_ZERO);
|
|
|
|
//right click and drag the mouse to alter the entity heading
|
|
if (ioMouse::GetButtons() & ioMouse::MOUSE_RIGHT)
|
|
{
|
|
if(!(ioMapper::DebugKeyDown(KEY_UP) || ioMapper::DebugKeyDown(KEY_RIGHT))) //check that we are not rotating round another axis
|
|
{
|
|
CEntity* pEntity = FocusEntities_Get(0);
|
|
if (pEntity)
|
|
{
|
|
|
|
TUNE_GROUP_FLOAT(DEBUG_RENDER, rotationMarkerBoundRadiusMult, 1.0f, 0.001f, 10.0f,0.001f);
|
|
Matrix34 debugAxis = MAT34V_TO_MATRIX34(pEntity->GetMatrix());
|
|
debugAxis.d.z+=pEntity->GetBoundingBoxMax().z;
|
|
grcDebugDraw::Axis(debugAxis, pEntity->GetBoundRadius()*rotationMarkerBoundRadiusMult, true);
|
|
|
|
// if there's been a change in the mouse x, rotate the entities heading
|
|
if (GetMouseDX()!=0)
|
|
{
|
|
TUNE_GROUP_FLOAT( DEBUG_CONTROL, focusEntityRotationSensitivity, 0.01f, 0.0001f, 0.5f,0.001f);
|
|
float newHeading = pEntity->GetTransform().GetHeading() + ( (float)(GetMouseDX())*focusEntityRotationSensitivity );
|
|
float fRotateAngle = ( (float)(GetMouseDX())*focusEntityRotationSensitivity );
|
|
|
|
if (newHeading < -PI)
|
|
{
|
|
newHeading = (TWO_PI + newHeading);
|
|
}
|
|
else if (newHeading > PI)
|
|
{
|
|
newHeading = (-TWO_PI + newHeading);
|
|
}
|
|
|
|
if (pEntity->GetIsTypePed())
|
|
{
|
|
CPed* pPed = static_cast<CPed*>(pEntity);
|
|
if (pPed)
|
|
{
|
|
#if __BANK
|
|
if (CAnimPlacementEditor::IsUsingPed(pPed))
|
|
{
|
|
CAnimPlacementEditor::RotateTool(pPed, ( (float)(GetMouseDX())*focusEntityRotationSensitivity ));
|
|
}
|
|
else
|
|
#endif // __BANK
|
|
{
|
|
pPed->SetHeading(newHeading);
|
|
pPed->SetDesiredHeading(newHeading);
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//instead of setting its heading just rotate round the z axis
|
|
Matrix34 mMat = MAT34V_TO_MATRIX34(pEntity->GetMatrix());
|
|
mMat.RotateLocalZ(fRotateAngle);
|
|
pEntity->SetMatrix(mMat);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//Rotate the object round its local y axis
|
|
if (ioMouse::GetButtons() & ioMouse::MOUSE_RIGHT && ioMapper::DebugKeyDown(KEY_UP))
|
|
{
|
|
CEntity* pEntity = FocusEntities_Get(0);
|
|
if (pEntity)
|
|
{
|
|
if (!pEntity->GetIsTypePed())
|
|
{
|
|
TUNE_GROUP_FLOAT( DEBUG_CONTROL, focusEntityRotationSensitivity, 0.01f, 0.0001f, 0.5f,0.001f);
|
|
float fRotateAngle = ( (float)(GetMouseDX())*focusEntityRotationSensitivity );
|
|
|
|
|
|
TUNE_GROUP_FLOAT(DEBUG_RENDER, rotationMarkerBoundRadiusMult, 1.0f, 0.001f, 10.0f,0.001f);
|
|
Matrix34 debugAxis = MAT34V_TO_MATRIX34(pEntity->GetMatrix());
|
|
debugAxis.d.z+=pEntity->GetBoundingBoxMax().z;
|
|
grcDebugDraw::Axis(debugAxis, pEntity->GetBoundRadius()*rotationMarkerBoundRadiusMult, true);
|
|
|
|
|
|
Matrix34 mMat = MAT34V_TO_MATRIX34(pEntity->GetMatrix());
|
|
mMat.RotateLocalY(fRotateAngle);
|
|
pEntity->SetMatrix(mMat);
|
|
}
|
|
}
|
|
}
|
|
|
|
//Rotate the object round its local y axis
|
|
if (ioMouse::GetButtons() & ioMouse::MOUSE_RIGHT && ioMapper::DebugKeyDown(KEY_RIGHT))
|
|
{
|
|
CEntity* pEntity = FocusEntities_Get(0);
|
|
if (pEntity)
|
|
{
|
|
if (!pEntity->GetIsTypePed())
|
|
{
|
|
TUNE_GROUP_FLOAT( DEBUG_CONTROL, focusEntityRotationSensitivity, 0.01f, 0.0001f, 0.5f,0.001f);
|
|
float fRotateAngle = ( (float)(GetMouseDX())*focusEntityRotationSensitivity );
|
|
|
|
|
|
TUNE_GROUP_FLOAT(DEBUG_RENDER, rotationMarkerBoundRadiusMult, 1.0f, 0.001f, 10.0f,0.001f);
|
|
Matrix34 debugAxis = MAT34V_TO_MATRIX34(pEntity->GetMatrix());
|
|
debugAxis.d.z+=pEntity->GetBoundingBoxMax().z;
|
|
grcDebugDraw::Axis(debugAxis, pEntity->GetBoundRadius()*rotationMarkerBoundRadiusMult, true);
|
|
|
|
Matrix34 mMat = MAT34V_TO_MATRIX34(pEntity->GetMatrix());
|
|
mMat.RotateLocalX(fRotateAngle);
|
|
pEntity->SetMatrix(mMat);
|
|
}
|
|
}
|
|
}
|
|
// hold middle mouse and drag vertically to alter entity z
|
|
if (ioMouse::GetButtons() & ioMouse::MOUSE_MIDDLE || ioMapper::DebugKeyDown(KEY_LSHIFT) || ioMapper::DebugKeyDown(KEY_RSHIFT) )
|
|
{
|
|
CEntity* pEntity = FocusEntities_Get(0);
|
|
if (pEntity)
|
|
{
|
|
//draw a line to represent the movement axis
|
|
const Vector3 vEntityPosition = VEC3V_TO_VECTOR3(pEntity->GetTransform().GetPosition());
|
|
grcDebugDraw::Line(vEntityPosition - Vector3(0.0f,0.0f,100.0f), vEntityPosition + Vector3(0.0f,0.0f,100.0f),Color_blue);
|
|
|
|
// if there's been a change in the mouse y, change the entity height
|
|
if (GetMouseDY()!=0)
|
|
{
|
|
TUNE_GROUP_FLOAT( DEBUG_CONTROL, focusEntityZSensitivity, 0.02f, 0.0001f, 2.0f,0.001f);
|
|
float deltaZ = -( (float)(GetMouseDY())*focusEntityZSensitivity );
|
|
|
|
CPed* pPed = static_cast<CPed*>(pEntity);
|
|
if (pPed)
|
|
{
|
|
#if __BANK
|
|
if (CAnimPlacementEditor::IsUsingPed(pPed))
|
|
{
|
|
CAnimPlacementEditor::TranslateTool(pPed,Vector3(0.0f,0.0f,deltaZ));
|
|
}
|
|
else
|
|
#endif // __BANK
|
|
{
|
|
pPed->SetPosition(vEntityPosition+Vector3(0.0f,0.0f,deltaZ), true, true, true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pEntity->SetPosition(vEntityPosition+Vector3(0.0f,0.0f,deltaZ));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Click and drag the mouse to move the entity around
|
|
if (ioMouse::GetButtons() & ioMouse::MOUSE_LEFT)
|
|
{
|
|
CEntity* pEntity = FocusEntities_Get(0);
|
|
int archetypeFlags;
|
|
Vector3 groundPosition(VEC3_ZERO);
|
|
Vector3 groundOffset(VEC3_ZERO);
|
|
|
|
if (pEntity)
|
|
{
|
|
|
|
archetypeFlags = GetArchetypeFlags(pEntity);
|
|
|
|
switch(pEntity->GetType())
|
|
{
|
|
case ENTITY_TYPE_PED:
|
|
{
|
|
groundOffset.z = static_cast<CPed*>(pEntity)->GetCapsuleInfo()->GetGroundToRootOffset();
|
|
}
|
|
break;
|
|
|
|
case ENTITY_TYPE_VEHICLE:
|
|
{
|
|
CVehicle* pVehicle = static_cast<CVehicle*>(pEntity);
|
|
groundOffset.z = -pVehicle->GetBoundingBoxMin().z;
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
//test for the ground under the entities current position and get the z offset
|
|
WorldProbe::CShapeTestProbeDesc probeDesc;
|
|
WorldProbe::CShapeTestFixedResults<> probeResult;
|
|
probeDesc.SetResultsStructure(&probeResult);
|
|
const Vector3 vEntityPosition = VEC3V_TO_VECTOR3(pEntity->GetTransform().GetPosition());
|
|
probeDesc.SetStartAndEnd(vEntityPosition, vEntityPosition - Vector3(0.0f,0.0f,1000.0f));
|
|
probeDesc.SetIncludeFlags(archetypeFlags);
|
|
probeDesc.SetExcludeEntity(pEntity);
|
|
if(WorldProbe::GetShapeTestManager()->SubmitTest(probeDesc))
|
|
{
|
|
groundOffset = (vEntityPosition - probeResult[0].GetHitPosition());
|
|
}
|
|
}
|
|
}
|
|
|
|
if(GetWorldPositionUnderMouse(thisFrameWorldPosition, archetypeFlags))
|
|
{
|
|
Vector2 thisFrameScreenPos, lastFrameScreenPos, adjustedPedScreenPos;
|
|
|
|
GetScreenPosFromWorldPoint(thisFrameWorldPosition, thisFrameScreenPos.x, thisFrameScreenPos.y); //convert our second point to screen
|
|
GetScreenPosFromWorldPoint(ms_lastFrameWorldPosition, lastFrameScreenPos.x, lastFrameScreenPos.y); //convert our first point to screen
|
|
|
|
GetScreenPosFromWorldPoint(VEC3V_TO_VECTOR3(pEntity->GetTransform().GetPosition()) - groundOffset, adjustedPedScreenPos.x, adjustedPedScreenPos.y); //convert our the ped point on screen, get his feet pos for correct line probe test
|
|
|
|
adjustedPedScreenPos = adjustedPedScreenPos + (thisFrameScreenPos - lastFrameScreenPos ); //convert final position in screen space
|
|
|
|
if (GetWorldPositionFromScreenPos(adjustedPedScreenPos.x, adjustedPedScreenPos.y, groundPosition, archetypeFlags))
|
|
{
|
|
//the mouse position has moved so update the ped
|
|
if (MouseMovedThisFrame())
|
|
{
|
|
switch(pEntity->GetType())
|
|
{
|
|
case ENTITY_TYPE_PED:
|
|
{
|
|
#if __BANK
|
|
CPed* pPed = static_cast<CPed*>(pEntity);
|
|
|
|
// check if this is a placement tool ped, if so we shouldn't update it
|
|
if (!CAnimPlacementEditor::IsUsingPed(pPed))
|
|
{
|
|
pPed->Teleport(groundPosition+groundOffset, pPed->GetTransform().GetHeading());
|
|
}
|
|
#endif // __BANK
|
|
}
|
|
break;
|
|
|
|
case ENTITY_TYPE_VEHICLE:
|
|
{
|
|
CVehicle* pVehicle = static_cast<CVehicle*>(pEntity);
|
|
pVehicle->Teleport(groundPosition+groundOffset, pVehicle->GetTransform().GetHeading());
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
pEntity->SetPosition(groundPosition+groundOffset);
|
|
}
|
|
}
|
|
}
|
|
ms_lastFrameWorldPosition = thisFrameWorldPosition;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif // __BANK
|
|
}
|
|
|
|
int CDebugScene::GetArchetypeFlags(CEntity* pEntity)
|
|
{
|
|
switch(pEntity->GetType())
|
|
{
|
|
case ENTITY_TYPE_VEHICLE:
|
|
{
|
|
return (ArchetypeFlags::GTA_MAP_TYPE_MOVER | ArchetypeFlags::GTA_OBJECT_TYPE);
|
|
}
|
|
default:
|
|
{
|
|
return (ArchetypeFlags::GTA_MAP_TYPE_MOVER | ArchetypeFlags::GTA_VEHICLE_TYPE | ArchetypeFlags::GTA_OBJECT_TYPE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// name: CDebugScene::GetWorldPositionUnderMouse
|
|
// description: Return the world position under the mouse pointer
|
|
bool CDebugScene::GetWorldPositionUnderMouse(Vector3& posn, s32 iOptionalFlags, Vector3* pvNormal, void **entity, bool onVectorMap )
|
|
{
|
|
Vector3 mouseScreen, mouseFar;
|
|
GetMousePointing(mouseScreen, mouseFar, onVectorMap);
|
|
|
|
Vector3 StartPos;
|
|
|
|
if(iOptionalFlags == 0)
|
|
{
|
|
iOptionalFlags = ArchetypeFlags::GTA_ALL_TYPES_MOVER;
|
|
}
|
|
|
|
// check for nans in position passed in.
|
|
if(mouseScreen==mouseScreen && mouseFar==mouseFar)
|
|
{
|
|
WorldProbe::CShapeTestProbeDesc probeDesc;
|
|
WorldProbe::CShapeTestFixedResults<> probeResult;
|
|
probeDesc.SetResultsStructure(&probeResult);
|
|
probeDesc.SetStartAndEnd(mouseScreen, mouseFar);
|
|
probeDesc.SetIncludeFlags(iOptionalFlags);
|
|
if(WorldProbe::GetShapeTestManager()->SubmitTest(probeDesc))
|
|
{
|
|
posn = probeResult[0].GetHitPosition();
|
|
|
|
phInst* pInst = probeResult[0].GetHitInst();
|
|
if( pInst )
|
|
{
|
|
CEntity* pEntity = CPhysics::GetEntityFromInst(pInst);
|
|
if( pEntity && entity)
|
|
*entity = pEntity;
|
|
}
|
|
|
|
if( pvNormal )
|
|
{
|
|
*pvNormal = probeResult[0].GetHitNormal();
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// name: CDebugScene::CheckMouse
|
|
// description: any debug only functions that use the mouse, ie teleport to mouse, select ai entity etc
|
|
void CDebugScene::CheckMouse()
|
|
{
|
|
if(fwTimer::GetSystemFrameCount() < 120)
|
|
{
|
|
// JB : Wait for ther game & viewports to be set up before processing this, or else
|
|
// there is an assert about invalid start & end points for a line-of-sight.
|
|
return;
|
|
}
|
|
|
|
// AI bank must be active for clicking on players to do anything
|
|
#if __BANK
|
|
bool keyLControlDown=CControlMgr::GetKeyboard().GetKeyDown(KEY_LCONTROL, KEYBOARD_MODE_DEBUG, "Multiple select on");
|
|
bool keyRControlDown=CControlMgr::GetKeyboard().GetKeyDown(KEY_RCONTROL, KEYBOARD_MODE_DEBUG, "Multiple select on");
|
|
bool keyGDown=CControlMgr::GetKeyboard().GetKeyDown(KEY_G, KEYBOARD_MODE_DEBUG, "Teleport to Mouse");
|
|
bool keyGReleased=CControlMgr::GetKeyboard().GetKeyJustUp(KEY_G, KEYBOARD_MODE_DEBUG);
|
|
bool keyNDown=CControlMgr::GetKeyboard().GetKeyDown(KEY_N, KEYBOARD_MODE_DEBUG, "Focus-ped navmesh to Mouse");
|
|
bool keyNReleased=CControlMgr::GetKeyboard().GetKeyJustUp(KEY_N, KEYBOARD_MODE_DEBUG);
|
|
bool keyTDown=CControlMgr::GetKeyboard().GetKeyDown(KEY_T, KEYBOARD_MODE_DEBUG, "Give AI task to focus-ped");
|
|
bool keyTReleased=CControlMgr::GetKeyboard().GetKeyJustUp(KEY_T, KEYBOARD_MODE_DEBUG);
|
|
|
|
bool checkMouseSelectEntity = ms_changeSelectedEntityOnHover || GetMouseLeftPressed();
|
|
|
|
if (keyGDown||keyGReleased||keyNDown||keyNReleased||keyTDown||keyTReleased||checkMouseSelectEntity)
|
|
{
|
|
if( checkMouseSelectEntity && !ms_lockFocusEntities )
|
|
{
|
|
#if !__FINAL
|
|
s32 physicsTypeFlags = 0;
|
|
if(ms_clickTestForPeds) { physicsTypeFlags |= ArchetypeFlags::GTA_PED_TYPE;}
|
|
if(ms_clickTestForRagdolls) { physicsTypeFlags |= ArchetypeFlags::GTA_RAGDOLL_TYPE;}
|
|
// Dummy peds are special as they don't have any physics...
|
|
if(ms_clickTestForVehicles) { physicsTypeFlags |= (ArchetypeFlags::GTA_VEHICLE_TYPE | ArchetypeFlags::GTA_BOX_VEHICLE_TYPE);}
|
|
if(ms_clickTestForObjects) { physicsTypeFlags |= ArchetypeFlags::GTA_OBJECT_TYPE;}
|
|
if(ms_clickTestForWeapons) { physicsTypeFlags |= ArchetypeFlags::GTA_PROJECTILE_TYPE;}
|
|
if(ms_clickTestForBuildingsAndMap) { physicsTypeFlags |= (ArchetypeFlags::GTA_MAP_TYPE_MOVER|ArchetypeFlags::GTA_PLANT_TYPE);}
|
|
|
|
CEntity* pEntity = GetEntityUnderMouse(NULL, NULL, physicsTypeFlags);
|
|
|
|
const bool doingControlClick = (keyLControlDown || keyRControlDown);
|
|
|
|
if(pEntity)
|
|
{
|
|
if(!doingControlClick)
|
|
{
|
|
CDebugScene::FocusEntities_Clear();
|
|
CDebugScene::FocusEntities_Set(pEntity, 0);
|
|
if(!CDebugScene::GetWorldPositionUnderMouse(ms_lastFrameWorldPosition, GetArchetypeFlags(pEntity)))
|
|
{
|
|
return ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Try to add another focus entity if not already in group.
|
|
int index = -1;
|
|
CDebugScene::FocusEntities_Add(pEntity, index);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!doingControlClick)
|
|
{
|
|
// Clear the selection when clicking on nothing.
|
|
CDebugScene::FocusEntities_Clear();
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
Vector3 Pos;
|
|
if(GetWorldPositionUnderMouse(Pos))
|
|
{
|
|
grcDebugDraw::Sphere(Pos, 0.3f, Color32(0xff, 0x00, 0x00, 0xff));
|
|
|
|
if(keyGReleased) //released G so teleport
|
|
{
|
|
CPlayerInfo* pPlayerInfo = CGameWorld::GetMainPlayerInfo();
|
|
// Vector3 PlayerPos=pPlayerInfo->GetPos();
|
|
#if !__FINAL
|
|
Pos.z += 1.0f;
|
|
pPlayerInfo->GetPlayerPed()->Teleport(Pos, pPlayerInfo->GetPlayerPed()->GetCurrentHeading());
|
|
#endif
|
|
}
|
|
if(keyNReleased) //if we've got focus-ped, then goto pos
|
|
{
|
|
CEntity* pFocusEntity = FocusEntities_Get(0);
|
|
if(pFocusEntity && pFocusEntity->GetIsTypePed())
|
|
{
|
|
CPed* pFocusPed = static_cast<CPed*>(pFocusEntity);
|
|
CTaskParachute* pParachuteTask = static_cast<CTaskParachute*>(pFocusPed->GetPedIntelligence()->FindTaskActiveByType(CTaskTypes::TASK_PARACHUTE));
|
|
if( pParachuteTask )
|
|
{
|
|
pParachuteTask->SetTargetPosition(VECTOR3_TO_VEC3V(Pos));
|
|
pParachuteTask->GetParachuteFlags().SetFlag(CTaskParachute::PF_SkipSkydiving);
|
|
}
|
|
|
|
CPedDebugVisualiserMenu::MakePedFollowNavMeshToCoord(pFocusPed, Pos);
|
|
}
|
|
}
|
|
if(keyTReleased) //if we've got focus-ped, then give AI task from debug visualiser
|
|
{
|
|
CEntity* pFocusEntity = FocusEntities_Get(0);
|
|
if(pFocusEntity && pFocusEntity->GetIsTypePed())
|
|
{
|
|
CPed* pFocusPed = static_cast<CPed*>(pFocusEntity);
|
|
CTaskComplexEvasiveStep * pTask = rage_new CTaskComplexEvasiveStep(Pos);
|
|
pFocusPed->GetPedIntelligence()->GetTaskManager()->SetTask(PED_TASK_TREE_PRIMARY, pTask, PED_TASK_PRIORITY_PRIMARY);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CPhysics::UpdateHistoryRendering();
|
|
|
|
if( CPhysics::ms_bDebugPullThingsAround )
|
|
{
|
|
CPhysics::UpdatePullingThingsAround();
|
|
}
|
|
else if ( CPhysics::ms_mouseInput && phMouseInput::IsEnabled() )
|
|
{
|
|
CPhysics::ms_mouseInput->Update(fwTimer::IsGamePaused(), ScalarV(fwTimer::GetTimeStep() / CPhysics::GetNumTimeSlices()).GetIntrin128ConstRef(), &gVpMan.GetGameViewport()->GetGrcViewport());
|
|
}
|
|
else if( CPhysics::ms_bMouseShooter || audPedFootStepAudio::sm_bMouseFootstep || audPedFootStepAudio::sm_bMouseFootstepBullet)
|
|
{
|
|
CPhysics::UpdateMouseShooter();
|
|
}
|
|
else if( CPhysics::ms_bDebugMeasuringTool )
|
|
{
|
|
CPhysics::UpdateDebugMeasuringTool();
|
|
}
|
|
else if(CPedDebugVisualiserMenu::IsDebugPedDraggingActivated())
|
|
{
|
|
CPedDebugVisualiserMenu::UpdatePedDragging();
|
|
}
|
|
else if(CPedDebugVisualiserMenu::IsDebugDefensiveAreaDraggingActivated())
|
|
{
|
|
CPedDebugVisualiserMenu::UpdateDefensiveAreaDragging();
|
|
}
|
|
else if(CPedDebugVisualiserMenu::IsNMInteractiveShooterActivated())
|
|
{
|
|
CPedDebugVisualiserMenu::UpdateNMInteractiveShooter();
|
|
}
|
|
else if(CPedDebugVisualiserMenu::IsNMInteractiveGrabberActivated())
|
|
{
|
|
CPedDebugVisualiserMenu::UpdateNMInteractiveGrabber();
|
|
}
|
|
#if SCENARIO_DEBUG
|
|
else if (CScenarioDebug::ms_Editor.IsEditing())
|
|
{
|
|
CScenarioDebug::ms_Editor.Update();
|
|
}
|
|
#endif // SCENARIO_DEBUG
|
|
else if(audCollisionAudioEntity::sm_EnableModelEditor)
|
|
{
|
|
audCollisionAudioEntity::UpdateModelEditorSelector();
|
|
}
|
|
else
|
|
{
|
|
FRAGTUNE->Update(&gVpMan.GetGameViewport()->GetGrcViewport());
|
|
}
|
|
#endif //__BANK
|
|
}
|
|
|
|
#if __DEV
|
|
|
|
const Vector3 modelViewerPosn(0.0f, 0.0f, 1000.0f);
|
|
const Vector3 modelViewerCamPosn(0.0f, -10.0f, 1001.0f);
|
|
const Vector3 modelViewerCamDir(0.0f, 0.0f, 0.0f);
|
|
static bool gEnableModelViewer = false;
|
|
static RegdEnt gpModelViewerEntity(NULL);
|
|
static s32 gModelViewerIndex = 0;
|
|
static char gModelViewerName[STORE_NAME_LENGTH];
|
|
static char gNumMeshesName[64];
|
|
static char gNumPolysName[64];
|
|
static s32 gNumMeshes = 0;
|
|
static s32 gNumPolys = 0;
|
|
static s32 gMeshIndex = -1;
|
|
|
|
static void SwitchModelViewerOnOff()
|
|
{
|
|
if(gEnableModelViewer)
|
|
CDebugScene::InitModelViewer();
|
|
else
|
|
CDebugScene::ShutdownModelViewer(SHUTDOWN_WITH_MAP_LOADED);
|
|
}
|
|
|
|
//
|
|
// name: CountGeometriesInDrawable
|
|
// description: Count geometies and polys in drawable
|
|
static s32 CountGeometriesInDrawable(rmcDrawable* pDrawable, s32& polyCount)
|
|
{
|
|
s32 count=0;
|
|
if(pDrawable == NULL)
|
|
return 0;
|
|
rmcLod* pLod = &pDrawable->GetLodGroup().GetLod(LOD_HIGH);
|
|
if(pLod == NULL)
|
|
return 0;
|
|
for(s32 i=0; i<pLod->GetCount(); i++)
|
|
{
|
|
count += pLod->GetModel(i)->GetGeometryCount();
|
|
for(s32 j=0; j<pLod->GetModel(i)->GetGeometryCount(); j++)
|
|
polyCount += pLod->GetModel(i)->GetGeometry(j).GetPrimitiveCount();
|
|
}
|
|
return count;
|
|
}
|
|
|
|
static s32 CountGeometriesInFragInst(fragInst* pFrag, s32& polyCount)
|
|
{
|
|
s32 count = 0;
|
|
fragTypeChild** pChildren = pFrag->GetTypePhysics()->GetAllChildren();
|
|
|
|
for(s32 i=0; i<pFrag->GetTypePhysics()->GetNumChildren(); i++)
|
|
{
|
|
fragDrawable* pDrawable = pChildren[i]->GetUndamagedEntity();
|
|
if(pDrawable)
|
|
count += CountGeometriesInDrawable(pDrawable, polyCount);
|
|
}
|
|
return count;
|
|
}
|
|
|
|
static s32 CountGeometriesInEntity(CEntity* pEntity, s32& polyCount)
|
|
{
|
|
//peds do something funny they say they are fragments but their physics inst is just a normal inst
|
|
if(pEntity->GetIsTypePed())
|
|
return CountGeometriesInDrawable(pEntity->GetDrawable(), polyCount);
|
|
else if(pEntity->GetFragInst())
|
|
return CountGeometriesInFragInst(pEntity->GetFragInst(), polyCount);
|
|
else
|
|
return CountGeometriesInDrawable(pEntity->GetDrawable(), polyCount);
|
|
}
|
|
|
|
//
|
|
// name: DrawGeometryInDrawable
|
|
// description: Draw a single geometry from a drawable
|
|
static void DrawGeometryInDrawable(rmcDrawable* pDrawable, const Matrix34& rootMatrix, const Matrix34* pMatrix, s32 num)
|
|
{
|
|
if(gNumMeshes == 0 || num >= gNumMeshes)
|
|
return;
|
|
|
|
Assert(pDrawable);
|
|
if(pDrawable == NULL)
|
|
return;
|
|
rmcLod* pLod = &pDrawable->GetLodGroup().GetLod(LOD_HIGH);
|
|
if(pLod == NULL)
|
|
return;
|
|
|
|
for(s32 i=0; i<pLod->GetCount(); i++)
|
|
{
|
|
grmModel* pModel = pLod->GetModel(i);
|
|
s32 idx = pModel->GetMatrixIndex();
|
|
Matrix34 worldMatrix;
|
|
if(pMatrix)
|
|
{
|
|
worldMatrix.Dot(pMatrix[idx], rootMatrix);
|
|
}
|
|
else
|
|
{
|
|
worldMatrix = rootMatrix;
|
|
}
|
|
grcViewport::SetCurrentWorldMtx(RCC_MAT34V(worldMatrix));
|
|
if(num < pModel->GetGeometryCount())
|
|
{
|
|
grmShader& shader = pDrawable->GetShaderGroup().GetShader(pModel->GetShaderIndex(num));
|
|
shader.Draw(*pModel, num, 0, true);
|
|
break;
|
|
}
|
|
num -= pModel->GetGeometryCount();
|
|
}
|
|
grcStateBlock::Default();
|
|
}
|
|
|
|
static void DrawGeometryInFragInst(fragInst* pFragInst, const Matrix34& rootMatrix, Matrix34* pMatrices, s32 num)
|
|
{
|
|
if(gNumMeshes == 0 || num >= gNumMeshes)
|
|
return;
|
|
Assert(pFragInst);
|
|
fragTypeChild** pChildren = pFragInst->GetTypePhysics()->GetAllChildren();
|
|
|
|
for(s32 i=0; i<pFragInst->GetTypePhysics()->GetNumChildren(); i++)
|
|
{
|
|
fragDrawable* pDrawable = pChildren[i]->GetUndamagedEntity();
|
|
s32 polyCount=0;
|
|
s32 count = CountGeometriesInDrawable(pDrawable, polyCount);
|
|
if(num < count)
|
|
{
|
|
DrawGeometryInDrawable(pDrawable, rootMatrix, pMatrices, num);
|
|
break;
|
|
}
|
|
num -= count;
|
|
}
|
|
|
|
}
|
|
|
|
static void DrawGeometryInEntity(CEntity* pEntity, s32 num)
|
|
{
|
|
//peds do something funny they say they are fragments but their physics inst is just a normal inst
|
|
if(pEntity->GetIsTypePed())
|
|
{
|
|
DrawGeometryInDrawable(pEntity->GetDrawable(), MAT34V_TO_MATRIX34(pEntity->GetMatrix()), reinterpret_cast<const Matrix34*>(((CDynamicEntity*)pEntity)->GetSkeleton()->GetObjectMtxs()), num);
|
|
}
|
|
else if(pEntity->GetFragInst())
|
|
{
|
|
DrawGeometryInFragInst(pEntity->GetFragInst(), MAT34V_TO_MATRIX34(pEntity->GetMatrix()), reinterpret_cast<Matrix34*>(((CDynamicEntity*)pEntity)->GetSkeleton()->GetObjectMtxs()), num);
|
|
}else
|
|
DrawGeometryInDrawable(pEntity->GetDrawable(), MAT34V_TO_MATRIX34(pEntity->GetMatrix()), NULL, num);
|
|
}
|
|
|
|
//
|
|
// name: FindGeometryInDrawable
|
|
// description: Find a single geometry from a drawable
|
|
static grmGeometry* FindGeometryInDrawable(rmcDrawable* pDrawable, s32 num)
|
|
{
|
|
if(gNumMeshes == 0 || num >= gNumMeshes)
|
|
return NULL;
|
|
|
|
Assert(pDrawable);
|
|
rmcLod* pLod = &pDrawable->GetLodGroup().GetLod(LOD_HIGH);
|
|
if(pLod == NULL)
|
|
return NULL;
|
|
|
|
for(s32 i=0; i<pLod->GetCount(); i++)
|
|
{
|
|
grmModel* pModel = pLod->GetModel(i);
|
|
if(num < pModel->GetGeometryCount())
|
|
{
|
|
return &pModel->GetGeometry(num);
|
|
}
|
|
num -= pModel->GetGeometryCount();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static grmGeometry* FindGeometryInFragInst(fragInst* pFragInst, s32 num)
|
|
{
|
|
if(gNumMeshes == 0 || num >= gNumMeshes)
|
|
return NULL;
|
|
Assert(pFragInst);
|
|
fragTypeChild** pChildren = pFragInst->GetTypePhysics()->GetAllChildren();
|
|
|
|
for(s32 i=0; i<pFragInst->GetTypePhysics()->GetNumChildren(); i++)
|
|
{
|
|
fragDrawable* pDrawable = pChildren[i]->GetUndamagedEntity();
|
|
s32 polyCount=0;
|
|
s32 count = CountGeometriesInDrawable(pDrawable, polyCount);
|
|
if(num < count)
|
|
{
|
|
return FindGeometryInDrawable(pDrawable, num);
|
|
}
|
|
num -= count;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static grmGeometry* FindGeometryInEntity(CEntity* pEntity, s32 num)
|
|
{
|
|
//peds do something funny they say they are fragments but their physics inst is just a normal inst
|
|
if(pEntity->GetIsTypePed())
|
|
{
|
|
return FindGeometryInDrawable(pEntity->GetDrawable(), num);
|
|
}
|
|
else if(pEntity->GetFragInst())
|
|
{
|
|
return FindGeometryInFragInst(pEntity->GetFragInst(), num);
|
|
}
|
|
else
|
|
return FindGeometryInDrawable(pEntity->GetDrawable(), num);
|
|
}
|
|
|
|
//
|
|
// name: GetModelIndexFromName/GetModelNameFromIndex
|
|
// description: Convert model index to name and vice versa
|
|
static void GetModelIndexFromName()
|
|
{
|
|
fwModelId modelId;
|
|
CModelInfo::GetBaseModelInfoFromName(gModelViewerName, &modelId);
|
|
if(modelId.IsValid())
|
|
gModelViewerIndex = modelId.GetModelIndex();
|
|
}
|
|
|
|
static void GetModelNameFromIndex()
|
|
{
|
|
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfo(fwModelId(strLocalIndex(gModelViewerIndex)));
|
|
if(pModelInfo)
|
|
strcpy(gModelViewerName, pModelInfo->GetModelName());
|
|
}
|
|
|
|
|
|
//
|
|
// name: CDebugScene::AddModelViewerBankWidgets
|
|
// description:
|
|
void CDebugScene::AddModelViewerBankWidgets(bkBank& bank)
|
|
{
|
|
bank.PushGroup("Model Viewer", false);
|
|
bank.AddToggle("On/Off", &gEnableModelViewer, &SwitchModelViewerOnOff);
|
|
bank.AddText("Modelname", &gModelViewerName[0], sizeof(gModelViewerName), false, &GetModelIndexFromName);
|
|
bank.AddSlider("Modelindex", &gModelViewerIndex, 0, CModelInfo::GetMaxModelInfos(), 1, &GetModelNameFromIndex);
|
|
bank.AddText("Num meshes", &gNumMeshesName[0], sizeof(gNumMeshesName), true);
|
|
bank.AddText("Num primitives", &gNumPolysName[0], sizeof(gNumPolysName), true);
|
|
bank.AddSlider("Mesh render", &gMeshIndex, -1, 1000, 1);
|
|
bank.PopGroup();
|
|
}
|
|
|
|
//
|
|
// name: CDebugScene::InitModelViewer
|
|
// description: Initialise model viewer
|
|
void CDebugScene::InitModelViewer()
|
|
{
|
|
camDebugDirector& debugDirector = camInterface::GetDebugDirector();
|
|
debugDirector.ActivateFreeCam(); //Turn on debug free cam.
|
|
|
|
//Move free camera to desired place.
|
|
camFrame& freeCamFrame = debugDirector.GetFreeCamFrameNonConst();
|
|
freeCamFrame.SetPosition(modelViewerCamPosn);
|
|
|
|
Matrix34 worldMatrix;
|
|
CScriptEulers::MatrixFromEulers(worldMatrix, modelViewerCamDir * DtoR, EULER_YXZ);
|
|
|
|
freeCamFrame.SetWorldMatrix(worldMatrix);
|
|
|
|
CControlMgr::SetDebugPadOn(true);
|
|
}
|
|
|
|
CEntity* CreateModelViewerEntity(strLocalIndex modelIndex)
|
|
{
|
|
const CControlledByInfo localAiControl(false, false);
|
|
CEntity* pEntity;
|
|
fwModelId modelId(modelIndex);
|
|
switch(CModelInfo::GetBaseModelInfo(modelId)->GetModelType())
|
|
{
|
|
case MI_TYPE_VEHICLE:
|
|
pEntity = CVehicleFactory::GetFactory()->Create(modelId, ENTITY_OWNEDBY_DEBUG, POPTYPE_TOOL, NULL);
|
|
break;
|
|
case MI_TYPE_PED:
|
|
pEntity = CPedFactory::GetFactory()->CreatePed(localAiControl, modelId, NULL, true, true, false);
|
|
((CPed*)pEntity)->PopTypeSet(POPTYPE_TOOL);
|
|
((CPed*)pEntity)->SetDefaultDecisionMaker();
|
|
((CPed*)pEntity)->SetCharParamsBasedOnManagerType();
|
|
((CPed*)pEntity)->GetPedIntelligence()->SetDefaultRelationshipGroup();
|
|
break;
|
|
default:
|
|
pEntity = rage_new CBuilding( ENTITY_OWNEDBY_DEBUG );
|
|
|
|
pEntity->SetModelId(modelId);
|
|
|
|
pEntity->InitPhys();
|
|
pEntity->CreateDrawable();
|
|
if(pEntity->GetIsDynamic())
|
|
((CDynamicEntity*)pEntity)->CreateSkeleton();
|
|
break;
|
|
}
|
|
return pEntity;
|
|
}
|
|
|
|
void DeleteModelViewerEntity(CEntity* pEntity)
|
|
{
|
|
switch(pEntity->GetBaseModelInfo()->GetModelType())
|
|
{
|
|
case MI_TYPE_VEHICLE:
|
|
CVehicleFactory::GetFactory()->Destroy((CVehicle*)pEntity);
|
|
break;
|
|
case MI_TYPE_PED:
|
|
CPedFactory::GetFactory()->DestroyPed((CPed*)pEntity);
|
|
break;
|
|
default:
|
|
delete pEntity;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// name: CDebugScene::ShutdownModelViewer
|
|
// description: Shutdown model viewer
|
|
void CDebugScene::ShutdownModelViewer(unsigned /*shutdownMode*/)
|
|
{
|
|
if(gpModelViewerEntity)
|
|
DeleteModelViewerEntity(gpModelViewerEntity);
|
|
}
|
|
|
|
void CDebugScene::UpdateModelViewer()
|
|
{
|
|
IF_COMMERCE_STORE_RETURN();
|
|
|
|
if(gEnableModelViewer == false)
|
|
return;
|
|
|
|
if(gpModelViewerEntity)
|
|
{
|
|
// update number of polys
|
|
if(gMeshIndex == -1)
|
|
{
|
|
gNumPolys=0;
|
|
gNumMeshes = CountGeometriesInEntity(gpModelViewerEntity, gNumPolys);
|
|
sprintf(gNumPolysName, "%d", gNumPolys);
|
|
}
|
|
else
|
|
{
|
|
grmGeometry* pGeom = FindGeometryInEntity(gpModelViewerEntity, gMeshIndex);
|
|
if(pGeom)
|
|
sprintf(gNumPolysName, "%d", pGeom->GetPrimitiveCount());
|
|
}
|
|
// Check if index has changed
|
|
if(gpModelViewerEntity->GetModelIndex() != (u32)gModelViewerIndex)
|
|
{
|
|
DeleteModelViewerEntity(gpModelViewerEntity);
|
|
gpModelViewerEntity = NULL;
|
|
}
|
|
}
|
|
if(!gpModelViewerEntity)
|
|
{
|
|
fwModelId modelId((strLocalIndex(gModelViewerIndex)));
|
|
if(modelId.IsValid())
|
|
{
|
|
// if object is in memory. Create version of object
|
|
if(CModelInfo::HaveAssetsLoaded(modelId))
|
|
{
|
|
gpModelViewerEntity = CreateModelViewerEntity(strLocalIndex(gModelViewerIndex));
|
|
gpModelViewerEntity->SetPosition(modelViewerPosn);
|
|
|
|
gNumPolys=0;
|
|
gNumMeshes = CountGeometriesInEntity(gpModelViewerEntity, gNumPolys);
|
|
sprintf(gNumMeshesName, "%d", gNumMeshes);
|
|
sprintf(gNumPolysName, "%d", gNumPolys);
|
|
gMeshIndex = -1;
|
|
}
|
|
// request object be streamed
|
|
else
|
|
CModelInfo::RequestAssets(modelId, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// name: CDebugScene::RenderModelViewer
|
|
// description: Render model viewer
|
|
|
|
void CDebugScene::RenderModelViewer()
|
|
{
|
|
IF_COMMERCE_STORE_RETURN();
|
|
|
|
if(gEnableModelViewer == false)
|
|
return;
|
|
|
|
if(gpModelViewerEntity)
|
|
{
|
|
gpModelViewerEntity->PreRender();
|
|
if(gMeshIndex < 0)
|
|
{
|
|
// can't call render buckets through an entity any more
|
|
//gpModelViewerEntity->RenderBuckets(CRenderer::RB_OPAQUE, rmStandard);
|
|
//gpModelViewerEntity->RenderBuckets(CRenderer::RB_ALPHA, rmStandard);
|
|
//gpModelViewerEntity->RenderBuckets(CRenderer::RB_DECAL, rmStandard);
|
|
//gpModelViewerEntity->RenderBuckets(CRenderer::RB_CUTOUT, rmStandard);
|
|
|
|
// don't know if this works...
|
|
DrawGeometryInEntity(gpModelViewerEntity, 0);
|
|
}
|
|
else
|
|
DrawGeometryInEntity(gpModelViewerEntity, gMeshIndex);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
#if __BANK
|
|
//
|
|
// name: CDebugScene::DisplayEntitiesOnVMap
|
|
// description: Displays peds,cars and mission objects on the vector map
|
|
|
|
void CDebugScene::DisplayEntitiesOnVectorMap()
|
|
{
|
|
IF_COMMERCE_STORE_RETURN();
|
|
|
|
char debugText[100];
|
|
|
|
//--------------------------------------------------------------------------
|
|
// PROXIMITY AREA
|
|
if(ms_drawProximityAreaOnVM)
|
|
{
|
|
// Determine if we should draw this frame or not.
|
|
bool drawThisFrame = true;
|
|
if(ms_drawProximityAreaOnVMFlashes)
|
|
{
|
|
static bool frameFlasher = true;
|
|
frameFlasher = !frameFlasher;
|
|
drawThisFrame = frameFlasher;
|
|
}
|
|
if(drawThisFrame)
|
|
{
|
|
CVectorMap::DrawCircle(ms_proximityTestPoint, ms_proximityMaxAllowableRadialDiff, Color32(255, 100, 100, 255), false);
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// WATER
|
|
if (bDisplayWaterOnVMap)
|
|
{
|
|
Water::RenderDebug(Color32(100,100,255,255), Color32(0), Color32(255,255,0,255), false, true, true);
|
|
}
|
|
if (bDisplayCalmingWaterOnVMap)
|
|
{
|
|
Water::RenderDebug(Color32(0), Color32(0,0,255,255), Color32(0), false, true, true);
|
|
}
|
|
if(bDisplayShoreLinesOnVMap)
|
|
{
|
|
g_AmbientAudioEntity.RenderShoreLinesDebug();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// BUILDINGS
|
|
if (bDisplayBuildingsOnVMap)
|
|
{
|
|
// Go over all the buildings.
|
|
CBuilding::Pool *BuildingPool = CBuilding::GetPool();
|
|
CBuilding* pBuilding;
|
|
s32 i=BuildingPool->GetSize();
|
|
while(i--)
|
|
{
|
|
pBuilding = BuildingPool->GetSlot(i);
|
|
if(pBuilding)
|
|
{
|
|
// Determine what colour to draw the building.
|
|
Color32 Colour(255, 255, 255, 255);
|
|
|
|
// Draw the building.
|
|
CDebugScene::DrawEntityBoundingBoxOnVMap(pBuilding, Colour);
|
|
}
|
|
}
|
|
|
|
// Go over all the animated buildings.
|
|
CAnimatedBuilding::Pool *AnimatedBuildingPool = CAnimatedBuilding::GetPool();
|
|
CAnimatedBuilding* pAnimatedBuilding;
|
|
i=AnimatedBuildingPool->GetSize();
|
|
while(i--)
|
|
{
|
|
pAnimatedBuilding = AnimatedBuildingPool->GetSlot(i);
|
|
if(pAnimatedBuilding)
|
|
{
|
|
// Determine what colour to draw the animated building.
|
|
Color32 Colour(0, 100, 255, 255);
|
|
|
|
// Draw the building.
|
|
CDebugScene::DrawEntityBoundingBoxOnVMap(pAnimatedBuilding, Colour);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// VEHICLES
|
|
if (bDisplayVehiclesOnVMap || bDisplayVehiclesOnVMapAsActiveInactive || bDisplayVehiclesOnVMapTimesliceUpdates || bDisplayVehiclesOnVMapBasedOnOcclusion || bDisplayVehiclesToBeStreamedOutOnVMap)
|
|
{
|
|
CVehicle::Pool *VehPool = CVehicle::GetPool();
|
|
CVehicle* pVeh;
|
|
s32 i = (s32) VehPool->GetSize();
|
|
|
|
while(i--)
|
|
{
|
|
pVeh = VehPool->GetSlot(i);
|
|
|
|
if(pVeh)
|
|
{
|
|
Color32 Colour;
|
|
Color32 ActiveColour = Color_green;
|
|
if( (pVeh->GetCurrentPhysicsInst() && CPhysics::GetLevel()->IsActive(pVeh->GetCurrentPhysicsInst()->GetLevelIndex())))
|
|
{
|
|
if( pVeh->GetVehicleAiLod().GetDummyMode() == VDM_REAL )
|
|
{
|
|
ActiveColour = Color_red;
|
|
}
|
|
else
|
|
{
|
|
ActiveColour = Color_orange;
|
|
}
|
|
}
|
|
|
|
switch(pVeh->GetVehicleAiLod().GetDummyMode())
|
|
{
|
|
case VDM_REAL:
|
|
default:
|
|
Colour = Color_purple;
|
|
break;
|
|
case VDM_DUMMY:
|
|
Colour = Color_orange;
|
|
break;
|
|
case VDM_SUPERDUMMY:
|
|
Colour = Color_green;
|
|
break;
|
|
}
|
|
|
|
if(pVeh->GetIsInReusePool())
|
|
{
|
|
if(!CVehiclePopulation::ms_bDebugVehicleReusePool && !CVehiclePopulation::ms_bDisplayVehicleReusePool) // don't show vehicles in reuse pool on vector map
|
|
{
|
|
continue; //skip this vehicle
|
|
}
|
|
else
|
|
{
|
|
// vehicles in the reuse pool are blue
|
|
Colour = Color_blue;
|
|
}
|
|
}
|
|
|
|
if (!pVeh->PopTypeIsMission())
|
|
{
|
|
// Mission vehicles are twice as bright as regular vehicles
|
|
Colour.SetRed( Colour.GetRed()/2 );
|
|
Colour.SetGreen( Colour.GetGreen()/2 );
|
|
Colour.SetBlue( Colour.GetBlue()/2 );
|
|
}
|
|
|
|
bool bEmptyPopCar = false;
|
|
if( CNetwork::IsGameInProgress() && !pVeh->IsUsingPretendOccupants() &&
|
|
((NetworkInterface::GetSyncedTimeInMilliseconds() - pVeh->m_LastTimeWeHadADriver) > 5000 ) && (!pVeh->GetLastDriver() || !pVeh->GetLastDriver()->IsAPlayerPed() ) )
|
|
{
|
|
bEmptyPopCar = true;
|
|
}
|
|
|
|
const bool bWrecked = pVeh->GetStatus() == STATUS_WRECKED || pVeh->m_nVehicleFlags.bIsDrowning;
|
|
|
|
const bool bEmptyOrWrecked = !pVeh->PopTypeIsMission() && (pVeh->PopTypeGet() != POPTYPE_RANDOM_PARKED || bWrecked ) && (pVeh->IsLawEnforcementVehicle() || bEmptyPopCar || bWrecked || pVeh->m_nVehicleFlags.bRemoveWithEmptyCopOrWreckedVehs) &&
|
|
(!pVeh->HasAlivePedsInIt() || pVeh->m_nVehicleFlags.bCanBeDeletedWithAlivePedsInIt) && !pVeh->HasMissionCharsInIt();
|
|
|
|
if( bDisplayLinesToLocalDrivingCars )
|
|
{
|
|
if( !pVeh->IsNetworkClone() && ((pVeh->PopTypeGet() == POPTYPE_RANDOM_AMBIENT) || (pVeh->PopTypeGet() == POPTYPE_RANDOM_SCENARIO) ) && !bEmptyOrWrecked )
|
|
{
|
|
CVectorMap::DrawLine(CGameWorld::FindLocalPlayerCoors(), VEC3V_TO_VECTOR3(pVeh->GetTransform().GetPosition()), Color_red, Color_red);
|
|
}
|
|
}
|
|
|
|
if (bDisplayVehiclesToBeStreamedOutOnVMap)
|
|
{
|
|
Colour.Setf(0.4f, 0.4f, 0.4f, 1.0f);
|
|
if (CModelInfo::GetAssetsAreDeletable(pVeh->GetModelId()))
|
|
{
|
|
float Mult = 0.6f + 0.4f * ((fwTimer::GetTimeInMilliseconds() & 512) / 512.0f);
|
|
Colour.Setf( Colour.GetRedf() * Mult, Colour.GetGreenf() * Mult, Colour.GetBluef() * Mult, 1.0f );
|
|
}
|
|
}
|
|
|
|
if (NetworkInterface::IsGameInProgress())
|
|
{
|
|
if(bDisplayNetworkGameOnVMap)
|
|
{
|
|
if(pVeh->GetNetworkObject() && pVeh->GetNetworkObject()->GetPlayerOwner())
|
|
{
|
|
PhysicalPlayerIndex playerIndex = pVeh->GetNetworkObject()->GetPlayerOwner()->GetPhysicalPlayerIndex();
|
|
NetworkColours::NetworkColour colour = NetworkColours::GetDefaultPlayerColour(playerIndex);
|
|
Colour = NetworkColours::GetNetworkColour(colour);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( !bEmptyOrWrecked )
|
|
{
|
|
Colour = pVeh->IsNetworkClone() ? Color_blue : Color_green;
|
|
}
|
|
else
|
|
{
|
|
Colour = pVeh->IsNetworkClone() ? Color_purple : Color_red;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fade as we get closer to being removed.
|
|
if(bDisplayVehiclesUsesFadeOnVMap)
|
|
{
|
|
float portionRemaining = 1.0f - pVeh->DelayedRemovalTimeGetPortion();
|
|
Colour.SetRed(255-(int)(portionRemaining*255));
|
|
Colour.SetGreen((int)(portionRemaining*255));
|
|
Colour.SetBlue((int)(portionRemaining*255));
|
|
}
|
|
|
|
if(!bDisplayCarCreation DEV_ONLY(|| (pVeh->GetNetworkObject() && (fwTimer::GetSystemTimeInMilliseconds() - ((CNetObjVehicle *)pVeh->GetNetworkObject())->m_timeCreated) <= 1000)))
|
|
{
|
|
if( bDisplayVehiclesOnVMap )
|
|
{
|
|
CVectorMap::DrawVehicle(pVeh, Colour);
|
|
}
|
|
if( bDisplayVehiclesOnVMapAsActiveInactive )
|
|
{
|
|
float fScale = CVectorMap::m_vehicleVectorMapScale;
|
|
CVectorMap::m_vehicleVectorMapScale = fScale * ((bDisplayVehiclesOnVMap) ? 1.3f:1.0f);
|
|
CVectorMap::DrawVehicle(pVeh, ActiveColour);
|
|
CVectorMap::m_vehicleVectorMapScale = fScale;
|
|
}
|
|
if( bDisplayVehiclesOnVMapBasedOnOcclusion )
|
|
{
|
|
Color32 occlusionColour = Color_green;
|
|
if( !pVeh->GetIsVisibleInSomeViewportThisFrame() )
|
|
{
|
|
occlusionColour = Color_orange;
|
|
}
|
|
else
|
|
{
|
|
spdAABB tempBox;
|
|
const spdAABB & aabb = pVeh->GetBoundBox(tempBox);
|
|
bool bVehicleIsOccluded = !COcclusion::IsBoxVisibleFast(aabb);
|
|
if( bVehicleIsOccluded )
|
|
{
|
|
occlusionColour = Color_red;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bDisplayVehiclesOnVMapTimesliceUpdates )
|
|
{
|
|
if( CVehicleAILodManager::ShouldDoFullUpdate(*pVeh) )
|
|
{
|
|
CVectorMap::DrawVehicle(pVeh, Color_green);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// PEDS
|
|
if (bDisplayPedsOnVMap || bDisplayPedsOnVMapAsActiveInactive || bDisplayPedsOnVMapTimesliceUpdates || bDisplayPedsToBeStreamedOutOnVMap)
|
|
{
|
|
if (bDisplayPedsOnVMap || bDisplayPedsOnVMapAsActiveInactive || bDisplayPedsOnVMapTimesliceUpdates)
|
|
{
|
|
// Go over all the peds.
|
|
CPed::Pool *PedPool = CPed::GetPool();
|
|
CPed* pPed;
|
|
s32 i=PedPool->GetSize();
|
|
while(i--)
|
|
{
|
|
pPed = PedPool->GetSlot(i);
|
|
if(pPed)
|
|
{
|
|
if(pPed->GetPedConfigFlag(CPED_CONFIG_FLAG_PedIsInReusePool))
|
|
{
|
|
if(!CPedPopulation::ms_bDebugPedReusePool && !CPedPopulation::ms_bDisplayPedReusePool)
|
|
continue; // skip peds in the reuse pool
|
|
}
|
|
|
|
// Determine what colour to draw the ped.
|
|
Color32 Colour(255, 255, 255, 255);
|
|
{
|
|
if (!pPed->PopTypeIsMission())
|
|
{ // Mission chars are twice as bright as regular peds
|
|
Colour.SetRed( Colour.GetRed()/2 );
|
|
Colour.SetGreen( Colour.GetGreen()/2 );
|
|
Colour.SetBlue( Colour.GetBlue()/2 );
|
|
}
|
|
|
|
|
|
if (pPed->IsPlayer())
|
|
{
|
|
Colour = Color32(255, 255, 255, 255);
|
|
if (fwTimer::GetTimeInMilliseconds() & 512)
|
|
{
|
|
Colour = Color32(0, 0, 0, 255);
|
|
}
|
|
}
|
|
|
|
if (pPed->PopTypeGet() == POPTYPE_RANDOM_SCENARIO)
|
|
{
|
|
Colour = Color32(0, 130, 0, 255);
|
|
}
|
|
|
|
if (NetworkInterface::IsGameInProgress() && bDisplayNetworkGameOnVMap)
|
|
{
|
|
if(pPed->GetNetworkObject() && pPed->GetNetworkObject()->GetPlayerOwner())
|
|
{
|
|
PhysicalPlayerIndex playerIndex = pPed->GetNetworkObject()->GetPlayerOwner()->GetPhysicalPlayerIndex();
|
|
NetworkColours::NetworkColour colour = NetworkColours::GetDefaultPlayerColour(playerIndex);
|
|
Colour = NetworkColours::GetNetworkColour(colour);
|
|
}
|
|
}
|
|
|
|
// Fade as we get closer to being removed.
|
|
float portionRemaining = 1.0f - pPed->DelayedRemovalTimeGetPortion();
|
|
Colour.SetAlpha( (int) (255 * portionRemaining) );
|
|
|
|
if(pPed->GetPedConfigFlag(CPED_CONFIG_FLAG_PedIsInReusePool))
|
|
{
|
|
// draw reused peds as purple
|
|
Colour = Color_purple;
|
|
|
|
// fade them like non mission peds
|
|
Colour.SetRed( Colour.GetRed()/2 );
|
|
Colour.SetGreen( Colour.GetGreen()/2 );
|
|
Colour.SetBlue( Colour.GetBlue()/2 );
|
|
}
|
|
}
|
|
|
|
// Draw the ped.
|
|
if( bDisplayPedsOnVMap )
|
|
{
|
|
CVectorMap::DrawPed(pPed, Colour);
|
|
}
|
|
|
|
if( bDisplayPedsOnVMapAsActiveInactive )
|
|
{
|
|
if(pPed->GetPedConfigFlag(CPED_CONFIG_FLAG_PedIsInReusePool))
|
|
continue; // skip peds in the reuse pool. they're not in the physics level anyway
|
|
|
|
Color32 ActiveColour = pPed->GetVehiclePedInside() ? Color_blue: Color_green;
|
|
if( (pPed->GetCurrentPhysicsInst() && CPhysics::GetLevel()->IsActive(pPed->GetCurrentPhysicsInst()->GetLevelIndex())))
|
|
{
|
|
// Draw an extra circle as they can be odd orientaitons
|
|
if( pPed->GetRagdollState()==RAGDOLL_STATE_PHYS )
|
|
{
|
|
ActiveColour = Color_purple;
|
|
CVectorMap::DrawCircle(VEC3V_TO_VECTOR3(pPed->GetTransform().GetPosition()), 2.0f, ActiveColour);
|
|
}
|
|
else
|
|
{
|
|
ActiveColour = Color_red;
|
|
}
|
|
}
|
|
float fScale = CVectorMap::m_pedVectorMapScale;
|
|
CVectorMap::m_pedVectorMapScale = fScale * 1.3f;
|
|
CVectorMap::DrawPed(pPed, ActiveColour);
|
|
CVectorMap::m_pedVectorMapScale = fScale;
|
|
}
|
|
|
|
if( bDisplayPedsOnVMapTimesliceUpdates )
|
|
{
|
|
if(CPedAILodManager::ShouldDoFullUpdate(*pPed))
|
|
{
|
|
CVectorMap::DrawPed(pPed, Color_green);
|
|
}
|
|
}
|
|
|
|
// If this ped is in a vehicle we draw it too.
|
|
if (bDisplayPedsOnVMap && (pPed->GetPedConfigFlag( CPED_CONFIG_FLAG_InVehicle ) && pPed->GetMyVehicle()))
|
|
{
|
|
CVectorMap::DrawVehicle(pPed->GetMyVehicle(), Color32(100, 100, 100, 255) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bDisplayPedsToBeStreamedOutOnVMap)
|
|
{
|
|
CPed::Pool *PedPool = CPed::GetPool();
|
|
CPed* pPed;
|
|
s32 i=PedPool->GetSize();
|
|
|
|
while(i--)
|
|
{
|
|
pPed = PedPool->GetSlot(i);
|
|
|
|
if(pPed)
|
|
{
|
|
Color32 Colour(255, 255, 255, 255);
|
|
|
|
if (pPed->RemovalIsPriority(pPed->GetModelId()) && (fwTimer::GetTimeInMilliseconds() & 512))
|
|
{
|
|
Colour.SetRed( 0 );
|
|
Colour.SetGreen( 0 );
|
|
Colour.SetBlue( 0 );
|
|
}
|
|
|
|
|
|
CVectorMap::DrawPed(pPed, Colour);
|
|
|
|
// if this ped is in a vehicle we draw this too
|
|
if (pPed->GetPedConfigFlag( CPED_CONFIG_FLAG_InVehicle ) && pPed->GetMyVehicle())
|
|
{
|
|
CVectorMap::DrawVehicle(pPed->GetMyVehicle(), Color32(100, 100, 100, 255) );
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Objects
|
|
if (bDisplayObjectsOnVMap || bDisplayLineAboveObjects)
|
|
{
|
|
if (bDisplayObjectsOnVMap)
|
|
{
|
|
CObject::Pool *ObjPool = CObject::GetPool();
|
|
CObject* pObj;
|
|
s32 i = (s32) ObjPool->GetSize();
|
|
s32 numObjects = 0;
|
|
|
|
while(i--)
|
|
{
|
|
pObj = ObjPool->GetSlot(i);
|
|
|
|
if(pObj)
|
|
{
|
|
numObjects++;
|
|
Color32 Colour = (pObj->GetCurrentPhysicsInst() && CPhysics::GetLevel()->IsActive(pObj->GetCurrentPhysicsInst()->GetLevelIndex())) ? Color_red : Color_green;
|
|
if (pObj->GetOwnedBy() != ENTITY_OWNEDBY_SCRIPT)
|
|
{
|
|
// Mission objects are twice as bright as regular objects
|
|
Colour.SetRed( Colour.GetRed()/2 );
|
|
Colour.SetGreen( Colour.GetGreen()/2 );
|
|
Colour.SetBlue( Colour.GetBlue()/2 );
|
|
}
|
|
|
|
if (NetworkInterface::IsGameInProgress() && bDisplayNetworkGameOnVMap)
|
|
{
|
|
if(pObj->GetNetworkObject() && pObj->GetNetworkObject()->GetPlayerOwner())
|
|
{
|
|
PhysicalPlayerIndex playerIndex = pObj->GetNetworkObject()->GetPlayerOwner()->GetPhysicalPlayerIndex();
|
|
NetworkColours::NetworkColour colour = NetworkColours::GetDefaultPlayerColour(playerIndex);
|
|
Colour = NetworkColours::GetNetworkColour(colour);
|
|
}
|
|
}
|
|
spdAABB box;
|
|
box = pObj->GetBoundBox(box);
|
|
CVectorMap::Draw3DBoundingBoxOnVMap(box, Colour);
|
|
//CVectorMap::DrawMarker(VEC3V_TO_VECTOR3(pObj->GetTransform().GetPosition()), Colour);
|
|
}
|
|
}
|
|
sprintf(debugText, "Number of objects in pool: %d %d", numObjects, (int) CObject::GetPool()->GetSize());
|
|
grcDebugDraw::AddDebugOutput(debugText);
|
|
}
|
|
if (bDisplayLineAboveObjects)
|
|
{
|
|
CObject::Pool *ObjPool = CObject::GetPool();
|
|
CObject* pObj;
|
|
s32 i = (s32) ObjPool->GetSize();
|
|
|
|
while(i--)
|
|
{
|
|
pObj = ObjPool->GetSlot(i);
|
|
|
|
if(pObj)
|
|
{
|
|
Color32 Colour(255, 255, 255, 255);
|
|
if (pObj->GetOwnedBy() != ENTITY_OWNEDBY_SCRIPT)
|
|
{
|
|
// Mission objects are twice as bright as regular objects
|
|
Colour.SetRed( Colour.GetRed()/2 );
|
|
Colour.SetGreen( Colour.GetGreen()/2 );
|
|
Colour.SetBlue( Colour.GetBlue()/2 );
|
|
}
|
|
|
|
if (NetworkInterface::IsGameInProgress() && bDisplayNetworkGameOnVMap)
|
|
{
|
|
if(pObj->GetNetworkObject() && pObj->GetNetworkObject()->GetPlayerOwner())
|
|
{
|
|
PhysicalPlayerIndex playerIndex = pObj->GetNetworkObject()->GetPlayerOwner()->GetPhysicalPlayerIndex();
|
|
NetworkColours::NetworkColour colour = NetworkColours::GetDefaultPlayerColour(playerIndex);
|
|
Colour = NetworkColours::GetNetworkColour(colour);
|
|
}
|
|
}
|
|
|
|
const Vector3 vObjPosition = VEC3V_TO_VECTOR3(pObj->GetTransform().GetPosition());
|
|
grcDebugDraw::Line(vObjPosition, vObjPosition+Vector3(0.0f, 0.0f, 15.0f), Colour);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Check for duplicate objects
|
|
if(CDebugScene::bDisplayDuplicateObjectsBB || CDebugScene::bDisplayDuplicateObjectsOnVMap)
|
|
{
|
|
dev_float fDuplicateSepThresholdSq = 0.2f*0.2f;
|
|
CObject::Pool* objectPool = CObject::GetPool();
|
|
s32 i = (s32) objectPool->GetSize();
|
|
while(i--)
|
|
{
|
|
s32 j = i;
|
|
while(j--)
|
|
{
|
|
CObject* pObject = objectPool->GetSlot(i);
|
|
CObject* pOtherObject = objectPool->GetSlot(j);
|
|
if(pObject && pOtherObject
|
|
&& (pObject->GetModelIndex() == pOtherObject->GetModelIndex())
|
|
)
|
|
{
|
|
// Check if centres of these objects are close to each other,
|
|
// and also if their positions are both inside each other's bounding boxes
|
|
|
|
Vector3 vCentre1;
|
|
Vector3 vCentre2;
|
|
pOtherObject->GetBoundCentre(vCentre2);
|
|
pObject->GetBoundCentre(vCentre1);
|
|
spdAABB tempBox1;
|
|
spdAABB tempBox2;
|
|
const spdAABB &box1 = pObject->GetBoundBox(tempBox1);
|
|
const spdAABB &box2 = pOtherObject->GetBoundBox(tempBox2);
|
|
float fSeperationSq = (vCentre1 - vCentre2).Mag2();
|
|
|
|
if((fSeperationSq < fDuplicateSepThresholdSq)
|
|
&& box1.ContainsPoint(RCC_VEC3V(vCentre2))
|
|
&& box2.ContainsPoint(RCC_VEC3V(vCentre1))
|
|
//&& (pOtherObject->GetPhysArch()->GetBound()->GetName() == pObject->GetPhysArch()->GetBound()->GetName())
|
|
)
|
|
{
|
|
// Objects are overlapping so highlight them
|
|
|
|
if(CDebugScene::bDisplayDuplicateObjectsBB)
|
|
{
|
|
CDebugScene::DrawEntityBoundingBox(pObject, Color32(255,0,0));
|
|
CDebugScene::DrawEntityBoundingBox(pOtherObject, Color32(0,255,0));
|
|
}
|
|
if(CDebugScene::bDisplayDuplicateObjectsOnVMap)
|
|
{
|
|
CVectorMap::DrawMarker(VEC3V_TO_VECTOR3(pObject->GetTransform().GetPosition()),Color32(255,0,0));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // End if display duplicate objects
|
|
|
|
//--------------------------------------------------------------------------
|
|
// PICKUPS
|
|
if (bDisplayPickupsOnVMap)
|
|
{
|
|
CPickupPlacement::Pool *PickupPool = CPickupPlacement::GetPool();
|
|
CPickupPlacement* pPlacement;
|
|
s32 i=PickupPool->GetSize();
|
|
s32 numPickups = 0;
|
|
|
|
while(i--)
|
|
{
|
|
pPlacement = PickupPool->GetSlot(i);
|
|
|
|
if(pPlacement)
|
|
{
|
|
numPickups++;
|
|
Color32 Colour(128, 128, 128, 255);
|
|
|
|
if (pPlacement->GetPickup())
|
|
{
|
|
if (pPlacement->GetPickup()->GetNetworkObject() && pPlacement->GetPickup()->GetNetworkObject()->GetPlayerOwner())
|
|
{
|
|
NetworkColours::NetworkColour colour = NetworkColours::GetDefaultPlayerColour(pPlacement->GetPickup()->GetNetworkObject()->GetPlayerOwner()->GetPhysicalPlayerIndex());
|
|
Colour = NetworkColours::GetNetworkColour(colour);
|
|
}
|
|
else
|
|
{
|
|
Colour = Color32(255, 0, 0, 255);
|
|
}
|
|
}
|
|
|
|
CVectorMap::DrawMarker(pPlacement->GetPickupPosition(), Colour);
|
|
}
|
|
}
|
|
sprintf(debugText, "Number of pickups in pool: %d %d", numPickups, CPickupPlacement::GetPool()->GetSize());
|
|
grcDebugDraw::AddDebugOutput(debugText);
|
|
}
|
|
|
|
#if __DEV
|
|
//--------------------------------------------------------------------------
|
|
// SCENE UPDATE
|
|
if (bDisplaySceneUpdateCostOnVMap)
|
|
{
|
|
if (bDisplaySceneUpdateCostSelectedOnly)
|
|
{
|
|
// Pick the selected entity and display the cost only for that one.
|
|
fwEntity *entity = g_PickerManager.GetSelectedEntity();
|
|
|
|
if (entity)
|
|
{
|
|
fwSceneUpdateExtension *extension = entity->GetExtension<fwSceneUpdateExtension>();
|
|
|
|
if (extension)
|
|
{
|
|
DisplaySceneUpdateCost(*entity, &iDisplaySceneUpdateCostStep);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Show the cost for all entities.
|
|
fwSceneUpdate::RunCustomCallbackBits(1 << iDisplaySceneUpdateCostStep, DisplaySceneUpdateCost, &iDisplaySceneUpdateCostStep);
|
|
}
|
|
}
|
|
#endif // __DEV
|
|
//--------------------------------------------------------------------------
|
|
// PORTALS
|
|
if (bDisplayPortalInstancesOnVMap)
|
|
{
|
|
CPortalInst::Pool *Pool = CPortalInst::GetPool();
|
|
CPortalInst* pPortalInst;
|
|
s32 i=Pool->GetSize();
|
|
s32 numObjects = 0;
|
|
|
|
while(i--)
|
|
{
|
|
pPortalInst = Pool->GetSlot(i);
|
|
|
|
if(pPortalInst)
|
|
{
|
|
numObjects++;
|
|
Color32 Colour(100, 100, 255, 100);
|
|
CVectorMap::DrawMarker(VEC3V_TO_VECTOR3(pPortalInst->GetTransform().GetPosition()), Colour);
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CAMERAS
|
|
if(bDisplayRemotePlayerCameras)
|
|
{
|
|
if(NetworkInterface::IsGameInProgress())
|
|
{
|
|
unsigned numRemotePhysicalPlayers = netInterface::GetNumRemotePhysicalPlayers();
|
|
const netPlayer * const *remotePhysicalPlayers = netInterface::GetRemotePhysicalPlayers();
|
|
|
|
for(unsigned index = 0; index < numRemotePhysicalPlayers; index++)
|
|
{
|
|
const CNetGamePlayer *pPlayer = SafeCast(const CNetGamePlayer, remotePhysicalPlayers[index]);
|
|
|
|
CPed* pPlayerPed = pPlayer->GetPlayerPed();
|
|
|
|
if(pPlayerPed)
|
|
{
|
|
grcViewport *pViewport = ((CNetObjPlayer*)pPlayerPed->GetNetworkObject())->GetViewport();
|
|
|
|
if(pViewport)
|
|
{
|
|
NetworkColours::NetworkColour colour = NetworkColours::GetDefaultPlayerColour(pPlayer->GetPhysicalPlayerIndex());
|
|
Color32 Colour = NetworkColours::GetNetworkColour(colour);
|
|
CVectorMap::DrawRemotePlayerCamera(RCC_MATRIX34(pViewport->GetCameraMtx()), pViewport->GetFarClip(), pViewport->GetTanHFOV(), Colour);
|
|
|
|
// draw the line from the actual to predicted position
|
|
bool playerInVehicle = pPlayerPed->GetPedConfigFlag( CPED_CONFIG_FLAG_InVehicle ) && pPlayerPed->GetMyVehicle();
|
|
Vector3 velocity = playerInVehicle ? (pPlayerPed->GetMyVehicle()->GetVelocity() * CVehiclePopulation::ms_NetworkPlayerPredictionTime) : pPlayerPed->GetVelocity();
|
|
Vector3 futurePosition = VEC3V_TO_VECTOR3(pPlayerPed->GetTransform().GetPosition()) + velocity; // predict one second into the future
|
|
|
|
if(!velocity.IsZero())
|
|
{
|
|
CVectorMap::DrawLine(VEC3V_TO_VECTOR3(pPlayer->GetPlayerPed()->GetTransform().GetPosition()), futurePosition, Colour, Colour);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if __DEV
|
|
//--------------------------------------------------------------------------
|
|
// NETWORKING
|
|
NetworkInterface::DisplayNetworkingVectorMap();
|
|
#endif // __DEV
|
|
}
|
|
#endif
|
|
#if __DEV
|
|
|
|
#if __BANK
|
|
void CDebugScene::UpdateSceneUpdateCostStep()
|
|
{
|
|
IF_COMMERCE_STORE_RETURN();
|
|
|
|
safecpy(DisplaySceneUpdateCostStepName, fwSceneUpdate::GetSceneUpdateName(1 << iDisplaySceneUpdateCostStep));
|
|
}
|
|
#endif // __BANK
|
|
|
|
void CDebugScene::DisplaySceneUpdateCost(fwEntity &entity, void *userData)
|
|
{
|
|
int updateToProfile = *((int *) userData);
|
|
Vec3V position = entity.GetTransform().GetPosition();
|
|
|
|
fwSceneUpdateExtension *extension = entity.GetExtension<fwSceneUpdateExtension>();
|
|
FastAssert(extension); // If we get to this function, it must have an extension.
|
|
|
|
float radius = (float) extension->m_timeSpent[updateToProfile] / 50.0f;
|
|
float colorRange = (float) extension->m_timeSpent[updateToProfile] / 100.0f;
|
|
colorRange = 1.0f - Clamp(colorRange, 0.0f, 1.0f);
|
|
|
|
Color32 color(1.0f, colorRange, colorRange);
|
|
|
|
CVectorMap::DrawCircle(RCC_VECTOR3(position), radius + 0.5f, color);
|
|
}
|
|
|
|
|
|
#endif //__DEV
|
|
|
|
#if !__FINAL
|
|
void CDebugScene::PreUpdate()
|
|
{
|
|
#if DR_ENABLED
|
|
if (debugPlayback::DebugRecorder::GetInstance())
|
|
{
|
|
debugPlayback::DebugRecorder::GetInstance()->PreUpdate();
|
|
}
|
|
#endif // DR_ENABLED
|
|
}
|
|
|
|
void CDebugScene::Update()
|
|
{
|
|
IF_COMMERCE_STORE_RETURN();
|
|
|
|
#if __BANK
|
|
FlushTuneWidgetQueue();
|
|
#endif // __BANK
|
|
|
|
g_pFocusEntity = FocusEntities_Get(0);
|
|
|
|
if( (FocusEntities_Get(0) == NULL) &&
|
|
(atStringHash(ms_focusEntity0AddressString) != atStringHashNone))
|
|
{
|
|
formatf(ms_focusEntity0AddressString, 64, "%s", "None");
|
|
|
|
DEV_ONLY( formatf(ms_focusEntity0ModelInfoString, 64, "%s", "None"); )
|
|
}
|
|
|
|
#if ENABLE_ASYNC_STRESS_TEST
|
|
if(WorldProbe::CShapeTestManager::ms_bAsyncStressTestEveryFrame)
|
|
{
|
|
WorldProbe::DebugAsyncStressTestOnce();
|
|
}
|
|
#endif // ENABLE_ASYNC_STRESS_TEST
|
|
|
|
#if __DEV
|
|
if(ms_makeFocusEntitiesFlash)
|
|
{
|
|
for(int i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
|
|
{
|
|
if(ms_focusEntities[i])
|
|
{
|
|
ms_focusEntities[i]->SetIsVisibleForModule( SETISVISIBLE_MODULE_DEBUG, (fwTimer::GetSystemFrameCount() & 1) );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Scenario update
|
|
CScenarioDebug::DebugUpdate();
|
|
|
|
CVehicleFactory::DebugUpdate();
|
|
UpdateAttachTest();
|
|
#endif // __DEV
|
|
|
|
if (CPad* pPad = (camInterface::GetDebugDirector().IsFreeCamActive() && CControlMgr::IsDebugPadOn() ? &CControlMgr::GetDebugPad() : CControlMgr::GetPlayerPad()))
|
|
{
|
|
static bool debugTouchInputEnabled = PARAM_touchDebug.Get();
|
|
#if RSG_ORBIS
|
|
if (!debugTouchInputEnabled)
|
|
{
|
|
debugTouchInputEnabled = pPad->GetButtonCircle() && pPad->GetButtonCross() && pPad->GetNumTouches() == 2;
|
|
}
|
|
#endif //RSG_ORBIS
|
|
|
|
if (debugTouchInputEnabled)
|
|
{
|
|
#if RSG_ORBIS
|
|
if (pPad->GetNumTouches() > 0)
|
|
#else
|
|
if (pPad->GetLeftShoulder2())
|
|
#endif // RSG_ORBIS
|
|
{
|
|
#if __BANK
|
|
DisableInputsForTouchDebug();
|
|
#endif
|
|
|
|
#if RSG_ORBIS
|
|
const bool twoTouches = (pPad->GetNumTouches() == 2);
|
|
#else
|
|
const bool twoTouches = false;
|
|
#endif // RSG_ORBIS
|
|
static u32 dirs = 0;
|
|
static const u32 left = BIT0;
|
|
static const u32 right = BIT1;
|
|
static const u32 up = BIT2;
|
|
static const u32 down = BIT3;
|
|
dirs |= pPad->GetDPadLeft() ? left : 0;
|
|
dirs |= pPad->GetDPadRight() ? right : 0;
|
|
dirs |= pPad->GetDPadUp() ? up : 0;
|
|
dirs |= pPad->GetDPadDown() ? down : 0;
|
|
|
|
if (!pPad->GetDPadDown() && !pPad->GetDPadLeft() && !pPad->GetDPadRight() && !pPad->GetDPadUp())
|
|
{
|
|
#if __BANK
|
|
if (pPad->ButtonTriangleJustUp())
|
|
{
|
|
ms_DebugTimerMode = (ms_DebugTimerMode + 1) % DTM_NUM_MODES;
|
|
|
|
switch (ms_DebugTimerMode)
|
|
{
|
|
case DTM_FrameCount:
|
|
{
|
|
break;
|
|
}
|
|
case DTM_TimerStart:
|
|
{
|
|
ms_DebugTimer = 0.0f;
|
|
break;
|
|
}
|
|
case DTM_Off:
|
|
{
|
|
ms_DebugTimer = -1.0f;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
#endif // __BANK
|
|
|
|
if (twoTouches && !PARAM_touchDebugDisableTwoTouchCommands.Get())
|
|
{
|
|
if (dirs == down)
|
|
{
|
|
// Delete focus peds.
|
|
for (int i = (CDebugScene::FOCUS_ENTITIES_MAX - 1); i >= 0; i--)
|
|
{
|
|
if (CEntity* pFocus = FocusEntities_Get(i))
|
|
{
|
|
if (pFocus->GetIsTypePed())
|
|
{
|
|
if (static_cast<const CPed*>(pFocus)->IsPlayer())
|
|
{
|
|
// Don't try deleting a player
|
|
continue;
|
|
}
|
|
}
|
|
|
|
CGameWorld::RemoveEntity(pFocus);
|
|
}
|
|
}
|
|
}
|
|
else if (dirs == up)
|
|
{
|
|
}
|
|
else if (dirs == left)
|
|
{
|
|
// Pause / unpause.
|
|
fwTimer::SetDeferredDebugPause(!fwTimer::IsGamePaused());
|
|
Displayf("Debug pause toggled by Orbis touchpad with -touchDebug on the commandline");
|
|
}
|
|
else if (dirs == right)
|
|
{
|
|
// Step a frame / pause.
|
|
if (fwTimer::IsGamePaused())
|
|
{
|
|
fwTimer::SetWantsToSingleStepNextFrame();
|
|
}
|
|
else
|
|
{
|
|
fwTimer::SetDeferredDebugPause(true);
|
|
}
|
|
}
|
|
else if (dirs == (right | up))
|
|
{
|
|
}
|
|
else if (dirs == (left | up))
|
|
{
|
|
}
|
|
else if (dirs == (down | right))
|
|
{
|
|
// Delete all except the focus ped.
|
|
CEntity* pFocusEnt = FocusEntities_Get(0);
|
|
CPed* pExceptPed = pFocusEnt && pFocusEnt->GetIsTypePed() ? static_cast<CPed*>(pFocusEnt) : nullptr;
|
|
CPedPopulation::RemoveAllPedsWithException(pExceptPed, CPedPopulation::PMR_ForceAllRandomAndMission);
|
|
}
|
|
else if (dirs == (down | left))
|
|
{
|
|
//Remove all vehicles except the players
|
|
CPed* pPed = CGameWorld::FindLocalPlayer();
|
|
CVehicle* pPlayerVehicle = pPed->GetVehiclePedInside();
|
|
|
|
CVehiclePopulation::RemoveAllVehsWithException(pPlayerVehicle);
|
|
|
|
CPedPopulation::RemoveAllPedsWithException(NULL, CPedPopulation::PMR_ForceAllRandomAndMission);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dirs == down)
|
|
{
|
|
// Down. Clear.
|
|
FocusEntities_Clear();
|
|
}
|
|
else if (dirs == up)
|
|
{
|
|
// Up. All.
|
|
FocusFilter filter;
|
|
filter.bAnimal = true;
|
|
filter.bBird = true;
|
|
filter.bHuman = true;
|
|
FocusEntities_Clear();
|
|
FocusAddClosestAIPed(filter);
|
|
}
|
|
else if (dirs == left)
|
|
{
|
|
// Left. Humans.
|
|
FocusFilter filter;
|
|
filter.bHuman = true;
|
|
FocusEntities_Clear();
|
|
FocusAddClosestAIPed(filter);
|
|
}
|
|
else if (dirs == right)
|
|
{
|
|
// Right. Animals.
|
|
FocusFilter filter;
|
|
filter.bAnimal = true;
|
|
FocusEntities_Clear();
|
|
FocusAddClosestAIPed(filter);
|
|
}
|
|
else if (dirs == (right | up))
|
|
{
|
|
// Up-Right. Vehicles.
|
|
FocusFilter filter;
|
|
filter.bVehicle = true;
|
|
FocusEntities_Clear();
|
|
FocusAddClosestAIPed(filter);
|
|
}
|
|
else if (dirs == (left | up))
|
|
{
|
|
// Up-Left. Player.
|
|
FocusFilter filter;
|
|
filter.bPlayer = true;
|
|
FocusEntities_Clear();
|
|
FocusAddClosestAIPed(filter);
|
|
}
|
|
else if (dirs == (down | right))
|
|
{
|
|
// Down-Right. All animals.
|
|
FocusFilter filter;
|
|
filter.bAnimal = true;
|
|
filter.bBird = true;
|
|
FocusEntities_Clear();
|
|
FocusAddClosestAIPed(filter);
|
|
}
|
|
else if (dirs == (down | left))
|
|
{
|
|
// Down-Left. Dead stuff!
|
|
FocusFilter filter;
|
|
filter.bDead = true;
|
|
filter.bAnimal = true;
|
|
filter.bBird = true;
|
|
filter.bHuman = true;
|
|
FocusEntities_Clear();
|
|
FocusAddClosestAIPed(filter);
|
|
}
|
|
}
|
|
|
|
// Clear the dirs var.
|
|
dirs = 0;
|
|
}
|
|
|
|
}
|
|
#if RSG_ORBIS
|
|
static u8 sequence = 0;
|
|
const u8 touchCount = pPad->GetNumTouches();
|
|
sequence = touchCount == 0 ? 0 : sequence;
|
|
sequence = (sequence == 0 && touchCount == 1) ? 1 : sequence;
|
|
sequence = (sequence == 1 && touchCount == 2) ? 2 : sequence;
|
|
sequence = (sequence == 2 && touchCount == 1) ? 3 : sequence;
|
|
sequence = (sequence == 3 && touchCount == 2) ? 4 : sequence;
|
|
if (sequence == 4)
|
|
{
|
|
sequence = 0;
|
|
if (!PARAM_touchDebugTapTapTapOhWhyHasTheGamePaused.Get())
|
|
{
|
|
fwTimer::SetDeferredDebugPause(!fwTimer::IsDebugPause());
|
|
}
|
|
}
|
|
#endif // RSG_ORBIS
|
|
}
|
|
}
|
|
|
|
#if __DEV
|
|
if(ms_bEraserEnabled)
|
|
{
|
|
// delete all focus entities
|
|
// This allows point and click erasing
|
|
DeleteFocusEntities();
|
|
}
|
|
#endif // __DEV
|
|
|
|
#if __BANK
|
|
CPedVariationDebug::DebugUpdate();
|
|
|
|
CVehicleDamage::UpdateNetworkDamageDebug();
|
|
if (ms_bEnableFocusEntityDragging)
|
|
{
|
|
UpdateFocusEntityDragging();
|
|
}
|
|
#endif //__BANK
|
|
|
|
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_F1, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
{
|
|
SetDisplayDebugSummary(!GetDisplayDebugSummary());
|
|
}
|
|
|
|
#if __BANK
|
|
ms_lastFrameMouseX = ioMouse::GetX();
|
|
ms_lastFrameMouseY = ioMouse::GetY();
|
|
#endif //__BANK
|
|
|
|
#if __BANK
|
|
// Init inspector gadget window thing
|
|
if (!m_pInspectorWindow)
|
|
{
|
|
CUiColorScheme colorScheme;
|
|
float afColumnOffsets[] = { 0.0f, 192.0f };
|
|
|
|
m_pInspectorWindow = rage_new CUiGadgetInspector(0.0f, 0.0f, 500.0f, GADGET_NUM, 2, afColumnOffsets, colorScheme);
|
|
m_pInspectorWindow->SetUpdateCellCB(PopulateDebugSceneInspectorWindowCB);
|
|
m_pInspectorWindow->SetNumEntries(GADGET_NUM);
|
|
|
|
if (!m_bIsInspectorAttached)
|
|
{
|
|
m_bIsInspectorAttached = true;
|
|
CGtaPickerInterface* pickerInterface = (CGtaPickerInterface*)g_PickerManager.GetInterface();
|
|
if (pickerInterface)
|
|
{
|
|
pickerInterface->AttachInspectorChild(m_pInspectorWindow);
|
|
}
|
|
}
|
|
}
|
|
#endif // __BANK
|
|
#if DR_ENABLED
|
|
if (debugPlayback::DebugRecorder::GetInstance())
|
|
{
|
|
debugPlayback::DebugRecorder::GetInstance()->Update();
|
|
}
|
|
#endif // DR_ENABLED
|
|
|
|
#if __BANK
|
|
INSTANCE_STORE.GetBoxStreamer().UpdateDebug();
|
|
g_fwMetaDataStore.GetBoxStreamer().UpdateDebug();
|
|
g_StaticBoundsStore.GetBoxStreamer().UpdateDebug();
|
|
#endif
|
|
}
|
|
|
|
void CDebugScene::PreRender()
|
|
{
|
|
}
|
|
|
|
// Templated function to make RederDebug code more paletable.
|
|
template<class T> void RenderDebugWholePool(void)
|
|
{
|
|
typename T::Pool* pPool = T::GetPool();
|
|
s32 poolSize = (s32) pPool->GetSize();
|
|
for(s32 slot = 0; slot < poolSize; ++slot)
|
|
{
|
|
const T* pItem = pPool->GetSlot(slot);
|
|
if(pItem)
|
|
{
|
|
pItem->RenderDebug();
|
|
}
|
|
}
|
|
}
|
|
|
|
#include<stdio.h>
|
|
|
|
void CDebugScene::Render_RenderThread()
|
|
{
|
|
IF_COMMERCE_STORE_RETURN();
|
|
|
|
// render physics simulation debug
|
|
#if __PFDRAW
|
|
|
|
grcDebugDraw::SetDefaultDebugRenderStates();
|
|
// Override lighting mode
|
|
grcLightState::SetEnabled(true);
|
|
|
|
const Matrix34 & cameraMtx = RCC_MATRIX34(grcViewport::GetCurrent()->GetCameraMtx());
|
|
GetRageProfileDraw().SendDrawCameraForServer(cameraMtx);
|
|
GetRageProfileDraw().Render();
|
|
GetRageProfileDraw().SetDrawImmediately(true);
|
|
#endif // __PFDRAW
|
|
|
|
CPhysics::RenderDebug();
|
|
|
|
#if __BANK
|
|
NetworkDebug::RenderDebug();
|
|
|
|
CAnimSceneManager::ProcessDebugRender();
|
|
#endif // __BANK
|
|
|
|
#if __PFDRAW
|
|
GetRageProfileDraw().SetDrawImmediately(false);
|
|
if(PFDGROUP_Fragment.WillDraw())
|
|
{
|
|
FRAGMGR->ProfileDraw();
|
|
}
|
|
#endif
|
|
|
|
#if __BANK
|
|
// render procedural object debug info
|
|
g_procObjMan.RenderDebug();
|
|
#endif //__BANK
|
|
|
|
#if __BANK
|
|
CWorldDebugHelper::DrawDebug();
|
|
gWorldMgr.DrawDebug();
|
|
CSceneIsolator::Draw();
|
|
g_SceneCostTracker.DrawDebug();
|
|
DEBUGSTREAMGRAPH.DrawDebug();
|
|
|
|
#if ENABLE_STATS_CAPTURE
|
|
MetricsCapture::DrawWindows();
|
|
#endif // ENABLE_STATS_CAPTURE
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#if DEBUG_DRAW
|
|
extern bool bDisplayName; // In PedVariationMgr.cpp
|
|
extern bool bDisplayFadeValue; // in pedvariationMgr.cpp
|
|
extern bool bShowMissingLowLOD; // In ped.cpp
|
|
extern bool bShowPedLODLevelData; // in ped.cpp
|
|
//extern bool CVehicleFactory::ms_bShowVehicleLODLevelData; // in vehicleFactory.cpp
|
|
#endif
|
|
|
|
void CDebugScene::Render_MainThread()
|
|
{
|
|
#if USE_PROFILER_BASIC
|
|
AttachProfilingVariables();
|
|
#endif
|
|
|
|
#if DEBUG_DRAW
|
|
//Process ped debug visualiser keys every frame
|
|
CPedDebugVisualiserMenu::Process();
|
|
CVehicleDebugVisualiser::Process();
|
|
#endif
|
|
|
|
PF_AUTO_PUSH_TIMEBAR("CDebugScene::Render_MainThread");
|
|
|
|
IF_COMMERCE_STORE_RETURN();
|
|
|
|
// Patrol route rendering
|
|
CPatrolRoutes::DebugRenderRoutes();
|
|
|
|
#if SCENARIO_DEBUG
|
|
// Scenario rendering
|
|
CScenarioDebug::DebugRender();
|
|
#endif // SCENARIO_DEBUG
|
|
|
|
#if __BANK
|
|
// Scenario rendering
|
|
CRandomEventManager::DebugRender();
|
|
#endif // __BANK
|
|
|
|
// Render cover-points, etc
|
|
CCover::Render();
|
|
|
|
#if __BANK
|
|
// Render the animation viewer?
|
|
CAnimViewer::DebugRender();
|
|
CAnimSceneManager::ProcessDebugRender();
|
|
#endif
|
|
|
|
#if __DEV
|
|
// IKManager viewer debug render
|
|
CIkManager::DebugRender();
|
|
#endif // __DEV
|
|
|
|
#if DEBUG_DRAW
|
|
// Ped debug visualiser rendering. Inputs processed at start of Render_MainThread.
|
|
CPedDebugVisualiserMenu::Render();
|
|
CIncidentManager::GetInstance().DebugRender();
|
|
CDispatchManager::GetInstance().DebugRender();
|
|
|
|
const CPed* pPlayerPed = FindPlayerPed();
|
|
if(pPlayerPed)
|
|
{
|
|
const CWanted* pWanted = pPlayerPed->GetPlayerWanted();
|
|
if(pWanted)
|
|
{
|
|
pWanted->DebugRender();
|
|
}
|
|
}
|
|
#endif // DEBUG_DRAW
|
|
|
|
#if __BANK // See JW
|
|
CWeaponDebug::RenderDebug(); //Render weapons debug.
|
|
CClimbDebug::RenderDebug(); //Render climbing debug.
|
|
CDropDownDetector::RenderDebug(); //Render drop down debug.
|
|
camManager::DebugRender(); //Render camera debug.
|
|
CVehiclePopulation::UpdateDebugDrawing(); // Vehicle population, vector map, etc
|
|
CVehicleAILodManager::Debug();
|
|
CJunctions::RenderDebug();
|
|
RenderDebugWholePool<CVehicle>();
|
|
CObjectPopulation::UpdateDebugDrawing();
|
|
#if USE_OLD_DEBUGWINDOW
|
|
CDebugWindowMgr::GetMgr().Draw();
|
|
#endif // USE_OLD_DEBUGWINDOW
|
|
CDebugTextureViewerWindowMgr::GetMgr().Draw();
|
|
g_UiGadgetRoot.DrawAll();
|
|
#endif // __BANK
|
|
|
|
#if __BANK
|
|
#if WORLD_PROBE_DEBUG
|
|
WorldProbe::GetShapeTestManager()->RenderDebug(); // Render game shape test debug.
|
|
#endif // WORLD_PROBE_DEBUG
|
|
CDeformableObjectManager::GetInstance().RenderDebug();
|
|
CVehicleGadgetForks::RenderDebug();
|
|
#endif // __BANK
|
|
|
|
#if __DEV
|
|
CNmDebug::RenderDebug(); // Render Natural Motion related debugging without an active NM task.
|
|
#endif // __DEV
|
|
|
|
if (CPatrolRoutes::ms_bRender2DEffects)
|
|
{
|
|
#if __DEV
|
|
CWorldPoints::RenderDebug();
|
|
#endif
|
|
}
|
|
|
|
#if __BANK
|
|
CShockingEventsManager::RenderShockingEvents();
|
|
#endif
|
|
|
|
#if __BANK
|
|
CFleeDebug::Render();
|
|
#endif
|
|
|
|
CCombatManager::GetInstance().DebugRender();
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
// display navmeshes, etc
|
|
#if __BANK
|
|
CPathServer::Visualise();
|
|
CScenarioBlockingAreas::RenderScenarioBlockingAreas();
|
|
#endif
|
|
|
|
#if __BANK
|
|
// display paths
|
|
ThePaths.RenderDebug();
|
|
CPedPopulation::RenderDebug();
|
|
#endif // __DEV
|
|
|
|
#if __BANK
|
|
// Print name of ped model above head.
|
|
if(bDisplayName || bShowMissingLowLOD || bDisplayFadeValue || bShowPedLODLevelData)
|
|
{
|
|
CPed::Pool &PedPool = *CPed::GetPool();
|
|
CPed* pPed;
|
|
s32 k= PedPool.GetSize();
|
|
while(k--)
|
|
{
|
|
pPed = PedPool.GetSlot(k);
|
|
if(pPed)
|
|
{
|
|
char debugText[50];
|
|
CPedModelInfo* pPMI = pPed->GetPedModelInfo();
|
|
Assert(pPMI);
|
|
|
|
sprintf(debugText, "OK");
|
|
|
|
if(bDisplayName){
|
|
sprintf(debugText, "%s", pPMI->GetModelName());
|
|
}
|
|
|
|
if(bDisplayFadeValue){
|
|
sprintf(debugText, "(%d)", pPed->GetPedDrawHandler().GetVarData().GetLODFadeValue());
|
|
}
|
|
|
|
if(bShowMissingLowLOD && !pPMI->GetVarInfo()->HasLowLODs()){
|
|
sprintf(debugText, "no LOD:%s", pPMI->GetModelName());
|
|
}
|
|
|
|
if (bShowPedLODLevelData)
|
|
{
|
|
Vector3 pedPos = VEC3V_TO_VECTOR3(pPed->GetTransform().GetPosition());
|
|
float pedDist = sqrtf(pedPos.Dist2(FRAGMGR->GetInterestMatrix().d));
|
|
|
|
if (pPed->GetPedDrawHandler().GetVarData().GetIsHighLOD()) { sprintf(debugText, " %3.0f : High", pedDist); }
|
|
else if (pPed->GetPedDrawHandler().GetVarData().GetIsSuperLOD()) { sprintf(debugText, " %3.0f : Super LOD", pedDist); }
|
|
else { sprintf(debugText," %3.0f : Standard", pedDist); }
|
|
}
|
|
|
|
grcDebugDraw::Text(VEC3V_TO_VECTOR3(pPed->GetTransform().GetPosition()) + Vector3(0.f,0.f,1.3f), CRGBA(255, 255, 128, 255), debugText);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Print debug vehicle stuff
|
|
if(CVehicleFactory::ms_bShowVehicleLODLevelData)
|
|
{
|
|
CVehicle::Pool &VehiclePool = *CVehicle::GetPool();
|
|
CVehicle* pVehicle;
|
|
s32 k = (s32) VehiclePool.GetSize();
|
|
while(k--)
|
|
{
|
|
pVehicle = VehiclePool.GetSlot(k);
|
|
if(pVehicle)
|
|
{
|
|
char debugText[64];
|
|
CVehicleModelInfo* pVMI = pVehicle->GetVehicleModelInfo();
|
|
Assert(pVMI);
|
|
|
|
sprintf(debugText, "OK");
|
|
|
|
if(bDisplayName){
|
|
sprintf(debugText, "%s", pVMI->GetModelName());
|
|
}
|
|
|
|
// if(bShowMissingLowLOD && !pVMI->GetVarInfo()->HasLowLODs()){
|
|
// sprintf(debugText, "no LOD:%s", pPMI->GetModelName());
|
|
// }
|
|
|
|
if (CVehicleFactory::ms_bShowVehicleLODLevelData)
|
|
{
|
|
Vector3 vehiclePos = VEC3V_TO_VECTOR3(pVehicle->GetTransform().GetPosition());
|
|
float vehicleDist = sqrtf(vehiclePos.Dist2(FRAGMGR->GetInterestMatrix().d));
|
|
|
|
{
|
|
rmcDrawable *drawable = pVMI->GetDrawable();
|
|
if (drawable){
|
|
float dist0 = drawable->GetLodGroup().GetLodThresh(LOD_HIGH);
|
|
float dist1 = drawable->GetLodGroup().GetLodThresh(LOD_MED);
|
|
float dist2 = drawable->GetLodGroup().GetLodThresh(LOD_LOW);
|
|
float dist3 = drawable->GetLodGroup().GetLodThresh(LOD_VLOW);
|
|
u32 exists0 = drawable->GetLodGroup().ContainsLod(LOD_HIGH);
|
|
u32 exists1 = drawable->GetLodGroup().ContainsLod(LOD_MED);
|
|
u32 exists2 = drawable->GetLodGroup().ContainsLod(LOD_LOW);
|
|
u32 exists3 = drawable->GetLodGroup().ContainsLod(LOD_VLOW);
|
|
|
|
sprintf(debugText,"%s %2.0f : HD(%2.0f), (%2.0f,%2.0f,%2.0f,%2.0f) : (%d,%d,%d,%d)",
|
|
(pVehicle->GetIsCurrentlyHD() ? "STR HIGH" : ""),
|
|
vehicleDist, pVMI->GetHDDist(), dist0, dist1, dist2, dist3, exists0, exists1, exists2, exists3);
|
|
}
|
|
}
|
|
}
|
|
|
|
grcDebugDraw::Text(VEC3V_TO_VECTOR3(pVehicle->GetTransform().GetPosition()) + Vector3(0.f,0.f,1.3f), CRGBA(255, 255, 128, 255), debugText);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if(CAmbientClipStreamingManager::DISPLAY_AMBIENT_STREAMING_USE)
|
|
{
|
|
CAmbientClipStreamingManager::GetInstance()->DisplayAmbientStreamingUse();
|
|
}
|
|
|
|
#if __BANK
|
|
Color32 assetColors[fwBoxStreamerAsset::ASSET_TOTAL] =
|
|
{
|
|
Color32(255,0,0), /* ASSET_STATICBOUNDS_MOVER */
|
|
Color32(255,255,0), /* ASSET_STATICBOUNDS_WEAPONS */
|
|
Color32(0,255,255), /* ASSET_STATICBOUNDS_MATERIAL */
|
|
Color32(128,255,0), /* ASSET_MAPDATA_HIGH */
|
|
Color32(128,255,0), /* ASSET_MAPDATA_HIGH_CRITICAL */
|
|
Color32(128,255,0), /* ASSET_MAPDATA_MEDIUM */
|
|
Color32(128,255,0), /* ASSET_MAPDATA_LOW */
|
|
Color32(0,255,128) /* ASSET_METADATA */
|
|
};
|
|
INSTANCE_STORE.GetBoxStreamer().RenderDebug(assetColors);
|
|
g_fwMetaDataStore.GetBoxStreamer().RenderDebug(assetColors);
|
|
g_StaticBoundsStore.GetBoxStreamer().RenderDebug(assetColors);
|
|
#endif //__BANK
|
|
|
|
// Render the train tracks.
|
|
CTrain::RenderTrainDebug();
|
|
|
|
CVehicleRecordingMgr::Render();
|
|
|
|
#if __BANK
|
|
CWaypointRecording::Debug();
|
|
CCompEntity::DebugRender();
|
|
#endif
|
|
|
|
// Render the collision geometry of buildings & the world
|
|
if(CRenderer::sm_bRenderCollisionGeometry)
|
|
{
|
|
CDebugScene::RenderCollisionGeometry();
|
|
}
|
|
|
|
#if __DEV
|
|
CPortalInst::ShowPortalInstances();
|
|
CPortalTracker::RenderTrackerDebug();
|
|
CInteriorGroupManager::DrawDebug();
|
|
#endif
|
|
|
|
#if __BANK
|
|
CBoardingPointEditor::Process();
|
|
#endif
|
|
|
|
#if __JUNCTION_EDITOR
|
|
CJunctionEditor::Render();
|
|
#endif
|
|
|
|
#if __NAVEDITORS
|
|
CNavResAreaEditor::Render();
|
|
CNavDataCoverpointEditor::Render();
|
|
#endif
|
|
|
|
#if PRIORITIZED_CLIP_SET_STREAMER_WIDGETS
|
|
CPrioritizedClipSetStreamer::GetInstance().RenderDebug();
|
|
#endif
|
|
|
|
#if DEBUG_DRAW
|
|
CPrioritizedClipSetRequestManager::GetInstance().RenderDebug();
|
|
#endif // DEBUG_DRAW
|
|
|
|
#if __BANK
|
|
CTacticalAnalysis::Render();
|
|
|
|
if(bDisplayDoorPersistentInfo)
|
|
{
|
|
CDoorSystem::DebugDraw();
|
|
}
|
|
#endif
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
#if __DEV
|
|
|
|
if(ms_drawProximityArea)
|
|
{
|
|
// Determine if we should draw this frame or not.
|
|
bool drawThisFrame = true;
|
|
if(ms_drawProximityAreaFlashes)
|
|
{
|
|
static bool frameFlasher = true;
|
|
frameFlasher = !frameFlasher;
|
|
drawThisFrame = frameFlasher;
|
|
}
|
|
if(drawThisFrame)
|
|
{
|
|
Vec3V vMin(ms_proximityTestPoint.x-ms_proximityMaxAllowableRadialDiff, ms_proximityTestPoint.y-ms_proximityMaxAllowableRadialDiff, ms_proximityTestPoint.z-ms_proximityMaxAllowableVerticalDiff);
|
|
Vec3V vMax(ms_proximityTestPoint.x+ms_proximityMaxAllowableRadialDiff, ms_proximityTestPoint.y+ms_proximityMaxAllowableRadialDiff, ms_proximityTestPoint.z+ms_proximityMaxAllowableVerticalDiff);
|
|
grcDebugDraw::BoxAxisAligned(vMin,vMax,Color32(255, 100, 100, 255));
|
|
}
|
|
}
|
|
|
|
if (bDisplayDoorInfo)
|
|
{
|
|
CEntity* pCurrentEntity = GetEntityUnderMouse();
|
|
if(pCurrentEntity && pCurrentEntity->GetIsTypeObject() && ((CObject*)pCurrentEntity)->IsADoor())
|
|
{
|
|
Vector3 vecPosition = VEC3V_TO_VECTOR3(pCurrentEntity->GetTransform().GetPosition());
|
|
vecPosition.x = rage::Floorf(vecPosition.x + 0.5f);
|
|
vecPosition.y = rage::Floorf(vecPosition.y + 0.5f);
|
|
vecPosition.z = rage::Floorf(vecPosition.z + 0.5f);
|
|
|
|
grcDebugDraw::AddDebugOutput("Door %s, Pos (%g, %g, %g) %s", pCurrentEntity->GetModelName(), vecPosition.x, vecPosition.y, vecPosition.z, pCurrentEntity->IsBaseFlagSet(fwEntity::IS_FIXED) ? "Fixed" : "Not Fixed");
|
|
}
|
|
|
|
const int maxDoors = (int) CObject::GetPool()->GetSize();
|
|
for(int i = 0; i < maxDoors; i++)
|
|
{
|
|
const CObject* pObj = CObject::GetPool()->GetSlot(i);
|
|
if(!pObj || !pObj->IsADoor())
|
|
{
|
|
continue;
|
|
}
|
|
const CDoor* pDoor = static_cast<const CDoor*>(pObj);
|
|
|
|
char line1[1024];
|
|
char line2[1024];
|
|
char line3[1024];
|
|
char buff[1024];
|
|
|
|
const int doorType = pDoor->GetDoorType();
|
|
formatf(line1, "Door %s 0x%x, Open %.2f, Tgt %.2f, %s, Type %d", pDoor->GetModelName(), pDoor, pDoor->GetDoorOpenRatio(), pDoor->GetTargetDoorRatio(), pDoor->IsBaseFlagSet(fwEntity::IS_FIXED) ? "Fixed" : "Not Fixed", doorType);
|
|
|
|
if(CDoor::DoorTypeAutoOpens(doorType))
|
|
{
|
|
Vec3V testCenterV;
|
|
float testRadius;
|
|
pDoor->CalcAutoOpenInfo(testCenterV, testRadius);
|
|
bool taper = true;
|
|
const CDoorTuning* tuning = pDoor->GetTuning();
|
|
if (tuning)
|
|
{
|
|
taper = tuning->m_AutoOpenCloseRateTaper;
|
|
}
|
|
formatf(line2, "Auto Open: Override Rate %.2f, Override Distance %.2f, Used Rate %.2f, Used Dist %.2f %s", pDoor->GetAutomaticRate(), pDoor->GetAutomaticDist(), pDoor->GetEffectiveAutoOpenRate(), testRadius, (taper)? "Tapered":"");
|
|
}
|
|
else
|
|
{
|
|
line2[0] = '\0';
|
|
}
|
|
#if __BANK
|
|
float massX = 1.0f;
|
|
const char* tuningName = "No tuning";
|
|
StdDoorRotDir stdDoorRotDir = StdDoorOpenBothDir;
|
|
const CDoorTuning* tuning = pDoor->GetTuning();
|
|
if(tuning)
|
|
{
|
|
tuningName = CDoorTuningManager::GetInstance().FindNameForTuning(*tuning);
|
|
massX = tuning->m_MassMultiplier;
|
|
stdDoorRotDir = tuning->m_StdDoorRotDir;
|
|
}
|
|
|
|
const char* rotDir = "";
|
|
if (stdDoorRotDir == StdDoorOpenNegDir)
|
|
{
|
|
rotDir = "RotDir Neg";
|
|
}
|
|
else if (stdDoorRotDir == StdDoorOpenPosDir)
|
|
{
|
|
rotDir = "RotDir Pos";
|
|
}
|
|
formatf(line3, "%s XMass %.2f %s", tuningName, massX, rotDir);
|
|
#else
|
|
const CDoorTuning* tuning = pDoor->GetTuning();
|
|
if(tuning)
|
|
{
|
|
const char* rotDir = "";
|
|
if (tuning->m_StdDoorRotDir == StdDoorOpenNegDir)
|
|
{
|
|
rotDir = "RotDir Neg";
|
|
}
|
|
else if (tuning->m_StdDoorRotDir == StdDoorOpenPosDir)
|
|
{
|
|
rotDir = "RotDir Pos";
|
|
}
|
|
|
|
formatf(line3, "XMass %.2f %s", tuning->m_MassMultiplier, rotDir);
|
|
}
|
|
else
|
|
{
|
|
line3[0] = '\0';
|
|
}
|
|
#endif
|
|
|
|
|
|
formatf(buff, "%s\n%s\n%s", line1, line2, line3);
|
|
|
|
grcDebugDraw::Text(pDoor->GetTransform().GetPosition(), Color_white, buff);
|
|
|
|
}
|
|
}
|
|
|
|
if (sm_VisualizeAutoOpenBounds)
|
|
{
|
|
const int maxDoors = (int) CObject::GetPool()->GetSize();
|
|
for(int i = 0; i < maxDoors; i++)
|
|
{
|
|
const CObject* pObj = CObject::GetPool()->GetSlot(i);
|
|
if(!pObj || !pObj->IsADoor())
|
|
{
|
|
continue;
|
|
}
|
|
const CDoor* pDoor = static_cast<const CDoor*>(pObj);
|
|
|
|
if(CDoor::DoorTypeAutoOpens(pDoor->GetDoorType()))
|
|
{
|
|
const CDoorTuning* tuning = pDoor->GetTuning();
|
|
if (!tuning || (tuning && !tuning->m_CustomTriggerBox))
|
|
{
|
|
Vec3V testCenterV;
|
|
float testRadius;
|
|
pDoor->CalcAutoOpenInfo(testCenterV, testRadius);
|
|
grcDebugDraw::Sphere(testCenterV, testRadius, Color32(0xFFFF0000), false);
|
|
}
|
|
else
|
|
{
|
|
spdAABB localBBox;
|
|
Mat34V mat;
|
|
pDoor->CalcAutoOpenInfoBox(localBBox, mat);
|
|
grcDebugDraw::BoxOriented(localBBox.GetMin(), localBBox.GetMax(), mat, Color32(0xFFFF0000), false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(ms_drawFocusEntitiesBoundBox || ms_drawFocusEntitiesBoundBoxOnVMap || ms_drawFocusEntitiesSkeleton ||
|
|
ms_drawFocusEntitiesSkeletonNonOrthonormalities || ms_drawFocusEntitiesSkeletonNonOrthoDataOnly || ms_drawFocusEntitiesSkeletonBoneNamesAndIds
|
|
|| ms_drawFocusEntitiesSkeletonChannels || ms_drawFocusEntitiesSkeletonNonOrthonoMats)
|
|
{
|
|
for(int i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
|
|
{
|
|
if(ms_focusEntities[i])
|
|
{
|
|
if(ms_drawFocusEntitiesBoundBox)
|
|
{
|
|
DrawEntityBoundingBox(ms_focusEntities[i], Color32(255, 0, 0, 255));
|
|
}
|
|
else if(ms_drawFocusEntitiesBoundBoxOnVMap)
|
|
{
|
|
// Make sure the VMap version flashesas if it was the entity drawing.
|
|
if(ms_focusEntities[i]->GetIsVisible())
|
|
{
|
|
DrawEntityBoundingBoxOnVMap(ms_focusEntities[i], Color32(255, 0, 0, 255));
|
|
}
|
|
else
|
|
{
|
|
DrawEntityBoundingBoxOnVMap(ms_focusEntities[i], Color32(255, 0, 0, 64));
|
|
}
|
|
}
|
|
|
|
if(ms_focusEntities[i]->GetIsDynamic())
|
|
{
|
|
#if DEBUG_DRAW
|
|
CDynamicEntity* pDynEnt = static_cast<CDynamicEntity*>(ms_focusEntities[i].Get());
|
|
if(pDynEnt->GetSkeleton())
|
|
{
|
|
for(int iBoneIndex = 0; iBoneIndex < pDynEnt->GetSkeleton()->GetSkeletonData().GetNumBones(); iBoneIndex++)
|
|
{
|
|
const crBoneData* boneData = pDynEnt->GetSkeletonData().GetBoneData(iBoneIndex);
|
|
|
|
Matrix34 matDraw;
|
|
pDynEnt->GetGlobalMtx(iBoneIndex,matDraw);
|
|
|
|
float fNonOrtho = matDraw.MeasureNonOrthonormality();
|
|
bool bNonOrtho = fNonOrtho >= 1.0f;
|
|
bool bDraw = !ms_drawFocusEntitiesSkeletonNonOrthoDataOnly || bNonOrtho;
|
|
|
|
if(!bDraw)
|
|
continue;
|
|
|
|
if( ms_drawFocusEntitiesSkeleton )
|
|
{
|
|
grcDebugDraw::Axis(matDraw,0.1f,true);
|
|
}
|
|
|
|
int lineNum = 0;
|
|
char printBuffer[512];
|
|
|
|
if( ms_drawFocusEntitiesSkeletonBoneNamesAndIds )
|
|
{
|
|
formatf(printBuffer,512,"%s, %i",boneData->GetName(), boneData->GetBoneId());
|
|
grcDebugDraw::Text(matDraw.d,Color_white, 0, (grcDebugDraw::GetScreenSpaceTextHeight()-1) * lineNum++, printBuffer, true);
|
|
}
|
|
|
|
if( ms_drawFocusEntitiesSkeletonNonOrthonormalities || ms_drawFocusEntitiesSkeletonNonOrthonoMats)
|
|
{
|
|
Color32 col = fNonOrtho >= 1.0f ? Color_red : Color_white;
|
|
|
|
if( fNonOrtho >= 100.0f )
|
|
{
|
|
col = Color_firebrick;
|
|
}
|
|
|
|
//Reasons for acceptable non-orthonormality
|
|
if( boneData->HasDofs(crBoneData::SCALE)
|
|
|| (Matrix33(matDraw).IsEqual(Matrix33(Matrix33::ZeroType) ) ) )
|
|
{
|
|
col = Color_copper;
|
|
}
|
|
|
|
if( ms_drawFocusEntitiesSkeletonNonOrthonormalities )
|
|
{
|
|
formatf(printBuffer,512,"%d:%f", iBoneIndex, fNonOrtho);
|
|
grcDebugDraw::Text(matDraw.d,col, 0, (grcDebugDraw::GetScreenSpaceTextHeight()-1) * lineNum++, printBuffer, true);
|
|
}
|
|
|
|
if( fNonOrtho >= 1.0f )
|
|
{
|
|
if(ms_drawFocusEntitiesSkeletonNonOrthonoMats)
|
|
{
|
|
formatf(printBuffer,512,"[%.3f, %.3f, %.3f][%.3f, %.3f, %.3f][%.3f, %.3f, %.3f]",
|
|
matDraw.a.x, matDraw.a.y, matDraw.a.z, matDraw.b.x, matDraw.b.y, matDraw.b.z, matDraw.c.x, matDraw.c.y, matDraw.c.z);
|
|
grcDebugDraw::Text(matDraw.d,col, 0, (grcDebugDraw::GetScreenSpaceTextHeight()-1) * lineNum++, printBuffer, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
if( ms_drawFocusEntitiesSkeletonChannels )
|
|
{
|
|
formatf(printBuffer,512,"Rot Channels:%s. Scale Channels:%s. Trans Channels:%s", boneData->HasDofs(crBoneData::ROTATION) ? "true" : "false", boneData->HasDofs(crBoneData::SCALE) ? "true" : "false", boneData->HasDofs(crBoneData::TRANSLATION) ? "true" : "false");
|
|
grcDebugDraw::Text(matDraw.d, Color_white, 0, (grcDebugDraw::GetScreenSpaceTextHeight()-1) * lineNum++, printBuffer, true);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(ms_drawFocusEntitiesInfo)
|
|
{
|
|
for(int i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
|
|
{
|
|
if(ms_focusEntities[i])
|
|
{
|
|
PrintInfoAboutEntity(ms_focusEntities[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
if(ms_drawFocusEntitiesCoverTuning)
|
|
{
|
|
for(int i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
|
|
{
|
|
if(ms_focusEntities[i])
|
|
{
|
|
PrintCoverTuningForEntity(ms_focusEntities[i]);
|
|
}
|
|
}
|
|
}
|
|
#endif // __BANK
|
|
|
|
#endif // __DEV
|
|
|
|
#if DEBUG_DRAW
|
|
if(GetDisplayDebugSummary())
|
|
{
|
|
bool curr = grcDebugDraw::GetDisplayDebugText();
|
|
grcDebugDraw::SetDisplayDebugText(true);
|
|
char debugText[1024];
|
|
|
|
GetDebugSummary(debugText, GetDisplayLODCounts());
|
|
|
|
char *pch = strtok (debugText, "\n");
|
|
while (pch != NULL)
|
|
{
|
|
grcDebugDraw::AddDebugOutput(pch);
|
|
pch = strtok (NULL, "\n");
|
|
}
|
|
|
|
grcDebugDraw::SetDisplayDebugText(curr);
|
|
}
|
|
#endif // DEBUG_DRAW
|
|
|
|
}
|
|
|
|
#endif //__FINAL
|
|
|
|
#endif //!__FINAL
|
|
|
|
#if __BANK
|
|
//
|
|
// PURPOSE : copies debug summary information in a buffer
|
|
//
|
|
// NOTE : The buffer has to be big enough !
|
|
void CDebugScene::GetDebugSummary(char* summary, bool addLodCount)
|
|
{
|
|
//num peds
|
|
if (CPed::Pool * pPedPool = CPed::GetPool())
|
|
{
|
|
int totalCount = pPedPool->GetNoOfUsedSpaces();
|
|
int otherCount = CPedPopulation::ms_nNumOnFootOther + CPedPopulation::ms_nNumInVehOther;
|
|
int missionCount = 0;
|
|
int reusedCount = 0;
|
|
int reusePool = 0;
|
|
for(int i=0; i<pPedPool->GetSize(); i++)
|
|
{
|
|
if(const CPed * pPed = pPedPool->GetSlot(i))
|
|
{
|
|
missionCount += (pPed->PopTypeIsMission() ? 1 : 0);
|
|
reusedCount += (pPed->GetPedConfigFlag(CPED_CONFIG_FLAG_PedWasReused) ? 1 : 0);
|
|
reusePool += (pPed->GetPedConfigFlag(CPED_CONFIG_FLAG_PedIsInReusePool) ? 1 : 0);
|
|
}
|
|
}
|
|
|
|
sprintf(summary, "Peds: %d/%d (mission: %d, scenario (foot/car) %d/%d, ambient: (foot/car) %d/%d, other: %d, reusePool: %d) Reused: %d\n",
|
|
totalCount, pPedPool->GetSize(), missionCount,
|
|
CPedPopulation::ms_nNumOnFootScenario,
|
|
CPedPopulation::ms_nNumInVehScenario,
|
|
CPedPopulation::ms_nNumOnFootAmbient,
|
|
CPedPopulation::ms_nNumInVehAmbient, otherCount, reusePool, reusedCount);
|
|
}
|
|
|
|
//num cars
|
|
int iVehiclePoolSize, iTotalNumVehicles, iNumMission, iNumParked, iNumAmbient, iNumDesiredAmbient, iNumReal, iNumRealTraffic, iNumDummy, iNumSuperDummy, iNumRandomGenerated, iNumPathGenerated, iNumCargenGenerated, iNumReused, iNumInReusePool;
|
|
CVehiclePopulation::GetPopulationCounts(iVehiclePoolSize, iTotalNumVehicles, iNumMission, iNumParked, iNumAmbient, iNumDesiredAmbient, iNumReal, iNumRealTraffic, iNumDummy, iNumSuperDummy, iNumRandomGenerated, iNumPathGenerated, iNumCargenGenerated, iNumReused, iNumInReusePool);
|
|
|
|
sprintf(summary, "%sCars: %d/%d (ambient: %d/%d, mission: %d, parked: %d, reusePool: %d) (real: %d(%d traffic), dummy: %d, superdummy: %d) Reused: %d\n",
|
|
summary, iTotalNumVehicles, iVehiclePoolSize,
|
|
iNumAmbient, iNumDesiredAmbient,
|
|
iNumMission, iNumParked, iNumInReusePool,
|
|
iNumReal, iNumRealTraffic, iNumDummy, iNumSuperDummy, iNumReused);
|
|
|
|
sprintf(summary, "%sRandom Cars: %d Path Cars: %d Cargen Cars: %d\n",
|
|
summary, iNumRandomGenerated, iNumPathGenerated, iNumCargenGenerated);
|
|
|
|
// Objects
|
|
CObject::Pool* objPool = CObject::GetPool();
|
|
CDummyObject::Pool* dummyObjPool = CDummyObject::GetPool();
|
|
|
|
if (objPool && dummyObjPool)
|
|
{
|
|
int totalObjects = (int) objPool->GetNoOfUsedSpaces();
|
|
int totalDummy = (int) dummyObjPool->GetNoOfUsedSpaces();
|
|
sprintf(summary, "%sObjects: %d/%d - Dummy Objects: %d/%d\n",
|
|
summary, totalObjects, objPool->GetSize(),
|
|
totalDummy, dummyObjPool->GetSize());
|
|
}
|
|
|
|
// Display active (and total) peds, ragdolls, objects, and vehicles.
|
|
s32 instPedsActive = 0;
|
|
s32 instPedsTotal = 0;
|
|
s32 instVehiclesActive = 0;
|
|
s32 instVehiclesTotal = 0;
|
|
s32 instObjectsTotal = 0;
|
|
s32 instObjectsActive = 0;
|
|
s32 instRagdollsActive = 0;
|
|
s32 instRagdollsTotal = 0;
|
|
for(int i = 0; CPhysics::GetLevel() && i < CPhysics::GetLevel()->GetMaxObjects(); ++i)
|
|
{
|
|
if(!CPhysics::GetLevel()->IsNonexistent(i))
|
|
{
|
|
phInst* pInst = CPhysics::GetLevel()->GetInstance(i);
|
|
CEntity* pEntity = CPhysics::GetEntityFromInst(pInst);
|
|
if(pEntity && pInst->GetClassType() != PH_INST_MAPCOL)
|
|
{
|
|
bool bActive = CPhysics::GetLevel()->IsActive(pInst->GetLevelIndex());
|
|
if(pEntity->GetIsTypeVehicle())
|
|
{
|
|
instVehiclesTotal++;
|
|
instVehiclesActive += bActive ? 1 : 0;
|
|
}
|
|
if(pEntity->GetIsTypeObject())
|
|
{
|
|
instObjectsTotal++;
|
|
instObjectsActive += bActive ? 1 : 0;
|
|
}
|
|
if(pEntity->GetIsTypePed())
|
|
{
|
|
instPedsTotal++;
|
|
instPedsActive += bActive ? 1 : 0;
|
|
if(((CPed*)pEntity)->GetRagdollState()==RAGDOLL_STATE_PHYS)
|
|
{
|
|
instRagdollsTotal++;
|
|
instRagdollsActive += bActive ? 1 : 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sprintf(summary, "%sPhysics instances (active/total): objects %d/%d, cars: %d/%d, peds: %d/%d, ragdolls: %d/%d\n",
|
|
summary, instObjectsActive, instObjectsTotal, instVehiclesActive, instVehiclesTotal,
|
|
instPedsActive, instPedsTotal, instRagdollsActive, instRagdollsTotal);
|
|
|
|
//num lights and shadow casting lights
|
|
int shadowLightCount=0;
|
|
int lightCount=0;
|
|
|
|
for (int i=0;i<Lights::m_numPrevSceneShadowLights;i++)
|
|
{
|
|
if (CParaboloidShadow::GetLightShadowIndex(Lights::m_prevSceneShadowLights[i],true)!=-1)
|
|
shadowLightCount++;
|
|
|
|
lightCount++;
|
|
}
|
|
|
|
sprintf(summary, "%slights: %d shadow casters:%d\n", summary, lightCount, shadowLightCount);
|
|
|
|
#if RAGE_TIMEBARS
|
|
s32 callcount;
|
|
float timea = 0.0f,timeb = 0.0f;
|
|
g_pfTB.GetFunctionTotals("Physics",callcount,timea,0);
|
|
g_pfTB.GetFunctionTotals("Script",callcount,timeb,0);
|
|
sprintf(summary, "%sscript: %.2fms physics: %.2fms\n", summary, timeb, timea);
|
|
#endif
|
|
|
|
// B*537883
|
|
if( addLodCount )
|
|
{
|
|
int iNumActive, iNumInactive;
|
|
int iNumPeds;
|
|
int iNumEventScanHi, iNumEventScanLo;
|
|
int iNumMotionTaskHi, iNumMotionTaskLo;
|
|
int iTimeslicingHi, iTimeslicingLo;
|
|
int iNumPhysicsHi, iNumPhysicsLo;
|
|
int iNumEntityScanHi, iNumEntityScanLo;
|
|
int iNumTimesliced;
|
|
|
|
sprintf(summary, "%sVehicle and Ped LOD Counts\n", summary);
|
|
|
|
// Get the info for the Vehicle LOD Counts.
|
|
sprintf(summary, "%sVehicles:-\n", summary);
|
|
CVehiclePopulation::GetVehicleLODCounts(true, iTotalNumVehicles, iNumReal, iNumDummy, iNumSuperDummy, iNumActive, iNumInactive, iNumTimesliced );
|
|
sprintf(summary, "%sParked: %i\n", summary, iTotalNumVehicles);
|
|
sprintf(summary, "%s%i real, %i dummy, %i superdummy\n", summary, iNumReal, iNumDummy, iNumSuperDummy);
|
|
sprintf(summary, "%s%i active, %i inactive\n", summary, iNumActive, iNumInactive);
|
|
sprintf(summary, "%s%i timesliced\n", summary, iNumTimesliced);
|
|
|
|
CVehiclePopulation::GetVehicleLODCounts(false, iTotalNumVehicles, iNumReal, iNumDummy, iNumSuperDummy, iNumActive, iNumInactive, iNumTimesliced );
|
|
sprintf(summary, "%sMoving: %i\n", summary, iTotalNumVehicles);
|
|
sprintf(summary, "%s%i real, %i dummy, %i superdummy\n", summary, iNumReal, iNumDummy, iNumSuperDummy);
|
|
sprintf(summary, "%s%i active, %i inactive\n", summary, iNumActive, iNumInactive);
|
|
sprintf(summary, "%s%i timesliced\n", summary, iNumTimesliced);
|
|
|
|
// Get the info for the Ped LOD Counts.
|
|
sprintf(summary, "%sPeds:-\n", summary);
|
|
CPedPopulation::GetPedLODCounts(iNumPeds, iNumEventScanHi, iNumEventScanLo, iNumMotionTaskHi, iNumMotionTaskLo, iNumPhysicsHi, iNumPhysicsLo, iNumEntityScanHi, iNumEntityScanLo, iNumActive, iNumInactive, iTimeslicingHi, iTimeslicingLo );
|
|
sprintf(summary, "%sCount = %i\n", summary, iNumPeds);
|
|
sprintf(summary, "%sEvent scanning (h:%i/l:%i), Motion task (h:%i/l:%i), physics(h:%i/l:%i), Entity scanning (h:%i/l:%i), Timeslicing (h:%i/l:%i)\n", summary, iNumEventScanHi, iNumEventScanLo, iNumMotionTaskHi, iNumMotionTaskLo, iNumPhysicsHi, iNumPhysicsLo, iNumEntityScanHi, iNumEntityScanLo, iTimeslicingHi, iTimeslicingLo);
|
|
sprintf(summary, "%s%i active, %i inactive\n", summary, iNumActive, iNumInactive);
|
|
}
|
|
}
|
|
|
|
CAuthoringHelper::CAuthoringHelper(const char* Label, bool useHelpersMenu)
|
|
{
|
|
Init();
|
|
m_Label = Label;
|
|
m_useHelpersMenu = useHelpersMenu;
|
|
}
|
|
|
|
CAuthoringHelper::~CAuthoringHelper()
|
|
{
|
|
if(ms_SelectedAuthorHelper == this)
|
|
{
|
|
ms_DistanceToCamera = FLT_MAX;
|
|
ms_SelectedAuthorHelper = NULL;
|
|
}
|
|
|
|
//if( ms_LastSelectedAuthorHelper == this)
|
|
//{
|
|
// ms_LastSelectedAuthorHelper = NULL;
|
|
//}
|
|
|
|
|
|
delete ms_pAuthorToolBar;
|
|
ms_pAuthorToolBar = NULL;
|
|
}
|
|
|
|
void CAuthoringHelper::Init()
|
|
{
|
|
m_ScreenSpaceTangentVector.Set(0.0f, 0.0f);
|
|
m_CurrentInput = NO_INPUT;
|
|
m_IsAxisSelected = false;
|
|
m_IsFirstUpdate = false;
|
|
m_useHelpersMenu = true;
|
|
|
|
m_AxisBox.RelativePositionOnAxis = 0.5f;
|
|
m_AxisBox.ScaledBoxDimensions = 0.5f;
|
|
m_AxisBox.NonScaledBoxDimenstions = 0.05f;
|
|
|
|
m_PlaneBox.RelativePositionOnAxis = 0.2f;
|
|
m_PlaneBox.ScaledBoxDimensions = 0.2f;
|
|
m_PlaneBox.NonScaledBoxDimenstions = 0.001f;
|
|
|
|
m_StartedTextInput = false;
|
|
}
|
|
|
|
|
|
void CAuthoringHelper::CreateBoxMatMinAndMaxVectors(const Matrix34& Mat, const Vector3& Axis, float scale, const Vector3& Offset, const BoxDimensions& Dimensions, Matrix34& BoxMat, Vector3& VecMin, Vector3& VecMax)
|
|
{
|
|
Matrix34 debugAxis(Mat);
|
|
Vector3 OffsetPos;
|
|
|
|
debugAxis.Transform(Offset, OffsetPos);
|
|
|
|
debugAxis.d = OffsetPos;
|
|
|
|
BoxMat = debugAxis;
|
|
|
|
Vector3 AxisVec(scale * Dimensions.RelativePositionOnAxis * Axis.x, scale * Dimensions.RelativePositionOnAxis * Axis.y, scale * Dimensions.RelativePositionOnAxis * Axis.z);
|
|
Vector3 AxisVecWorld;
|
|
|
|
BoxMat.Transform(AxisVec, AxisVecWorld);
|
|
|
|
//position matrix relative to scene origin
|
|
BoxMat.d = AxisVecWorld;
|
|
|
|
//create a local vector to create a collision box
|
|
|
|
for(int i = 0; i < 3; i++)
|
|
{
|
|
if(Axis[i] > 0.0f)
|
|
{
|
|
VecMax[i] = scale * Dimensions.ScaledBoxDimensions;
|
|
}
|
|
else
|
|
{
|
|
VecMax[i] = Dimensions.NonScaledBoxDimenstions;
|
|
}
|
|
}
|
|
|
|
// Create a min vector which is the opposite of the max
|
|
VecMin = VecMax;
|
|
|
|
VecMin.Scale(-1.0f);
|
|
};
|
|
|
|
void CAuthoringHelper::CreateTranslationCollisionBox(const Matrix34& Mat, const Vector3& Axis, float scale, const Vector3& Offset, const BoxDimensions& Dimensions, spdOrientedBB & Bound)
|
|
{
|
|
Matrix34 BoxMat;
|
|
Vector3 VecMin = VEC3_ZERO;
|
|
Vector3 VecMax = VEC3_ZERO;
|
|
|
|
CreateBoxMatMinAndMaxVectors(Mat, Axis, scale, Offset, Dimensions, BoxMat, VecMin, VecMax);
|
|
|
|
const spdAABB& LocalBox = spdAABB(VECTOR3_TO_VEC3V(VecMin), VECTOR3_TO_VEC3V(VecMax));
|
|
|
|
Bound.Set(LocalBox, MATRIX34_TO_MAT34V(BoxMat));
|
|
|
|
}
|
|
|
|
void CAuthoringHelper::RenderTranslationCollisionBox(const Matrix34& Mat, const Vector3& Axis, float scale, const Vector3& Offset,const Color32 color, const BoxDimensions& Dimensions)
|
|
{
|
|
Matrix34 BoxMat;
|
|
Vector3 VecMin = VEC3_ZERO;
|
|
Vector3 VecMax = VEC3_ZERO;
|
|
|
|
CreateBoxMatMinAndMaxVectors(Mat, Axis, scale, Offset, Dimensions, BoxMat, VecMin, VecMax);
|
|
|
|
grcDebugDraw::BoxOriented( VECTOR3_TO_VEC3V(VecMin), VECTOR3_TO_VEC3V(VecMax), MATRIX34_TO_MAT34V(BoxMat), color, false );
|
|
}
|
|
|
|
void CAuthoringHelper::UpdateMouseTranslationCollisionBox(spdOrientedBB & MouseProbe)
|
|
{
|
|
Vector3 mouseScreen, mouseFar;
|
|
CDebugScene::GetMousePointing(mouseScreen, mouseFar, false);
|
|
|
|
Matrix34 ScreenMouseMat;
|
|
|
|
Vector3 MouseFront = mouseFar - mouseScreen;
|
|
MouseFront.NormalizeSafe();
|
|
|
|
camFrame::ComputeWorldMatrixFromFront(MouseFront, ScreenMouseMat);
|
|
ScreenMouseMat.d = mouseScreen;
|
|
|
|
Vector3 LocalProbe(0.0f, 500.0f, 0.0f);
|
|
Vector3 ProbeWorld;
|
|
|
|
ScreenMouseMat.Transform(LocalProbe, ProbeWorld);
|
|
|
|
Matrix34 MouseMat(ScreenMouseMat);
|
|
MouseMat.d = ProbeWorld;
|
|
|
|
//grcDebugDraw::Axis(MouseMat, 1.0f, true);
|
|
|
|
Vector3 MouseLocalMax (0.001f, 500.0f, 0.001f);
|
|
Vector3 MouseLocalMin (-0.001f, -500.0f, -0.001f);
|
|
|
|
const spdAABB& MouseLocalBox = spdAABB(VECTOR3_TO_VEC3V(MouseLocalMin), VECTOR3_TO_VEC3V(MouseLocalMax));
|
|
MouseProbe.Set(MouseLocalBox, MATRIX34_TO_MAT34V(MouseMat));
|
|
}
|
|
|
|
void CAuthoringHelper::RenderTranslationHelper(const Matrix34& AuthoringMat, float Scale, const Vector3& UNUSED_PARAM(Offset))
|
|
{
|
|
|
|
|
|
#if DEBUG_DRAW
|
|
//grcDebugDraw::Axis(AuthoringMat, Scale, true);
|
|
grcDebugDraw::GizmoPosition(MATRIX34_TO_MAT34V(AuthoringMat), Scale, m_CurrentInput);
|
|
#endif
|
|
|
|
#if 0 //enable this if you want to see the collision boxes
|
|
if(ms_SelectedAuthorHelper == this || ms_SelectedAuthorHelper == NULL)
|
|
{
|
|
Vector3 XYAxis = XAXIS + YAXIS;
|
|
Vector3 XZAxis = XAXIS + ZAXIS;
|
|
Vector3 ZYAxis = ZAXIS + YAXIS;
|
|
|
|
if(m_CurrentInput != XY_PLANE)
|
|
{
|
|
CAuthoringHelper::RenderTranslationCollisionBox(AuthoringMat, XYAxis, Scale, VEC3_ZERO, Color_red, m_PlaneBox);
|
|
}
|
|
else
|
|
{
|
|
CAuthoringHelper::RenderTranslationCollisionBox(AuthoringMat, XYAxis, Scale, VEC3_ZERO, Color_white, m_PlaneBox);
|
|
}
|
|
|
|
if(m_CurrentInput != XZ_PLANE)
|
|
{
|
|
CAuthoringHelper::RenderTranslationCollisionBox(AuthoringMat, XZAxis, Scale, VEC3_ZERO, Color_blue, m_PlaneBox);
|
|
}
|
|
else
|
|
{
|
|
CAuthoringHelper::RenderTranslationCollisionBox(AuthoringMat, XZAxis, Scale, VEC3_ZERO, Color_white, m_PlaneBox);
|
|
}
|
|
|
|
if(m_CurrentInput != ZY_PLANE)
|
|
{
|
|
CAuthoringHelper::RenderTranslationCollisionBox(AuthoringMat, ZYAxis, Scale, VEC3_ZERO, Color_green, m_PlaneBox);
|
|
}
|
|
else
|
|
{
|
|
CAuthoringHelper::RenderTranslationCollisionBox(AuthoringMat, ZYAxis, Scale, VEC3_ZERO, Color_white, m_PlaneBox);
|
|
}
|
|
|
|
if(m_CurrentInput == X_AXIS)
|
|
{
|
|
RenderTranslationCollisionBox(AuthoringMat, XAXIS, Scale, VEC3_ZERO, Color_white, m_AxisBox);
|
|
}
|
|
|
|
if(m_CurrentInput == Y_AXIS)
|
|
{
|
|
RenderTranslationCollisionBox(AuthoringMat, YAXIS, Scale, VEC3_ZERO, Color_white, m_AxisBox);
|
|
}
|
|
|
|
if(m_CurrentInput == Z_AXIS)
|
|
{
|
|
RenderTranslationCollisionBox(AuthoringMat, ZAXIS, Scale, VEC3_ZERO, Color_white, m_AxisBox);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
Vector3 CAuthoringHelper::UpdateTranslationAxis(const Matrix34& Mat, const Vector3& Axis ,const spdPlane& Plane )
|
|
{
|
|
//if(CDebugScene::GetMouseDX() == 0 && CDebugScene::GetMouseDY() == 0)
|
|
int MouseDx = ioMouse::GetX() - m_LastFrameMouseX;
|
|
int MouseDy = ioMouse::GetY() - m_LastFrameMouseY;
|
|
|
|
if( MouseDx == 0 && MouseDy == 0)
|
|
{
|
|
return VEC3_ZERO;
|
|
}
|
|
|
|
Vector3 mouseScreen, mouseFar;
|
|
//CDebugScene::GetMousePointing(mouseScreen, mouseFar, false);
|
|
float windowX, windowY;
|
|
|
|
//get current screen space of matrix origin
|
|
CDebugScene::GetScreenPosFromWorldPoint(Mat.d, windowX, windowY);
|
|
|
|
const float viewportX = windowX + (float)MouseDx;
|
|
const float viewportY = windowY + (float)MouseDy;
|
|
|
|
//Displayf("mouse: %f, %f ", (float)(ioMouse::GetX() - m_lastFrameMouseX), (float)(ioMouse::GetX() - m_lastFrameMouseX));
|
|
|
|
gVpMan.GetGameViewport()->GetGrcViewport().ReverseTransform(viewportX, viewportY, (Vec3V&)mouseScreen, (Vec3V&)mouseFar);
|
|
|
|
Vec3V WorldPos;
|
|
|
|
Vector3 Dir = mouseFar - mouseScreen;
|
|
|
|
Plane.IntersectRayV(VECTOR3_TO_VEC3V(mouseScreen), VECTOR3_TO_VEC3V(Dir), WorldPos);
|
|
|
|
// Displayf("Mat.d: %f, %f ", (float)CDebugScene::GetMouseDX(), (float)CDebugScene::GetMouseDY());
|
|
|
|
Vector3 LocalToMat;
|
|
|
|
//grcDebugDraw::Sphere( WorldPos, 0.2f, Color_blue );
|
|
|
|
Mat.UnTransform(VEC3V_TO_VECTOR3(WorldPos), LocalToMat);
|
|
|
|
Vector3 FinalVectorToApply = VEC3_ZERO;
|
|
|
|
for(int i =0; i < 3; i++)
|
|
{
|
|
Vector3 LocalAxis = VEC3_ZERO;
|
|
Vector3 MatAxis = VEC3_ZERO;
|
|
float AxisScalar = 0.0f;
|
|
|
|
if(Axis[i] > 0.0f && i == 0)
|
|
{
|
|
MatAxis = Mat.a;
|
|
LocalAxis = XAXIS;
|
|
}
|
|
|
|
if(Axis[i] > 0.0f && i == 1)
|
|
{
|
|
MatAxis = Mat.b;
|
|
LocalAxis = YAXIS;
|
|
}
|
|
|
|
if(Axis[i] > 0.0f && i == 2)
|
|
{
|
|
MatAxis = Mat.c;
|
|
LocalAxis = ZAXIS;
|
|
}
|
|
|
|
AxisScalar = LocalAxis.Dot(LocalToMat);
|
|
FinalVectorToApply += MatAxis * AxisScalar;
|
|
}
|
|
|
|
return FinalVectorToApply;
|
|
}
|
|
|
|
bool CAuthoringHelper::Update(Matrix34& mat)
|
|
{
|
|
Vector3 Offset(VEC3_ZERO);
|
|
float Scale = 1.0f;
|
|
|
|
Matrix34 parentMat(Matrix34::IdentityType);
|
|
|
|
return Update(mat, Scale, Offset, mat, parentMat);
|
|
}
|
|
|
|
bool CAuthoringHelper::Update(const Matrix34& mat, float Scale, const Vector3& Offset, Matrix34& UpdatedMat)
|
|
{
|
|
const Matrix34 parentMat(Matrix34::IdentityType);
|
|
|
|
return Update(mat, Scale, Offset, UpdatedMat, parentMat);
|
|
}
|
|
|
|
bool CAuthoringHelper::Update(const Matrix34& mat, float Scale, const Vector3& Offset, Matrix34& UpdatedMat, const Matrix34& ParentMat)
|
|
{
|
|
UpdatedMat = mat;
|
|
|
|
//UpdateHelperFromInput(UpdatedMat);
|
|
|
|
UpdatedMat.Dot(ParentMat);
|
|
|
|
bool update = false;
|
|
|
|
UpdateAuthorUi(UpdatedMat);
|
|
|
|
if(ms_AuthorMode == TRANS_GBL || ms_AuthorMode == TRANS_LCL)
|
|
{
|
|
update = UpdateTranslationHelper(UpdatedMat, Scale, Offset, UpdatedMat);
|
|
}
|
|
|
|
if(ms_AuthorMode == ROT_GBL || ms_AuthorMode == ROT_LCL)
|
|
{
|
|
update = UpdateRotationHelper(UpdatedMat, Scale, Offset, UpdatedMat);
|
|
}
|
|
|
|
|
|
Assertf(UpdatedMat.IsOrthonormal(), "Helper produced non orthonormal");
|
|
|
|
|
|
if(m_Label.GetLength() > 0)
|
|
{
|
|
grcDebugDraw::Text(UpdatedMat.d, Color_black, 0, 0, m_Label.c_str());
|
|
}
|
|
|
|
UpdatedMat.DotTranspose(ParentMat);
|
|
|
|
m_LastFrameMouseY = ioMouse::GetY();
|
|
m_LastFrameMouseX = ioMouse::GetX();
|
|
|
|
return update;
|
|
}
|
|
|
|
//void CAuthoringHelper::UpdateHelperFromInput(Matrix34& UpdatedMat)
|
|
//{
|
|
// if(ms_pAuthorToolBar && ms_LastSelectedAuthorHelper == this)
|
|
// {
|
|
// float userValue = 0.0f;
|
|
// s32 authorMode = ms_pAuthorToolBar->GetCurrentIndex();
|
|
// char info[64];
|
|
//
|
|
// if(ms_pAuthorToolBar->UserProcessClick())
|
|
// {
|
|
// s32 currentAuthorMode = ms_pAuthorToolBar->GetCurrentIndex();
|
|
// if(ms_AuthorMode == TRANS_GBL || ms_AuthorMode == TRANS_LCL)
|
|
// {
|
|
// m_StartedTextInput = false;
|
|
// m_Keyboardbuffer.Clear();
|
|
//
|
|
// if(currentAuthorMode == INPUT_X)
|
|
// {
|
|
// char temp[32];
|
|
// formatf(temp, "%f", UpdatedMat.d.x);
|
|
// m_Keyboardbuffer =temp;
|
|
// }
|
|
//
|
|
// if(currentAuthorMode == INPUT_Y)
|
|
// {
|
|
// char temp[32];
|
|
// formatf(temp, "%f", UpdatedMat.d.y);
|
|
// m_Keyboardbuffer =temp;
|
|
// }
|
|
// if(currentAuthorMode == INPUT_Z)
|
|
// {
|
|
// char temp[32];
|
|
// formatf(temp, "%f", UpdatedMat.d.z);
|
|
// m_Keyboardbuffer =temp;
|
|
// }
|
|
//
|
|
// }
|
|
// }
|
|
// if(authorMode == INPUT_X)
|
|
// {
|
|
// formatf(info, "X:%s", m_Keyboardbuffer.c_str());
|
|
// ms_pAuthorToolBar->SetCell(0, 4, NULL);
|
|
// ms_pAuthorToolBar->SetCell(0, 4, info);
|
|
// }
|
|
//
|
|
// if(authorMode == INPUT_Y)
|
|
// {
|
|
// formatf(info, "Y:%s", m_Keyboardbuffer.c_str());
|
|
// ms_pAuthorToolBar->SetCell(0, 5, NULL);
|
|
// ms_pAuthorToolBar->SetCell(0, 5, info);
|
|
// }
|
|
//
|
|
// if(authorMode == INPUT_Z)
|
|
// {
|
|
// formatf(info, "Z:%s", m_Keyboardbuffer.c_str());
|
|
// ms_pAuthorToolBar->SetCell(0, 6, NULL);
|
|
// ms_pAuthorToolBar->SetCell(0, 6, info);
|
|
// }
|
|
//
|
|
// if(UpdateKeyboardInput(userValue))
|
|
// {
|
|
// if(ms_AuthorMode == TRANS_GBL || ms_AuthorMode ==TRANS_LCL)
|
|
// {
|
|
// if(authorMode == INPUT_X)
|
|
// {
|
|
// UpdatedMat.d.x = userValue;
|
|
// }
|
|
//
|
|
// if(authorMode == INPUT_Y)
|
|
// {
|
|
// UpdatedMat.d.y = userValue;
|
|
// }
|
|
//
|
|
// if(authorMode == INPUT_Z)
|
|
// {
|
|
// UpdatedMat.d.z = userValue;
|
|
// }
|
|
// }
|
|
//
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
|
|
bool CAuthoringHelper::IsMakingAuthorMenuSelection()
|
|
{
|
|
if(ms_pAuthorToolBar)
|
|
{
|
|
return ms_pAuthorToolBar->ContainsMouse();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//bool CAuthoringHelper::UpdateKeyboardInput(float &newValue)
|
|
//{
|
|
// if(ms_pAuthorToolBar)
|
|
// {
|
|
// s32 authorMode = ms_pAuthorToolBar->GetCurrentIndex();
|
|
//
|
|
// if(authorMode == INPUT_X || authorMode == INPUT_Y || authorMode == INPUT_Z )
|
|
// {
|
|
// bool haveKeyInput = false;
|
|
// atString tempBuffer;
|
|
// if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_NUMPAD0, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
// {
|
|
// tempBuffer += "0";
|
|
// haveKeyInput = true;
|
|
// }
|
|
//
|
|
// if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_NUMPAD1, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
// {
|
|
// tempBuffer += "1";
|
|
// haveKeyInput = true;
|
|
// }
|
|
//
|
|
// if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_NUMPAD2, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
// {
|
|
// tempBuffer += "2";
|
|
// haveKeyInput = true;
|
|
// }
|
|
//
|
|
// if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_NUMPAD3, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
// {
|
|
// tempBuffer += "3";
|
|
// haveKeyInput = true;
|
|
// }
|
|
//
|
|
// if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_NUMPAD4, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
// {
|
|
// tempBuffer += "4";
|
|
// haveKeyInput = true;
|
|
// }
|
|
//
|
|
// if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_NUMPAD5, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
// {
|
|
// tempBuffer += "5";
|
|
// haveKeyInput = true;
|
|
// }
|
|
//
|
|
// if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_NUMPAD6, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
// {
|
|
// tempBuffer += "6";
|
|
// haveKeyInput = true;
|
|
// }
|
|
//
|
|
// if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_NUMPAD7, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
// {
|
|
// tempBuffer += "7";
|
|
// haveKeyInput = true;
|
|
// }
|
|
//
|
|
// if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_NUMPAD8, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
// {
|
|
// tempBuffer += "8";
|
|
// haveKeyInput = true;
|
|
//
|
|
// }
|
|
//
|
|
// if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_NUMPAD9, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
// {
|
|
// tempBuffer += "9";
|
|
// haveKeyInput = true;
|
|
// }
|
|
//
|
|
// if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SUBTRACT, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
// {
|
|
// if(!m_StartedTextInput)
|
|
// {
|
|
// tempBuffer += "-";
|
|
// haveKeyInput = true;
|
|
// }
|
|
// }
|
|
//
|
|
// if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_DECIMAL, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
// {
|
|
// if(m_StartedTextInput)
|
|
// {
|
|
// if(m_Keyboardbuffer.IndexOf(".") == -1 && m_Keyboardbuffer.GetLength() != 0)
|
|
// {
|
|
// tempBuffer += ".";
|
|
// haveKeyInput = true;
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// if(haveKeyInput)
|
|
// {
|
|
// if(!m_StartedTextInput)
|
|
// {
|
|
// m_StartedTextInput = true;
|
|
// m_Keyboardbuffer.Clear();
|
|
// }
|
|
// m_Keyboardbuffer += tempBuffer;
|
|
// }
|
|
//
|
|
// if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_NUMPADENTER, KEYBOARD_MODE_DEBUG, "Toggle debug summary")||
|
|
// CControlMgr::GetKeyboard().GetKeyJustDown(KEY_RETURN, KEYBOARD_MODE_DEBUG, "Toggle debug summary"))
|
|
// {
|
|
// //ms_pAuthorToolBar->SetCurrentIndex(ms_AuthorMode);
|
|
// m_StartedTextInput = false;
|
|
// newValue = (float) atof(m_Keyboardbuffer.c_str());
|
|
// //m_Keyboardbuffer.Clear();
|
|
//
|
|
// return true;
|
|
//
|
|
// }
|
|
// }
|
|
// }
|
|
// return false;
|
|
//};
|
|
|
|
void CAuthoringHelper::UpdateAuthorUi(const Matrix34& UpdatedMat)
|
|
{
|
|
if(m_useHelpersMenu)
|
|
{
|
|
CreateAuthorUi();
|
|
|
|
if(ms_pAuthorToolBar)
|
|
{
|
|
ms_pAuthorToolBar->RequestSetViewportToShowSelected();
|
|
|
|
ms_pAuthorToolBar->SetDisplay(true);
|
|
|
|
s32 authorMode = ms_pAuthorToolBar->GetCurrentIndex();
|
|
|
|
if(ms_pAuthorToolBar->UserProcessClick())
|
|
{
|
|
s32 currentAuthorMode = ms_pAuthorToolBar->GetCurrentIndex();
|
|
|
|
authorMode = currentAuthorMode;
|
|
|
|
if(authorMode < MAX_AUTHOR_MODES && authorMode > NO_AUTHOR_MODE)
|
|
{
|
|
ms_AuthorMode = authorMode;
|
|
}
|
|
}
|
|
|
|
if(ms_SelectedAuthorHelper == this)
|
|
{
|
|
if(ms_AuthorMode == TRANS_GBL || ms_AuthorMode == TRANS_LCL)
|
|
{
|
|
char info[64];
|
|
|
|
formatf(info, "X:%f", UpdatedMat.d.x);
|
|
ms_pAuthorToolBar->SetCell(0, 4, info);
|
|
|
|
formatf(info, "Y:%f", UpdatedMat.d.y);
|
|
ms_pAuthorToolBar->SetCell(0, 5, info);
|
|
|
|
formatf(info, "Z:%f", UpdatedMat.d.z);
|
|
ms_pAuthorToolBar->SetCell(0, 6, info);
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CAuthoringHelper::CreateAuthorUi()
|
|
{
|
|
if(ms_pAuthorToolBar == NULL)
|
|
{
|
|
|
|
ms_pAuthorToolBar = rage_new CUiGadgetSimpleListAndWindow("Author", 100.0f, 100.0f, 100.0f, 7);
|
|
ms_pAuthorToolBar->SetNumEntries(7);
|
|
ms_pAuthorToolBar->SetCell(0, 0, "Trans:GBL");
|
|
ms_pAuthorToolBar->SetCell(0, 1, "Trans:LCL");
|
|
ms_pAuthorToolBar->SetCell(0, 2, "Rot:GBL");
|
|
ms_pAuthorToolBar->SetCell(0, 3, "Rot:LCL");
|
|
ms_pAuthorToolBar->SetCell(0, 4, "X:");
|
|
ms_pAuthorToolBar->SetCell(0, 5, "Y:");
|
|
ms_pAuthorToolBar->SetCell(0, 6, "Z:");
|
|
ms_pAuthorToolBar->SetCurrentIndex(ms_AuthorMode);
|
|
}
|
|
}
|
|
|
|
void CAuthoringHelper::UpdateAxisRotation(const Matrix34& AuthoringMat, Matrix34& UpdatedMat, const Vector3& SelectionVec, const Vector3& SelectionWorld)
|
|
{
|
|
TUNE_GROUP_FLOAT( DEBUG_CONTROL, focusEntityRotationSensitivity, 0.01f, 0.000f, 100.0f,0.10f);
|
|
|
|
if(m_IsFirstUpdate)
|
|
{
|
|
Vector3 RotatedLocal(SelectionVec);
|
|
|
|
switch (m_CurrentInput)
|
|
{
|
|
case ROT_Z_PLANE: //Y
|
|
{
|
|
RotatedLocal.RotateZ(HALF_PI);
|
|
}
|
|
break;
|
|
case ROT_Y_PLANE:
|
|
{
|
|
RotatedLocal.RotateY(HALF_PI);
|
|
}
|
|
break;
|
|
case ROT_X_PLANE:
|
|
{
|
|
RotatedLocal.RotateX(HALF_PI);
|
|
}
|
|
break;
|
|
}
|
|
|
|
RotatedLocal.NormalizeSafe();
|
|
|
|
Vector3 Result = SelectionVec + RotatedLocal;
|
|
|
|
AuthoringMat.Transform(Result);
|
|
|
|
Vector2 Screenextend;
|
|
Vector2 ScreenBase;
|
|
|
|
CDebugScene::GetScreenPosFromWorldPoint(Result, Screenextend.x, Screenextend.y);
|
|
|
|
CDebugScene::GetScreenPosFromWorldPoint(SelectionWorld, ScreenBase.x, ScreenBase.y);
|
|
|
|
m_ScreenSpaceTangentVector = Screenextend - ScreenBase;
|
|
|
|
m_ScreenSpaceTangentVector.NormalizeSafe();
|
|
|
|
}
|
|
|
|
int MouseDx = ioMouse::GetX() - m_LastFrameMouseX;
|
|
int MouseDy = ioMouse::GetY() - m_LastFrameMouseY;
|
|
|
|
if( MouseDx != 0 || MouseDy != 0)
|
|
{
|
|
// if(CDebugScene::MouseMovedThisFrame())
|
|
// {
|
|
Vector2 MouseDelta((float)MouseDx, (float)MouseDy);
|
|
|
|
float heading = m_ScreenSpaceTangentVector.Dot(MouseDelta);
|
|
|
|
heading *= focusEntityRotationSensitivity;
|
|
|
|
switch (m_CurrentInput)
|
|
{
|
|
case ROT_Z_PLANE: //Y
|
|
{
|
|
if(ms_AuthorMode == ROT_LCL)
|
|
{
|
|
UpdatedMat.RotateLocalZ(heading);
|
|
}
|
|
else
|
|
{
|
|
UpdatedMat.RotateZ(heading);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ROT_Y_PLANE:
|
|
{
|
|
if(ms_AuthorMode == ROT_LCL)
|
|
{
|
|
UpdatedMat.RotateLocalY(heading);
|
|
}
|
|
else
|
|
{
|
|
UpdatedMat.RotateY(heading);
|
|
}
|
|
}
|
|
break;
|
|
case ROT_X_PLANE:
|
|
{
|
|
if(ms_AuthorMode == ROT_LCL)
|
|
{
|
|
UpdatedMat.RotateLocalX(heading);
|
|
}
|
|
else
|
|
{
|
|
UpdatedMat.RotateX(heading);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CAuthoringHelper::ShouldUpdateSelectedHelper(const Vector3& MatrixPosition )
|
|
{
|
|
bool ShouldUpdate = false;
|
|
if(m_CurrentInput != NO_INPUT)
|
|
{
|
|
//reset this
|
|
m_IsFirstUpdate = false;
|
|
|
|
if (ioMouse::GetReleasedButtons() & ioMouse::MOUSE_LEFT)
|
|
{
|
|
m_CurrentInput = NO_INPUT;
|
|
m_IsAxisSelected = false;
|
|
ms_SelectedAuthorHelper = NULL;
|
|
ms_DistanceToCamera = FLT_MAX;
|
|
}
|
|
|
|
if(ioMouse::GetPressedButtons() & ioMouse::MOUSE_LEFT)
|
|
{
|
|
//select the helper nearest the camera
|
|
float distToCamera = MatrixPosition.Dist2(camInterface::GetPos());
|
|
|
|
if(ms_SelectedAuthorHelper == NULL || distToCamera < ms_DistanceToCamera)
|
|
{
|
|
ms_SelectedAuthorHelper = this;
|
|
//ms_LastSelectedAuthorHelper = ms_SelectedAuthorHelper;
|
|
ms_DistanceToCamera = distToCamera;
|
|
m_IsAxisSelected = true;
|
|
m_IsFirstUpdate = true;
|
|
}
|
|
}
|
|
|
|
if(ioMouse::GetButtons() & ioMouse::MOUSE_LEFT && m_IsAxisSelected)
|
|
{
|
|
if(ms_SelectedAuthorHelper == this)
|
|
{
|
|
ShouldUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
return ShouldUpdate;
|
|
}
|
|
|
|
void CAuthoringHelper::RenderRotationHelper(const Matrix34& AuthoringMat, const Matrix34& updatedMat, float Scale)
|
|
{
|
|
#if DEBUG_DRAW
|
|
Matrix34 renderedMat(updatedMat);
|
|
renderedMat.d = AuthoringMat.d;
|
|
grcDebugDraw::Axis(renderedMat, Scale, true);
|
|
grcDebugDraw::GizmoRotation(MATRIX34_TO_MAT34V(AuthoringMat), Scale, m_CurrentInput);
|
|
#endif
|
|
|
|
#if 0
|
|
if(ms_SelectedAuthorHelper == this || ms_SelectedAuthorHelper == NULL)
|
|
{
|
|
if(m_CurrentInput != ROT_Z_PLANE)
|
|
{
|
|
grcDebugDraw::Circle(VECTOR3_TO_VEC3V(AuthoringMat.d), Scale, Color_blue, VECTOR3_TO_VEC3V(AuthoringMat.a), VECTOR3_TO_VEC3V(AuthoringMat.b), false, false,1, 30);
|
|
}
|
|
else
|
|
{
|
|
|
|
grcDebugDraw::Circle(VECTOR3_TO_VEC3V(AuthoringMat.d), Scale, Color_white, VECTOR3_TO_VEC3V(AuthoringMat.a), VECTOR3_TO_VEC3V(AuthoringMat.b), false, false,1, 30);
|
|
}
|
|
|
|
if(m_CurrentInput != ROT_Y_PLANE)
|
|
{
|
|
grcDebugDraw::Circle(VECTOR3_TO_VEC3V(AuthoringMat.d), Scale, Color_green, VECTOR3_TO_VEC3V(AuthoringMat.c), VECTOR3_TO_VEC3V(AuthoringMat.a), false, false,1, 30);
|
|
}
|
|
else
|
|
{
|
|
grcDebugDraw::Circle(VECTOR3_TO_VEC3V(AuthoringMat.d), Scale, Color_white, VECTOR3_TO_VEC3V(AuthoringMat.c), VECTOR3_TO_VEC3V(AuthoringMat.a), false, false,1, 30);
|
|
}
|
|
|
|
if(m_CurrentInput != ROT_X_PLANE)
|
|
{
|
|
grcDebugDraw::Circle(VECTOR3_TO_VEC3V(AuthoringMat.d), Scale, Color_red, VECTOR3_TO_VEC3V(AuthoringMat.c), VECTOR3_TO_VEC3V(AuthoringMat.b), false, false, 1,30);
|
|
}
|
|
else
|
|
{
|
|
grcDebugDraw::Circle(VECTOR3_TO_VEC3V(AuthoringMat.d), Scale, Color_white, VECTOR3_TO_VEC3V(AuthoringMat.c), VECTOR3_TO_VEC3V(AuthoringMat.b), false, false, 1,30);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
void CAuthoringHelper::UpdateRotationAxisSelection(const Matrix34& AuthoringMat, float Scale, Vector3& SelectionVec, Vector3&SelectionWorld)
|
|
{
|
|
if(!m_IsAxisSelected)
|
|
{
|
|
spdSphere sphere = spdSphere(VECTOR3_TO_VEC3V(AuthoringMat.d), ScalarV(Scale));
|
|
|
|
Vector3 mouseStart, mouseEnd;
|
|
CDebugScene::GetMousePointing(mouseStart, mouseEnd, false);
|
|
|
|
Vector3 w = mouseEnd - mouseStart;
|
|
w.Normalize();
|
|
|
|
Vector3 IntersectNear;
|
|
Vector3 IntersectFar;
|
|
Vector3 localNear(1.0f, 1.0f, 1.0f);
|
|
Vector3 localFar(1.0f, 1.0f, 1.0f);
|
|
bool isNearIntersection = false;
|
|
bool isFarIntersection = false;
|
|
|
|
TUNE_FLOAT(THIntersectTolerance, 0.08f, 0.0f, 1.0f, 0.001f)
|
|
|
|
if(fwGeom::IntersectSphereRay(sphere, mouseStart, w, IntersectNear, IntersectFar))
|
|
{
|
|
grcDebugDraw::Sphere(VECTOR3_TO_VEC3V(IntersectNear), 0.01f, Color_green);
|
|
grcDebugDraw::Sphere(VECTOR3_TO_VEC3V(IntersectFar), 0.01f, Color_red);
|
|
|
|
//convert the sphere intersection locally to the matrix
|
|
|
|
AuthoringMat.UnTransform(IntersectNear, localNear);
|
|
AuthoringMat.UnTransform(IntersectFar, localFar);
|
|
}
|
|
|
|
Vector3 LocalNear(localNear);
|
|
Vector3 LocalFar(localFar);
|
|
|
|
LocalNear.NormalizeSafe();
|
|
LocalFar.NormalizeSafe();
|
|
|
|
if(AreNearlyEqual(LocalNear.z, 0.0f, THIntersectTolerance) || AreNearlyEqual(LocalFar.z, 0.0f, THIntersectTolerance) )
|
|
{
|
|
m_CurrentInput = ROT_Z_PLANE;
|
|
|
|
if(AreNearlyEqual(LocalNear.z, 0.0f, THIntersectTolerance))
|
|
{
|
|
isNearIntersection = true;
|
|
}
|
|
else
|
|
{
|
|
isFarIntersection = true;
|
|
}
|
|
}
|
|
else if(AreNearlyEqual(LocalNear.y, 0.0f, THIntersectTolerance) || AreNearlyEqual(LocalFar.y, 0.0f, THIntersectTolerance))
|
|
{
|
|
m_CurrentInput = ROT_Y_PLANE;
|
|
|
|
if(AreNearlyEqual(LocalNear.y, 0.0f, THIntersectTolerance))
|
|
{
|
|
isNearIntersection = true;
|
|
}
|
|
else
|
|
{
|
|
isFarIntersection = true;
|
|
}
|
|
}
|
|
else if(AreNearlyEqual(LocalNear.x, 0.0f, THIntersectTolerance) || AreNearlyEqual(LocalFar.x, 0.0f, THIntersectTolerance))
|
|
{
|
|
m_CurrentInput = ROT_X_PLANE;
|
|
|
|
if(AreNearlyEqual(LocalNear.x, 0.0f, THIntersectTolerance))
|
|
{
|
|
isNearIntersection = true;
|
|
}
|
|
else
|
|
{
|
|
isFarIntersection = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_CurrentInput = NO_INPUT;
|
|
}
|
|
|
|
SelectionVec = localFar;
|
|
SelectionWorld = IntersectFar;
|
|
if(isNearIntersection)
|
|
{
|
|
SelectionVec = localNear;
|
|
SelectionWorld = IntersectNear;
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
|
|
bool CAuthoringHelper::UpdateRotationHelper(const Matrix34& mat, float Scale, const Vector3& Offset, Matrix34& UpdatedMat)
|
|
{
|
|
UpdatedMat = mat;
|
|
|
|
Matrix34 AuthoringMat(mat);
|
|
AuthoringMat.d += Offset;
|
|
|
|
if(ms_AuthorMode == ROT_GBL)
|
|
{
|
|
AuthoringMat.Identity3x3();
|
|
}
|
|
|
|
Vector3 SelectionVec;
|
|
Vector3 SelectionWorld;
|
|
|
|
UpdateRotationAxisSelection(AuthoringMat, Scale, SelectionVec, SelectionWorld);
|
|
|
|
bool ShouldUpdate = ShouldUpdateSelectedHelper(AuthoringMat.d);
|
|
|
|
if(ShouldUpdate)
|
|
{
|
|
UpdateAxisRotation(mat, UpdatedMat, SelectionVec, SelectionWorld);
|
|
}
|
|
|
|
RenderRotationHelper(AuthoringMat, UpdatedMat, Scale);
|
|
|
|
return ShouldUpdate;
|
|
}
|
|
|
|
void CAuthoringHelper::UpdateTranslationCollisionBoxes(const Matrix34& AuthoringMat, float Scale, const Vector3& UNUSED_PARAM(Offset) )
|
|
{
|
|
if(!m_IsAxisSelected)
|
|
{
|
|
spdOrientedBB xBoundBox;
|
|
spdOrientedBB yBoundBox;
|
|
spdOrientedBB zBoundBox;
|
|
spdOrientedBB xyPlaneBoundBox;
|
|
spdOrientedBB xzPlaneBoundBox;
|
|
spdOrientedBB zyPlaneBoundBox;
|
|
|
|
const Vector3 XYAxis = XAXIS + YAXIS;
|
|
const Vector3 XZAxis = XAXIS + ZAXIS;
|
|
const Vector3 ZYAxis = ZAXIS + YAXIS;
|
|
|
|
//Create the collision boxes
|
|
CreateTranslationCollisionBox(AuthoringMat, XAXIS, Scale, VEC3_ZERO, m_AxisBox, xBoundBox);
|
|
CreateTranslationCollisionBox(AuthoringMat, YAXIS, Scale, VEC3_ZERO, m_AxisBox, yBoundBox);
|
|
CreateTranslationCollisionBox(AuthoringMat, ZAXIS, Scale, VEC3_ZERO, m_AxisBox, zBoundBox);
|
|
|
|
CreateTranslationCollisionBox(AuthoringMat, XYAxis, Scale, VEC3_ZERO, m_PlaneBox, xyPlaneBoundBox);
|
|
CreateTranslationCollisionBox(AuthoringMat, XZAxis, Scale, VEC3_ZERO, m_PlaneBox, xzPlaneBoundBox);
|
|
CreateTranslationCollisionBox(AuthoringMat, ZYAxis, Scale, VEC3_ZERO, m_PlaneBox, zyPlaneBoundBox);
|
|
|
|
//create the mouse probes
|
|
spdOrientedBB MouseProbeBB;
|
|
CAuthoringHelper::UpdateMouseTranslationCollisionBox(MouseProbeBB);
|
|
Vector3 AxisDirectionMultiplyer = VEC3_ZERO;
|
|
|
|
if(xBoundBox.IntersectsOrientedBB(MouseProbeBB))
|
|
{
|
|
m_CurrentInput = X_AXIS;
|
|
}
|
|
else if(yBoundBox.IntersectsOrientedBB(MouseProbeBB))
|
|
{
|
|
m_CurrentInput = Y_AXIS;
|
|
}
|
|
else if(zBoundBox.IntersectsOrientedBB(MouseProbeBB))
|
|
{
|
|
m_CurrentInput = Z_AXIS;
|
|
}
|
|
else if(xyPlaneBoundBox.IntersectsOrientedBB(MouseProbeBB))
|
|
{
|
|
m_CurrentInput = XY_PLANE;
|
|
}
|
|
else if(xzPlaneBoundBox.IntersectsOrientedBB(MouseProbeBB))
|
|
{
|
|
m_CurrentInput = XZ_PLANE;
|
|
}
|
|
else if(zyPlaneBoundBox.IntersectsOrientedBB(MouseProbeBB))
|
|
{
|
|
m_CurrentInput = ZY_PLANE;
|
|
}
|
|
else
|
|
{
|
|
m_CurrentInput = NO_INPUT;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CAuthoringHelper::UpdateTranslationPosition(const Matrix34& AuthoringMat, Matrix34& UpdatedMat)
|
|
{
|
|
const float planeMax = 10.0f;
|
|
const float planeMin = -10.0f;
|
|
const Vector3 XYAxis = XAXIS + YAXIS;
|
|
const Vector3 XZAxis = XAXIS + ZAXIS;
|
|
const Vector3 ZYAxis = ZAXIS + YAXIS;
|
|
|
|
switch (m_CurrentInput)
|
|
{
|
|
case X_AXIS:
|
|
{
|
|
Vector3 corner1(planeMin, 0.0f, planeMax);
|
|
Vector3 corner2(planeMax, 0.0f, planeMin);
|
|
Vector3 corner3(planeMin, 0.0f, planeMin);
|
|
|
|
AuthoringMat.Transform(corner1);
|
|
AuthoringMat.Transform(corner2);
|
|
AuthoringMat.Transform(corner3);
|
|
|
|
Vector4 PlaneDef;
|
|
|
|
PlaneDef.ComputePlane(corner1, corner2, corner3);
|
|
|
|
spdPlane Plane(PlaneDef);
|
|
|
|
UpdatedMat.d = UpdatedMat.d + UpdateTranslationAxis(AuthoringMat, XAXIS , Plane);
|
|
|
|
// grcDebugDraw::Poly(corner1, corner2, corner3, Color_green, Color_green, Color_green, true);
|
|
|
|
}
|
|
break;
|
|
|
|
case Y_AXIS:
|
|
{
|
|
Vector3 corner1(planeMin, planeMax, 0.0f);
|
|
Vector3 corner2(planeMax, planeMin, 0.0f);
|
|
Vector3 corner3(planeMin, planeMin, 0.0f);
|
|
|
|
AuthoringMat.Transform(corner1);
|
|
AuthoringMat.Transform(corner2);
|
|
AuthoringMat.Transform(corner3);
|
|
|
|
Vector4 PlaneDef;
|
|
|
|
PlaneDef.ComputePlane(corner1, corner2, corner3);
|
|
|
|
spdPlane Plane(PlaneDef);
|
|
|
|
UpdatedMat.d = UpdatedMat.d + UpdateTranslationAxis(AuthoringMat, YAXIS, Plane);
|
|
// grcDebugDraw::Poly(corner1, corner2, corner3, Color_green, Color_green, Color_green, true);
|
|
|
|
}
|
|
break;
|
|
|
|
case Z_AXIS:
|
|
{
|
|
Vector3 corner1(planeMin, 0.0f, planeMax);
|
|
Vector3 corner2(planeMax, 0.0f, planeMin);
|
|
Vector3 corner3(planeMin, 0.0f, planeMin);
|
|
|
|
AuthoringMat.Transform(corner1);
|
|
AuthoringMat.Transform(corner2);
|
|
AuthoringMat.Transform(corner3);
|
|
|
|
Vector4 PlaneDef;
|
|
|
|
PlaneDef.ComputePlane(corner1, corner2, corner3);
|
|
|
|
spdPlane Plane(PlaneDef);
|
|
|
|
UpdatedMat.d = UpdatedMat.d + UpdateTranslationAxis(AuthoringMat, ZAXIS, Plane);
|
|
|
|
//grcDebugDraw::Poly(corner1, corner2, corner3, Color_green, Color_green, Color_green, true);
|
|
}
|
|
break;
|
|
|
|
case XY_PLANE:
|
|
{
|
|
Vector3 corner1(planeMin, planeMax, 0.0f);
|
|
Vector3 corner2(planeMax, planeMin, 0.0f);
|
|
Vector3 corner3(planeMin, planeMin, 0.0f);
|
|
|
|
|
|
AuthoringMat.Transform(corner1);
|
|
AuthoringMat.Transform(corner2);
|
|
AuthoringMat.Transform(corner3);
|
|
|
|
Vector4 PlaneDef;
|
|
|
|
PlaneDef.ComputePlane(corner1, corner2, corner3);
|
|
spdPlane Plane(PlaneDef);
|
|
|
|
UpdatedMat.d = UpdatedMat.d + UpdateTranslationAxis(AuthoringMat, XYAxis, Plane);
|
|
}
|
|
break;
|
|
|
|
case XZ_PLANE:
|
|
{
|
|
Vector3 corner1(planeMin, 0.0f, planeMax);
|
|
Vector3 corner2(planeMax, 0.0f, planeMin);
|
|
Vector3 corner3(planeMin, 0.0f, planeMin);
|
|
|
|
|
|
AuthoringMat.Transform(corner1);
|
|
AuthoringMat.Transform(corner2);
|
|
AuthoringMat.Transform(corner3);
|
|
|
|
Vector4 PlaneDef;
|
|
|
|
PlaneDef.ComputePlane(corner1, corner2, corner3);
|
|
spdPlane Plane(PlaneDef);
|
|
|
|
UpdatedMat.d = UpdatedMat.d + UpdateTranslationAxis(AuthoringMat, XZAxis, Plane);
|
|
}
|
|
break;
|
|
|
|
case ZY_PLANE:
|
|
{
|
|
Vector3 corner1(0.0f, planeMin, planeMax);
|
|
Vector3 corner2(0.0f, planeMax, planeMin);
|
|
Vector3 corner3(0.0f, planeMin, planeMin);
|
|
|
|
|
|
AuthoringMat.Transform(corner1);
|
|
AuthoringMat.Transform(corner2);
|
|
AuthoringMat.Transform(corner3);
|
|
|
|
Vector4 PlaneDef;
|
|
|
|
PlaneDef.ComputePlane(corner1, corner2, corner3);
|
|
spdPlane Plane(PlaneDef);
|
|
|
|
UpdatedMat.d = UpdatedMat.d + UpdateTranslationAxis(AuthoringMat, ZYAxis, Plane);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool CAuthoringHelper::UpdateTranslationHelper(const Matrix34& mat, float Scale, const Vector3& Offset, Matrix34& UpdatedMat)
|
|
{
|
|
UpdatedMat = mat;
|
|
|
|
Matrix34 AuthoringMat(mat);
|
|
|
|
AuthoringMat.d += Offset;
|
|
|
|
if(ms_AuthorMode == TRANS_GBL)
|
|
{
|
|
AuthoringMat.Identity3x3();
|
|
}
|
|
|
|
UpdateTranslationCollisionBoxes(AuthoringMat, Scale, Offset);
|
|
|
|
bool ShouldUpdate = ShouldUpdateSelectedHelper(AuthoringMat.d);
|
|
|
|
if(ShouldUpdate)
|
|
{
|
|
UpdateTranslationPosition(AuthoringMat, UpdatedMat);
|
|
}
|
|
|
|
RenderTranslationHelper(AuthoringMat, Scale, Offset);
|
|
|
|
return ShouldUpdate;
|
|
}
|
|
#endif
|