ManualControl AttachMovementInput(ViewEngineBase view, bool EnableMouse, bool Visualize)
        {
            var mc = new ManualControl();

            var stage = this.stage;

            if (stage == null)
            {
                throw new Exception("stage is null");
            }


            var snapcontainer = new Shape();

            var vectorized = new Shape();
            var delta      = new Shape {
                alpha = 0.5
            };

            if (Visualize)
            {
                snapcontainer.AttachTo(this);
                vectorized.AttachTo(this);
                delta.AttachTo(this);
            }


            var mouseDown_args  = default(Point);
            var mouseUp_fadeOut = default(Timer);

            uint color = 0;

            var snap_radius = 64;

            mc.down =
                p =>
            {
                if (!MovementEnabled)
                {
                    return;
                }

                color = 0;


                // snap to old point
                if (!mc.disable_join)
                {
                    if (mouseDown_args != null)
                    {
                        if (snapcontainer.alpha > 0)
                        {
                            if ((mouseDown_args - p).length < snap_radius)
                            {
                                color = 0xff;

                                p = mouseDown_args;
                            }
                        }
                    }
                }

                mouseDown_args  = p;
                mc.disable_join = false;
            };

            if (EnableMouse)
            {
                stage.mouseDown +=
                    e =>
                {
                    mc.down(e.ToStagePoint());

                    //Write("down ", new { e.localX, e.localY, e.buttonDown });
                }
            }
            ;

            Action <Shape, double, double, uint> DrawArrow =
                (s, x, y, c) =>
            {
                if (Visualize)
                {
                    s.graphics.lineStyle(2, c, 1);
                    s.graphics.moveTo(mouseDown_args.x, mouseDown_args.y);
                    s.graphics.lineTo(x, y);
                    s.graphics.drawCircle(x, y, 4);
                }
            };

            var mouseMove_args = default(Point);
            var delta_pos      = 0.0;

            mc.move =
                p =>
            {
                if (!MovementEnabled)
                {
                    return;
                }

                if (mouseDown_args == null)
                {
                    return;
                }

                mouseMove_args = p;

                if (mouseUp_fadeOut != null)
                {
                    mouseUp_fadeOut.stop();
                }

                vectorized.alpha = 1;
                vectorized.graphics.clear();

                snapcontainer.alpha = 1;
                snapcontainer.graphics.clear();


                snapcontainer.graphics.lineStyle(2, 0xff, 1);
                snapcontainer.graphics.drawCircle(mouseDown_args.x, mouseDown_args.y, snap_radius);

                DrawArrow(vectorized, mouseMove_args.x, mouseMove_args.y, color);
            };

            if (EnableMouse)
            {
                stage.mouseMove +=
                    e =>
                {
                    if (e.buttonDown)
                    {
                        mc.move(e.ToStagePoint());
                    }
                }
            }
            ;

            mc.up +=
                delegate
            {
                if (mouseUp_fadeOut != null)
                {
                    mouseUp_fadeOut.stop();
                }

                var _vectorized    = vectorized;
                var _snapcontainer = snapcontainer;

                mouseUp_fadeOut = 50.AtInterval(
                    t =>
                {
                    if (vectorized.alpha < 0)
                    {
                        t.stop();
                        return;
                    }

                    _vectorized.alpha    -= 0.02;
                    _snapcontainer.alpha -= 0.04;
                }
                    );
            };

            if (EnableMouse)
            {
                stage.mouseUp +=
                    delegate
                {
                    mc.up();
                }
            }
            ;



            (1000 / 24).AtInterval(
                t =>
            {
                if (mouseDown_args == null)
                {
                    return;
                }

                if (mouseMove_args == null)
                {
                    return;
                }

                delta.graphics.clear();

                if (vectorized.alpha == 1)
                {
                    delta_pos    += mc.delta_acc;
                    mc.delta_acc += mc.delta_acc_acc;
                }
                else
                {
                    mc.delta_acc -= mc.delta_acc_acc * 3;
                    if (mc.delta_acc < mc.delta_acc_min)
                    {
                        mc.delta_acc = mc.delta_acc_min;
                    }


                    delta_pos -= mc.delta_acc;
                }

                delta_pos = delta_pos.Min(1).Max(0);

                var u = (mouseMove_args - mouseDown_args) * delta_pos;
                var z = mouseDown_args + u;

                var Q1    = mouseDown_args.y < DefaultControlHeight * 1 / 6;
                var Q4    = mouseDown_args.y > DefaultControlHeight * 5 / 6;
                var IsPan = Q1 || Q4;


                if (delta_pos > 0)
                {
                    if (!IsPan)
                    {
                        NextViewDirection += u.x * 0.0004;

                        NextViewPosition = NextViewPosition.MoveToArc(NextViewDirection, -u.y.Max(-snap_radius * 2).Min(snap_radius * 2) * 0.001);
                    }
                    else
                    {
                        NextViewPosition = NextViewPosition.MoveToArc(u.GetRotation() + NextViewDirection + 270.DegreesToRadians(), -(u.length.Min(snap_radius * 2)) * 0.001);
                    }
                }

                DrawArrow(delta, z.x, z.y, 0xff00);
            }
                );

            return(mc);
        }
Esempio n. 2
0
        private void Initialize()
        {
            txtMain = new TextField
            {
                defaultTextFormat = new TextFormat
                {
                    font  = "Verdana",
                    align = TextFormatAlign.LEFT,
                    size  = 10,
                    color = 0xffffff
                },
                autoSize = TextFieldAutoSize.LEFT,
                text     = "0"
            };

            AddFullscreenMenu();



            EgoView = new ViewEngineBase(DefaultWidth, DefaultHeight)
            {
                FloorAndCeilingVisible = false,

                ViewPosition = new Point {
                    x = 4, y = 22
                },
                ViewDirection = 90.DegreesToRadians(),
            };

            var Portals = new List <PortalInfo>();

            EgoView.ViewDirectionChanged += () => Portals.ForEach(Portal => Portal.View.ViewDirection = EgoView.ViewDirection);

            #region create a dual portal
            var PortalA = new PortalInfo
            {
                Color      = 0xFF6A00,
                ViewVector = new Vector {
                    Direction = EgoView.ViewDirection, Position = new Point {
                        x = 4.5, y = 14
                    }
                },
                SpriteVector = new Vector {
                    Direction = EgoView.ViewDirection, Position = new Point {
                        x = 3.5, y = 20
                    }
                },
            }.AddTo(Portals);


            EgoView.Sprites.Add(PortalA.Sprite);


            var PortalB = new PortalInfo
            {
                Color        = 0xff00,
                ViewVector   = PortalA.SpriteVector,
                SpriteVector = PortalA.ViewVector,
            }.AddTo(Portals);


            EgoView.Sprites.Add(PortalB.Sprite);
            #endregion



            var Ego = default(SpriteInfo);


            EgoView.ViewPositionChanged +=
                delegate
            {
                foreach (var Portal in Portals)
                {
                    var p = EgoView.SpritesFromPointOfView.SingleOrDefault(i => i.Sprite == Portal.Sprite);

                    if (p != null)
                    {
                        if (p.Distance < Portal.Sprite.Range)
                        {
                            // we are going thro the portal, show it

                            new Bitmap(EgoView.Buffer.clone())
                            {
                                scaleX = DefaultScale,
                                scaleY = DefaultScale
                            }.AttachTo(this).FadeOutAndOrphanize(1000 / 24, 0.2);

                            Assets.SoundFiles.teleport.ToSoundAsset().play();

                            // fixme: should use Ego.MovementDirection instead
                            // currently stepping backwards into the portal will behave recursivly
                            EgoView.ViewPosition = Portal.View.ViewPosition.MoveToArc(EgoView.ViewDirection, Portal.Sprite.Range + p.Distance);

                            break;
                        }
                    }
                }
            };

            var CameraView = new ViewEngineBase(64, 48)
            {
            };


            EgoView.RenderOverlay          += DrawMinimap;
            EgoView.FramesPerSecondChanged += () => txtMain.text = EgoView.FramesPerSecond + " fps " + new { EgoView.ViewPositionX, EgoView.ViewPositionY };

            EgoView.Image.AttachTo(this);

            txtMain.AttachTo(this);



            EgoView.Image.scaleX = DefaultScale;
            EgoView.Image.scaleY = DefaultScale;
            //this.filters = new[] { new BlurFilter() };


            KeyboardButton fKeyTurnLeft  = new uint[] { Keyboard.LEFT, 'j', 'J', };
            KeyboardButton fKeyTurnRight = new uint[] { Keyboard.RIGHT, 'l', 'L', };

            KeyboardButton fKeyStrafeLeft  = new uint[] { 'a', 'A' };
            KeyboardButton fKeyStrafeRight = new uint[] { 'd', 'D' };

            KeyboardButton fKeyUp   = new uint[] { Keyboard.UP, 'i', 'I', 'w', 'W' };
            KeyboardButton fKeyDown = new uint[] { Keyboard.DOWN, 'k', 'K', 's', 'S' };


            stage.keyDown +=
                e =>
            {
                var key = e.keyCode;

                fKeyStrafeLeft.ProcessKeyDown(key);
                fKeyStrafeRight.ProcessKeyDown(key);
                fKeyTurnLeft.ProcessKeyDown(key);
                fKeyTurnRight.ProcessKeyDown(key);

                fKeyUp.ProcessKeyDown(key);
                fKeyDown.ProcessKeyDown(key);
            };

            stage.keyUp +=
                e =>
            {
                var key = e.keyCode;


                fKeyStrafeLeft.ProcessKeyUp(key);
                fKeyStrafeRight.ProcessKeyUp(key);

                fKeyTurnLeft.ProcessKeyUp(key);
                fKeyTurnRight.ProcessKeyUp(key);

                fKeyUp.ProcessKeyUp(key);
                fKeyDown.ProcessKeyUp(key);
            };


            Action UpdateEgoPosition =
                delegate
            {
                if (Ego != null)
                {
                    Ego.Position  = EgoView.ViewPosition;
                    Ego.Direction = EgoView.ViewDirection;
                }
            };

            EgoView.ViewPositionChanged +=
                delegate
            {
                UpdateEgoPosition();
            };

            (1000 / 30).AtInterval(
                delegate
            {
                if (fKeyTurnRight.IsPressed)
                {
                    EgoView.ViewDirection += 10.DegreesToRadians();
                }
                else if (fKeyTurnLeft.IsPressed)
                {
                    EgoView.ViewDirection -= 10.DegreesToRadians();
                }

                if (fKeyUp.IsPressed || fKeyStrafeLeft.IsPressed || fKeyStrafeRight.IsPressed)
                {
                    var d = EgoView.ViewDirection;



                    if (fKeyStrafeLeft.IsPressed)
                    {
                        d -= 90.DegreesToRadians();
                    }
                    else if (fKeyStrafeRight.IsPressed)
                    {
                        d += 90.DegreesToRadians();
                    }


                    EgoView.MoveTo(
                        EgoView.ViewPositionX + Math.Cos(d) * 0.2,
                        EgoView.ViewPositionY + Math.Sin(d) * 0.2
                        );
                }
                else if (fKeyDown.IsPressed)
                {
                    EgoView.MoveTo(
                        EgoView.ViewPositionX + Math.Cos(EgoView.ViewDirection) * -0.2,
                        EgoView.ViewPositionY + Math.Sin(EgoView.ViewDirection) * -0.2
                        );
                }
            }
                );

            var UpdatePortals = true;

            stage.keyUp +=
                e =>
            {
                if (e.keyCode == Keyboard.V)
                {
                    UpdatePortals = !UpdatePortals;
                }

                if (e.keyCode == Keyboard.N)
                {
                    EgoView.RenderLowQualityWalls = !EgoView.RenderLowQualityWalls;
                }

                if (e.keyCode == Keyboard.M)
                {
                    DrawMinimapEnabled = !DrawMinimapEnabled;
                }

                if (e.keyCode == Keyboard.B)
                {
                    EgoView.SpritesVisible = !EgoView.SpritesVisible;
                }

                if (e.keyCode == Keyboard.F)
                {
                    EgoView.FloorAndCeilingVisible = !EgoView.FloorAndCeilingVisible;
                }

                if (e.keyCode == Keyboard.DELETE)
                {
                    EgoView.Sprites.RemoveAll(p => p != Ego);
                }
            };


            Action <Bitmap[]> BitmapsLoadedAction =
                Bitmaps =>
            {
                if (Bitmaps == null)
                {
                    throw new Exception("No bitmaps");
                }

                Func <Texture64[], Texture64[]> Reorder8 =
                    p =>
                    Enumerable.ToArray(
                        from i in Enumerable.Range(0, 8)
                        select p[(i + 6) % 8]
                        );

                var BitmapStream = Bitmaps.Select(i => (Texture64)i).GetEnumerator();

                Func <Texture64[]> Next8 =
                    delegate
                {
                    // keeping compiler happy with full delegate form

                    if (BitmapStream == null)
                    {
                        throw new Exception("BitmapStream is null");
                    }

                    return(Reorder8(BitmapStream.Take(8)));
                };


                var Stand = Next8();
                var Spawn = default(Func <SpriteInfo>);

                if (Bitmaps.Length == 8)
                {
                    Spawn = () => CreateWalkingDummy(Stand);
                }
                else
                {
                    var Walk = new[]
                    {
                        Next8(),
                        Next8(),
                        Next8(),
                        Next8(),
                    };



                    Spawn = () => CreateWalkingDummy(Stand, Walk);
                }

                Ego = Spawn();


                UpdateEgoPosition();



                stage.keyUp +=
                    e =>
                {
                    if (e.keyCode == Keyboard.SPACE)
                    {
                        var s = Spawn();

                        //s.Direction += 180.DegreesToRadians();

                        CameraView.ViewPosition  = s.Position;
                        CameraView.ViewDirection = s.Direction;
                    }

                    if (e.keyCode == Keyboard.INSERT)
                    {
                        var s = Spawn();

                        s.Direction += 180.DegreesToRadians();
                        s.Position   = Ego.Position.MoveToArc(Ego.Direction, 0.5);
                    }

                    if (e.keyCode == Keyboard.ENTER)
                    {
                        EgoView.ViewPosition = new Point {
                            x = 4, y = 22
                        };
                        EgoView.ViewDirection = 270.DegreesToRadians();
                    }



                    if (e.keyCode == Keyboard.BACKSPACE)
                    {
                        (1000 / 30).AtInterval(
                            t =>
                        {
                            EgoView.ViewDirection += 18.DegreesToRadians();

                            if (t.currentCount == 10)
                            {
                                t.stop();
                            }
                        }
                            );
                    }
                };
            };


            Assets.ZipFiles.MyZipFile
            .ToFiles()
            .Where(f => f.FileName.EndsWith(".png"))
            .ToBitmapArray(BitmapsLoadedAction);



            Assets.ZipFiles.MyStuff.ToFiles().ToBitmapDictionary(
                f =>
            {
                // ! important
                // ----------------------------------------------------
                // ! loading png via bytes affects pixel values
                // ! this is why map is in gif format

                EgoView.Map.WorldMap = Texture32.Of(f["Map1.gif"], false);

                Action <IEnumerator <Texture64.Entry>, Texture64, Action <SpriteInfo> > AddSpriteByTexture =
                    (SpaceForStuff, tex, handler) => SpaceForStuff.Take().Do(p => CreateDummy(tex).Do(handler).Position.To(p.XIndex + 0.5, p.YIndex + 0.5));

                var FreeSpaceForStuff = EgoView.Map.WorldMap.Entries.Where(i => i.Value == 0).Randomize().GetEnumerator();

                Action <Bitmap> AddSprite =
                    e => AddSpriteByTexture(FreeSpaceForStuff, e, null);

                Assets.ZipFiles.MySprites.ToFiles().ToBitmapArray(
                    sprites =>
                {
                    foreach (var s in sprites)
                    {
                        for (int i = 0; i < 3; i++)
                        {
                            AddSprite(s);
                        }
                    }
                }
                    );
                #region gold

                Assets.ZipFiles.MyGold.ToFiles().ToBitmapArray(
                    sprites =>
                {
                    var GoldSprites = new List <SpriteInfo>();

                    foreach (var s in sprites)
                    {
                        for (int i = 0; i < 20; i++)
                        {
                            // compiler bug: get a delegate to BCL class
                            //AddSpriteByTexture(FreeSpaceForStuff, s, GoldSprites.Add);

                            AddSpriteByTexture(FreeSpaceForStuff, s,
                                               k =>
                            {
                                k.Range = 0.5;
                                GoldSprites.Add(k);
                            }
                                               );
                        }
                    }

                    var LastPosition = new Point();

                    EgoView.ViewPositionChanged +=
                        delegate
                    {
                        // only check for items each 0.5 distance travelled
                        if ((EgoView.ViewPosition - LastPosition).length < 0.5)
                        {
                            return;
                        }

                        Action Later = delegate { };


                        foreach (var Item in EgoView.SpritesFromPointOfView)
                        {
                            var Item_Sprite = Item.Sprite;

                            if (Item.Distance < Item_Sprite.Range)
                            {
                                if (GoldSprites.Contains(Item_Sprite))
                                {
                                    // ding-ding-ding!

                                    new Bitmap(new BitmapData(DefaultWidth, DefaultHeight, false, 0xffff00))
                                    {
                                        scaleX = DefaultScale,
                                        scaleY = DefaultScale
                                    }.AttachTo(this).FadeOutAndOrphanize(1000 / 24, 0.2);

                                    InternalGotGold();
                                    Later += () => EgoView.Sprites.Remove(Item_Sprite);
                                }
                            }
                        }

                        Later();

                        LastPosition = EgoView.ViewPosition;
                    };
                }
                    );
                #endregion

                #region ammo

                Assets.ZipFiles.ammo.ToFiles().ToBitmapArray(
                    sprites =>
                {
                    var AmmoSprites = new List <SpriteInfo>();

                    foreach (var s in sprites)
                    {
                        for (int i = 0; i < 20; i++)
                        {
                            // compiler bug: get a delegate to BCL class
                            //AddSpriteByTexture(FreeSpaceForStuff, s, GoldSprites.Add);

                            AddSpriteByTexture(FreeSpaceForStuff, s,
                                               k =>
                            {
                                k.Range = 0.5;
                                AmmoSprites.Add(k);
                            }
                                               );
                        }
                    }

                    var LastPosition = new Point();

                    EgoView.ViewPositionChanged +=
                        delegate
                    {
                        // only check for items each 0.5 distance travelled
                        if ((EgoView.ViewPosition - LastPosition).length < 0.5)
                        {
                            return;
                        }

                        Action Later = delegate { };


                        foreach (var Item in EgoView.SpritesFromPointOfView)
                        {
                            var Item_Sprite = Item.Sprite;

                            if (Item.Distance < Item_Sprite.Range)
                            {
                                if (AmmoSprites.Contains(Item_Sprite))
                                {
                                    // ding-ding-ding!

                                    new Bitmap(new BitmapData(DefaultWidth, DefaultHeight, false, 0x8080ff))
                                    {
                                        scaleX = DefaultScale,
                                        scaleY = DefaultScale
                                    }.AttachTo(this).FadeOutAndOrphanize(1000 / 24, 0.2);


                                    InternalGotAmmo();


                                    Later += () => EgoView.Sprites.Remove(Item_Sprite);
                                }
                            }
                        }

                        Later();

                        LastPosition = EgoView.ViewPosition;
                    };
                }
                    );
                #endregion

                Func <string, Texture64> t =
                    texname => f[texname + ".png"];

                EgoView.FloorTexture   = t("floor");
                EgoView.CeilingTexture = t("roof");



                var DynamicTextureBitmap = new Bitmap(new BitmapData(Texture64.SizeConstant, Texture64.SizeConstant, false, 0));
                Texture64 DynamicTexture = DynamicTextureBitmap;
                uint DynamicTextureKey   = 0xffffff;

                EgoView.Map.WorldMap[2, 22] = DynamicTextureKey;
                EgoView.Map.WorldMap[3, 15] = DynamicTextureKey;


                EgoView.Map.Textures = new Dictionary <uint, Texture64>
                {
                    { 0xff0000, t("graywall") },
                    { 0x0000ff, t("bluewall") },
                    { 0x00ff00, t("greenwall") },
                    { 0x7F3300, t("woodwall") },

                    { DynamicTextureKey, DynamicTexture }
                };


                if (EgoView.CurrentTile != 0)
                {
                    throw new Exception("bad start position: " + new { EgoView.ViewPositionX, EgoView.ViewPositionY, EgoView.CurrentTile }.ToString());
                }



                CameraView.Map.WorldMap = EgoView.Map.WorldMap;
                CameraView.Map.Textures = EgoView.Map.Textures;
                CameraView.Sprites      = EgoView.Sprites;
                CameraView.ViewPosition = EgoView.ViewPosition;

                foreach (var Portal in Portals)
                {
                    Portal.View.Map.WorldMap = EgoView.Map.WorldMap;
                    Portal.View.Map.Textures = EgoView.Map.Textures;
                    Portal.View.Sprites      = EgoView.Sprites;
                    Portal.AlphaMask         = f["portalmask.png"];
                }


                EgoView.RenderScene();


                var MirrorFrame = f["mirror.png"];
                var counter     = 0;

                stage.enterFrame += e =>
                {
                    counter++;

                    if (UpdatePortals)
                    {
                        // updateing it too often causes framerate to drop

                        foreach (var Portal in Portals)
                        {
                            Portal.Update();
                        }

                        DynamicTextureBitmap.bitmapData.fillRect(DynamicTextureBitmap.bitmapData.rect, (uint)(counter * 8 % 256));
                        var m = new Matrix();

                        // to center
                        m.translate(0, 10);
                        // m.scale(0.3, 0.3);

                        CameraView.RenderScene();

                        DynamicTextureBitmap.bitmapData.draw(CameraView.Image.bitmapData, m);
                        DynamicTextureBitmap.bitmapData.draw(MirrorFrame.bitmapData);

                        DynamicTexture.Update();
                    }

                    EgoView.RenderScene();
                };
            }
                );

            AttachMovementInput(EgoView);
        }
        void AttachMovementInput(ViewEngineBase view)
        {
            var stage = this.stage;

            if (stage == null)
            {
                throw new Exception("stage is null");
            }


            var snapcontainer = new Shape().AttachTo(this);
            var vectorized = new Shape().AttachTo(this);
            var delta = new Shape {
                alpha = 0.5
            }.AttachTo(this);



            var mouseDown_args  = default(MouseEvent);
            var mouseUp_fadeOut = default(Timer);

            uint color = 0;

            var snap_radius = 64;

            stage.mouseDown +=
                e =>
            {
                color = 0;

                // snap to old point
                if (mouseDown_args != null)
                {
                    if (snapcontainer.alpha > 0)
                    {
                        if ((mouseDown_args.ToStagePoint() - e.ToStagePoint()).length < snap_radius)
                        {
                            color = 0xff;

                            e = mouseDown_args;
                        }
                    }
                }

                mouseDown_args = e;

                //Write("down ", new { e.localX, e.localY, e.buttonDown });
            };

            Action <Shape, double, double, uint> DrawArrow =
                (s, x, y, c) =>
            {
                s.graphics.lineStyle(2, c, 1);
                s.graphics.moveTo(mouseDown_args.stageX, mouseDown_args.stageY);
                s.graphics.lineTo(x, y);
                s.graphics.drawCircle(x, y, 4);
            };

            var mouseMove_args = default(MouseEvent);
            var delta_pos      = 0.0;

            stage.mouseMove +=
                e =>
            {
                if (e.buttonDown)
                {
                    mouseMove_args = e;

                    if (mouseUp_fadeOut != null)
                    {
                        mouseUp_fadeOut.stop();
                    }

                    vectorized.alpha = 1;
                    vectorized.graphics.clear();

                    snapcontainer.alpha = 1;
                    snapcontainer.graphics.clear();


                    snapcontainer.graphics.lineStyle(2, 0xff, 1);
                    snapcontainer.graphics.drawCircle(mouseDown_args.stageX, mouseDown_args.stageY, snap_radius);

                    DrawArrow(vectorized, e.stageX, e.stageY, color);
                }
            };

            stage.mouseUp +=
                e =>
            {
                if (mouseUp_fadeOut != null)
                {
                    mouseUp_fadeOut.stop();
                }

                var _vectorized    = vectorized;
                var _snapcontainer = snapcontainer;

                mouseUp_fadeOut = 50.AtInterval(
                    t =>
                {
                    if (vectorized.alpha < 0)
                    {
                        t.stop();
                        return;
                    }

                    _vectorized.alpha    -= 0.02;
                    _snapcontainer.alpha -= 0.04;
                }
                    );
            };


            var delta_acc_min = 0.02;
            var delta_acc     = delta_acc_min;
            var delta_acc_acc = delta_acc_min * 0.01;

            var delta_deacc_min = 0.03;
            var delta_deacc     = delta_deacc_min;

            (1000 / 24).AtInterval(
                t =>
            {
                if (mouseDown_args == null)
                {
                    return;
                }

                if (mouseMove_args == null)
                {
                    return;
                }

                delta.graphics.clear();

                if (vectorized.alpha == 1)
                {
                    delta_pos += delta_acc;
                    delta_acc += delta_acc_acc;
                }
                else
                {
                    delta_acc -= delta_acc_acc * 3;
                    if (delta_acc < delta_acc_min)
                    {
                        delta_acc = delta_acc_min;
                    }


                    delta_pos -= delta_acc;
                }

                delta_pos = Math.Max(Math.Min((double)1, (double)delta_pos), (double)0);

                var u = (mouseMove_args.ToStagePoint() - mouseDown_args.ToStagePoint()) * delta_pos;
                var z = mouseDown_args.ToStagePoint() + u;

                var Q1    = mouseDown_args.stageY < stage.height * 1 / 6;
                var Q4    = mouseDown_args.stageY > stage.height * 5 / 6;
                var IsPan = Q1 || Q4;


                if (delta_pos > 0)
                {
                    if (!IsPan)
                    {
                        view.ViewDirection += u.x * 0.0004;

                        view.ViewPosition = view.ViewPosition.MoveToArc(view.ViewDirection,
                                                                        Math.Min(
                                                                            Math.Max(-u.y, -snap_radius * 2), (snap_radius * 2) * 0.001
                                                                            )
                                                                        );
                    }
                    else
                    {
                        view.ViewPosition = view.ViewPosition.MoveToArc(u.GetRotation() + view.ViewDirection + 270.DegreesToRadians(), -(u.length.Min(snap_radius * 2)) * 0.001);
                    }
                }

                DrawArrow(delta, z.x, z.y, 0xff00);
            }
                );
        }