Clamp() public static method

public static Clamp ( float value, float min, float max ) : float
value float
min float
max float
return float
Esempio n. 1
0
        /// <summary>
        /// Processes an area and applies a gradient calculation to each part of the area.
        /// </summary>
        /// <param name="position">The center of the gradient.</param>
        /// <param name="strength">The width of the gradient spread.</param>
        /// <param name="angle">The angle to apply the gradient.</param>
        /// <param name="area">The area to calculate.</param>
        /// <param name="applyAction">The callback called for each part of the area.</param>
        public static void GradientFill(Point cellSize, Point position, int strength, int angle, Rectangle area, ColorGradient gradient, Action <int, int, Color> applyAction)
        {
            double radians = angle * Math.PI / 180; // = Math.Atan2(x1 - x2, y1 - y2);

            Vector2 angleVector = new Vector2((float)(Math.Sin(radians) * strength), (float)(Math.Cos(radians) * strength)) / 2;
            Vector2 location    = new Vector2(position.X, position.Y);

            if (cellSize.X > cellSize.Y)
            {
                angleVector.Y *= cellSize.X / cellSize.Y;
            }

            else if (cellSize.X < cellSize.Y)
            {
                angleVector.X *= cellSize.Y / cellSize.X;
            }

            Vector2 endingPoint   = location + angleVector;
            Vector2 startingPoint = location - angleVector;

            double x1 = (startingPoint.X / (double)area.Width) * 2.0f - 1.0f;
            double y1 = (startingPoint.Y / (double)area.Height) * 2.0f - 1.0f;
            double x2 = (endingPoint.X / (double)area.Width) * 2.0f - 1.0f;
            double y2 = (endingPoint.Y / (double)area.Height) * 2.0f - 1.0f;

            double start = x1 * angleVector.X + y1 * angleVector.Y;
            double end   = x2 * angleVector.X + y2 * angleVector.Y;

            for (int x = area.Left; x < area.Width; x++)
            {
                for (int y = area.Top; y < area.Height; y++)
                {
                    // but we need vectors from (-1, -1) to (1, 1)
                    // instead of pixels from (0, 0) to (width, height)
                    double u = (x / (double)area.Width) * 2.0f - 1.0f;
                    double v = (y / (double)area.Height) * 2.0f - 1.0f;

                    double here = u * angleVector.X + v * angleVector.Y;

                    double lerp = (start - here) / (start - end);

                    //lerp = Math.Abs((lerp - (int)lerp));

                    lerp = MyMathHelper.Clamp((float)lerp, 0f, 1.0f);

                    int counter;
                    for (counter = 0; counter < gradient.Stops.Length && gradient.Stops[counter].Stop < (float)lerp; counter++)
                    {
                        ;
                    }

                    counter--;
                    counter = (int)MyMathHelper.Clamp(counter, 0, gradient.Stops.Length - 2);

                    float newLerp = (gradient.Stops[counter].Stop - (float)lerp) / (gradient.Stops[counter].Stop - gradient.Stops[counter + 1].Stop);

                    applyAction(x, y, ColorHelper.Lerp(gradient.Stops[counter].Color, gradient.Stops[counter + 1].Color, newLerp));
                }
            }
        }
Esempio n. 2
0
        private void CalcControlSize()
        {
            var  canvas      = this.MinimapCanvas;
            Size minimapSize = new Size(canvas?.Width ?? 0, canvas?.Height ?? 0);

            //计算边框
            int top    = this.resource.N.Height,
                bottom = this.resource.S.Height,
                left   = this.resource.W.Width,
                right  = this.resource.E.Width;

            //计算实际大小
            Size desireSize = new Size(minimapSize.Width + left + right, minimapSize.Height + top + bottom);

            //计算标题
            if (this.lblStreetName.Text != null)
            {
                this.lblStreetName.Measure(new Size(double.MaxValue, double.MaxValue));
                var lblRight = Canvas.GetLeft(this.lblStreetName) + this.lblStreetName.DesiredSize.Width;
                desireSize.Width = Math.Max(desireSize.Width, lblRight);
            }
            if (this.lblMapName.Text != null)
            {
                this.lblMapName.Measure(new Size(double.MaxValue, double.MaxValue));
                var lblRight = Canvas.GetLeft(this.lblMapName) + this.lblMapName.DesiredSize.Width;
                desireSize.Width = Math.Max(desireSize.Width, lblRight);
            }

            this.Width  = MathHelper.Clamp(desireSize.Width, this.MinWidth, this.MaxWidth);
            this.Height = MathHelper.Clamp(desireSize.Height, this.MinHeight, this.MaxHeight);
            this.MapAreaControl.Width  = Math.Max(0, this.Width - left - right);
            this.MapAreaControl.Height = Math.Max(0, this.Height - top - bottom);
        }
Esempio n. 3
0
        /// <summary>
        /// Zooms the camera when Pinch/Stretch is detected.
        /// </summary>
        /// <param name="pinchGesture">The pinch gesture.</param>
        private void ZoomCamera(GestureSample pinchGesture)
        {
            // Get the current and the previous location of the two fingers.
            Vector2 p1New = pinchGesture.Position;
            Vector2 p1Old = pinchGesture.Position - pinchGesture.Delta;
            Vector2 p2New = pinchGesture.Position2;
            Vector2 p2Old = pinchGesture.Position2 - pinchGesture.Delta2;

            // Get the distance between the current and the previous locations.
            float dNew = Vector2.Distance(p1New, p2New);
            float dOld = Vector2.Distance(p1Old, p2Old);

            // Use the ratio between old and new distance to scale the camera distance.
            float scale = dOld / dNew;

            if (!Numeric.IsNaN(scale))
            {
                _cameraDistance *= scale;
                _cameraDistance  = MathHelper.Clamp(_cameraDistance, MinCameraDistance, MaxCameraDistance);
            }
        }
        /// <overloads>
        /// <summary>
        /// Gets a the bounds of the specified object relative to the viewport.
        /// </summary>
        /// </overloads>
        ///
        /// <summary>
        /// Gets a the bounds of the specified geometric object relative to the viewport.
        /// </summary>
        /// <param name="cameraNode">The camera node.</param>
        /// <param name="geometricObject">The geometric object.</param>
        /// <returns>
        /// The bounds (left, top, right, bottom) where each entry is in the range [0, 1].
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="cameraNode"/> or <paramref name="geometricObject"/> is
        /// <see langword="null"/>.
        /// </exception>
        internal static Vector4F GetBounds(CameraNode cameraNode, IGeometricObject geometricObject)
        {
            // Notes:
            // Do not call this GetBounds() method for spheres. Use the other overload for spheres.
            //
            // At first this problem seems trivial, we only have to get the support
            // points of the geometric object's shape in the directions of the frustum
            // plane normal vectors. The we project these points to the near plane...
            // But this does not work because which can be seen if you draw simple
            // drop down sketch. Actually each eye ray has its own direction therefore
            // it has its normal and its own support direction!

            if (cameraNode == null)
            {
                throw new ArgumentNullException("cameraNode");
            }
            if (geometricObject == null)
            {
                throw new ArgumentNullException("geometricObject");
            }

            Debug.Assert(!(geometricObject.Shape is SphereShape), "Call a different GetBounds() overload for spheres!");

            // Projection properties.
            var   camera     = cameraNode.Camera;
            var   projection = camera.Projection;
            float near       = projection.Near;
            float left       = projection.Left;
            float right      = projection.Right;
            float width      = projection.Width;
            float top        = projection.Top;
            float bottom     = projection.Bottom;
            float height     = projection.Height;

            // Get AABB in view space.
            Pose localToViewPose = cameraNode.PoseWorld.Inverse * geometricObject.Pose;
            Aabb aabb            = geometricObject.Shape.GetAabb(geometricObject.Scale, localToViewPose);

            // Is the AABB in front of the near plane (= totally clipped)?
            if (aabb.Minimum.Z >= -near)
            {
                return(new Vector4F(0));
            }

            // Does the AABB contain the origin?
            if (GeometryHelper.HaveContact(aabb, Vector3F.Zero))
            {
                return(new Vector4F(0, 0, 1, 1));
            }

            // Project the AABB far face to the near plane.
            Vector2F min;

            min.X = aabb.Minimum.X / -aabb.Minimum.Z * near;
            min.Y = aabb.Minimum.Y / -aabb.Minimum.Z * near;
            Vector2F max;

            max.X = aabb.Maximum.X / -aabb.Minimum.Z * near;
            max.Y = aabb.Maximum.Y / -aabb.Minimum.Z * near;

            // If the AABB z extent overlaps the origin, some results are invalid.
            if (aabb.Maximum.Z > -Numeric.EpsilonF)
            {
                if (aabb.Minimum.X < 0)
                {
                    min.X = left;
                }
                if (aabb.Maximum.X > 0)
                {
                    max.X = right;
                }
                if (aabb.Minimum.Y < 0)
                {
                    min.Y = bottom;
                }
                if (aabb.Maximum.Y > 0)
                {
                    max.Y = top;
                }
            }
            else
            {
                // The AABB near face is also in front. Project AABB near face to near plane
                // and take the most extreme.
                min.X = Math.Min(min.X, aabb.Minimum.X / -aabb.Maximum.Z * near);
                min.Y = Math.Min(min.Y, aabb.Minimum.Y / -aabb.Maximum.Z * near);
                max.X = Math.Max(max.X, aabb.Maximum.X / -aabb.Maximum.Z * near);
                max.Y = Math.Max(max.Y, aabb.Maximum.Y / -aabb.Maximum.Z * near);
            }

            Vector4F bounds;

            bounds.X = (min.X - left) / width;
            bounds.Y = (top - max.Y) / height;
            bounds.Z = (max.X - left) / width;
            bounds.W = (top - min.Y) / height;

            bounds.X = MathHelper.Clamp(bounds.X, 0, 1);
            bounds.Y = MathHelper.Clamp(bounds.Y, 0, 1);
            bounds.Z = MathHelper.Clamp(bounds.Z, bounds.X, 1);
            bounds.W = MathHelper.Clamp(bounds.W, bounds.Y, 1);

            return(bounds);
        }
        /// <summary>
        /// Gets the bounds of the specified sphere relative to the viewport.
        /// </summary>
        /// <param name="cameraNode">The camera node.</param>
        /// <param name="positionWorld">The sphere center in world space.</param>
        /// <param name="radius">The sphere radius.</param>
        /// <returns>
        /// The bounds (left, top, right, bottom) where each entry is in the range [0, 1].
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="cameraNode"/> is <see langword="null"/>.
        /// </exception>
        internal static Vector4F GetBounds(CameraNode cameraNode, Vector3F positionWorld, float radius)
        {
            var   camera     = cameraNode.Camera;
            var   projection = camera.Projection;
            float near       = projection.Near;
            float left       = projection.Left;
            float width      = projection.Width;
            float top        = projection.Top;
            float height     = projection.Height;

            Vector3F l = cameraNode.PoseWorld.ToLocalPosition(positionWorld);
            float    r = radius;

            // Default bounds (left, top, right, bottom)
            var bounds = new Vector4F(0, 0, 1, 1);

            // ----- Solve for N = (x, 0, z).

            // Discriminant already divided by 4:
            float d = (r * r * l.X * l.X - (l.X * l.X + l.Z * l.Z) * (r * r - l.Z * l.Z));

            if (d > 0)
            {
                // Camera is outside the sphere.

                float rootD = (float)Math.Sqrt(d);

                // Now check two possible solutions (+/- rootD):
                float nx1 = (r * l.X + rootD) / (l.X * l.X + l.Z * l.Z);
                float nx2 = (r * l.X - rootD) / (l.X * l.X + l.Z * l.Z);

                float nz1 = (r - nx1 * l.X) / l.Z;
                float nz2 = (r - nx2 * l.X) / l.Z;

                // Compute tangent position (px, 0, pz) on the sphere.
                float pz1 = (l.X * l.X + l.Z * l.Z - r * r) / (l.Z - (nz1 / nx1) * l.X);
                float pz2 = (l.X * l.X + l.Z * l.Z - r * r) / (l.Z - (nz2 / nx2) * l.X);

                if (pz1 < 0)
                {
                    // Plane (nx1, 0, nz1) is within camera frustum.

                    float px = -pz1 * nz1 / nx1;

                    float x       = nz1 * near / nx1;   // x coordinate on the near plane.
                    float boundsX = (x - left) / width; // Value relative to viewport. (0 = left, 1 = right)

                    // Shrink the scissor rectangle on the left or on the right side.
                    if (px < l.X)
                    {
                        bounds.X = Math.Max(bounds.X, boundsX);
                    }
                    else
                    {
                        bounds.Z = Math.Min(bounds.Z, boundsX);
                    }
                }

                if (pz2 < 0)
                {
                    float px = -pz2 * nz2 / nx2;

                    float x        = nz2 * near / nx2;
                    float scissorX = (x - left) / width;

                    if (px < l.X)
                    {
                        bounds.X = Math.Max(bounds.X, scissorX);
                    }
                    else
                    {
                        bounds.Z = Math.Min(bounds.Z, scissorX);
                    }
                }
            }

            // ----- Solve for N = (0, y, z) first.

            d = (r * r * l.Y * l.Y - (l.Y * l.Y + l.Z * l.Z) * (r * r - l.Z * l.Z));
            if (d > 0)
            {
                // Camera is outside the sphere.

                float rootD = (float)Math.Sqrt(d);

                float ny1 = (r * l.Y + rootD) / (l.Y * l.Y + l.Z * l.Z);
                float ny2 = (r * l.Y - rootD) / (l.Y * l.Y + l.Z * l.Z);

                float nz1 = (r - ny1 * l.Y) / l.Z;
                float nz2 = (r - ny2 * l.Y) / l.Z;

                float pz1 = (l.Y * l.Y + l.Z * l.Z - r * r) / (l.Z - (nz1 / ny1) * l.Y);
                float pz2 = (l.Y * l.Y + l.Z * l.Z - r * r) / (l.Z - (nz2 / ny2) * l.Y);

                if (pz1 < 0)
                {
                    float py = -pz1 * nz1 / ny1;

                    float y        = nz1 * near / ny1;
                    float scissorY = -(y - top) / height;

                    if (py > l.Y)
                    {
                        bounds.Y = Math.Max(bounds.Y, scissorY);
                    }
                    else
                    {
                        bounds.W = Math.Min(bounds.W, scissorY);
                    }
                }

                if (pz2 < 0)
                {
                    float py = -pz2 * nz2 / ny2;

                    float y        = nz2 * near / ny2;
                    float scissorY = -(y - top) / height;

                    if (py > l.Y)
                    {
                        bounds.Y = Math.Max(bounds.Y, scissorY);
                    }
                    else
                    {
                        bounds.W = Math.Min(bounds.W, scissorY);
                    }
                }
            }

            bounds.X = MathHelper.Clamp(bounds.X, 0, 1);
            bounds.Y = MathHelper.Clamp(bounds.Y, 0, 1);
            bounds.Z = MathHelper.Clamp(bounds.Z, bounds.X, 1);
            bounds.W = MathHelper.Clamp(bounds.W, bounds.Y, 1);

            return(bounds);
        }
Esempio n. 6
0
        private void UpdateSky()
        {
            // Update ephemeris model.
#if XBOX
            _ephemeris.Time = new DateTimeOffset(_time.Ticks, TimeSpan.Zero);
#else
            _ephemeris.Time = _time;
#endif
            _ephemeris.Update();

            // Update rotation of milky way. We also need to add an offset because the
            // cube map texture is rotated.
            _milkyWayNode.PoseWorld = new Pose(
                (Matrix33F)_ephemeris.EquatorialToWorld.Minor
                * Matrix33F.CreateRotationZ(ConstantsF.PiOver2 + -0.004f)
                * Matrix33F.CreateRotationX(ConstantsF.PiOver2 + -0.002f));

            // Update rotation of stars.
            _starfieldNode.PoseWorld = new Pose((Matrix33F)_ephemeris.EquatorialToWorld.Minor);

            // Update direction of sun.
            SunDirection = (Vector3F)_ephemeris.SunDirectionRefracted;
            var sunUp = SunDirection.Orthonormal1;
            _sunNode.LookAt(SunDirection, sunUp);

            // Update direction of moon.
            var moonDirection = (Vector3F)_ephemeris.MoonPosition.Normalized;
            var moonUp        = (Vector3F)_ephemeris.EquatorialToWorld.TransformDirection(Vector3D.Up);
            _moonNode.LookAt(moonDirection, moonUp);

            // The moon needs to know the sun position and brightness to compute the moon phase.
            _moonNode.SunDirection = (Vector3F)_ephemeris.SunPosition.Normalized;
            _moonNode.SunLight     = Ephemeris.ExtraterrestrialSunlight * SunlightScale;

            // The ScatteringSky needs the sun direction and brightness to compute the sky colors.
            _scatteringSkyNode.SunDirection = SunDirection;
            _scatteringSkyNode.SunColor     = Ephemeris.ExtraterrestrialSunlight * ScatteringSkyLightScale;

            // Update the light directions.
            _sunlightNode.LookAt(-SunDirection, sunUp);
            _moonlightNode.LookAt(-moonDirection, moonUp);

            // The ScatteringSkyNode can compute the actual sunlight.
            SunLight = _scatteringSkyNode.GetSunlight();

            // Undo the ScatteringSkyLightScale and apply a custom scale for the sunlight.
            SunLight = SunLight / ScatteringSkyLightScale * SunlightScale;

            // The ScatteringSkyNode can also compute the ambient light by sampling the
            // sky hemisphere.
            AmbientLight = _scatteringSkyNode.GetAmbientLight(256);
            AmbientLight = AmbientLight / ScatteringSkyLightScale * SunlightScale;

            // Desaturate the ambient light to avoid very blue shadows.
            AmbientLight = InterpolationHelper.Lerp(
                new Vector3F(Vector3F.Dot(AmbientLight, GraphicsHelper.LuminanceWeights)),
                AmbientLight,
                0.5f);

            // The Ephemeris model can compute the actual moonlight.
            Vector3F moonlight, moonAmbient;
            Ephemeris.GetMoonlight(
                _scatteringSkyNode.ObserverAltitude,
                2.2f,
                _ephemeris.MoonPosition,
                (float)_ephemeris.MoonPhaseAngle,
                out moonlight,
                out moonAmbient);
            moonlight   *= MoonlightScale;
            moonAmbient *= MoonlightScale;

            // Scale sun light to 0 at horizon.
            var directionalLightColor = SunLight;
            directionalLightColor *= MathHelper.Clamp(SunDirection.Y / 0.1f, 0, 1);

            var directionalLight = ((DirectionalLight)_sunlightNode.Light);
            directionalLight.Color = directionalLightColor;
            ((DirectionalLight)_moonlightNode.Light).Color = moonlight;
            ((AmbientLight)_ambientLightNode.Light).Color  = AmbientLight + moonAmbient + LightPollution;

            // Use the sunlight color to create a bright sun disk.
            var sunDiskColor = SunLight;
            sunDiskColor.TryNormalize();
            _sunNode.GlowColor0 = sunDiskColor * Ephemeris.ExtraterrestrialSunlight.Length * SunlightScale * 10;

            if (_enableClouds)
            {
                // Update lighting info of cloud layer nodes.
                _cloudLayerNode0.SunDirection = SunDirection;
                _cloudLayerNode0.SunLight     = SunLight;
                _cloudLayerNode0.AmbientLight = AmbientLight;

                // The second cloud layer uses simple unlit clouds (only ambient lighting).
                _cloudLayerNode1.SunDirection = SunDirection;
                _cloudLayerNode1.SunLight     = Vector3F.Zero;
                _cloudLayerNode1.AmbientLight = AmbientLight + SunLight;

                // Use the cloud map as the texture for the directional light to create cloud shadows.
                if (EnableCloudShadows)
                {
                    directionalLight.Texture = _cloudLayerNode0.CloudMap.Texture;
                }
                else
                {
                    directionalLight.Texture = null;
                }

                // Compute a texture offset so that the current sun position and the projected cloud
                // shadows match.
                // Since sky dome is always centered on the camera, position the sunlight node in
                // line with the camera.
                var cameraPosition = _cameraObject.CameraNode.PoseWorld.Position;
                var upVector       = Vector3F.AreNumericallyEqual(SunDirection, Vector3F.UnitZ) ? Vector3F.UnitY : Vector3F.UnitZ;
                _sunlightNode.LookAt(cameraPosition + SunDirection, cameraPosition, upVector);

                // Choose a scale for the cloud shadows.
                directionalLight.TextureScale = new Vector2F(-1000);

                // Get the scaled texture offset for the sun direction.
                directionalLight.TextureOffset = _cloudLayerNode0.GetTextureCoordinates(SunDirection) *
                                                 directionalLight.TextureScale;
            }

            // The ScatteringSkyNode can also estimate a fog color by sampling the horizon colors.
            Vector3F fogColor = _scatteringSkyNode.GetFogColor(256, FogSampleAngle);

            // Desaturate the fog color.
            fogColor = InterpolationHelper.Lerp(
                new Vector3F(Vector3F.Dot(fogColor, GraphicsHelper.LuminanceWeights)),
                fogColor,
                FogSaturation);

            // Find any FogNode in the scene and update its fog color.
            foreach (var fogNode in ((Scene)_scene).GetSubtree().OfType <FogNode>())
            {
                var fog = fogNode.Fog;
                fog.Color0             = fog.Color1 = new Vector4F(fogColor, 1);
                fog.ScatteringSymmetry = FogScatteringSymmetry;
            }

            // TODO: If the fog is dense, reduce the direct light and increase the ambient light.
        }
Esempio n. 7
0
            protected override void OnDraw(Renderer spriterenderer, double elapsedGameTime, float opacity)
            {
                base.OnDraw(spriterenderer, elapsedGameTime, opacity);

                if (this.MinimapTexture == null || this.MapRegion.Width <= 0 || this.MapRegion.Height <= 0)
                {
                    return;
                }

                var pos  = this.RenderPosition;
                var size = this.RenderSize;

                spriterenderer.End();
                spriterenderer.BeginClipped(new Rect(pos.X, pos.Y, size.Width, size.Height));

                Matrix  transform;
                Vector2 cameraPos;
                Vector2 cameraSize;

                //绘制canvas
                {
                    var canvas    = this.MinimapTexture;
                    var mapRegion = this.MapRegion;

                    //计算世界坐标系到小地图坐标系的转换
                    transform = Matrix.CreateTranslation(-mapRegion.X, -mapRegion.Y, 0)
                                * Matrix.CreateScale((float)canvas.Width / mapRegion.Width, (float)canvas.Height / mapRegion.Height, 0);
                    var vp = this.CameraViewPort;
                    cameraPos  = Vector2.Transform(new Vector2(vp.X, vp.Y), transform);
                    cameraSize = new Vector2(vp.Width * transform.Scale.X, vp.Height * transform.Scale.Y);

                    //计算小地图显示位置
                    PointF canvasPos = new PointF(-this.canvasPosCache.X, -this.canvasPosCache.Y);

                    if (this.Width >= canvas.Width)
                    {
                        canvasPos.X = (this.Width - canvas.Width) / 2;
                    }
                    else
                    {
                        if (cameraPos.X < canvasPos.X)
                        {
                            canvasPos.X = cameraPos.X;
                        }
                        else if (cameraPos.X + cameraSize.X > canvasPos.X + this.Width)
                        {
                            canvasPos.X = cameraPos.X + cameraSize.X - this.Width;
                        }
                        canvasPos.X = -MathHelper.Clamp(canvasPos.X, 0, canvas.Width - this.Width);
                    }
                    if (this.Height >= canvas.Height)
                    {
                        canvasPos.Y = (this.Height - canvas.Height) / 2;
                    }
                    else
                    {
                        if (cameraPos.Y < canvasPos.Y)
                        {
                            canvasPos.Y = cameraPos.Y;
                        }
                        else if (cameraPos.Y + cameraSize.Y > canvasPos.Y + this.Height)
                        {
                            canvasPos.Y = cameraPos.Y + cameraSize.Y - this.Height;
                        }
                        canvasPos.Y = -MathHelper.Clamp(canvasPos.Y, 0, canvas.Height - this.Height);
                    }

                    this.canvasPosCache = canvasPos;
                    //计算全局坐标
                    canvasPos = new PointF(pos.X + canvasPos.X, pos.Y + canvasPos.Y);


                    transform *= Matrix.CreateTranslation(canvasPos.X, canvasPos.Y, 0);

                    //绘制小地图
                    spriterenderer.Draw(canvas, canvasPos, new Size(canvas.Width, canvas.Height), new ColorW(1f, 1f, 1f, opacity), false);
                }

                /* 绘制框线*/
                if (CameraRegionVisible)
                {
                    using (var gb = spriterenderer.CreateGeometryBuffer())
                    {
                        var pts = new List <PointF>();
                        pts.Add(new PointF(cameraPos.X, cameraPos.Y));
                        pts.Add(new PointF(cameraPos.X + cameraSize.X, cameraPos.Y));
                        pts.Add(new PointF(cameraPos.X + cameraSize.X, cameraPos.Y + cameraSize.Y));
                        pts.Add(new PointF(cameraPos.X, cameraPos.Y + cameraSize.Y));
                        pts.Add(pts[0]);
                        gb.FillColor(pts, GeometryPrimitiveType.LineStrip);

                        spriterenderer.DrawGeometryColor(gb,
                                                         new PointF(pos.X + canvasPosCache.X, pos.Y + canvasPosCache.Y),
                                                         new ColorW(255, 255, 0), opacity, 0f);
                    }
                }

                //绘制小图标
                Func <TextureBase, PointF, Rect> drawIconFunc = (texture, worldPos) =>
                {
                    var iconPos = Vector2.Transform(new Vector2(worldPos.X, worldPos.Y), transform);
                    var posF    = new PointF(
                        Math.Round(iconPos.X - texture.Width / 2 - 0),
                        Math.Round(iconPos.Y - texture.Height / 2 - 5));
                    var iconSize = new Size(texture.Width, texture.Height);
                    spriterenderer.Draw(texture, posF, iconSize, new ColorW(1f, 1f, 1f, opacity), false);
                    return(new Rect(posF.X - pos.X, posF.Y - pos.Y, iconSize.Width, iconSize.Height));
                };

                iconRectCache.Clear();
                foreach (var icon in this.Icons)
                {
                    switch (icon.IconType)
                    {
                    case IconType.Portal:
                    {
                        var texture = this.FindResource("portal") as TextureBase;
                        if (texture != null)
                        {
                            var rect = drawIconFunc(texture, icon.WorldPosition);
                            iconRectCache.Add(new IconRect()
                                {
                                    Rect = rect, Tooltip = icon.Tooltip
                                });
                        }
                    }
                    break;

                    case IconType.EnchantPortal:
                    {
                        var texture = this.FindResource("enchantportal") as TextureBase;
                        if (texture != null)
                        {
                            var rect = drawIconFunc(texture, icon.WorldPosition);
                            iconRectCache.Add(new IconRect()
                                {
                                    Rect = rect, Tooltip = icon.Tooltip
                                });
                        }
                    }
                    break;

                    case IconType.HiddenPortal:
                    {
                        var texture = this.FindResource("hiddenportal") as TextureBase;
                        if (texture != null)
                        {
                            var rect = drawIconFunc(texture, icon.WorldPosition);
                            iconRectCache.Add(new IconRect()
                                {
                                    Rect = rect, Tooltip = icon.Tooltip
                                });
                        }
                    }
                    break;

                    case IconType.Transport:
                    {
                        var texture = this.FindResource("transport") as TextureBase;
                        if (texture != null)
                        {
                            var rect = drawIconFunc(texture, icon.WorldPosition);
                            iconRectCache.Add(new IconRect()
                                {
                                    Rect = rect, Tooltip = icon.Tooltip
                                });
                        }
                    }
                    break;

                    case IconType.Npc:
                    {
                        var texture = this.FindResource("npc") as TextureBase;
                        if (texture != null)
                        {
                            var rect = drawIconFunc(texture, icon.WorldPosition);
                            iconRectCache.Add(new IconRect()
                                {
                                    Rect = rect, Tooltip = icon.Tooltip
                                });
                        }
                    }
                    break;

                    case IconType.EventNpc:
                    {
                        var texture = this.FindResource("eventnpc") as TextureBase;
                        if (texture != null)
                        {
                            var rect = drawIconFunc(texture, icon.WorldPosition);
                            iconRectCache.Add(new IconRect()
                                {
                                    Rect = rect, Tooltip = icon.Tooltip
                                });
                        }
                    }
                    break;

                    case IconType.Shop:
                    {
                        var texture = this.FindResource("shop") as TextureBase;
                        if (texture != null)
                        {
                            var rect = drawIconFunc(texture, icon.WorldPosition);
                            iconRectCache.Add(new IconRect()
                                {
                                    Rect = rect, Tooltip = icon.Tooltip
                                });
                        }
                    }
                    break;

                    case IconType.Trunk:
                    {
                        var texture = this.FindResource("trunk") as TextureBase;
                        if (texture != null)
                        {
                            var rect = drawIconFunc(texture, icon.WorldPosition);
                            iconRectCache.Add(new IconRect()
                                {
                                    Rect = rect, Tooltip = icon.Tooltip
                                });
                        }
                    }
                    break;

                    case IconType.ArrowUp:
                    {
                        var texture = this.FindResource("arrowup") as TextureBase;
                        if (texture != null)
                        {
                            var rect = drawIconFunc(texture, icon.WorldPosition);
                            iconRectCache.Add(new IconRect()
                                {
                                    Rect = rect, Tooltip = icon.Tooltip
                                });
                        }
                    }
                    break;
                    }
                }

                spriterenderer.EndClipped();
                spriterenderer.Begin();
            }
Esempio n. 8
0
        private void HandleKeyboardInput(GameTime gameTime)
        {
            float dt            = (float)gameTime.ElapsedGameTime.TotalSeconds;
            var   keyboardState = Keyboard.GetState();

            if (keyboardState.IsKeyDown(Keys.Escape))
            {
                Exit();
            }

            if (keyboardState.IsKeyDown(Keys.P) && _previousKeyboardState.IsKeyUp(Keys.P))
            {
                _pause = !_pause;
            }

            if (keyboardState.IsKeyDown(Keys.PageUp) && _previousKeyboardState.IsKeyUp(Keys.PageUp))
            {
                NextPattern();
            }
            else if (keyboardState.IsKeyDown(Keys.PageDown) && _previousKeyboardState.IsKeyUp(Keys.PageDown))
            {
                PreviousPattern();
            }

            if (keyboardState.IsKeyDown(Keys.LeftControl) && _previousKeyboardState.IsKeyUp(Keys.LeftControl))
            {
                AddBullet();
            }

            if (keyboardState.IsKeyDown(Keys.Space))
            {
                AddBullet();
            }

            if (keyboardState.IsKeyDown(Keys.Delete))
            {
                _moverManager.Clear();
            }

            if (keyboardState.IsKeyDown(Keys.E) && _previousKeyboardState.IsKeyUp(Keys.E))
            {
                EditCurrentPatternFile();
            }

            // Mover manager position

            if (keyboardState.IsKeyDown(Keys.I))
            {
                _moverManagerPosition -= new Vector2(0, 250) * dt;
            }

            if (keyboardState.IsKeyDown(Keys.K))
            {
                _moverManagerPosition += new Vector2(0, 250) * dt;
            }

            if (keyboardState.IsKeyDown(Keys.J))
            {
                _moverManagerPosition -= new Vector2(250, 0) * dt;
            }

            if (keyboardState.IsKeyDown(Keys.L))
            {
                _moverManagerPosition += new Vector2(250, 0) * dt;
            }

            // Camera
            if (keyboardState.IsKeyDown(Keys.NumPad7))
            {
                _camera.Zoom -= dt * 0.5f;
            }

            if (keyboardState.IsKeyDown(Keys.NumPad9))
            {
                _camera.Zoom += dt * 0.5f;
            }

            _camera.Zoom = MathHelper.Clamp(_camera.Zoom, 0.1f, 10f);

            if (keyboardState.IsKeyDown(Keys.NumPad8))
            {
                _camera.Position -= new Vector2(0, 250) * dt;
            }

            if (keyboardState.IsKeyDown(Keys.NumPad5))
            {
                _camera.Position += new Vector2(0, 250) * dt;
            }

            if (keyboardState.IsKeyDown(Keys.NumPad4))
            {
                _camera.Position -= new Vector2(250, 0) * dt;
            }

            if (keyboardState.IsKeyDown(Keys.NumPad6))
            {
                _camera.Position += new Vector2(250, 0) * dt;
            }

            if (keyboardState.IsKeyDown(Keys.NumPad1))
            {
                Config.GameAeraSize += Config.GameAeraSize * (-0.01f);
            }

            if (keyboardState.IsKeyDown(Keys.NumPad3))
            {
                Config.GameAeraSize += Config.GameAeraSize * 0.01f;
            }

            _previousKeyboardState = Keyboard.GetState();
        }
Esempio n. 9
0
    protected override void OnHandleInput(InputContext context)
    {
      var inputService = InputService;


      if (_isTouchDevice)
      {
        // Scrolling on phone/tablet has priority over the actions of the visual children.
        // Therefore base.OnHandleInput() is called after this code section.

        Vector2F mousePosition = inputService.MousePosition;
        float t = (float)context.DeltaTime.TotalSeconds;
        if (_isDragging)
        {
          if (inputService.IsMouseOrTouchHandled || inputService.IsUp(MouseButtons.Left))
          {
            // Dragging ends.
            _isDragging = false;

            // Check flick gesture.
            foreach (var gesture in inputService.Gestures)
            {
              if (gesture.GestureType == GestureType.Flick)
              {
                // Flick detected.
                // --> Set a scroll velocity proportional to the flick delta.
                _scrollVelocity = (Vector2F)(-gesture.Delta * FlickScrollVelocityFactor / t);
                _scrollVelocity = Vector2F.Clamp(_scrollVelocity, -MaxScrollVelocity, MaxScrollVelocity);

                inputService.IsMouseOrTouchHandled = true;
                break;
              }
            }
          }
          else
          {
            // Dragging continues.
            bool canScrollHorizontally = (ExtentWidth > ViewportWidth);
            bool canScrollVertically = (ExtentHeight > ViewportHeight);
            if (!_scrollToleranceExceeded)
            {
              // Check if drag tolerance has been exceeded.
              if (canScrollHorizontally && Math.Abs(mousePosition.X - _scrollStartPosition.X) > _scrollThreshold
                  || canScrollVertically && Math.Abs(mousePosition.Y - _scrollStartPosition.Y) > _scrollThreshold)
              {
                // Start dragging. (Use current mouse position to avoid a "jump".)
                _scrollStartPosition = mousePosition;
                _scrollToleranceExceeded = true;
              }
            }

            if (_scrollToleranceExceeded)
            {
              // Drag content.
              if (canScrollHorizontally && inputService.MousePositionDelta.X != 0
                  || canScrollVertically && inputService.MousePositionDelta.Y != 0)
              {
                inputService.IsMouseOrTouchHandled = true;

                Vector2F minOffset = new Vector2F(0, 0);
                Vector2F maxOffset = new Vector2F(Math.Max(ExtentWidth - ViewportWidth, 0),
                  Math.Max(ExtentHeight - ViewportHeight, 0));
                Vector2F minVirtualOffset = minOffset - new Vector2F(SpringLength);
                Vector2F maxVirtualOffset = maxOffset + new Vector2F(SpringLength);
                Vector2F newOffset = _scrollStartOffset + _scrollStartPosition - mousePosition;

                if (canScrollHorizontally)
                {
                  HorizontalOffset = MathHelper.Clamp(newOffset.X, minOffset.X, maxOffset.X);
                  _virtualOffset.X = MathHelper.Clamp(newOffset.X, minVirtualOffset.X, maxVirtualOffset.X);
                }

                if (canScrollVertically)
                {
                  VerticalOffset = MathHelper.Clamp(newOffset.Y, minOffset.Y, maxOffset.Y);
                  _virtualOffset.Y = MathHelper.Clamp(newOffset.Y, minVirtualOffset.Y, maxVirtualOffset.Y);
                }

                _scrollVelocity = -inputService.MousePositionDelta / t;
                _scrollVelocity = Vector2F.Clamp(_scrollVelocity, -MaxScrollVelocity, MaxScrollVelocity);
              }
            }
          }
        }
        else
        {
          if (!inputService.IsMouseOrTouchHandled
              && inputService.IsPressed(MouseButtons.Left, false)
              && IsMouseOver)
          {
            // Dragging starts.
            _isDragging = true;

            // Remember the mouse position.
            _scrollStartPosition = mousePosition;
            _scrollStartOffset = _virtualOffset;
            _scrollToleranceExceeded = false;
          }
        }

        if (!inputService.IsMouseOrTouchHandled && inputService.IsDown(MouseButtons.Left))
          _scrollVelocity = Vector2F.Zero;
      }


      base.OnHandleInput(context);

      if (!IsLoaded)
        return;


      // Mouse wheel scrolls vertically when the mouse cursor is over the scroll viewer.
      if (!inputService.IsMouseOrTouchHandled && IsMouseOver)
      {
        if (inputService.MouseWheelDelta != 0
            && VerticalScrollBarVisibility != ScrollBarVisibility.Disabled
            && _verticalScrollBar != null)
        {
          inputService.IsMouseOrTouchHandled = true;

          var screen = Screen;
          float offset = inputService.MouseWheelDelta / screen.MouseWheelScrollDelta * screen.MouseWheelScrollLines;
          offset *= _verticalScrollBar.SmallChange;
          offset = VerticalOffset - offset;
          if (offset < 0)
            offset = 0;
          if (offset > ExtentHeight - ViewportHeight)
            offset = ExtentHeight - ViewportHeight;

          VerticalOffset = offset;
        }
      }


      // Scroll with game pad right stick.
      if (!inputService.IsGamePadHandled(context.AllowedPlayer))
      {
        var gamePadState = inputService.GetGamePadState(context.AllowedPlayer);
        Vector2 rightStick = gamePadState.ThumbSticks.Right;
        float x = rightStick.X;
        float y = rightStick.Y;

        if (!Numeric.IsZero(x + y) && IsInActiveWindow())
        {
          if (_horizontalScrollBar != null)
          {
            float offset = HorizontalOffset + 0.5f * x * _horizontalScrollBar.SmallChange;
            offset = MathHelper.Clamp(offset, 0, ExtentWidth - ViewportWidth);
            HorizontalOffset = offset;
          }

          if (_verticalScrollBar != null)
          {
            float offset = VerticalOffset - 0.5f * y * _verticalScrollBar.SmallChange;
            offset = MathHelper.Clamp(offset, 0, ExtentHeight - ViewportHeight);
            VerticalOffset = offset;
          }

          inputService.SetGamePadHandled(context.AllowedPlayer, true);
        }
      }
    }
Esempio n. 10
0
    protected override void OnUpdate(TimeSpan deltaTime)
    {

      float t = (float)deltaTime.TotalSeconds;
      bool canScrollHorizontally = (ExtentWidth > ViewportWidth);
      bool canScrollVertically = (ExtentHeight > ViewportHeight);

      Vector2F minOffset = new Vector2F(0, 0);
      Vector2F maxOffset = new Vector2F(Math.Max(ExtentWidth - ViewportWidth, 0), Math.Max(ExtentHeight - ViewportHeight, 0));
      Vector2F minVirtualOffset = minOffset - new Vector2F(SpringLength);
      Vector2F maxVirtualOffset = maxOffset + new Vector2F(SpringLength);

      if (!_isDragging)
      {
        // The user is currently not interacting with the content:
        // Move content on with current velocity.

        // ----- Spring
        // Apply spring force if user has dragged content beyond the limit.
        Vector2F springLength = new Vector2F();
        if (_virtualOffset.X < minOffset.X)
          springLength.X = minOffset.X - _virtualOffset.X;
        else if (_virtualOffset.X > maxOffset.X)
          springLength.X = maxOffset.X - _virtualOffset.X;
        if (_virtualOffset.Y < minOffset.Y)
          springLength.Y = minOffset.Y - _virtualOffset.Y;
        else if (_virtualOffset.Y > maxOffset.Y)
          springLength.Y = maxOffset.Y - _virtualOffset.Y;

        _scrollVelocity = _scrollVelocity + SpringConstant * springLength * t;

        // ----- Damping
        // Apply damping to velocity.
        // See DigitalRune Blog for an explanation of damping formulas:
        // http://www.digitalrune.com/Support/Blog/tabid/719/EntryId/78/Damping-in-Computer-Games.aspx

        // Use a stronger damping if the spring is active.
        Vector2F damping = new Vector2F(springLength.X != 0 ? SpringDamping : ScrollDamping,
                                        springLength.Y != 0 ? SpringDamping : ScrollDamping);

        _scrollVelocity = (Vector2F.One - Vector2F.Min(damping * t, Vector2F.One)) * _scrollVelocity;

        // ----- Position Update
        // Compute new scroll offset.
        Vector2F newOffset = _virtualOffset + _scrollVelocity * t;

        // ----- Limits
        // Stop scroll velocity when we hit the max spring length.
        if (newOffset.X < minVirtualOffset.X || newOffset.X > maxVirtualOffset.X)
          _scrollVelocity.X = 0;
        if (newOffset.Y < minVirtualOffset.Y || newOffset.Y > maxVirtualOffset.Y)
          _scrollVelocity.Y = 0;

        // ----- Snapping
        // Snap to min or max offset when the spring pushes the content back.
        if (_virtualOffset.X < minOffset.X && newOffset.X > minOffset.X)
        {
          newOffset.X = minOffset.X;
          _scrollVelocity.X = 0;
        }
        else if (_virtualOffset.X > maxOffset.X && newOffset.X < maxOffset.X)
        {
          newOffset.X = maxOffset.X;
          _scrollVelocity.X = 0;
        }
        if (_virtualOffset.Y < minOffset.Y && newOffset.Y > minOffset.Y)
        {
          newOffset.Y = minOffset.Y;
          _scrollVelocity.Y = 0;
        }
        else if (_virtualOffset.Y > maxOffset.Y && newOffset.Y < maxOffset.Y)
        {
          newOffset.Y = maxOffset.Y;
          _scrollVelocity.Y = 0;
        }

        // ----- Velocity Clamping
        // When the velocity reaches a min limit, clamp it to zero. Otherwise, the content 
        // never really stops.
        if (_scrollVelocity.LengthSquared() < MinScrollVelocity * MinScrollVelocity)
          _scrollVelocity = Vector2F.Zero;

        // ----- Update HorizontalOffset and VerticalOffset.
        if (canScrollHorizontally)
        {
          HorizontalOffset = MathHelper.Clamp(newOffset.X, minOffset.X, maxOffset.X);
          _virtualOffset.X = MathHelper.Clamp(newOffset.X, minVirtualOffset.X, maxVirtualOffset.X);
        }

        if (canScrollVertically)
        {
          VerticalOffset = MathHelper.Clamp(newOffset.Y, minOffset.Y, maxOffset.Y);
          _virtualOffset.Y = MathHelper.Clamp(newOffset.Y, minVirtualOffset.Y, maxVirtualOffset.Y);
        }
      }

      // ----- Scale Transform
      if (Content != null)
      {
        // Apply scale transform to content if it is pushed beyond the limit.
        Vector2F scale = Vector2F.One;
        Vector2F transformOrigin = new Vector2F(0.5f);

        // Scale content horizontally.
        if (_virtualOffset.X < minOffset.X)
        {
          // User pushes content to the right.
          scale.X = (ExtentWidth - (minOffset.X - _virtualOffset.X)) / ExtentWidth;
          transformOrigin.X = 1.0f;
        }
        else if (_virtualOffset.X > maxOffset.X)
        {
          // User pushes content to the left.
          scale.X = (ExtentWidth - (_virtualOffset.X - maxOffset.X)) / ExtentWidth;
          transformOrigin.X = 0.0f;
        }

        // Scale content vertically.
        if (_virtualOffset.Y < minOffset.Y)
        {
          // User pushes content down.
          scale.Y = (ExtentHeight - (minOffset.Y - _virtualOffset.Y)) / ExtentHeight;
          transformOrigin.Y = 1.0f;
        }
        else if (_virtualOffset.Y > maxOffset.Y)
        {
          // User pushes content up.
          scale.Y = (ExtentHeight - (_virtualOffset.Y - maxOffset.Y)) / ExtentHeight;
          transformOrigin.Y = 0.0f;
        }

        Content.RenderScale = scale;
        Content.RenderTransformOrigin = transformOrigin;
      }

      // ----- ScrollBar Opacity Animation
      if (_isTouchDevice)
      {
        // Animate opacity of horizontal and vertical scroll bars.
        if (!_isDragging && _scrollVelocity.LengthSquared() < 1)
        {
          // Fade out.
          if (_horizontalScrollBar != null
              && _horizontalScrollBar.IsVisible
              && _horizontalScrollBar.Opacity > 0)
          {
            _horizontalScrollBar.Opacity = MathHelper.Clamp(_horizontalScrollBar.Opacity - ScrollBarFadeVelocity * t, 0,
              1);
          }
          if (_verticalScrollBar != null
              && _verticalScrollBar.IsVisible
              && _verticalScrollBar.Opacity > 0)
          {
            _verticalScrollBar.Opacity = MathHelper.Clamp(_verticalScrollBar.Opacity - ScrollBarFadeVelocity * t, 0, 1);
          }
        }
        else if (_scrollVelocity.LengthSquared() >= 1)
        {
          // Fade in.
          if (_horizontalScrollBar != null
              && _horizontalScrollBar.IsVisible
              && canScrollHorizontally
              && _horizontalScrollBar.Opacity < 1)
          {
            _horizontalScrollBar.Opacity = MathHelper.Clamp(
              _horizontalScrollBar.Opacity + 2 * ScrollBarFadeVelocity * t, 0, 1);
          }
          if (_verticalScrollBar != null
              && _verticalScrollBar.IsVisible
              && canScrollVertically
              && _verticalScrollBar.Opacity < 1)
          {
            _verticalScrollBar.Opacity = MathHelper.Clamp(_verticalScrollBar.Opacity + 2 * ScrollBarFadeVelocity * t, 0,
              1);
          }
        }
      }
#else
      // Coerce offsets to allowed range.
      Vector2F minOffset = new Vector2F(0, 0);
      Vector2F maxOffset = new Vector2F(Math.Max(ExtentWidth - ViewportWidth, 0), Math.Max(ExtentHeight - ViewportHeight, 0));

      float horizontalOffset = HorizontalOffset;
      if (horizontalOffset < minOffset.X)
        HorizontalOffset = minOffset.X;
      else if (horizontalOffset > maxOffset.X)
        HorizontalOffset = maxOffset.X;

      float verticalOffset = VerticalOffset;
      if (verticalOffset < minOffset.Y)
        VerticalOffset = minOffset.Y;
      else if (verticalOffset > maxOffset.Y)
        VerticalOffset = maxOffset.Y;


      base.OnUpdate(deltaTime);
    }
Esempio n. 11
0
 public static void Clamp(ref Vector2 value1, ref Vector2 min, ref Vector2 max, out Vector2 result)
 {
     result = new Vector2(
         MathHelper.Clamp(value1.X, min.X, max.X),
         MathHelper.Clamp(value1.Y, min.Y, max.Y));
 }
Esempio n. 12
0
 public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max)
 {
     return(new Vector2(
                MathHelper.Clamp(value1.X, min.X, max.X),
                MathHelper.Clamp(value1.Y, min.Y, max.Y)));
 }