Пример #1
0
        public override ProgrammingElement Clone()
        {
            MouseFilter clone = new MouseFilter();

            CopyTo(clone);
            return(clone);
        }
Пример #2
0
        public override bool MatchAction(Reflex reflex, out object param)
        {
            param = null;

            GUIButton button = GUIButtonManager.GetButton(color);

            bool clicked = (null != button) && button.Clicked;


            if (reflex.Sensor is MouseSensor)
            {
                clicked &= button.MouseControlled;

                MouseFilter mouseFilter = reflex.Data.GetFilterByType(typeof(MouseFilter)) as MouseFilter;
                if (null != mouseFilter)
                {
                    switch (mouseFilter.type)
                    {
                    case MouseFilterType.LeftButton:
                        clicked &= button.MouseLeftClick;
                        break;

                    case MouseFilterType.RightButton:
                        clicked &= !button.MouseLeftClick;
                        break;

                    case MouseFilterType.Hover:
                        clicked = button.MouseOver;
                        break;

                    default:
                        clicked = false;
                        break;
                    }
                }
            }
            else
            {
                clicked &= !button.MouseControlled;
            }

            return(clicked);
        }
Пример #3
0
 protected void CopyTo(MouseFilter clone)
 {
     base.CopyTo(clone);
     clone.type = this.type;
 }
Пример #4
0
        public override ActionSet ComposeActionSet(Reflex reflex, GameActor gameActor)
        {
            ClearActionSet(actionSet);
            //UpdateCanBlend(reflex);

            if (!reflex.targetSet.AnyAction)
            {
                return(actionSet);
            }

            TurnModifier         turnMod         = reflex.GetModifierByType(typeof(TurnModifier)) as TurnModifier;
            GamePadStickFilter   stickFilt       = reflex.Data.GetFilterByType(typeof(GamePadStickFilter)) as GamePadStickFilter;
            GamePadTriggerFilter triggerFilt     = reflex.Data.GetFilterByType(typeof(GamePadTriggerFilter)) as GamePadTriggerFilter;
            MouseFilter          mouseFilt       = reflex.Data.GetFilterByType(typeof(MouseFilter)) as MouseFilter;
            TouchGestureFilter   touchFilt       = reflex.Data.GetFilterByType(typeof(TouchGestureFilter)) as TouchGestureFilter;
            KeyBoardKeyFilter    keyBoardKeyFilt = reflex.Data.GetFilterByType(typeof(KeyBoardKeyFilter)) as KeyBoardKeyFilter;

            // Will be modified depending on stick or trigger position.
            float speedModifier = 1.0f;

            //
            // Start by looking at the input filters to attenuate speed.
            //

            if (stickFilt != null)
            {
                // Note that we take the sign into account further below.
                // For now, just get the magnitude.
                speedModifier *= (float)Math.Abs(stickFilt.stickPosition.X);
            }
            else if (triggerFilt != null)
            {
                speedModifier *= triggerFilt.triggerValue;
            }
            else if (mouseFilt != null)
            {
                // Note that we take the sign into account further below.
                // For now, just get the magnitude.
                speedModifier *= Math.Abs(mouseFilt.ScreenPosition.X);
            }
            else if (touchFilt != null)
            {
                if (touchFilt.type == TouchGestureFilterType.Rotate)
                {
                    reflex.Task.GameActor.Chassis.WasTouchRotated = true;
                }
            }

            // Decide if we're turning toward a particular direction or
            // setting a turn rate.  Note, this will miss some cases
            // that we clean up further down.  The failure is rooted
            // in TurnModifier if you want to go fix it.  :-)

            Vector3 desiredHeading = Vector3.Zero;
            float   targetHeading  = 0;

            // See if the modifiers want to give us an absolute direction.
            reflex.ModifyHeading(gameActor, Modifier.ReferenceFrames.World, ref desiredHeading);
            targetHeading = MyMath.ZRotationFromDirection(desiredHeading);

            // If we have a desiredHeading, use that, else assume we're just turning.
            if (desiredHeading != Vector3.Zero)
            {
                // We were given an absolute direction, use it.
                actionSet.AddActionTarget(Action.AllocHeadingAction(reflex, targetHeading, speedModifier));
            }
            else
            {
                // Determine which relative direction we should use.
                TurnModifier.TurnDirections direction = TurnModifier.TurnDirections.None;

                if (turnMod != null)
                {
                    // If a turn modifier was specified, use its direction.
                    direction = turnMod.direction;
                }
                else if (stickFilt != null)
                {
                    // No turn modifier but we have a gamepad stick, use it to determine turn direction.
                    direction = stickFilt.stickPosition.X > 0 ? TurnModifier.TurnDirections.Right : TurnModifier.TurnDirections.Left;
                }
                else if (triggerFilt != null)
                {
                    // No turn modifier but we have a gamepad trigger, use it to determine turn direction.
                    // Basically this automatically maps left trigger to left turn and right trigger to right turn.
                    direction = triggerFilt.trigger == GamePadTriggerFilter.GamePadTrigger.LeftTrigger ? TurnModifier.TurnDirections.Left : TurnModifier.TurnDirections.Right;
                }
                else if (mouseFilt != null)
                {
                    // No turn modifier but we do have mouse input.
                    direction = mouseFilt.ScreenPosition.X > 0 ? TurnModifier.TurnDirections.Right : TurnModifier.TurnDirections.Left;
                    // This scaling by 2 has no real justification except
                    // that it matches the magnitude of the original code
                    // so this is more compatible with older games.
                    speedModifier *= 2.0f;
                }
                else if (touchFilt != null)
                {
                    // No turn modifier but we do have touch input.
                    if (touchFilt.type == TouchGestureFilterType.Rotate)
                    {
                        if (touchFilt.DeltaRotation < 0)
                        {
                            direction = TurnModifier.TurnDirections.Left;
                        }
                        else if (touchFilt.DeltaRotation > 0)
                        {
                            direction = TurnModifier.TurnDirections.Right;
                        }
                    }
                    else if (touchFilt.type == TouchGestureFilterType.Tap)
                    {
                        direction = TurnModifier.TurnDirections.Toward;
                    }
                }
                else if (keyBoardKeyFilt != null)
                {
                    if (reflex.targetSet != null)
                    {
                        Vector2 dir = (Vector2)(reflex.targetSet.Param);
                        if (dir.X == 1)
                        {
                            direction = TurnModifier.TurnDirections.Right;
                        }
                        else if (dir.X == -1)
                        {
                            direction = TurnModifier.TurnDirections.Left;
                        }
                    }
                }
                else
                {
                    // Nothing exists that would help us decide which way we should turn, choose left.
                    // This could be the user programming WHEN DO Turn
                    direction = TurnModifier.TurnDirections.Left;
                }

                // Calculate the new direction we want to face.
                switch (direction)
                {
                // Turn to our left.
                case TurnModifier.TurnDirections.Left:
                {
                    float angle = 0.0f;

                    if (touchFilt != null && touchFilt.type == TouchGestureFilterType.Rotate)
                    {
                        angle = gameActor.Movement.RotationZ + Math.Abs(touchFilt.DeltaRotation);
                    }
                    else
                    {
                        angle = gameActor.Movement.RotationZ + MathHelper.PiOver2;
                    }
                    desiredHeading = new Vector3((float)Math.Cos(angle), (float)Math.Sin(angle), 0);

                    actionSet.AddActionTarget(Action.AllocTurnSpeedAction(reflex, speedModifier), 0);
                }
                break;

                // Turn to our right.
                case TurnModifier.TurnDirections.Right:
                {
                    float angle = 0.0f;

                    if (touchFilt != null && touchFilt.type == TouchGestureFilterType.Rotate)
                    {
                        angle = gameActor.Movement.RotationZ - Math.Abs(touchFilt.DeltaRotation);
                    }
                    else
                    {
                        angle = gameActor.Movement.RotationZ - MathHelper.PiOver2;
                    }

                    desiredHeading = new Vector3((float)Math.Cos(angle), (float)Math.Sin(angle), 0);

                    actionSet.AddActionTarget(Action.AllocTurnSpeedAction(reflex, -speedModifier), 0);
                }
                break;

                // Turn to face the direction we are moving.
                case TurnModifier.TurnDirections.Forward:
                {
                    float angle = MyMath.ZRotationFromDirection(gameActor.Movement.Velocity);
                    desiredHeading = new Vector3((float)Math.Cos(angle), (float)Math.Sin(angle), 0);

                    actionSet.AddActionTarget(Action.AllocHeadingAction(reflex, targetHeading, speedModifier));
                }
                break;

                // Turn to face the sensed object.
                case TurnModifier.TurnDirections.Toward:
                    // We're probably here because of WHEN Mouse Left DO Turn Toward.
                    // This is another case where we want a Heading Action.
                    if (reflex.targetSet.Nearest != null)
                    {
                        speedModifier = 1;

                        // If we're doing mouse-look (WHEN Mouse Over DO Turn Toward) try
                        // and create a bit of a dead-zone in the middle.
                        bool mouseOver = false;
                        foreach (Filter f in reflex.Filters)
                        {
                            MouseFilter mf = f as MouseFilter;
                            if (mf != null && mf.type == MouseFilterType.Hover)
                            {
                                mouseOver = true;
                                break;
                            }
                        }

                        desiredHeading = reflex.targetSet.Nearest.Direction;
                        targetHeading  = MyMath.ZRotationFromDirection(desiredHeading);

                        // If mouseOver, calc damping to slow down turning when already looking
                        // in the direction we want.  This helps make it less twitchy.
                        float dampingFactor = 1.0f;
                        if (mouseOver)
                        {
                            float dot = Vector3.Dot(desiredHeading, gameActor.Movement.Heading);

                            float deadzoneAngle = 0.96f;
                            float dampzoneAngle = 0.9f;

                            // If very close to center, just treat as zero.
                            if (dot > deadzoneAngle)
                            {
                                dampingFactor = 0;
                            }
                            else if (dot > dampzoneAngle)
                            {
                                // Not in center, but close so damp turning.
                                // The closer we are to already looking in the correct direction, increase damping.
                                dampingFactor = MyMath.RemapRange(dot, deadzoneAngle, dampzoneAngle, 0, 1);
                                // Smooth the result to flatten out the center.
                                dampingFactor = MyMath.SmoothStep(0, 1, dampingFactor);
                            }
                        }

                        actionSet.AddActionTarget(Action.AllocHeadingAction(reflex, targetHeading, dampingFactor * speedModifier));
                    }
                    break;
                }
            }

            return(actionSet);
        }   // end of ComposeActionSet()
Пример #5
0
        public override void ComposeSensorTargetSet(GameActor gameActor, Reflex reflex)
        {
            if (terrainSensor != null)
            {
                terrainSensor.ComposeSensorTargetSet(gameActor, reflex);
            }
            else
            {
                List <Filter> filters = reflex.Filters;

                MouseFilter mouseFilter = reflex.Data.GetFilterByType(typeof(MouseFilter)) as MouseFilter;

                if (mouseFilter == null)
                {
                    // TODO this should trigger a hint.  You should always have a mouse filter with a mouse sensor.
                    return;
                }

                // Cause the filter to detect what is under the mouse cursor and set that information on the reflex.
                // MatchAction will be true if the MouseFilter passes but then we still need to filter on any other
                // filters including the ever annoying "not", "me" and "anything" filters.
                Object param       = null;
                bool   matchAction = mouseFilter.MatchAction(reflex, out param);

                //-----------------------------
                //GUI Button filter.
                GUIButtonFilter guiButtonFilter = reflex.Data.GetFilterByType(typeof(GUIButtonFilter)) as GUIButtonFilter;
                if (null != guiButtonFilter)
                {
                    matchAction = guiButtonFilter.MatchAction(reflex, out param);
                }

                bool notFilter      = reflex.Data.FilterExists("filter.not");
                bool anythingFilter = reflex.Data.FilterExists("filter.anything");

                // Give the anythingFilter a chance to kill the action.
                if (anythingFilter && reflex.MouseActor == null)
                {
                    matchAction = false;
                }

                bool mouseCursorTarget = false;
                bool mouseTargetNeeded = false;
                if (matchAction || reflex.IsMovement)
                {
                    GameActor mouseActor = reflex.MouseActor;   // Preserve this in case we null out the reflex ref and then restore it because of "not".  Argh.

                    // If we have an actor mouse target, check if it passes the filters.
                    // If not, null it out.
                    if (reflex.MouseActor != null)
                    {
                        // Create a target.
                        SensorTarget target = SensorTargetSpares.Alloc();
                        target.Init(reflex.Task.GameActor, reflex.MouseActor);

                        // Test againt the filters.
                        for (int i = 0; i < filters.Count; i++)
                        {
                            if (!filters[i].MatchTarget(reflex, target))
                            {
                                reflex.MouseActor = null;
                                matchAction       = false;
                            }
                        }

                        // Handle "not" filter.
                        if (notFilter)
                        {
                            if (reflex.MouseActor == null)
                            {
                                // Restore MouseActor.
                                reflex.MouseActor = mouseActor;
                            }
                            else
                            {
                                // Killed by the "not" filter.
                                reflex.MouseActor    = null;
                                reflex.MousePosition = null;
                                matchAction          = false;
                            }
                        }

                        // If we stil have a target, add it to the target set.
                        if (reflex.MouseActor != null)
                        {
                            reflex.targetSet.Add(target);
                            mouseCursorTarget = true;
                        }
                        else
                        {
                            // Don't really need this target so free it.
                            SensorTargetSpares.Free(target);
                        }
                    }
                    else
                    {
                        // No MouseActor case (the mouse click was not on an actor)

                        // If we have any classification filters, then we must have been
                        // looking for an actor. Since we don't have an actor, the
                        // result is false.
                        if (reflex.hasClassificationFitler)
                        {
                            matchAction = false;
                        }

                        // If we've got a me filter and not MouseActor we've failed.
                        if (reflex.hasMeFilter)
                        {
                            matchAction = false;
                        }

                        // MouseActor is null so we didn't click on anything which means that if we have an anything
                        // filter, matchAction should stay false.  Unless, of course we also have a notFilter.
                        if (!anythingFilter || notFilter)
                        {
                            // No mouse actor but if we have a "not" or this is a movement toward reflex then the result should be true.
                            // The WHEN Mouse Over DO Turn Toward option is used for mouse-look style controls.
                            // Note that if the reflex is Move Forward we don't want this to trigger.
                            if (notFilter || (reflex.IsMovement && reflex.selectorUpid == "selector.towardclosest") || (reflex.IsMovement && reflex.actuatorUpid == "actuator.turn"))
                            {
                                mouseTargetNeeded = true;
                                matchAction       = true;
                            }
                        }
                    }
                }
                else
                {
                    if (notFilter || reflex.IsMovement)
                    {
                        mouseTargetNeeded = true;
                    }
                }

                // If MouseActor is null, we may still want to target a position on the ground.
                //if (reflex.MouseActor == null && !matchAction && reflex.IsMovement)
                if (mouseTargetNeeded || (reflex.MouseActor == null && matchAction))
                {
                    if (reflex.MousePosition != null)
                    {
                        // We need to add the mouse position to the targetSet.
                        SensorTarget target = SensorTargetSpares.Alloc();
                        target.GameThing = senseSet.Nearest != null ? senseSet.Nearest.GameThing : NullActor.Instance;
                        target.Position  = reflex.MousePosition.Value;
                        target.Direction = target.Position - reflex.Task.GameActor.Movement.Position;
                        target.Range     = target.Direction.Length();

                        // If we've arrived at the target position, clear MousePosition.
                        Vector2 dir2d = new Vector2(target.Direction.X, target.Direction.Y);
                        if (dir2d.LengthSquared() < 0.1f)
                        {
                            reflex.MousePosition = null;
                        }

                        target.Direction /= target.Range;
                        reflex.targetSet.Add(target);
                        mouseCursorTarget = true;
                    }
                    else
                    {
                        // Is this a mouse move case?  If so translate the param values into
                        // a target the actuator can use.
                        MouseFilter filter = (MouseFilter)reflex.Data.GetFilterByType(typeof(MouseFilter));
                        if (filter.type == MouseFilterType.Move)
                        {
                            Vector2 position = (Vector2)param;

                            SensorTarget target = SensorTargetSpares.Alloc();

                            target.GameThing = senseSet.Nearest.GameThing;
                            // Calc fake position.
                            GameActor actor = reflex.Task.GameActor;
                            Vector3   pos   = actor.Movement.Position;

                            target.Position  = pos;
                            target.Direction = target.Position - reflex.Task.GameActor.Movement.Position;
                            target.Range     = target.Direction.Length();
                            if (target.Range == 0)
                            {
                                target.Direction = Vector3.Zero;
                            }
                            else
                            {
                                target.Direction /= target.Range;
                            }
                            reflex.targetSet.Add(target);
                            reflex.targetSet.Param = position;
                            mouseCursorTarget      = true;
                        }
                    }
                }

                reflex.targetSet.Action  = reflex.targetSet.Count > 0 && TestObjectSet(reflex);
                reflex.targetSet.Action |= matchAction;

                // This forces the movement to keep going toward the clicked position/bot
                // even if the mouse is no longer clicked.
                reflex.targetSet.ActionMouseTarget = mouseCursorTarget;

                reflex.targetSet.Action = PostProcessAction(reflex.targetSet.Action, reflex);
            }
        }
Пример #6
0
        private void RunActuators()
        {
            verbExecutions.SetAll(false);

            GameActor.Movement.UserControlled = IsUserControlled;

            // Do not update actuators during pre-game.
            if (InGame.inGame.PreGameActive)
            {
                return;
            }

            int initialTaskId = Brain.ActiveTaskId;

            for (int i = 0; i < reflexes.Count; ++i)
            {
                Reflex reflex = reflexes[i] as Reflex;
                if (reflex.Actuator != null && reflex.targetSet.AnyAction)
                {
                    if (reflex.Actuator is VerbActuator)
                    {
                        // Ugh, be backward compatible with the old arbitrated verb behavior.
                        VerbActuator verbAct = reflex.Actuator as VerbActuator;

                        // If the verb is exclusive AND we've already seen in then don't process it.
                        if (GameThing.VerbIsExclusive(verbAct.Verb) && verbExecutions.Get((int)verbAct.Verb))
                        {
                            continue;
                        }
                        else
                        {
                            // This is the first time we've seen the verb so flag it.
                            verbExecutions.Set((int)verbAct.Verb, true);
                        }
                    }

                    // If we have a mouse sensor AND a once modifier then
                    // we want to tag the mouse button with IgnoreUntilReleased.
                    // This makes once work correctly without blocking other
                    // reflexes from seeing the mouse.
                    if (reflex.Sensor is MouseSensor)
                    {
                        OnceModifier om = null;
                        for (int j = 0; j < reflex.Modifiers.Count; j++)
                        {
                            om = reflex.Modifiers[j] as OnceModifier;
                            if (om != null)
                            {
                                break;
                            }
                        }
                        if (om != null)
                        {
                            MouseFilter mf = null;
                            for (int j = 0; j < reflex.Filters.Count; j++)
                            {
                                mf = reflex.Filters[j] as MouseFilter;
                                if (mf != null)
                                {
                                    break;
                                }
                            }
                            if (mf != null)
                            {
                                // By setting IgnoreUntilReleased, this prevents another
                                // reflex from being triggered until the mouse is released.
                                switch (mf.type)
                                {
                                case MouseFilterType.LeftButton:
                                    MouseInput.Left.IgnoreUntilReleased = true;
                                    break;

                                case MouseFilterType.RightButton:
                                    MouseInput.Right.IgnoreUntilReleased = true;
                                    break;

                                default:
                                    // Nothing to see here, move along.
                                    break;
                                }
                            }
                        }
                    }

                    reflex.Actuator.Update(reflex);

                    // Stop updating actuators if we switched pages.
                    if (Brain.ActiveTaskId != initialTaskId)
                    {
                        break;
                    }
                }
            }
        }