Added A_SetViewPos(Vector3 Offset, int Flags = -1)
- Offset: The offset from the actor's view to move the camera about. - Flags: (Default is -1, which means don't change flags) - VPSF_ABSOLUTEOFFSET: Don't include actor angles in calculation. - VPSF_ABSOLUTEPOS: Position is absolute, and disables all transformations. Modders are responsible for being portal aware! Notes: - `ViewPos` in Actor will be `null` until A_SetViewPos is called for the first time. **Issues:** - Hiding sprite while in portal incomplete.
This commit is contained in:
parent
cd33fb8607
commit
4e8d59951b
10 changed files with 283 additions and 29 deletions
|
|
@ -654,6 +654,63 @@ struct FDropItem
|
|||
int Amount;
|
||||
};
|
||||
|
||||
enum EViewPosFlags // [MC] Flags for SetViewPos.
|
||||
{
|
||||
VPSF_ABSOLUTEOFFSET = 1 << 1, // Don't include angles.
|
||||
VPSF_ABSOLUTEPOS = 1 << 2, // Use absolute position.
|
||||
};
|
||||
|
||||
class FViewPosition : public DObject
|
||||
{
|
||||
DECLARE_CLASS(FViewPosition, DObject);
|
||||
public:
|
||||
// Variables
|
||||
// Exposed to ZScript
|
||||
DVector3 Offset;
|
||||
int Flags;
|
||||
|
||||
// Engine only.
|
||||
// Used to do a backwards trace to disable rendering over portals.
|
||||
bool isUsed;
|
||||
DVector3 PlrPos,
|
||||
CamPos;
|
||||
double Distance;
|
||||
sector_t *CamSec;
|
||||
|
||||
|
||||
// Functions
|
||||
FViewPosition()
|
||||
{
|
||||
Offset = PlrPos = CamPos = { 0,0,0 };
|
||||
isUsed = false;
|
||||
Distance = 0.0;
|
||||
CamSec = nullptr;
|
||||
}
|
||||
|
||||
void Set(DVector3 &off, int f = -1)
|
||||
{
|
||||
Offset = off;
|
||||
|
||||
if (f > -1)
|
||||
Flags = f;
|
||||
}
|
||||
|
||||
bool isZero()
|
||||
{
|
||||
return Offset.isZero();
|
||||
}
|
||||
|
||||
void ResetTraceInfo()
|
||||
{
|
||||
isUsed = false;
|
||||
PlrPos = CamPos = {0,0,0};
|
||||
Distance = 0.;
|
||||
CamSec = nullptr;
|
||||
}
|
||||
|
||||
bool TraceBack(AActor *Owner);
|
||||
};
|
||||
|
||||
const double MinVel = EQUAL_EPSILON;
|
||||
|
||||
// Map Object definition.
|
||||
|
|
@ -974,7 +1031,8 @@ public:
|
|||
DAngle SpriteAngle;
|
||||
DAngle SpriteRotation;
|
||||
DRotator Angles;
|
||||
DRotator ViewAngles; // Offsets for cameras
|
||||
DRotator ViewAngles; // Angle offsets for cameras
|
||||
FViewPosition *ViewPos; // Position offsets for cameras
|
||||
DVector2 Scale; // Scaling values; 1 is normal size
|
||||
double Alpha; // Since P_CheckSight makes an alpha check this can't be a float. It has to be a double.
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ struct secplane_t;
|
|||
struct FCheckPosition;
|
||||
struct FTranslatedLineTarget;
|
||||
struct FLinePortal;
|
||||
class FViewPosition;
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
@ -392,6 +393,10 @@ void P_PlaySpawnSound(AActor *missile, AActor *spawner);
|
|||
// [RH] Position the chasecam
|
||||
void P_AimCamera (AActor *t1, DVector3 &, DAngle &, sector_t *&sec, bool &unlinked);
|
||||
|
||||
// [MC] Aiming for ViewPos
|
||||
void P_AdjustViewPos(AActor *t1, DVector3 orig, DVector3 &, sector_t *&sec, bool &unlinked, FViewPosition *VP);
|
||||
|
||||
|
||||
// [RH] Means of death
|
||||
enum
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5423,6 +5423,62 @@ void P_AimCamera(AActor *t1, DVector3 &campos, DAngle &camangle, sector_t *&Came
|
|||
camangle = trace.SrcAngleFromTarget - 180.;
|
||||
}
|
||||
|
||||
// [MC] Used for ViewPos. Uses code borrowed from P_AimCamera.
|
||||
void P_AdjustViewPos(AActor *t1, DVector3 orig, DVector3 &campos, sector_t *&CameraSector, bool &unlinked, FViewPosition *VP)
|
||||
{
|
||||
FTraceResults trace;
|
||||
const DVector3 vvec = campos - orig;
|
||||
const double distance = vvec.Length();
|
||||
|
||||
// Trace handles all of the portal crossing, which is why there is no usage of Vec#Offset(Z).
|
||||
if (Trace(orig, t1->Sector, vvec.Unit(), distance, 0, 0, t1, trace) &&
|
||||
trace.Distance > 5)
|
||||
{
|
||||
// Position camera slightly in front of hit thing
|
||||
campos = orig + vvec.Unit() * (trace.Distance - 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
campos = trace.HitPos - trace.HitVector * 1 / 256.;
|
||||
}
|
||||
// DVector3 cpos = campos;
|
||||
CameraSector = trace.Sector;
|
||||
unlinked = trace.unlinked;
|
||||
|
||||
// Save the info for the renderers. Needed to disable sprites across portals.
|
||||
VP->Distance = distance;
|
||||
VP->isUsed = true;
|
||||
}
|
||||
|
||||
struct EViewPosFinder
|
||||
{
|
||||
AActor *Owner;
|
||||
};
|
||||
|
||||
static ETraceStatus TraceToOwner(FTraceResults &res, void *userdata)
|
||||
{
|
||||
// Try to guarantee hitting the owner if possible.
|
||||
if (res.HitType != TRACE_HitActor)
|
||||
return TRACE_Skip;
|
||||
|
||||
EViewPosFinder *data = (EViewPosFinder *)userdata;
|
||||
ETraceStatus ret = (res.Actor == data->Owner) ? TRACE_Stop : TRACE_Skip;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool FViewPosition::TraceBack(AActor *Owner)
|
||||
{
|
||||
if (!isUsed || !Owner)
|
||||
return false;
|
||||
|
||||
DVector3 vvec = (CamPos - PlrPos).Unit() * -1.0;
|
||||
FTraceResults res;
|
||||
EViewPosFinder TrcBack = {Owner};
|
||||
|
||||
bool ret = Trace(CamPos, CamSec, vvec, Distance, 0, 0, nullptr, res, TRACE_ReportPortals, TraceToOwner, &TrcBack);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
|||
|
|
@ -369,6 +369,7 @@ void AActor::Serialize(FSerializer &arc)
|
|||
A("spawnorder", SpawnOrder)
|
||||
A("friction", Friction)
|
||||
A("SpriteOffset", SpriteOffset)
|
||||
("viewpos", ViewPos)
|
||||
A("userlights", UserLights);
|
||||
|
||||
SerializeTerrain(arc, "floorterrain", floorterrain, &def->floorterrain);
|
||||
|
|
@ -4952,6 +4953,12 @@ void AActor::OnDestroy ()
|
|||
UnlinkFromWorld (nullptr);
|
||||
flags |= MF_NOSECTOR|MF_NOBLOCKMAP;
|
||||
|
||||
if (ViewPos != nullptr)
|
||||
{
|
||||
ViewPos->Destroy();
|
||||
ViewPos = nullptr;
|
||||
}
|
||||
|
||||
// Transform any playing sound into positioned, non-actor sounds.
|
||||
S_RelinkSound (this, NULL);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue