Last active
June 26, 2018 01:07
-
-
Save Kefta/045c3b839aac8aaae88f9bcb3494c9f6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Lua method declaration /// | |
// Placeholders, better methods probably already defined somewhere | |
bool CheckDefaultValue( int iStackPos, int iType ) | |
{ | |
int iRetType = g_Lua->GetType( iStackPos ); | |
if ( iRetType == iType ) | |
return true; | |
if ( iRetType != GarrysMod::Lua::Type::NONE && iRetType != GarrysMod::Lua::Type::NIL ) | |
g_Lua->ArgError( iStackPos, sprintf( "%s expected, got %s", g_Lua->GetTypeName( iType ), g_Lua->GetTypeName( iRetType ) ) ); | |
return false; | |
} | |
int CheckMultiValue( int iStackPos, int iType1, int iType2 ) | |
{ | |
int iRetType = g_Lua->GetType( iStackPos ); | |
if ( iRetType == iType1 ) | |
return iType1; | |
if ( iRetType == iType2 ) | |
return iType2; | |
g_Lua->ArgError( iStackPos, sprintf( "%s or %s expected, got %s", g_Lua->GetTypeName( iType1 ), g_Lua->GetTypeName( iType2 ), g_Lua->GetTypeName( iRetType ) ) ); | |
return iRetType; | |
} | |
/* Lua header: | |
// Maybe even make this a struct, there's a lotta args | |
ENTITY:AddDecal(Vector rayStart, Vector rayEnd, Vector decalCenter, IMaterial or string decalMat, | |
table (trace result struct) tr = nil, number w = IMaterial:GetMappingWidth(), number h = IMaterial:GetMappingHeight(), | |
Vector saxis = Vector(0, 0, 1) for studio mdls or nil for brush models, number (integer) flags = 0, number (integer) maxLODToDecal = ADDDECAL_TO_ALL_LODS) | |
*/ | |
void LUA_ENTITY_AddDecal() | |
{ | |
g_Lua->CheckType( 1, GarrysMod::Lua::Type::ENTITY ); // ENTITY | |
g_Lua->CheckType( 2, GarrysMod::Lua::Type::VECTOR ); // rayStart | |
g_Lua->CheckType( 3, GarrysMod::Lua::Type::VECTOR ); // rayEnd | |
g_Lua->CheckType( 4, GarrysMod::Lua::Type::VECTOR ); // decalCenter | |
bool bMaterial = CheckMultiValue( 5, GarrysMod::Lua::Type::MATERIAL, GarrysMod::Lua::Type::STRING ) == GarrysMod::Lua::Type::MATERIAL // decalName | |
bool doTrace = !CheckDefaultValue( 6, GarrysMod::Lua::Type::TABLE ); // tr | |
bool bWidth = CheckDefaultValue( 7, GarrysMod::Lua::Type::NUMBER ); // w | |
bool bHeight = CheckDefaultValue( 8, GarrysMod::Lua::Type::NUMBER ); // h | |
bool bAxis = CheckDefaultValue( 9, GarrysMod::Lua::Type::VECTOR ); // saxis | |
int iFlags = CheckDefaultValue( 10, GarrysMod::Lua::Type::NUMBER ) | |
? (int)g_Lua->ReadNumber( 10 ) : 0; | |
int maxLODToDecal = CheckDefaultValue( 11, GarrysMod::Lua::Type::NUMBER ) // maxLODToDecal | |
? (int)g_Lua->ReadNumber( 11 ) : ADDDECAL_TO_ALL_LODS; | |
// or whatever the method is | |
C_BaseEntity* pEntity = GetEntityValid( g_Lua, 1 ); | |
IMaterial* pMaterial; | |
if ( bMaterial ) | |
pMaterial = g_Lua->GetUserType<IMaterial>( 5, GarrysMod::Lua::Type::MATERIAL ); | |
else | |
// Get IMaterial by string | |
Assert( pMaterial != NULL ); | |
const Vector &rayStart = g_Lua->GetVector( 2 ); | |
const Vector &rayEnd = g_Lua->GetVector( 3 ); | |
trace_t tr; | |
if ( !doTrace ) | |
tr = GetTraceStruct( g_Lua, 6 ); | |
pEntity->AddDecal( rayStart, rayEnd, g_Lua->GetVector( 4 ), pMaterial, doTrace, tr, | |
bWidth ? g_Lua->GetNumber( 7 ) : pMaterial->GetMappingWidth(), | |
bHeight ? g_Lua->GetNumber( 8 ) : pMaterial->GetMappingHeight(), | |
bAxis ? &g_Lua->GetVector( 9 ) : NULL, iFlags, maxLODToDecal ); | |
} | |
/// c_baseentity.h /// | |
// New methods: | |
virtual void AddDecal( const Vector& rayStart, const Vector& rayEnd, IMaterial* decalMat, bool doTrace, trace_t& tr, | |
float w, float h, const Vector* saxis = NULL, int iFlags = 0, int maxLODToDecal = ADDDECAL_TO_ALL_LODS ); | |
void AddStudioDecal( const Ray_t& ray, IMaterial* decalMat, | |
float w, float h, const Vector* upaxis = NULL, int maxLODToDecal = ADDDECAL_TO_ALL_LODS, bool pokeThruSkip = false ); | |
void AddBrushModelDecal( const Vector& decalCenter, IMaterial* decalMat, | |
float w, float h, const Vector* saxis = NULL, int iFlags = 0 ); | |
// Backwards compatible: | |
virtual void AddDecal( const Vector& rayStart, const Vector& rayEnd, | |
const Vector& decalCenter, int hitbox, int decalIndex, bool doTrace, trace_t& tr, int maxLODToDecal = ADDDECAL_TO_ALL_LODS ); | |
void AddStudioDecal( const Ray_t& ray, int hitbox, int decalIndex, bool doTrace, trace_t& tr, int maxLODToDecal = ADDDECAL_TO_ALL_LODS ); | |
void AddBrushModelDecal( const Ray_t& ray, const Vector& decalCenter, int decalIndex, bool doTrace, trace_t& tr ); | |
/// c_baseentity.cpp /// | |
inline void DecalTrace( trace_t& tr, const Ray_t& ray ) | |
{ | |
enginetrace->ClipRayToEntity( ray, MASK_SHOT, this, &tr ); | |
/// This shouldn't be needed, the trace is already clipped to the entity | |
// Set the trace index appropriately... | |
//tr.m_pEnt = this; | |
} | |
// New methods: | |
void C_BaseEntity::AddDecal( const Vector& rayStart, const Vector& rayEnd, IMaterial* decalMat, | |
bool doTrace, trace_t& tr, float w, float h, const Vector* saxis, int iFlags, int maxLODToDecal ); | |
{ | |
Ray_t ray; | |
ray.Init( rayStart, rayEnd ); | |
if ( doTrace ) | |
{ | |
/// Only bloat the ray if we're simulating a trace | |
// FIXME: Better bloat? | |
// Bloat a little bit so we get the intersection | |
ray.m_Delta *= 1.1f; | |
::DecalTrace( tr, ray ); | |
} | |
if (tr.Fraction == 1.0f) | |
return; | |
int modelType = modelinfo->GetModelType( model ); | |
switch ( modelType ) | |
{ | |
case mod_studio: | |
bool pokeThruSkip = false; | |
if (doTrace && (GetSolid() == SOLID_VPHYSICS) && !tr.startsolid && !tr.allsolid) | |
{ | |
// Choose a more accurate normal direction | |
// Also, since we have more accurate info, we can avoid pokethru | |
Vector temp; | |
VectorSubtract( tr.endpos, tr.plane.normal, temp ); | |
ray.Init( tr.endpos, temp ); | |
pokeThruSkip = true; | |
} | |
AddStudioDecal( ray, decalMat, w, h, saxis, maxLODToDecal, pokeThruSkip ); | |
break; | |
case mod_brush: | |
// Use the trace's hitpos as the centre of the decal | |
AddBrushModelDecal( ray, tr.endpos, decalMat, w, h, saxis, iFlags ); | |
break; | |
default: | |
// By default, no collision | |
tr.fraction = 1.0f; | |
break; | |
} | |
} | |
void C_BaseEntity::AddStudioDecal( const Ray_t& ray, IMaterial* decalMat, | |
float w, float h, const Vector* upaxis, int maxLODToDecal, bool pokeThruSkip ) | |
{ | |
// Exit out after doing the trace so any other effects that want to happen can happen. | |
if ( !r_drawmodeldecals.GetBool() ) | |
return; | |
// Found the point, now lets apply the decals | |
CreateModelInstance(); | |
modelrender->AddDecal( m_ModelInstance, ray, upaxis == NULL ? Vector(0, 0, 1) : *upaxis, decalMat, GetStudioBody(), w, h, pokeThruSkip, maxLODToDecal ); | |
} | |
void C_BaseEntity::AddBrushModelDecal( const Vector& decalCenter, IMaterial* decalMat, | |
float w, float h, const Vector* saxis, int iFlags ) | |
{ | |
effects->DecalShoot( decalMat, index, | |
model, GetAbsOrigin(), GetAbsAngles(), decalCenter, w, h, saxis, iFlags ); | |
} | |
// Backwards compatible: | |
void C_BaseEntity::AddDecal( const Vector& rayStart, const Vector& rayEnd, | |
const Vector& decalCenter, int hitbox, int decalIndex, bool doTrace, trace_t& tr, Vector* saxis, int iFlags, int maxLODToDecal ) | |
{ | |
IMaterial* decalMat; | |
float w, h; | |
R_DecalGetMaterialAndSize( decalIndex, decalMat, w, h ); | |
// Material validity will be checked later, at least get a trace | |
AddDecal( rayStart, rayEnd, decalMat, doTrace, tr, w, h, NULL, 0, maxLODToDecal ); | |
} | |
void C_BaseEntity::AddStudioDecal( const Ray_t& ray, int hitbox, int decalIndex, bool doTrace, trace_t& tr, int maxLODToDecal ) | |
{ | |
if ( doTrace ) | |
::DecalTrace( tr, ray ); | |
if (tr.Fraction == 1.0f) | |
return; | |
IMaterial* decalMat; | |
float w, h; | |
R_DecalGetMaterialAndSize( decalIndex, decalMat, w, h ); | |
AddStudioDecal( ray, decalMat, w, h, NULL, maxLODToDecal, doTrace ); | |
} | |
void C_BaseEntity::AddBrushModelDecal( const Ray_t& ray, const Vector& decalCenter, int decalIndex, bool doTrace, trace_t& tr ) | |
{ | |
if ( doTrace ) | |
::DecalTrace( tr, ray ); | |
if (tr.Fraction == 1.0f) | |
return; | |
IMaterial* decalMat; | |
float w, h; | |
R_DecalGetMaterialAndSize( decalIndex, decalMat, w, h ); | |
AddBrushModelDecal( decalCenter, decalMat, w, h, NULL, 0 ); | |
} | |
/// l_studio.cpp /// | |
// New header: | |
AddDecal( ModelInstanceHandle_t handle, Ray_t const& ray, | |
const Vector& decalUp, IMaterial* decalMat, int body, float w, float h, bool noPokeThru, int maxLODToDecal ); | |
// Backwards compatible: | |
AddDecal( ModelInstanceHandle_t handle, Ray_t const& ray, | |
const Vector& decalUp, int decalIndex, int body, bool noPokeThru, int maxLODToDecal ); | |
// New method: | |
void CModelRender::AddDecal( ModelInstanceHandle_t handle, Ray_t const& ray, | |
const Vector& decalUp, IMaterial* decalMat, int body, float w, float h, bool noPokeThru, int maxLODToDecal ) | |
{ | |
if (handle == MODEL_INSTANCE_INVALID || decalMat == NULL) | |
return; | |
// FIXME: For now, don't render fading decals on props... | |
bool found = false; | |
decalMat->FindVar( "$decalFadeDuration", &found, false ); | |
if (found) | |
return; | |
/// This doesn't seem possible with how the renderer currently draws decals | |
/// Just use the width/height as the radius for now.. | |
// FIXME: Pass w and h into AddDecal | |
float radius = (w > h) ? w : h; | |
radius *= 0.5; | |
ModelInstance_t& inst = m_ModelInstances[handle]; | |
if (!IsModelInstanceValid(handle)) | |
{ | |
g_pStudioRender->DestroyDecalList(inst.m_DecalHandle); | |
inst.m_DecalHandle = STUDIORENDER_DECAL_INVALID; | |
} | |
Assert( modelloader->IsLoaded( inst.m_pModel ) && ( inst.m_pModel->type == mod_studio ) ); | |
if ( inst.m_DecalHandle == STUDIORENDER_DECAL_INVALID ) | |
{ | |
studiohwdata_t *pStudioHWData = g_pMDLCache->GetHardwareData( inst.m_pModel->studio ); | |
inst.m_DecalHandle = g_pStudioRender->CreateDecalList( pStudioHWData ); | |
} | |
matrix3x4_t *pBoneToWorld = SetupModelState( inst.m_pRenderable ); | |
g_pStudioRender->AddDecal( inst.m_DecalHandle, g_pMDLCache->GetStudioHdr( inst.m_pModel->studio ), | |
pBoneToWorld, ray, decalUp, decalMat, radius, body, noPokeThru, maxLODToDecal ); | |
} | |
// Backwards compatible: | |
void CModelRender::AddDecal( ModelInstanceHandle_t handle, Ray_t const& ray, | |
const Vector& decalUp, int decalIndex, int body, bool noPokeThru, int maxLODToDecal ) | |
{ | |
if (handle == MODEL_INSTANCE_INVALID) | |
return; | |
// Get the decal material + radius | |
IMaterial* pDecalMaterial; | |
float w, h; | |
R_DecalGetMaterialAndSize( decalIndex, pDecalMaterial, w, h ); | |
if ( pDecalMaterial == NULL ) | |
{ | |
DevWarning("Bad decal index %d\n", decalIndex ); | |
return; | |
} | |
AddDecal( handle, ray, decalUp, pDecalMaterial, body, w, h, noPokeThru, maxLODToDecal ); | |
} | |
/// r_efx.h /// | |
// New headers: | |
virtual void DecalShoot( IMaterial* decalMat, int entity, const model_t *model, const Vector& model_origin, const QAngle& model_angles, const Vector& position, float w, float h, const Vector *saxis, int flags); | |
virtual void DecalColorShoot( IMaterial* decalMat, int entity, const model_t *model, const Vector& model_origin, const QAngle& model_angles, const Vector& position, float w, float h, const Vector *saxis, int flags, const color32 &rgbaColor); | |
// Backwards compatible: | |
virtual void DecalShoot( int textureIndex, int entity, const model_t *model, const Vector& model_origin, const QAngle& model_angles, const Vector& position, const Vector *saxis, int flags); | |
virtual void DecalColorShoot( int textureIndex, int entity, const model_t *model, const Vector& model_origin, const QAngle& model_angles, const Vector& position, const Vector *saxis, int flags, const color32 &rgbaColor); | |
/// r_efx.cpp /// | |
// New methods: | |
void CVEfx::DecalShoot( IMaterial* decalMat, int entity, const model_t *model, const Vector& model_origin, const QAngle& model_angles, const Vector& position, float w, float h, const Vector *saxis, int flags) | |
{ | |
color32 white = {255,255,255,255}; | |
DecalColorShoot( decalMat, entity, model, model_origin, model_angles, position, w, h, saxis, flags, white ); | |
} | |
void CVEfx::DecalColorShoot( IMaterial* decalMat, int entity, const model_t *model, const Vector& model_origin, const QAngle& model_angles, | |
const Vector& position, float w, float h, const Vector *saxis, int flags, const color32 &rgbaColor) | |
{ | |
Vector localPosition = position; | |
if ( entity ) // Not world? | |
{ | |
matrix3x4_t matrix; | |
AngleMatrix( model_angles, model_origin, matrix ); | |
VectorITransform( position, matrix, localPosition ); | |
} | |
::R_DecalShoot( textureIndex, entity, model, localPosition, w, h, saxis, flags, rgbaColor ); | |
} | |
// Backward compatible: | |
void CVEfx::DecalShoot( int textureIndex, int entity, const model_t *model, const Vector& model_origin, const QAngle& model_angles, const Vector& position, const Vector *saxis, int flags) | |
{ | |
IMaterial* pDecalMaterial; | |
float w, h; | |
R_DecalGetMaterialAndSize( textureIndex, pDecalMaterial, w, h ); | |
DecalShoot( pDecalMaterial, entity, model, model_origin, model_angles, position, w, h, saxis, flags ); | |
} | |
void CVEfx::DecalColorShoot( int textureIndex, int entity, const model_t *model, const Vector& model_origin, const QAngle& model_angles, | |
const Vector& position, const Vector *saxis, int flags, const color32 &rgbaColor) | |
{ | |
IMaterial* pDecalMaterial; | |
float w, h; | |
R_DecalGetMaterialAndSize( textureIndex, pDecalMaterial, w, h ); | |
DecalColorShoot( pDecalMaterial, entity, model, model_origin, model_angles, position, w, h, saxis, flags, rgbaColor ); | |
} | |
/// r_decal.cpp /// | |
// New header: | |
void R_DecalShoot( IMaterial* pMaterial, int entity, const model_t *model, const Vector &position, const float *saxis, int flags, const color32 &rgbaColor ); | |
// Backwards compatible: | |
void R_DecalShoot( int textureIndex, int entity, const model_t *model, const Vector &position, const float *saxis, int flags, const color32 &rgbaColor ); | |
// New methods: | |
void R_DecalShoot( IMaterial* pMaterial, int entity, const model_t *model, const Vector &position, float w, float h, const Vector *saxis, int flags, const color32 &rgbaColor ) | |
{ | |
R_DecalShoot_( pMaterial, entity, model, position, w, h, saxis, flags, rgbaColor ); | |
} | |
static void R_DecalShoot_( IMaterial *pMaterial, int entity, const model_t *model, const Vector &position, | |
float w, float h, const Vector *saxis, int flags, const color32 &rgbaColor, void *userdata = 0 ) | |
{ | |
if ( !model || model->type != mod_brush || !pMaterial ) | |
return; | |
decalinfo_t decalInfo; | |
VectorCopy( position, decalInfo.m_Position ); // Pass position in global | |
decalInfo.m_pModel = (model_t *)model; | |
decalInfo.m_pBrush = model->brush.pShared; | |
// Deal with the s axis if one was passed in | |
if (saxis) | |
{ | |
flags |= FDECAL_USESAXIS; | |
VectorCopy( *saxis, decalInfo.m_SAxis ); | |
} | |
// More state used by R_DecalNode() | |
decalInfo.m_pMaterial = pMaterial; | |
decalInfo.m_pUserData = userdata; | |
// Don't optimize custom decals | |
if ( !(flags & FDECAL_CUSTOM) ) | |
flags |= FDECAL_CLIPTEST; | |
decalInfo.m_Flags = flags; | |
decalInfo.m_Entity = entity; | |
decalInfo.m_Size = w >> 1; | |
if ( (int)(h >> 1) > decalInfo.m_Size ) | |
decalInfo.m_Size = h >> 1; | |
// Compute scale of surface | |
// FIXME: cache this? | |
IMaterialVar *decalScaleVar; | |
bool found; | |
decalScaleVar = decalInfo.m_pMaterial->FindVar( "$decalScale", &found, false ); | |
if( found ) | |
{ | |
decalInfo.m_scale = 1.0f / decalScaleVar->GetFloatValue(); | |
decalInfo.m_Size *= decalScaleVar->GetFloatValue(); | |
} | |
else | |
{ | |
decalInfo.m_scale = 1.0f; | |
} | |
// compute the decal dimensions in world space | |
decalInfo.m_decalWidth = w / decalInfo.m_scale; | |
decalInfo.m_decalHeight = h / decalInfo.m_scale; | |
decalInfo.m_Color = rgbaColor; | |
decalInfo.m_aApplySurfs.Purge(); | |
// Clear the displacement tags because we use them in R_DecalNode. | |
DispInfo_ClearAllTags( decalInfo.m_pBrush->hDispInfos ); | |
mnode_t *pnodes = decalInfo.m_pBrush->nodes + decalInfo.m_pModel->brush.firstnode; | |
R_DecalNode( pnodes, &decalInfo ); | |
} | |
// Backwards compatible: | |
void R_DecalShoot( int textureIndex, int entity, const model_t *model, const Vector &position, const Vector *saxis, int flags, const color32 &rgbaColor ) | |
{ | |
IMaterial* pMaterial = Draw_DecalMaterial( textureIndex ); | |
if ( pMaterial == NULL ) | |
return; | |
R_DecalShoot_( pMaterial, entity, model, position, pMaterial->GetMappingWidth(), pMaterial->GetMappingHeight(), saxis, flags, rgbaColor ); | |
} | |
static void R_DecalShoot_( IMaterial *pMaterial, int entity, const model_t *model, | |
const Vector &position, const Vector *saxis, int flags, const color32 &rgbaColor, void *userdata = 0 ) | |
{ | |
if ( pMaterial == NULL ) | |
return; | |
R_DecalShoot_( pMaterial, entity, model, position, pMaterial->GetMappingWidth(), pMaterial->GetMappingHeight(), saxis, flags, rgbaColor, userdata ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment