/* ============== idGrabber::~idGrabber ============== */ idGrabber::~idGrabber( void ) { StopDrag( true ); if ( beam ) { delete beam; } if ( beamTarget ) { delete beamTarget; } }
void InputHandler::processEvents(sf::Window& window) { reset(); sf::Event event; while (window.pollEvent(event)) { switch (event.type) { case sf::Event::KeyPressed: if (key_press_callback_func != nullptr) key_press_callback_func(event.key); break; case sf::Event::KeyReleased: if (key_release_callback_func != nullptr) key_release_callback_func(event.key); break; case sf::Event::MouseMoved: m_NewMousePosition.x = event.mouseMove.x; m_NewMousePosition.y = event.mouseMove.y; if (mouse_moved_callback_func != nullptr) mouse_moved_callback_func(event.mouseMove); m_LastMousePosition.x = event.mouseMove.x; m_LastMousePosition.y = event.mouseMove.y; break; case sf::Event::MouseWheelScrolled: if (mouse_wheel_scroll_callback_func != nullptr) mouse_wheel_scroll_callback_func(event.mouseWheelScroll); break; case sf::Event::MouseButtonPressed: if (mouse_button_pressed_callback_func != nullptr) mouse_button_pressed_callback_func(event.mouseButton); StartDrag(event.mouseButton); break; case sf::Event::MouseButtonReleased: StopDrag(event.mouseButton); if (mouse_button_released_callback_func != nullptr) mouse_button_released_callback_func(event.mouseButton); break; case sf::Event::Closed: window.close(); break; } } }
/* ============== idGrabEntity::~idGrabEntity ============== */ idGrabEntity::~idGrabEntity( void ) { StopDrag( owner, true ); }
/* ============== idGrabber::Update ============== */ int idGrabber::Update( idPlayer *player, bool hide ) { trace_t trace; idEntity *newEnt; // pause before allowing refire if ( lastFiredTime + FIRING_DELAY > gameLocal.time ) { return 3; } // Dead players release the trigger if ( hide || player->health <= 0 ) { StopDrag( true ); if ( hide ) { lastFiredTime = gameLocal.time - FIRING_DELAY + 250; } return 3; } // Check if object being held has been removed (dead demon, projectile, etc.) if ( endTime > gameLocal.time ) { bool abort = !dragEnt.IsValid(); if ( !abort && dragEnt.GetEntity()->IsType( idProjectile::Type ) ) { idProjectile *proj = (idProjectile *)dragEnt.GetEntity(); if ( proj->GetProjectileState() >= 3 ) { abort = true; } } if ( !abort && dragEnt.GetEntity()->IsHidden() ) { abort = true; } // Not in multiplayer :: Pressing "reload" lets you carefully drop an item if ( !gameLocal.isMultiplayer && !abort && (( player->usercmd.flags & UCF_IMPULSE_SEQUENCE ) != ( oldUcmdFlags & UCF_IMPULSE_SEQUENCE )) && (player->usercmd.impulse == IMPULSE_13) ) { abort = true; } if ( abort ) { StopDrag( true ); return 3; } } owner = player; // if no entity selected for dragging if ( !dragEnt.GetEntity() ) { idBounds bounds; idVec3 end = player->firstPersonViewOrigin + player->firstPersonViewAxis[0] * dragTraceDist; bounds.Zero(); bounds.ExpandSelf( TRACE_BOUNDS_SIZE ); gameLocal.clip.TraceBounds( trace, player->firstPersonViewOrigin, end, bounds, MASK_SHOT_RENDERMODEL|CONTENTS_PROJECTILE|CONTENTS_MOVEABLECLIP, player ); // If the trace hit something if ( trace.fraction < 1.0f ) { newEnt = gameLocal.entities[ trace.c.entityNum ]; // if entity is already being grabbed then bypass if ( gameLocal.isMultiplayer && newEnt->IsGrabbed() ) { return 0; } // Check if this is a valid entity to hold if ( newEnt && ( newEnt->IsType( idMoveable::Type ) || newEnt->IsType( idMoveableItem::Type ) || newEnt->IsType( idProjectile::Type ) || newEnt->IsType( idAFEntity_Gibbable::Type ) ) && newEnt->noGrab == false && newEnt->GetPhysics()->GetBounds().GetRadius() < MAX_PICKUP_SIZE && newEnt->GetPhysics()->GetLinearVelocity().LengthSqr() < MAX_PICKUP_VELOCITY ) { bool validAF = true; if ( newEnt->IsType( idAFEntity_Gibbable::Type ) ) { idAFEntity_Gibbable *afEnt = static_cast<idAFEntity_Gibbable*>(newEnt); if ( grabbableAI( newEnt->spawnArgs.GetString( "classname" ) ) ) { // Make sure it's also active if ( !afEnt->IsActive() ) { validAF = false; } } else if ( !afEnt->IsActiveAF() ) { validAF = false; } } if ( validAF && player->usercmd.buttons & BUTTON_ATTACK ) { // Grab this entity and start dragging it around StartDrag( newEnt, trace.c.id ); } else if ( validAF ) { // A holdable object is ready to be grabbed return 1; } } } } // check backwards server time in multiplayer bool allow = true; if ( gameLocal.isMultiplayer ) { // if we've marched backwards if ( gameLocal.slow.time < startDragTime ) { allow = false; } } // if there is an entity selected for dragging if ( dragEnt.GetEntity() && allow ) { idPhysics *entPhys = dragEnt.GetEntity()->GetPhysics(); idVec3 goalPos; // If the player lets go of attack, or time is up if ( !( player->usercmd.buttons & BUTTON_ATTACK ) ) { StopDrag( false ); return 3; } if ( gameLocal.time > endTime ) { StopDrag( true ); return 3; } // Check if the player is standing on the object if ( !holdingAF ) { idBounds playerBounds; idBounds objectBounds = entPhys->GetAbsBounds(); idVec3 newPoint = player->GetPhysics()->GetOrigin(); // create a bounds at the players feet playerBounds.Clear(); playerBounds.AddPoint( newPoint ); newPoint.z -= 1.f; playerBounds.AddPoint( newPoint ); playerBounds.ExpandSelf( 8.f ); // If it intersects the object bounds, then drop it if ( playerBounds.IntersectsBounds( objectBounds ) ) { StopDrag( true ); return 3; } } // Shake the object at the end of the hold if ( g_grabberEnableShake.GetBool() && !gameLocal.isMultiplayer ) { ApplyShake(); } // Set and evaluate drag force goalPos = player->firstPersonViewOrigin + localPlayerPoint * player->firstPersonViewAxis; drag.SetGoalPosition( goalPos ); drag.Evaluate( gameLocal.time ); // If an object is flying too fast toward the player, stop it hard if ( g_grabberHardStop.GetBool() ) { idPlane theWall; idVec3 toPlayerVelocity, objectCenter; float toPlayerSpeed; toPlayerVelocity = -player->firstPersonViewAxis[0]; toPlayerSpeed = entPhys->GetLinearVelocity() * toPlayerVelocity; if ( toPlayerSpeed > 64.f ) { objectCenter = entPhys->GetAbsBounds().GetCenter(); theWall.SetNormal( player->firstPersonViewAxis[0] ); theWall.FitThroughPoint( goalPos ); if ( theWall.Side( objectCenter, 0.1f ) == PLANESIDE_BACK ) { int i, num; num = entPhys->GetNumClipModels(); for ( i=0; i<num; i++ ) { entPhys->SetLinearVelocity( vec3_origin, i ); } } } // Make sure the object isn't spinning too fast const float MAX_ROTATION_SPEED = 12.f; idVec3 angVel = entPhys->GetAngularVelocity(); float rotationSpeed = angVel.LengthFast(); if ( rotationSpeed > MAX_ROTATION_SPEED ) { angVel.NormalizeFast(); angVel *= MAX_ROTATION_SPEED; entPhys->SetAngularVelocity( angVel ); } } // Orient projectiles away from the player if ( dragEnt.GetEntity()->IsType( idProjectile::Type ) ) { idAngles ang = player->firstPersonViewAxis[0].ToAngles(); ang.pitch += 90.f; entPhys->SetAxis( ang.ToMat3() ); } // Some kind of effect from gun to object? UpdateBeams(); // If the object is stuck away from its intended position for more than 500ms, let it go. if ( drag.GetDistanceToGoal() > DRAG_FAIL_LEN ) { if ( dragFailTime < (gameLocal.slow.time - 500) ) { StopDrag( true ); return 3; } } else { dragFailTime = gameLocal.slow.time; } // Currently holding an object return 2; } // Not holding, nothing to hold return 0; }
/* ============== idGrabEntity::Update ============== */ void idGrabEntity::Update( idPlayer *player ) { owner = player; if ( lastThrownTime > gameLocal.time ) { prevViewAngles = player->viewAngles; return; } bool valid = dragEnt.IsValid(); // Check if object being held has been removed or player is dead if ( valid && dragEnt.GetEntity()->IsHidden() || player->health <= 0 ) { StopDrag( player, true ); prevViewAngles = player->viewAngles; return; } // attack throws object if ( valid && player->usercmd.buttons & BUTTON_ATTACK ) { StopDrag( player, false ); prevViewAngles = player->viewAngles; return; } // if there is an entity selected for dragging if ( dragEnt.GetEntity() ) { idPhysics *entPhys = dragEnt.GetEntity()->GetPhysics(); idVec3 goalPos; // Check if the player is standing on the object idBounds playerBounds; idBounds objectBounds = entPhys->GetAbsBounds(); idVec3 newPoint = player->GetPhysics()->GetOrigin(); // create a bounds at the players feet playerBounds.Clear(); playerBounds.AddPoint( newPoint ); newPoint.z -= 1.0f; playerBounds.AddPoint( newPoint ); playerBounds.ExpandSelf( 8.0f ); // If it intersects the object bounds, then drop it if ( playerBounds.IntersectsBounds( objectBounds ) ) { StopDrag( player, true ); prevViewAngles = player->viewAngles; return; } idAngles ang = entPhys->GetAxis().ToAngles(); ang.yaw += player->viewAngles.yaw - prevViewAngles.yaw; if ( ang.yaw > 180.0f ) ang.yaw -= 360.0f; else if ( ang.yaw < -180.0f ) ang.yaw += 360.0f; entPhys->SetAxis( ang.ToMat3() ); // Set and evaluate drag force goalPos = player->firstPersonViewOrigin + localPlayerPoint * player->firstPersonViewAxis; drag.SetGoalPosition( goalPos ); drag.Evaluate( gameLocal.time, false ); // If the object is stuck away from its intended position for more than 500ms, let it go. if ( drag.GetDistanceToGoal() > DRAG_FAIL_LEN ) { if ( dragFailTime < gameLocal.time ) { StopDrag( player, true ); prevViewAngles = player->viewAngles; return; } } else { dragFailTime = gameLocal.time + 1000; } } prevViewAngles = player->viewAngles; }
/* ============== idDragEntity::DeleteSelected ============== */ void idDragEntity::DeleteSelected( void ) { delete selected.GetEntity(); selected = NULL; StopDrag(); }
/* ============== idDragEntity::SetSelected ============== */ void idDragEntity::SetSelected( idEntity *ent ) { selected = ent; StopDrag(); }
/* ============== idDragEntity::Update ============== */ void idDragEntity::Update( idPlayer *player ) { idVec3 viewPoint, origin; idMat3 viewAxis, axis; trace_t trace; idEntity *newEnt; idAngles angles; jointHandle_t newJoint; idStr newBodyName; player->GetViewPos( viewPoint, viewAxis ); // if no entity selected for dragging if ( !dragEnt.GetEntity() ) { if ( player->usercmd.buttons & BUTTON_ATTACK ) { gameLocal.clip.TracePoint( trace, viewPoint, viewPoint + viewAxis[0] * MAX_DRAG_TRACE_DISTANCE, (CONTENTS_SOLID|CONTENTS_RENDERMODEL|CONTENTS_BODY), player ); if ( trace.fraction < 1.0f ) { newEnt = gameLocal.entities[ trace.c.entityNum ]; if ( newEnt ) { if ( newEnt->GetBindMaster() ) { if ( newEnt->GetBindJoint() ) { trace.c.id = JOINT_HANDLE_TO_CLIPMODEL_ID( newEnt->GetBindJoint() ); } else { trace.c.id = newEnt->GetBindBody(); } newEnt = newEnt->GetBindMaster(); } if ( newEnt->IsType( idAFEntity_Base::Type ) && static_cast<idAFEntity_Base *>(newEnt)->IsActiveAF() ) { idAFEntity_Base *af = static_cast<idAFEntity_Base *>(newEnt); // joint being dragged newJoint = CLIPMODEL_ID_TO_JOINT_HANDLE( trace.c.id ); // get the body id from the trace model id which might be a joint handle trace.c.id = af->BodyForClipModelId( trace.c.id ); // get the name of the body being dragged newBodyName = af->GetAFPhysics()->GetBody( trace.c.id )->GetName(); } else if ( !newEnt->IsType( idWorldspawn::Type ) ) { if ( trace.c.id < 0 ) { newJoint = CLIPMODEL_ID_TO_JOINT_HANDLE( trace.c.id ); } else { newJoint = INVALID_JOINT; } newBodyName = ""; } else { newJoint = INVALID_JOINT; newEnt = NULL; } } if ( newEnt ) { dragEnt = newEnt; selected = newEnt; joint = newJoint; id = trace.c.id; bodyName = newBodyName; if ( !cursor ) { cursor = ( idCursor3D * )gameLocal.SpawnEntityType( idCursor3D::Type ); } idPhysics *phys = dragEnt.GetEntity()->GetPhysics(); localPlayerPoint = ( trace.c.point - viewPoint ) * viewAxis.Transpose(); origin = phys->GetOrigin( id ); axis = phys->GetAxis( id ); localEntityPoint = ( trace.c.point - origin ) * axis.Transpose(); cursor->drag.Init( g_dragDamping.GetFloat() ); cursor->drag.SetPhysics( phys, id, localEntityPoint ); cursor->Show(); if ( phys->IsType( idPhysics_AF::Type ) || phys->IsType( idPhysics_RigidBody::Type ) || phys->IsType( idPhysics_Monster::Type ) ) { cursor->BecomeActive( TH_THINK ); } } } } } // if there is an entity selected for dragging idEntity *drag = dragEnt.GetEntity(); if ( drag ) { if ( !( player->usercmd.buttons & BUTTON_ATTACK ) ) { StopDrag(); return; } cursor->SetOrigin( viewPoint + localPlayerPoint * viewAxis ); cursor->SetAxis( viewAxis ); cursor->drag.SetDragPosition( cursor->GetPhysics()->GetOrigin() ); renderEntity_t *renderEntity = drag->GetRenderEntity(); idAnimator *dragAnimator = drag->GetAnimator(); if ( joint != INVALID_JOINT && renderEntity && dragAnimator ) { dragAnimator->GetJointTransform( joint, gameLocal.time, cursor->draggedPosition, axis ); cursor->draggedPosition = renderEntity->origin + cursor->draggedPosition * renderEntity->axis; gameRenderWorld->DrawText( va( "%s\n%s\n%s, %s", drag->GetName(), drag->GetType()->classname, dragAnimator->GetJointName( joint ), bodyName.c_str() ), cursor->GetPhysics()->GetOrigin(), 0.1f, colorWhite, viewAxis, 1 ); } else { cursor->draggedPosition = cursor->GetPhysics()->GetOrigin(); gameRenderWorld->DrawText( va( "%s\n%s\n%s", drag->GetName(), drag->GetType()->classname, bodyName.c_str() ), cursor->GetPhysics()->GetOrigin(), 0.1f, colorWhite, viewAxis, 1 ); } } // if there is a selected entity if ( selected.GetEntity() && g_dragShowSelection.GetBool() ) { // draw the bbox of the selected entity renderEntity_t *renderEntity = selected.GetEntity()->GetRenderEntity(); if ( renderEntity ) { gameRenderWorld->DebugBox( colorYellow, idBox( renderEntity->bounds, renderEntity->origin, renderEntity->axis ) ); } } }
/* ============== idDragEntity::~idDragEntity ============== */ idDragEntity::~idDragEntity( void ) { StopDrag(); selected = NULL; delete cursor; cursor = NULL; }