public override void OnBeforeRemovedFromContainer() { m_useObjectComp = null; if (Container.Entity.InScene) { Debug.Assert(m_respawns.Contains(this), "Double remove of respawn component from the respawns list"); m_respawns.Remove(this); } base.OnBeforeRemovedFromContainer(); }
private void GetUseComponentsFromParentStructure(IMyEntity currentEntity, List <MyUseObjectsComponentBase> useComponents) { MyUseObjectsComponentBase item = currentEntity.Components.Get <MyUseObjectsComponentBase>(); if (item != null) { useComponents.Add(item); } if (currentEntity.Parent != null) { this.GetUseComponentsFromParentStructure(currentEntity.Parent, useComponents); } }
protected override void DoDetection(bool useHead) { if (Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = false; } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version var cameraMatrix = MySector.MainCamera.WorldMatrix; dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE; //VRageRender.MyRenderProxy.DebugDrawLine3D(from, to, Color.Red, Color.Green, true); //VRageRender.MyRenderProxy.DebugDrawSphere(headPos, 0.05f, Color.Red.ToVector3(), 1.0f, false); MyPhysics.CastRay(from, to, m_hits); bool hasInteractive = false; int index = 0; while (index < m_hits.Count && (m_hits[index].HkHitInfo.Body == null || m_hits[index].HkHitInfo.Body.UserObject == Character.Physics || (Character.VirtualPhysics != null && m_hits[index].HkHitInfo.Body.UserObject == Character.VirtualPhysics) || m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))) // Skip invalid hits and self character { index++; } if (index < m_hits.Count) { //We must take only closest hit (others are hidden behind) var h = m_hits[index]; var entity = h.HkHitInfo.Body.GetEntity(); var interactive = entity as IMyUseObject; // TODO: Uncomment to enforce that character must face object by front to activate it //if (TestInteractionDirection(head.Forward, h.Position - GetPosition())) //return; if (entity != null) { MyUseObjectsComponentBase useObject = null; entity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(h.HkHitInfo.GetShapeKey(0)); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, (Vector3D)h.Position)) < interactive.InteractiveDistance && Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = true; MyHud.SelectedObjectHighlight.InteractiveObject = interactive; UseObject = interactive; hasInteractive = true; } } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } }
private void DoDetection(bool useHead, bool doModelIntersection) { if (Character == MySession.Static.ControlledEntity) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } var head = Character.GetHeadMatrix(false); Vector3D from = head.Translation; Vector3D dir = head.Forward; if (!useHead) { var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) if (Character == MySession.Static.LocalCharacter) { from = MySector.MainCamera.WorldMatrix.Translation; dir = MySector.MainCamera.WorldMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, from, (Vector3)dir); } else { from = headPos; dir = head.Forward; } } Vector3D to = from + dir * 2.5;//MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; HitMaterial = MyStringHash.NullOrEmpty; HitTag = null; m_hits.Clear(); Vector3 interactivePosition = Vector3D.Zero; try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); m_rayOrigin = from; m_rayDirection = dir; m_hits.Sort(CompareHits); if (m_hits.Count > 0) { bool isValidBlock = false; bool isPhysicalBlock = false; for (int index = 0; index < m_hits.Count; index++) { HkRigidBody body = m_hits[index].HkHitInfo.Body; IMyEntity entity = m_hits[index].HkHitInfo.GetHitEntity(); // Ignore self-interaction if (entity == Character) { continue; } if (entity is VRage.Game.Entity.MyEntitySubpart) { entity = entity.Parent; } isValidBlock = body != null && entity != null && entity != Character && !body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); isPhysicalBlock = entity != null && entity.Physics != null; if (hitEntity == null && isValidBlock) { hitEntity = entity; ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); } // If hit-entity is a grid, raycast it to see which block we hit first if (entity is MyCubeGrid) { MyCubeGrid grid = entity as MyCubeGrid; List <MyCube> cubeList = grid.RayCastBlocksAllOrdered(from, to); if (cubeList != null && cubeList.Count > 0) { var slimblock = cubeList[0].CubeBlock; if (slimblock.FatBlock != null) { entity = slimblock.FatBlock; isPhysicalBlock = true; hitEntity = entity; ShapeKey = 0; } } } // Set hit material etc. only for object's that have physical representation in the world, this exclude detectors if (HitMaterial.Equals(MyStringHash.NullOrEmpty) && isValidBlock && isPhysicalBlock) { HitBody = body; HitNormal = m_hits[index].HkHitInfo.Normal; HitPosition = m_hits[index].GetFixedPosition(); HitMaterial = body.GetBody().GetMaterialAt(HitPosition); interactivePosition = HitPosition; break; } else if (body != null) { interactivePosition = m_hits[index].GetFixedPosition(); break; } index++; } } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } // Do accurate collision checking on model if (doModelIntersection) { LineD line = new LineD(from, to); var character = hitEntity as MyCharacter; if (character == null) { MyIntersectionResultLineTriangleEx?result; bool success = hitEntity.GetIntersectionWithLine(ref line, out result, IntersectionFlags.ALL_TRIANGLES); if (success) { HitPosition = result.Value.IntersectionPointInWorldSpace; HitNormal = result.Value.NormalInWorldSpace; } } else { bool success = character.GetIntersectionWithLine(ref line, ref CharHitInfo); if (success) { HitPosition = CharHitInfo.Triangle.IntersectionPointInWorldSpace; HitNormal = CharHitInfo.Triangle.NormalInWorldSpace; HitTag = CharHitInfo; } } } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, interactivePosition)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } DisableDetectors(); }
protected override void DoDetection(bool useHead) { if (Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = false; } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version //var cameraMatrix = MySector.MainCamera.WorldMatrix; var cameraMatrix = Character.Get3rdBoneMatrix(true, true); dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * 2.5f; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; m_hits.Clear(); try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); int index = 0; while (index < m_hits.Count && (m_hits[index].HkHitInfo.Body == null || m_hits[index].HkHitInfo.GetHitEntity() == Character || m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))) // Skip invalid hits and self character { index++; } if (index < m_hits.Count) { hitEntity = m_hits[index].HkHitInfo.GetHitEntity(); ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); HitPosition = m_hits[index].Position; HitNormal = m_hits[index].HkHitInfo.Normal; HitMaterial = m_hits[index].HkHitInfo.Body.GetBody().GetMaterialAt(HitPosition + HitNormal * 0.1f); HitBody = m_hits[index].HkHitInfo.Body; } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, HitPosition)) < interactive.InteractiveDistance && Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = true; MyHud.SelectedObjectHighlight.InteractiveObject = interactive; UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } DisableDetectors(); }
void Container_ComponentRemoved(Type compType, MyEntityComponentBase component) { if (compType == typeof(MyUseObjectsComponentBase)) m_useObjectComp = null; }
void Container_ComponentAdded(Type compType, MyEntityComponentBase component) { if (compType == typeof(MyUseObjectsComponentBase)) m_useObjectComp = component as MyUseObjectsComponentBase; }
protected override void DoDetection(bool useHead) { if (Character == MySession.Static.ControlledEntity) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version var cameraMatrix = MySector.MainCamera.WorldMatrix; //var cameraMatrix = Character.Get3rdBoneMatrix(true, true); dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; HitMaterial = MyStringHash.NullOrEmpty; m_hits.Clear(); try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); if (m_hits.Count > 0) { int index = 0; bool isValidBlock = false; bool isPhysicalBlock = false; do { isValidBlock = m_hits[index].HkHitInfo.Body != null && m_hits[index].HkHitInfo.GetHitEntity() != Character && m_hits[index].HkHitInfo.GetHitEntity() != null && !m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); isPhysicalBlock = m_hits[index].HkHitInfo.GetHitEntity() != null && m_hits[index].HkHitInfo.GetHitEntity().Physics != null; if (hitEntity == null && isValidBlock) { hitEntity = m_hits[index].HkHitInfo.GetHitEntity(); ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); } // Set hit material etc. only for object's that have physical representation in the world, this exclude detectors if (HitMaterial.Equals(MyStringHash.NullOrEmpty) && isValidBlock && isPhysicalBlock) { HitBody = m_hits[index].HkHitInfo.Body; HitPosition = m_hits[index].Position; HitNormal = m_hits[index].HkHitInfo.Normal; HitMaterial = m_hits[index].HkHitInfo.Body.GetBody().GetMaterialAt(HitPosition + HitNormal * 0.1f); } index++; } while (index < m_hits.Count && (!isValidBlock || !isPhysicalBlock)); } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, HitPosition)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } DisableDetectors(); }
protected override void DoDetection(bool useHead) { ProfilerShort.Begin("DoDetection"); if (Character == MySession.Static.ControlledEntity) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version var cameraMatrix = MySector.MainCamera.WorldMatrix; dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; LineD intersectionLine = new LineD(from, to); // Processing of hit entities var geometryHit = MyEntities.GetIntersectionWithLine(ref intersectionLine, null, null, ignoreFloatingObjects: false); bool hasUseObject = false; if (geometryHit.HasValue) { var hitEntity = geometryHit.Value.Entity; // Cube Grids are special case var cubeGrid = hitEntity as MyCubeGrid; if (cubeGrid != null) { // For hit cube grids get the fat hit fatblock instead. var slimBlock = cubeGrid.GetTargetedBlock(geometryHit.Value.IntersectionPointInWorldSpace); if (slimBlock != null && slimBlock.FatBlock != null) { hitEntity = slimBlock.FatBlock; } } m_hitUseComponents.Clear(); var hitUseObject = hitEntity as IMyUseObject; // Retrive all above use components from parent structure. (Because of subParts) GetUseComponentsFromParentStructure(hitEntity, m_hitUseComponents); // Check for UseObjects and entities with UseObjectComponentBase. // Assuming that entity cannot be IMyUseObject and have UseObjectComponentBase in hierarchy // at the same time. if (hitUseObject != null || m_hitUseComponents.Count > 0) { if (m_hitUseComponents.Count > 0) { // Process the valid hit entity var closestDetectorDistance = float.MaxValue; double physicalHitDistance = Vector3D.Distance(from, geometryHit.Value.IntersectionPointInWorldSpace); MyUseObjectsComponentBase hitUseComp = null; // Evaluate the set of found detectors and try to find the closest one foreach (var hitUseComponent in m_hitUseComponents) { float detectorDistance; var interactive = hitUseComponent.RaycastDetectors(from, to, out detectorDistance); detectorDistance *= MyConstants.DEFAULT_INTERACTIVE_DISTANCE; if (Math.Abs(detectorDistance) < Math.Abs(closestDetectorDistance) && (detectorDistance < physicalHitDistance)) // Remove to fix the problem with picking through physic bodies, { // but will introduce new problem with detectors inside physic bodies. closestDetectorDistance = detectorDistance; hitUseComp = hitUseComponent; hitEntity = hitUseComponent.Entity; hitUseObject = interactive; } } // Detector found if (hitUseComp != null) { // Process successful hit with results var detectorPhysics = hitUseComp.DetectorPhysics; HitMaterial = detectorPhysics.GetMaterialAt(HitPosition); HitBody = geometryHit.Value.Entity.Physics.RigidBody; HitPosition = geometryHit.Value.IntersectionPointInWorldSpace; DetectedEntity = hitEntity; } } else { // Case for hitting IMyUseObject already before even looking for UseComponent. // Floating object case. HitMaterial = hitEntity.Physics.GetMaterialAt(HitPosition); HitBody = hitEntity.Physics.RigidBody; } // General logic for processing both cases. if (hitUseObject != null) { HitPosition = geometryHit.Value.IntersectionPointInWorldSpace; DetectedEntity = hitEntity; if (UseObject != null && UseObject != hitEntity && UseObject != hitUseObject) { UseObject.OnSelectionLost(); } if (Character == MySession.Static.ControlledEntity && hitUseObject.SupportedActions != UseActionEnum.None) { HandleInteractiveObject(hitUseObject); UseObject = hitUseObject; hasUseObject = true; } } } } if (!hasUseObject) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } ProfilerShort.End(); }
protected override void DoDetection(bool useHead) { Vector3D vectord2; Vector3D forward; if (ReferenceEquals(base.Character, MySession.Static.ControlledEntity)) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } MatrixD xd = base.Character.GetHeadMatrix(false, true, false, false, false); Vector3D planePoint = xd.Translation - (xd.Forward * 0.3); if (useHead) { forward = xd.Forward; vectord2 = planePoint; } else { MatrixD worldMatrix = MySector.MainCamera.WorldMatrix; forward = worldMatrix.Forward; vectord2 = MyUtils.LinePlaneIntersection(planePoint, (Vector3)forward, worldMatrix.Translation, (Vector3)forward); } Vector3D to = vectord2 + (forward * MyConstants.DEFAULT_INTERACTIVE_DISTANCE); base.StartPosition = vectord2; LineD line = new LineD(vectord2, to); MyIntersectionResultLineTriangleEx?nullable = Sandbox.Game.Entities.MyEntities.GetIntersectionWithLine(ref line, base.Character, null, false, false, true, IntersectionFlags.ALL_TRIANGLES, 0f, true); bool flag = false; if (nullable != null) { IMyEntity currentEntity = nullable.Value.Entity; Vector3D intersectionPointInWorldSpace = nullable.Value.IntersectionPointInWorldSpace; if ((currentEntity is MyCubeGrid) && (nullable.Value.UserObject != null)) { MySlimBlock cubeBlock = (nullable.Value.UserObject as MyCube).CubeBlock; if ((cubeBlock != null) && (cubeBlock.FatBlock != null)) { currentEntity = cubeBlock.FatBlock; } } this.m_hitUseComponents.Clear(); IMyUseObject interactive = currentEntity as IMyUseObject; this.GetUseComponentsFromParentStructure(currentEntity, this.m_hitUseComponents); if ((interactive != null) || (this.m_hitUseComponents.Count > 0)) { if (this.m_hitUseComponents.Count <= 0) { base.HitMaterial = currentEntity.Physics.GetMaterialAt(base.HitPosition); base.HitBody = currentEntity.Physics.RigidBody; } else { float maxValue = float.MaxValue; double num2 = Vector3D.Distance(vectord2, intersectionPointInWorldSpace); MyUseObjectsComponentBase base2 = null; foreach (MyUseObjectsComponentBase base3 in this.m_hitUseComponents) { float num3; IMyUseObject obj3 = base3.RaycastDetectors(vectord2, to, out num3); num3 *= MyConstants.DEFAULT_INTERACTIVE_DISTANCE; if ((Math.Abs(num3) < Math.Abs(maxValue)) && (num3 < num2)) { maxValue = num3; base2 = base3; currentEntity = base3.Entity; interactive = obj3; } } if (base2 != null) { base.HitMaterial = base2.DetectorPhysics.GetMaterialAt(base.HitPosition); this.HitBody = nullable.Value.Entity.Physics?.RigidBody; base.HitPosition = intersectionPointInWorldSpace; base.DetectedEntity = currentEntity; } } if (interactive != null) { base.HitPosition = intersectionPointInWorldSpace; base.DetectedEntity = currentEntity; if ((ReferenceEquals(base.Character, MySession.Static.ControlledEntity) && (interactive.SupportedActions != UseActionEnum.None)) && !base.Character.IsOnLadder) { HandleInteractiveObject(interactive); base.UseObject = interactive; flag = true; } if (base.Character.IsOnLadder) { base.UseObject = null; } } } } if (!flag) { base.UseObject = null; } }
protected override void DoDetection(bool useHead) { if (Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = false; } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version var cameraMatrix = MySector.MainCamera.WorldMatrix; dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(SHAPE_RADIUS); IMyEntity hitEntity = null; int shapeKey = -1; Vector3D hitPosition = Vector3D.Zero; m_hits.Clear(); try { MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); int index = 0; while (index < m_hits.Count && (m_hits[index].Body == null || m_hits[index].Body.UserObject == Character.Physics || (Character.VirtualPhysics != null && m_hits[index].Body.UserObject == Character.VirtualPhysics) || m_hits[index].Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))) // Skip invalid hits and self character { index++; } if (index < m_hits.Count) { hitEntity = m_hits[index].Body.GetEntity(); shapeKey = m_hits[index].ShapeKey; hitPosition = m_hits[index].HitPosition; } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(shapeKey); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, hitPosition)) < interactive.InteractiveDistance && Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = true; MyHud.SelectedObjectHighlight.InteractiveObject = interactive; UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } }
protected override void DoDetection(bool useHead) { ProfilerShort.Begin("DoDetection"); if (Character == MySession.Static.ControlledEntity) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version var cameraMatrix = MySector.MainCamera.WorldMatrix; dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; // Processing of hit entities MyPhysics.CastRay(from, to, m_hits, MyPhysics.CollisionLayers.FloatingObjectCollisionLayer); bool hasUseObject = false; int index = 0; while (index < m_hits.Count) { var hitEntity = m_hits[index].HkHitInfo.GetHitEntity(); // Skip invalid hits if (m_hits[index].HkHitInfo.Body == null || hitEntity == null || hitEntity == Character || m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT) || m_hits[index].HkHitInfo.Body.Layer == MyPhysics.CollisionLayers.VoxelLod1CollisionLayer) { index++; continue; } // Cube Grids are special case var cubeGrid = hitEntity as MyCubeGrid; if (cubeGrid != null) { // Correct the hit position (Physics offset) var correctedPosition = m_hits[index].Position - m_hits[index].HkHitInfo.Normal * m_hits[index].HkHitInfo.GetConvexRadius(); // For hit cube grids get the fat hit fatblock instead. var slimBlock = cubeGrid.GetTargetedBlock(correctedPosition); if (slimBlock != null && slimBlock.FatBlock != null) { hitEntity = slimBlock.FatBlock; } } m_hitUseComponents.Clear(); var hitUseObject = hitEntity as IMyUseObject; // Retrive all above use components from parent structure. (Because of subParts) GetUseComponentsFromParentStructure(hitEntity, m_hitUseComponents); // Check for UseObjects and entities with UseObjectComponentBase. // Assuming that entity cannot be IMyUseObject and have UseObjectComponentBase in hierarchy // at the same time. if (hitUseObject != null || m_hitUseComponents.Count > 0) { if (m_hitUseComponents.Count > 0) { // Process the valid hit entity var closestDetectorDistance = float.MaxValue; MyUseObjectsComponentBase hitUseComp = null; // Evaluate the set of found detectors and try to find the closest one foreach (var hitUseComponent in m_hitUseComponents) { float detectorDistance; var interactive = hitUseComponent.RaycastDetectors(from, to, out detectorDistance); if (Math.Abs(detectorDistance) < Math.Abs(closestDetectorDistance)) { closestDetectorDistance = detectorDistance; hitUseComp = hitUseComponent; hitEntity = hitUseComponent.Entity; hitUseObject = interactive; } } // Detector found if (hitUseComp != null) { // Process successful hit with results var detectorPhysics = hitUseComp.DetectorPhysics; HitMaterial = detectorPhysics.GetMaterialAt(HitPosition); HitBody = m_hits[index].HkHitInfo.Body; HitPosition = m_hits[index].Position; DetectedEntity = hitEntity; } } else { // Case for hitting IMyUseObject already before even looking for UseComponent. // Floating object case. HitMaterial = hitEntity.Physics.GetMaterialAt(HitPosition); HitBody = m_hits[index].HkHitInfo.Body; } // General logic for processing both cases. if (hitUseObject != null) { HitPosition = m_hits[index].Position; DetectedEntity = hitEntity; if (UseObject != null && UseObject != hitEntity) { UseObject.OnSelectionLost(); } if (hitUseObject.SupportedActions != UseActionEnum.None && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(hitUseObject); UseObject = hitUseObject; hasUseObject = true; } } break; } index++; } if (!hasUseObject) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } ProfilerShort.End(); }
private void DoDetection(bool useHead, bool doModelIntersection) { bool flag; if (ReferenceEquals(base.Character, MySession.Static.ControlledEntity)) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } MatrixD xd = base.Character.GetHeadMatrix(false, true, false, false, false); Vector3D translation = xd.Translation; Vector3D forward = xd.Forward; if (!useHead) { Vector3D planePoint = xd.Translation - (xd.Forward * 0.3); if (!ReferenceEquals(base.Character, MySession.Static.LocalCharacter)) { translation = planePoint; forward = xd.Forward; } else { translation = MySector.MainCamera.WorldMatrix.Translation; forward = MySector.MainCamera.WorldMatrix.Forward; translation = MyUtils.LinePlaneIntersection(planePoint, (Vector3)forward, translation, (Vector3)forward); } } Vector3D to = translation + (forward * 2.5); base.StartPosition = translation; MatrixD transform = MatrixD.CreateTranslation(translation); HkShape shape = (HkShape) new HkSphereShape(this.ShapeRadius); IMyEntity objA = null; base.ShapeKey = uint.MaxValue; base.HitPosition = Vector3D.Zero; base.HitNormal = Vector3.Zero; base.HitMaterial = MyStringHash.NullOrEmpty; base.HitTag = null; this.m_hits.Clear(); Vector3 zero = (Vector3)Vector3D.Zero; try { bool flag2; bool flag3; int num; base.EnableDetectorsInArea(translation); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref transform, 0, 0f, this.m_hits, true); this.m_rayOrigin = translation; this.m_rayDirection = forward; this.m_hits.Sort(new Comparison <MyPhysics.HitInfo>(this.CompareHits)); if (this.m_hits.Count <= 0) { goto TR_0012; } else { flag2 = false; flag3 = false; num = 0; } goto TR_002F; TR_0017: num++; TR_002F: while (true) { if (num >= this.m_hits.Count) { break; } HkRigidBody hkEntity = this.m_hits[num].HkHitInfo.Body; IMyEntity hitEntity = this.m_hits[num].HkHitInfo.GetHitEntity(); if (!ReferenceEquals(hitEntity, base.Character)) { int num1; if (hitEntity is MyEntitySubpart) { hitEntity = hitEntity.Parent; } if (((hkEntity == null) || (hitEntity == null)) || ReferenceEquals(hitEntity, base.Character)) { num1 = 0; } else { num1 = (int)!hkEntity.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); } flag2 = (bool)num1; flag3 = (hitEntity != null) && (hitEntity.Physics != null); if (ReferenceEquals(objA, null) & flag2) { objA = hitEntity; base.ShapeKey = this.m_hits[num].HkHitInfo.GetShapeKey(0); } if (hitEntity is MyCubeGrid) { List <MyCube> list = (hitEntity as MyCubeGrid).RayCastBlocksAllOrdered(translation, to); if ((list != null) && (list.Count > 0)) { MySlimBlock cubeBlock = list[0].CubeBlock; if (cubeBlock.FatBlock != null) { flag3 = true; objA = cubeBlock.FatBlock; base.ShapeKey = 0; } } } if (!((base.HitMaterial.Equals(MyStringHash.NullOrEmpty) & flag2) & flag3)) { if (hkEntity == null) { num++; goto TR_0017; } else { zero = this.m_hits[num].GetFixedPosition(); } } else { base.HitBody = hkEntity; base.HitNormal = this.m_hits[num].HkHitInfo.Normal; base.HitPosition = this.m_hits[num].GetFixedPosition(); base.HitMaterial = hkEntity.GetBody().GetMaterialAt(base.HitPosition); zero = (Vector3)base.HitPosition; } break; } goto TR_0017; } } finally { shape.RemoveReference(); } TR_0012: flag = false; IMyUseObject interactive = objA as IMyUseObject; base.DetectedEntity = objA; if (objA != null) { MyUseObjectsComponentBase component = null; objA.Components.TryGet <MyUseObjectsComponentBase>(out component); if (component != null) { interactive = component.GetInteractiveObject(base.ShapeKey); } if (doModelIntersection) { LineD line = new LineD(translation, to); MyCharacter character = objA as MyCharacter; if (character == null) { MyIntersectionResultLineTriangleEx?nullable; if (objA.GetIntersectionWithLine(ref line, out nullable, IntersectionFlags.ALL_TRIANGLES)) { base.HitPosition = nullable.Value.IntersectionPointInWorldSpace; base.HitNormal = nullable.Value.NormalInWorldSpace; } } else if (character.GetIntersectionWithLine(ref line, ref base.CharHitInfo, IntersectionFlags.ALL_TRIANGLES)) { base.HitPosition = base.CharHitInfo.Triangle.IntersectionPointInWorldSpace; base.HitNormal = base.CharHitInfo.Triangle.NormalInWorldSpace; base.HitTag = base.CharHitInfo; } } } if (((interactive != null) && ((interactive.SupportedActions != UseActionEnum.None) && (Vector3D.Distance(translation, zero) < interactive.InteractiveDistance))) && ReferenceEquals(base.Character, MySession.Static.ControlledEntity)) { HandleInteractiveObject(interactive); base.UseObject = interactive; flag = true; } if (!flag) { base.UseObject = null; } base.DisableDetectors(); }
private void DoDetection(bool useHead, bool doModelIntersection) { if (Character == MySession.Static.ControlledEntity) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version //var cameraMatrix = MySector.MainCamera.WorldMatrix; var cameraMatrix = Character.Get3rdBoneMatrix(true, true); dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * 2.5;//MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; HitMaterial = MyStringHash.NullOrEmpty; HitTag = null; m_hits.Clear(); Vector3 interactivePosition = Vector3D.Zero; try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); m_hits.Sort(delegate(MyPhysics.HitInfo info1, MyPhysics.HitInfo info2) { float dot1 = Vector3.Dot(head.Forward, Vector3.Normalize(info1.Position - StartPosition)); float dot2 = Vector3.Dot(head.Forward, Vector3.Normalize(info2.Position - StartPosition)); return(dot1.CompareTo(dot2)); }); if (m_hits.Count > 0) { int index = 0; bool isValidBlock = false; bool isPhysicalBlock = false; do { HkRigidBody body = m_hits[index].HkHitInfo.Body; IMyEntity entity = m_hits[index].HkHitInfo.GetHitEntity(); if (entity is VRage.Game.Entity.MyEntitySubpart) { entity = entity.Parent; } isValidBlock = body != null && entity != null && entity != Character && !body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); isPhysicalBlock = entity != null && entity.Physics != null; if (hitEntity == null && isValidBlock) { hitEntity = entity; ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); } // Set hit material etc. only for object's that have physical representation in the world, this exclude detectors if (HitMaterial.Equals(MyStringHash.NullOrEmpty) && isValidBlock && isPhysicalBlock) { HitBody = body; HitNormal = m_hits[index].HkHitInfo.Normal; HitPosition = m_hits[index].GetFixedPosition(); HitMaterial = body.GetBody().GetMaterialAt(HitPosition); interactivePosition = HitPosition; } else if (body != null) { interactivePosition = m_hits[index].GetFixedPosition(); } index++; } while (index < m_hits.Count && (!isValidBlock || !isPhysicalBlock)); } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } // Do accurate collision checking on model if (doModelIntersection) { LineD line = new LineD(from, to); var character = hitEntity as MyCharacter; if (character == null) { MyIntersectionResultLineTriangleEx?result; bool success = hitEntity.GetIntersectionWithLine(ref line, out result, IntersectionFlags.ALL_TRIANGLES); if (success) { HitPosition = result.Value.IntersectionPointInWorldSpace; HitNormal = result.Value.NormalInWorldSpace; } } else { bool success = character.GetIntersectionWithLine(ref line, ref CharHitInfo); if (success) { HitPosition = CharHitInfo.Triangle.IntersectionPointInWorldSpace; HitNormal = CharHitInfo.Triangle.NormalInWorldSpace; HitTag = CharHitInfo; } } } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, interactivePosition)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } DisableDetectors(); }