Models on VGUI Panels
Jump to navigation
Jump to search
Basic code dump for model render in vgui panel :
sdk_clientmode.cpp
void UpdateClassImageEntity( const char *pModelName, int x, int y, int width, int height );
CHandle<C_BaseAnimatingOverlay> g_ClassImagePlayer; // player CHandle<C_BaseAnimating> g_ClassImageWeapon; // weapon
// Utility to determine if the vgui panel is visible
bool WillPanelBeVisible( vgui::VPANEL hPanel )
{
while ( hPanel )
{
if ( !vgui::ipanel()->IsVisible( hPanel ) )
return false;
hPanel = vgui::ipanel()->GetParent( hPanel );
}
return true;
}
// Called to see if we should be creating or recreating the model instances
bool ShouldRecreateClassImageEntity( C_BaseAnimating *pEnt, const char *pNewModelName )
{
if ( !pNewModelName || !pNewModelName[0] )
return false;
if ( !pEnt )
return true;
const model_t *pModel = pEnt->GetModel();
if ( !pModel )
return true;
const char *pName = modelinfo->GetModelName( pModel );
if ( !pName )
return true;
// reload only if names are different
return( Q_stricmp( pName, pNewModelName ) != 0 );
}
void ClientModeSDKNormal::PostRenderVGui()
{
// If the team menu is up, then we will render the model of the character that is currently selected.
for ( int i=0; i < g_ClassImagePanels.Count(); i++ )
{
CClassImagePanel *pPanel = g_ClassImagePanels[i];
if ( WillPanelBeVisible( pPanel->GetVPanel() ) )
{
// Ok, we have a visible class image panel.
int x, y, w, h;
pPanel->GetBounds( x, y, w, h );
pPanel->LocalToScreen( x, y );
// Allow for the border.
x += 3;
y += 5;
w -= 2;
h -= 10;
UpdateClassImageEntity( g_ClassImagePanels[i]->m_ModelName, x, y, w, h );
return;
}
}
}
void UpdateClassImageEntity(
const char *pModelName,
int x, int y, int width, int height )
{
C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
if ( !pLocalPlayer )
return;
const char *pWeaponName = "models/weapons/f2000/w_f2000.mdl";
const char *pWeaponSequence = "Idle_Upper_Aug";
C_BaseAnimatingOverlay *pPlayerModel = g_ClassImagePlayer.Get();
// Does the entity even exist yet?
bool recreatePlayer = ShouldRecreateClassImageEntity( pPlayerModel, pModelName );
if ( recreatePlayer )
{
if ( pPlayerModel )
pPlayerModel->Remove();
pPlayerModel = new C_BaseAnimatingOverlay;
pPlayerModel->InitializeAsClientEntity( pModelName, RENDER_GROUP_OPAQUE_ENTITY );
pPlayerModel->AddEffects( EF_NODRAW ); // don't let the renderer draw the model normally
// have the player stand idle
pPlayerModel->SetSequence( pPlayerModel->LookupSequence( "Idle_lower" ) );
pPlayerModel->SetPoseParameter( 0, 0.0f ); // move_yaw
pPlayerModel->SetPoseParameter( 1, 10.0f ); // body_pitch, look down a bit
pPlayerModel->SetPoseParameter( 2, 0.0f ); // body_yaw
pPlayerModel->SetPoseParameter( 3, 0.0f ); // move_y
pPlayerModel->SetPoseParameter( 4, 0.0f ); // move_x, walk forward
g_ClassImagePlayer = pPlayerModel;
}
C_BaseAnimating *pWeaponModel = g_ClassImageWeapon.Get();
// Does the entity even exist yet?
if ( recreatePlayer || ShouldRecreateClassImageEntity( pWeaponModel, pWeaponName ) )
{
if ( pWeaponModel )
pWeaponModel->Remove();
pWeaponModel = new C_BaseAnimating;
pWeaponModel->InitializeAsClientEntity( pWeaponName, RENDER_GROUP_OPAQUE_ENTITY );
pWeaponModel->AddEffects( EF_NODRAW ); // don't let the renderer draw the model normally
pWeaponModel->FollowEntity( pPlayerModel ); // attach to player model
g_ClassImageWeapon = pWeaponModel;
}
Vector origin = pLocalPlayer->EyePosition();
Vector lightOrigin = origin;
// find a spot inside the world for the dlight's origin, or it won't illuminate the model
Vector testPos( origin.x - 100, origin.y, origin.z + 100 );
trace_t tr;
UTIL_TraceLine( origin, testPos, MASK_OPAQUE, pLocalPlayer, COLLISION_GROUP_NONE, &tr );
if ( tr.fraction == 1.0f )
{
lightOrigin = tr.endpos;
}
else
{
// Now move the model away so we get the correct illumination
lightOrigin = tr.endpos + Vector( 1, 0, -1 ); // pull out from the solid
Vector start = lightOrigin;
Vector end = lightOrigin + Vector( 100, 0, -100 );
UTIL_TraceLine( start, end, MASK_OPAQUE, pLocalPlayer, COLLISION_GROUP_NONE, &tr );
origin = tr.endpos;
}
float ambient = engine->GetLightForPoint( origin, true ).Length();
// Make a light so the model is well lit.
// use a non-zero number so we cannibalize ourselves next frame
dlight_t *dl = effects->CL_AllocDlight( LIGHT_INDEX_TE_DYNAMIC+1 );
dl->flags = DLIGHT_NO_WORLD_ILLUMINATION;
dl->origin = lightOrigin;
// Go away immediately so it doesn't light the world
dl->die = gpGlobals->curtime + 0.1f; too.
dl->color.r = dl->color.g = dl->color.b = 250;
if ( ambient < 1.0f )
{
dl->color.exponent = 1 + (1 - ambient) * 2;
}
dl->radius = 400;
// move player model in front of our view
pPlayerModel->SetAbsOrigin( origin );
pPlayerModel->SetAbsAngles( QAngle( 0, 210, 0 ) );
// set upper body animation
pPlayerModel->m_SequenceTransitioner.Update(
pPlayerModel->GetModelPtr(),
pPlayerModel->LookupSequence( "walk_lower" ),
pPlayerModel->GetCycle(),
pPlayerModel->GetPlaybackRate(),
gpGlobals->realtime,
false,
true
);
// Now, blend the lower and upper (aim) anims together
pPlayerModel->SetNumAnimOverlays( 2 );
int numOverlays = pPlayerModel->GetNumAnimOverlays();
for ( int i=0; i < numOverlays; ++i )
{
C_AnimationLayer *layer = pPlayerModel->GetAnimOverlay( i );
layer->flCycle = pPlayerModel->GetCycle();
if ( i )
layer->nSequence = pPlayerModel->LookupSequence( pWeaponSequence );
else
layer->nSequence = pPlayerModel->LookupSequence( "walk_lower" );
layer->flPlaybackrate = 1.0;
layer->flWeight = 1.0f;
layer->SetOrder( i );
}
pPlayerModel->FrameAdvance( gpGlobals->frametime );
// Now draw it.
CViewSetup view;
view.x = x;
view.y = y;
view.width = width;
view.height = height;
view.m_bOrtho = false;
view.fov = 54;
view.origin = origin + Vector( -110, -5, -5 );
Vector vMins, vMaxs;
pPlayerModel->C_BaseAnimating::GetRenderBounds( vMins, vMaxs );
view.origin.z += ( vMins.z + vMaxs.z ) * 0.55f;
view.angles.Init();
view.m_vUnreflectedOrigin = view.origin;
view.zNear = VIEW_NEARZ;
view.zFar = 1000;
view.m_bForceAspectRatio1To1 = false;
Frustum dummyFrustum;
render->ViewSetup3D( &view, dummyFrustum );
pPlayerModel->DrawModel( STUDIO_RENDER );
if ( pWeaponModel )
{
pWeaponModel->DrawModel( STUDIO_RENDER );
}
}
teammenu.h
class CClassImagePanel : public vgui::ImagePanel
{
public:
typedef vgui::ImagePanel BaseClass;
CClassImagePanel( vgui::Panel *pParent, const char *pName );
virtual ~CClassImagePanel();
virtual void ApplySettings( KeyValues *inResourceData );
virtual void Paint();
public:
char m_ModelName[128];
};
extern CUtlVector<CClassImagePanel*> g_ClassImagePanels;
teammenu.cpp
CUtlVector<CClassImagePanel*> g_ClassImagePanels;
CClassImagePanel::CClassImagePanel( vgui::Panel *pParent, const char *pName ) : vgui::ImagePanel( pParent, pName ) { g_ClassImagePanels.AddToTail( this ); m_ModelName[0] = 0; }
CClassImagePanel::~CClassImagePanel() { g_ClassImagePanels.FindAndRemove( this ); }
void CClassImagePanel::ApplySettings( KeyValues *inResourceData ) { const char *pName = inResourceData->GetString( "3DModel" ); if ( pName ) { Q_strncpy( m_ModelName, pName, sizeof( m_ModelName ) ); }
BaseClass::ApplySettings( inResourceData ); }
void CClassImagePanel::Paint() { BaseClass::Paint(); }
Panel *TeamMenu::CreateControlByName(const char *controlName) { if ( Q_stricmp( controlName, "ClassImagePanel" ) == 0 ) { return new CClassImagePanel( NULL, controlName ); }
return BaseClass::CreateControlByName( controlName ); }
teammenu.res
"classimage"
{
"ControlName" "ClassImagePanel"
"fieldName" "classimage"
"xpos" "270"
"ypos" "170"
"wide" "512"
"tall" "384"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"textAlignment" "west"
"3DModel" "models/player/iris.mdl"
"scaleImage" "1"
"zpos" "1"
}