void Apply(EditMode mode, ApplyOffsetForm f, bool previewOnly, ref Action reset)
        {
            var offset = new
            {
                f.Position,
                f.IsPositionLocal,
                Rotation = MathHelper.ToRadians(f.Rotation),
                f.IsRotationLocal,
                Quaternion = Quaternion.RotationYawPitchRoll(MathHelper.ToRadians(f.Rotation.Y), MathHelper.ToRadians(f.Rotation.X), MathHelper.ToRadians(f.Rotation.Z)),
                f.Weight,
                f.Distance,
                f.Color,
            };

            if (reset != null)
            {
                reset();
                reset = null;
            }

            switch (mode)
            {
            case EditMode.AccessoryMode:
                var acc = this.Scene.ActiveAccessory;

                if (acc != null)
                {
                    var rotationOffset = new Lazy <Quaternion>(() => GetLocalRotation(offset.IsRotationLocal, null, offset.Rotation, offset.Quaternion));

                    foreach (var i in acc.SelectedLayers)
                    {
                        var local    = i.CurrentLocalMotion;
                        var newLocal = new MotionData(local.Move, offset.IsRotationLocal ? Quaternion.Multiply(local.Rotation, offset.Quaternion) : Quaternion.Multiply(offset.Quaternion, local.Rotation));

                        newLocal.Move += GetLocalPosition(offset.IsPositionLocal, null, offset.Position, newLocal.Rotation);

                        reset += () => i.CurrentLocalMotion = local;
                        i.CurrentLocalMotion = newLocal;
                    }

                    if (!previewOnly)
                    {
                        foreach (var i in acc.Layers.SelectMany(_ => _.SelectedFrames))
                        {
                            var resetPosition   = i.Position;
                            var resetQuaternion = i.Quaternion;

                            reset += () =>
                            {
                                i.Position   = resetPosition;
                                i.Quaternion = resetQuaternion;
                            };
                            i.Quaternion = offset.IsRotationLocal ? Quaternion.Multiply(i.Quaternion, offset.Quaternion) : Quaternion.Multiply(offset.Quaternion, i.Quaternion);
                            i.Position  += GetLocalPosition(offset.IsPositionLocal, null, offset.Position, i.Quaternion);
                        }
                    }
                }

                break;

            case EditMode.None:
            case EditMode.CameraMode:
                foreach (var camera in this.Scene.Cameras.Where(_ => _.Layers.SelectMany(__ => __.SelectedFrames).Any()).DefaultIfEmpty(this.Scene.ActiveCamera).Where(_ => _ != null))
                {
                    var local    = camera.CurrentMotion;
                    var newLocal = new CameraMotionData(local.Position, local.Angle + offset.Rotation, local.Radius + offset.Distance, local.Fov);

                    newLocal.Position += GetLocalCameraPosition(offset.IsPositionLocal, offset.Position, newLocal.Angle);

                    reset += () => camera.CurrentMotion = local;
                    camera.CurrentMotion = newLocal;

                    if (!previewOnly)
                    {
                        foreach (var i in camera.Layers.SelectMany(_ => _.SelectedFrames))
                        {
                            var resetPosition = i.Position;
                            var resetAngle    = i.Angle;
                            var resetRadius   = i.Radius;

                            reset += () =>
                            {
                                i.Position = resetPosition;
                                i.Angle    = resetAngle;
                                i.Radius   = resetRadius;
                            };
                            i.Angle    += offset.Rotation;
                            i.Radius   += offset.Distance;
                            i.Position += GetLocalCameraPosition(offset.IsPositionLocal, offset.Position, i.Angle);
                        }
                    }
                }

                foreach (var light in this.Scene.Lights.Where(_ => _.SelectedFrames.Any()).DefaultIfEmpty(this.Scene.ActiveLight).Where(_ => _ != null))
                {
                    var local = light.CurrentMotion;

                    reset += () => light.CurrentMotion = local;
                    light.CurrentMotion = new LightMotionData(local.Position + offset.Position, local.Color + offset.Color);

                    if (!previewOnly)
                    {
                        foreach (var i in light.SelectedFrames)
                        {
                            var resetPosition = i.Position;
                            var resetColor    = i.Color;

                            reset += () =>
                            {
                                i.Position = resetPosition;
                                i.Color    = resetColor;
                            };
                            i.Position += offset.Position;
                            i.Color    += offset.Color;
                        }
                    }
                }

                break;

            case EditMode.CaptionMode:
                foreach (var i in this.Scene.SelectedCaptions)
                {
                    var resetLocation = i.Location;

                    reset      += () => i.Location = resetLocation;
                    i.Location += offset.Position;
                }

                break;

            case EditMode.EffectMode:
                var eff = this.Scene.ActiveEffect;

                if (eff != null)
                {
                    var local    = eff.CurrentMotion;
                    var newLocal = new MotionData(local.Move, offset.IsRotationLocal ? Quaternion.Multiply(local.Rotation, offset.Quaternion) : Quaternion.Multiply(offset.Quaternion, local.Rotation));

                    newLocal.Move += GetLocalPosition(offset.IsPositionLocal, null, offset.Position, newLocal.Rotation);

                    reset            += () => eff.CurrentMotion = local;
                    eff.CurrentMotion = newLocal;

                    if (!previewOnly)
                    {
                        foreach (var i in eff.SelectedFrames)
                        {
                            var resetPosition   = i.Position;
                            var resetQuaternion = i.Quaternion;

                            reset += () =>
                            {
                                i.Position   = resetPosition;
                                i.Quaternion = resetQuaternion;
                            };
                            i.Quaternion = offset.IsRotationLocal ? Quaternion.Multiply(i.Quaternion, offset.Quaternion) : Quaternion.Multiply(offset.Quaternion, i.Quaternion);
                            i.Position  += GetLocalPosition(offset.IsPositionLocal, null, offset.Position, i.Quaternion);
                        }
                    }
                }

                break;

            case EditMode.ModelMode:
                var model = this.Scene.ActiveModel;

                if (model != null)
                {
                    foreach (var bone in model.Bones)
                    {
                        var rotationOffset = new Lazy <Quaternion>(() => GetLocalRotation(offset.IsRotationLocal, bone, offset.Rotation, offset.Quaternion));

                        foreach (var i in bone.SelectedLayers)
                        {
                            var local    = i.CurrentLocalMotion;
                            var newLocal = new MotionData(local.Move, (bone.BoneFlags & BoneType.Rotate) != 0
                                                                        ? offset.IsRotationLocal ? Quaternion.Multiply(local.Rotation, rotationOffset.Value) : Quaternion.Multiply(rotationOffset.Value, local.Rotation)
                                                                        : local.Rotation);

                            if ((bone.BoneFlags & BoneType.XYZ) != 0)
                            {
                                newLocal.Move += GetLocalPosition(offset.IsPositionLocal, bone, offset.Position, newLocal.Rotation);
                            }

                            reset += () => i.CurrentLocalMotion = local;
                            i.CurrentLocalMotion = newLocal;
                        }

                        if (!previewOnly)
                        {
                            foreach (var i in bone.Layers.SelectMany(_ => _.SelectedFrames))
                            {
                                var resetPosition   = i.Position;
                                var resetQuaternion = i.Quaternion;

                                reset += () =>
                                {
                                    i.Position   = resetPosition;
                                    i.Quaternion = resetQuaternion;
                                };

                                i.Quaternion = offset.IsRotationLocal ? Quaternion.Multiply(i.Quaternion, rotationOffset.Value) : Quaternion.Multiply(rotationOffset.Value, i.Quaternion);
                                i.Position  += GetLocalPosition(offset.IsPositionLocal, bone, offset.Position, i.Quaternion);
                            }
                        }
                    }

                    foreach (var morph in model.Morphs)
                    {
                        if (morph.Selected)
                        {
                            var local = morph.CurrentWeight;

                            reset += () => morph.CurrentWeight = local;
                            morph.CurrentWeight += offset.Weight;
                        }

                        if (!previewOnly)
                        {
                            foreach (var i in morph.SelectedFrames)
                            {
                                var resetWeight = i.Weight;

                                reset    += () => i.Weight = resetWeight;
                                i.Weight += offset.Weight;
                            }
                        }
                    }
                }

                break;
            }
        }
        void Apply(EditMode mode, ApplyOffsetForm f, bool previewOnly, ref Action reset)
        {
            var offset = new
            {
                f.Position,
                f.IsPositionLocal,
                Rotation = MathHelper.ToRadians(f.Rotation),
                f.IsRotationLocal,
                Quaternion = Quaternion.RotationYawPitchRoll(MathHelper.ToRadians(f.Rotation.Y), MathHelper.ToRadians(f.Rotation.X), MathHelper.ToRadians(f.Rotation.Z)),
                f.Weight,
                f.Distance,
                f.Color,
            };

            if (reset != null)
            {
                reset();
                reset = null;
            }

            switch (mode)
            {
                case EditMode.AccessoryMode:
                    var acc = this.Scene.ActiveAccessory;

                    if (acc != null)
                    {
                        var rotationOffset = new Lazy<Quaternion>(() => GetLocalRotation(offset.IsRotationLocal, null, offset.Rotation, offset.Quaternion));

                        foreach (var i in acc.SelectedLayers)
                        {
                            var local = i.CurrentLocalMotion;
                            var newLocal = new MotionData(local.Move, offset.IsRotationLocal ? Quaternion.Multiply(local.Rotation, offset.Quaternion) : Quaternion.Multiply(offset.Quaternion, local.Rotation));

                            newLocal.Move += GetLocalPosition(offset.IsPositionLocal, null, offset.Position, newLocal.Rotation);

                            reset += () => i.CurrentLocalMotion = local;
                            i.CurrentLocalMotion = newLocal;
                        }

                        if (!previewOnly)
                            foreach (var i in acc.Layers.SelectMany(_ => _.SelectedFrames))
                            {
                                var resetPosition = i.Position;
                                var resetQuaternion = i.Quaternion;

                                reset += () =>
                                {
                                    i.Position = resetPosition;
                                    i.Quaternion = resetQuaternion;
                                };
                                i.Quaternion = offset.IsRotationLocal ? Quaternion.Multiply(i.Quaternion, offset.Quaternion) : Quaternion.Multiply(offset.Quaternion, i.Quaternion);
                                i.Position += GetLocalPosition(offset.IsPositionLocal, null, offset.Position, i.Quaternion);
                            }
                    }

                    break;
                case EditMode.None:
                case EditMode.CameraMode:
                    foreach (var camera in this.Scene.Cameras.Where(_ => _.Layers.SelectMany(__ => __.SelectedFrames).Any()).DefaultIfEmpty(this.Scene.ActiveCamera).Where(_ => _ != null))
                    {
                        var local = camera.CurrentMotion;
                        var newLocal = new CameraMotionData(local.Position, local.Angle + offset.Rotation, local.Radius + offset.Distance, local.Fov);

                        newLocal.Position += GetLocalCameraPosition(offset.IsPositionLocal, offset.Position, newLocal.Angle);

                        reset += () => camera.CurrentMotion = local;
                        camera.CurrentMotion = newLocal;

                        if (!previewOnly)
                            foreach (var i in camera.Layers.SelectMany(_ => _.SelectedFrames))
                            {
                                var resetPosition = i.Position;
                                var resetAngle = i.Angle;
                                var resetRadius = i.Radius;

                                reset += () =>
                                {
                                    i.Position = resetPosition;
                                    i.Angle = resetAngle;
                                    i.Radius = resetRadius;
                                };
                                i.Angle += offset.Rotation;
                                i.Radius += offset.Distance;
                                i.Position += GetLocalCameraPosition(offset.IsPositionLocal, offset.Position, i.Angle);
                            }
                    }

                    foreach (var light in this.Scene.Lights.Where(_ => _.SelectedFrames.Any()).DefaultIfEmpty(this.Scene.ActiveLight).Where(_ => _ != null))
                    {
                        var local = light.CurrentMotion;

                        reset += () => light.CurrentMotion = local;
                        light.CurrentMotion = new LightMotionData(local.Position + offset.Position, local.Color + offset.Color);

                        if (!previewOnly)
                            foreach (var i in light.SelectedFrames)
                            {
                                var resetPosition = i.Position;
                                var resetColor = i.Color;

                                reset += () =>
                                {
                                    i.Position = resetPosition;
                                    i.Color = resetColor;
                                };
                                i.Position += offset.Position;
                                i.Color += offset.Color;
                            }
                    }

                    break;
                case EditMode.CaptionMode:
                    foreach (var i in this.Scene.SelectedCaptions)
                    {
                        var resetLocation = i.Location;

                        reset += () => i.Location = resetLocation;
                        i.Location += offset.Position;
                    }

                    break;
                case EditMode.EffectMode:
                    var eff = this.Scene.ActiveEffect;

                    if (eff != null)
                    {
                        var local = eff.CurrentMotion;
                        var newLocal = new MotionData(local.Move, offset.IsRotationLocal ? Quaternion.Multiply(local.Rotation, offset.Quaternion) : Quaternion.Multiply(offset.Quaternion, local.Rotation));

                        newLocal.Move += GetLocalPosition(offset.IsPositionLocal, null, offset.Position, newLocal.Rotation);

                        reset += () => eff.CurrentMotion = local;
                        eff.CurrentMotion = newLocal;

                        if (!previewOnly)
                            foreach (var i in eff.SelectedFrames)
                            {
                                var resetPosition = i.Position;
                                var resetQuaternion = i.Quaternion;

                                reset += () =>
                                {
                                    i.Position = resetPosition;
                                    i.Quaternion = resetQuaternion;
                                };
                                i.Quaternion = offset.IsRotationLocal ? Quaternion.Multiply(i.Quaternion, offset.Quaternion) : Quaternion.Multiply(offset.Quaternion, i.Quaternion);
                                i.Position += GetLocalPosition(offset.IsPositionLocal, null, offset.Position, i.Quaternion);
                            }
                    }

                    break;
                case EditMode.ModelMode:
                    var model = this.Scene.ActiveModel;

                    if (model != null)
                    {
                        foreach (var bone in model.Bones)
                        {
                            var rotationOffset = new Lazy<Quaternion>(() => GetLocalRotation(offset.IsRotationLocal, bone, offset.Rotation, offset.Quaternion));

                            foreach (var i in bone.SelectedLayers)
                            {
                                var local = i.CurrentLocalMotion;
                                var newLocal = new MotionData(local.Move, (bone.BoneFlags & BoneType.Rotate) != 0
                                    ? offset.IsRotationLocal ? Quaternion.Multiply(local.Rotation, rotationOffset.Value) : Quaternion.Multiply(rotationOffset.Value, local.Rotation)
                                    : local.Rotation);

                                if ((bone.BoneFlags & BoneType.XYZ) != 0)
                                    newLocal.Move += GetLocalPosition(offset.IsPositionLocal, bone, offset.Position, newLocal.Rotation);

                                reset += () => i.CurrentLocalMotion = local;
                                i.CurrentLocalMotion = newLocal;
                            }

                            if (!previewOnly)
                                foreach (var i in bone.Layers.SelectMany(_ => _.SelectedFrames))
                                {
                                    var resetPosition = i.Position;
                                    var resetQuaternion = i.Quaternion;

                                    reset += () =>
                                    {
                                        i.Position = resetPosition;
                                        i.Quaternion = resetQuaternion;
                                    };

                                    i.Quaternion = offset.IsRotationLocal ? Quaternion.Multiply(i.Quaternion, rotationOffset.Value) : Quaternion.Multiply(rotationOffset.Value, i.Quaternion);
                                    i.Position += GetLocalPosition(offset.IsPositionLocal, bone, offset.Position, i.Quaternion);
                                }
                        }

                        foreach (var morph in model.Morphs)
                        {
                            if (morph.Selected)
                            {
                                var local = morph.CurrentWeight;

                                reset += () => morph.CurrentWeight = local;
                                morph.CurrentWeight += offset.Weight;
                            }

                            if (!previewOnly)
                                foreach (var i in morph.SelectedFrames)
                                {
                                    var resetWeight = i.Weight;

                                    reset += () => i.Weight = resetWeight;
                                    i.Weight += offset.Weight;
                                }
                        }
                    }

                    break;
            }
        }