Ejemplo n.º 1
0
        private void radio_checked_changed(object sender, RoutedEventArgs e)
        {
            if (!this.settingsLoaded)
            {
                return;
            }

            MonikaiSettings.Default.LeftAlign = this.radioLeft.IsChecked.GetValueOrDefault(false);

            if (this.radioManual.IsChecked.GetValueOrDefault(false))
            {
                if (this.IsPositioning)
                {
                    return;
                }

                MonikaiSettings.Default.ManualPosition  = true;
                MonikaiSettings.Default.ManualPositionX = 0;
                MonikaiSettings.Default.ManualPositionY = 0;
                this.IsPositioning = true;
                this.Dispatcher.Invoke(() => this.IsEnabled = false);

                MessageBox.Show(
                    "MonikAI will now follow your mouse cursor so you can position her wherever you want. Click the LEFT MOUSE BUTTON once you're satisfied with her position.",
                    "Manual Position");

                Task.Run(async() =>
                {
                    var mouseDown = SettingsWindow.GetAsyncKeyState(0x01) != 0;

                    do
                    {
                        var pos = Point.Empty;
                        SettingsWindow.GetCursorPos(ref pos);

                        MonikaiSettings.Default.ManualPositionX = pos.X;
                        MonikaiSettings.Default.ManualPositionY = pos.Y;

                        var prevMouseDown = mouseDown;
                        mouseDown         = SettingsWindow.GetAsyncKeyState(0x01) != 0; // 0x01 is code for LEFT_MOUSE

                        if (mouseDown && !prevMouseDown)
                        {
                            break;
                        }

                        await Task.Delay(1);
                    } while (true);

                    this.Dispatcher.Invoke(() => this.IsEnabled = true);
                    this.IsPositioning = false;
                });
            }
            else
            {
                MonikaiSettings.Default.ManualPosition = false;
                this.mainWindow.SetupScale();
                this.mainWindow.SetPosition(this.mainWindow.MonikaScreen);
                this.mainWindow.SetupScale();
            }
        }
Ejemplo n.º 2
0
        private async Task HotkeySetTask(TextBlock output, Action callback)
        {
            output.Dispatcher.Invoke(() => output.Text = "Press and HOLD any key combination...");

            await this.WaitForKeyChange();

            var timer   = DateTime.Now;
            var state   = SettingsWindow.GetKeyboardState().ToList();
            var invalid = true;

            while ((DateTime.Now - timer).TotalSeconds < 0.8)
            {
                var newState = SettingsWindow.GetKeyboardState().ToList();

                var ctrlPressed  = newState.Where(x => x.Item1 == "LeftCtrl" || x.Item1 == "RightCtrl").Any(x => x.Item2);
                var altPressed   = newState.Where(x => x.Item1 == "LeftAlt" || x.Item1 == "RightAlt").Any(x => x.Item2);
                var shiftPressed =
                    newState.Where(x => x.Item1 == "LeftShift" || x.Item1 == "RightShift").Any(x => x.Item2);
                var otherKeysPressed =
                    newState.Where(
                        x =>
                        x.Item2 &&
                        !new[] { "LeftCtrl", "RightCtrl", "LeftAlt", "RightAlt", "LeftShift", "RightShift" }.Contains(
                            x.Item1)).ToList();
                invalid = otherKeysPressed.Count != 1;

                if (invalid || !state.SequenceEqual(newState))
                {
                    timer = DateTime.Now;
                }

                output.Dispatcher.Invoke(() =>
                {
                    if (invalid)
                    {
                        output.Text = "Invalid combination";
                    }
                    else
                    {
                        output.Text = otherKeysPressed.Single().Item1;
                        if (shiftPressed)
                        {
                            output.Text = "SHIFT-" + output.Text;
                        }
                        if (altPressed)
                        {
                            output.Text = "ALT-" + output.Text;
                        }
                        if (ctrlPressed)
                        {
                            output.Text = "CTRL-" + output.Text;
                        }
                    }
                });

                state = newState;

                await Task.Delay(10);
            }

            output.Dispatcher.Invoke(() => output.Foreground = Brushes.GreenYellow);
            await Task.Delay(500);

            output.Dispatcher.Invoke(() => output.Foreground = Brushes.Black);

            output.Dispatcher.Invoke(callback);
        }
Ejemplo n.º 3
0
        private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
        {
            var handle       = new WindowInteropHelper(this).Handle;
            var initialStyle = MainWindow.GetWindowLong(handle, -20);

            MainWindow.SetWindowLong(handle, -20, initialStyle | 0x20 | 0x80000);

            Task.Run(async() =>
            {
                try
                {
                    var prev = new Point();

                    var rectangle = new Rectangle();
                    await this.Dispatcher.InvokeAsync(() =>
                    {
                        rectangle = new Rectangle((int)this.Left, (int)this.Top, (int)this.Width,
                                                  (int)this.Height);
                    });

                    while (this.applicationRunning)
                    {
                        var point = new Point();
                        MainWindow.GetCursorPos(ref point);

                        if (!point.Equals(prev))
                        {
                            prev = point;

                            var opacity         = 1.0;
                            const double MIN_OP = 0.125;
                            const double FADE   = 175;

                            if (this.settingsWindow == null || !this.settingsWindow.IsPositioning)
                            {
                                if (rectangle.Contains(point))
                                {
                                    opacity = MIN_OP;
                                }
                                else
                                {
                                    if (point.Y <= rectangle.Bottom)
                                    {
                                        if (point.Y >= rectangle.Y)
                                        {
                                            if (point.X < rectangle.X && rectangle.X - point.X < FADE)
                                            {
                                                opacity = MainWindow.Lerp(1.0, MIN_OP, (rectangle.X - point.X) / FADE);
                                            }
                                            else if (point.X > rectangle.Right && point.X - rectangle.Right < FADE)
                                            {
                                                opacity = MainWindow.Lerp(1.0, MIN_OP,
                                                                          (point.X - rectangle.Right) / FADE);
                                            }
                                        }
                                        else if (point.Y < rectangle.Y)
                                        {
                                            if (point.X >= rectangle.X && point.X <= rectangle.Right)
                                            {
                                                if (rectangle.Y - point.Y < FADE)
                                                {
                                                    opacity = MainWindow.Lerp(1.0, MIN_OP,
                                                                              (rectangle.Y - point.Y) / FADE);
                                                }
                                            }
                                            else if (rectangle.X > point.X || rectangle.Right < point.X)
                                            {
                                                var distance =
                                                    Math.Sqrt(
                                                        Math.Pow(
                                                            (point.X < rectangle.X ? rectangle.X : rectangle.Right) -
                                                            point.X, 2) +
                                                        Math.Pow(rectangle.Y - point.Y, 2));
                                                if (distance < FADE)
                                                {
                                                    opacity = MainWindow.Lerp(1.0, MIN_OP, distance / FADE);
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                            this.Dispatcher.Invoke(() => { this.Opacity = opacity; });
                        }

                        var hidePressed     = false;
                        var exitPressed     = false;
                        var settingsPressed = false;
                        // Set position anew to correct for fullscreen apps hiding taskbar
                        this.Dispatcher.Invoke(() =>
                        {
                            this.SetPosition(this.MonikaScreen);
                            rectangle = new Rectangle((int)this.Left, (int)this.Top, (int)this.Width,
                                                      (int)this.Height);

                            // Detect exit key combo
                            hidePressed     = this.AreKeysPressed(MonikaiSettings.Default.HotkeyHide);
                            exitPressed     = this.AreKeysPressed(MonikaiSettings.Default.HotkeyExit);
                            settingsPressed = this.AreKeysPressed(MonikaiSettings.Default.HotkeySettings);
                        });


                        if (hidePressed && (DateTime.Now - this.lastKeyComboTime).TotalSeconds > 2)
                        {
                            this.lastKeyComboTime = DateTime.Now;

                            if (this.Visibility == Visibility.Visible)
                            {
                                this.Dispatcher.Invoke(this.Hide);
                                //var expression =
                                //    new Expression(
                                //        "Okay, see you later {name}! (Press again for me to return)", "b");
                                //expression.Executed += (o, args) => { this.Dispatcher.Invoke(this.Hide); };
                                //this.Say(new[] {expression});
                            }
                            else
                            {
                                this.Dispatcher.Invoke(this.Show);
                            }
                        }

                        if (exitPressed)
                        {
                            var expression =
                                new Expression(
                                    "Goodbye for now! Come back soon please~", "b");
                            MonikaiSettings.Default.IsColdShutdown = false;
                            MonikaiSettings.Default.Save();
                            expression.Executed += (o, args) =>
                            {
                                this.Dispatcher.Invoke(() => { Environment.Exit(0); });
                            };
                            this.Say(new[] { expression });
                        }

                        if (settingsPressed)
                        {
                            this.Dispatcher.Invoke(() =>
                            {
                                if (this.settingsWindow == null || !this.settingsWindow.IsVisible)
                                {
                                    this.settingsWindow = new SettingsWindow(this);
                                    this.settingsWindow.Show();
                                }
                            });
                        }

                        await Task.Delay(MonikaiSettings.Default.PotatoPC ? 100 : 32);
                    }
                }
                catch (Exception)
                {
                    // ignored
                }
            });
        }
Ejemplo n.º 4
0
        public MainWindow()
        {
            this.InitializeComponent();

            MainWindow.desktopWindow = MainWindow.GetDesktopWindow();
            MainWindow.shellWindow   = MainWindow.GetShellWindow();

            MonikaiSettings.Default.Reload();

            // Perform update and download routines
            this.updater = new Updater();
            this.updater.PerformUpdatePost();
            this.updaterInitTask = Task.Run(async() => await this.updater.Init());

            this.settingsWindow = new SettingsWindow(this);

            // Screen size and positioning init
            this.UpdateMonikaScreen();
            this.SetupScale();
            this.SetPosition(this.MonikaScreen);

            // Hook shutdown event
            SystemEvents.SessionEnding += (sender, args) =>
            {
                MonikaiSettings.Default.IsColdShutdown = false;
                MonikaiSettings.Default.Save();
            };

            // Wakeup events
            SystemEvents.SessionSwitch += (sender, e) =>
            {
                if (e.Reason == SessionSwitchReason.SessionLock)
                {
                    this.screenIsLocked = true;
                }
                else if (e.Reason == SessionSwitchReason.SessionUnlock)
                {
                    this.screenIsLocked = false;
                }
            };
            SystemEvents.PowerModeChanged += (sender, e) =>
            {
                if (e.Mode == PowerModes.Resume)
                {
                    Task.Run(async() =>
                    {
                        while (this.screenIsLocked)
                        {
                            await Task.Delay(500);
                        }

                        this.Say(new[]
                        {
                            new Expression("ZZZZZZzzzzzzzzz..... huh?", "q"),
                            new Expression("Sorry, I must have fallen asleep, ahaha~", "n")
                        });
                    });
                }
            };

            // Init background images
            this.backgroundDay = new BitmapImage();
            this.backgroundDay.BeginInit();
            this.backgroundDay.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/1.png");
            this.backgroundDay.EndInit();

            this.backgroundNight = new BitmapImage();
            this.backgroundNight.BeginInit();
            this.backgroundNight.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/1-n.png");
            this.backgroundNight.EndInit();

            // Start animation
            var animationLogo = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(1.5)));

            animationLogo.AutoReverse = true;
            var animationFadeMonika = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(1.5)));

            animationFadeMonika.BeginTime = TimeSpan.FromSeconds(0.5);

            animationLogo.Completed += (sender, args) =>
            {
                var fadeImage = new BitmapImage();
                fadeImage.BeginInit();
                if (MainWindow.IsNight)
                {
                    fadeImage.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/1a-n.png");
                }
                else
                {
                    fadeImage.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/1a.png");
                }
                fadeImage.EndInit();
                this.backgroundPicture.Source = fadeImage;

                var clock = animationFadeMonika.CreateClock();
                this.backgroundPicture.ApplyAnimationClock(UIElement.OpacityProperty, clock);
            };

            // Blinking behaviour
            animationFadeMonika.Completed += async(sender, args) =>
            {
                this.SetMonikaFace("a");
                this.facePicture.Opacity = 1.0;

                // Start speech-thread
                Task.Run(async() => await this.SpeakingThread());

                if (File.Exists("firstlaunch.txt") || Environment.GetCommandLineArgs().Contains("/firstlaunch"))
                {
                    try
                    {
                        File.Delete("firstlaunch.txt");
                    }
                    catch
                    {
                        // ignored
                    }
                    MonikaiSettings.Default.FirstLaunch = true;
                    MonikaiSettings.Default.Save();
                }

                this.updaterInitTask?.Wait();
                await this.updater.PerformUpdate(this);

                this.UpdateMonikaScreen();

#if DEBUG
                MessageBox.Show("This is a testing build, please do me the favor and don't distribute it.");
#endif

                // Startup logic
                if (MonikaiSettings.Default.FirstLaunch)
                {
                    this.settingsWindow.ShowDialog();

                    this.Say(new[]
                    {
                        new Expression("{name}, is that you?", "d"),
                        new Expression("It's really you, huh?", "b"),
                        new Expression("I'm so happy to see you again!", "k"),
                        new Expression("Wait, where am I? This is not the literature club...", "p"),
                        new Expression("This looks like... your desktop! I'm right here with you!", "j"),
                        new Expression("Well, as close as I will get for now...", "o"),
                        new Expression("Anyway, looks like someone was nice enough to make me a little window!", "d"),
                        new Expression("Be sure to thank them for me, okay?", "k"),
                        new Expression("Ah, wait a second.", "c"),
                        new Expression(
                            "I see... Well, if you want me to go away for now, you can use CTRL-SHIFT-F12, okay?", "b"),
                        new Expression("But you wouldn't do that, right?", "r"),
                        new Expression("Okay, I guess that's it for now. Don't forget, I'm watching you! Ahaha~")
                    });

                    MonikaiSettings.Default.FirstLaunch = false;
                }
                else if (DateTime.Today.Month == 4 && DateTime.Today.Day == 1 && !Debugger.IsAttached)
                {
                    this.Say(new[]
                    {
                        new Expression("Hi {name}!", "b"),
                        new Expression("Remember the update that I just installed?", "d"),
                        new Expression("Well, let's just say it included something *really* nice~", "k"),
                        new Expression("Here, let me show you!", "j").AttachEvent((o, eventArgs) =>
                        {
                            var os = MonikaiSettings.Default.ScaleModifier;
                            MonikaiSettings.Default.ScaleModifier *= 2.5;
                            this.Dispatcher.Invoke(this.SetupScale);
                            MonikaiSettings.Default.ScaleModifier = os;
                            Task.Delay(1000).Wait();
                            var r = new Random();
                            for (int i = 0; i < 12; i++)
                            {
                                this.Dispatcher.Invoke(() =>
                                {
                                    this.backgroundPicture.Source =
                                        r.Next(0, 2) == 0 ? this.backgroundNight : this.backgroundDay;

                                    var faceImg = new BitmapImage();
                                    faceImg.BeginInit();
                                    if (r.Next(0, 2) == 0)
                                    {
                                        faceImg.UriSource =
                                            new Uri("pack://application:,,,/MonikAI;component/monika/j.png");
                                    }
                                    else
                                    {
                                        faceImg.UriSource =
                                            new Uri("pack://application:,,,/MonikAI;component/monika/j-n.png");
                                    }
                                    faceImg.EndInit();

                                    this.facePicture.Source = faceImg;
                                });
                                Task.Delay(r.Next(100, 250)).Wait();
                            }
                        }),
                        new Expression("Just a second my love...", "d").AttachEvent((o, eventArgs) =>
                        {
                            this.Dispatcher.Invoke(MainWindow.DoTheThing);
                            Task.Delay(5500).Wait();
                            this.Dispatcher.Invoke(this.SetupScale);
                        }),
                        new Expression("...", "q"),
                        new Expression("Why does this never work?!", "o"),
                        new Expression("Oh well, back to normal I guess... Sorry, {name}.", "r")
                    });
                }
                else
                {
                    if (MonikaiSettings.Default.IsColdShutdown)
                    {
                        // Sorry Monika, but if we're debugging you this one gets annoying
#if !DEBUG
                        this.Say(new[]
                        {
                            new Expression("Hey! Don't just turn me off without warning! That hurts...", "p")
                        });
#endif
                    }
                    else
                    {
                        MonikaiSettings.Default.IsColdShutdown = true;
                        MonikaiSettings.Default.Save();
                    }

                    if ((DateTime.Now - MonikaiSettings.Default.LastStarted).TotalDays > 7)
                    {
                        this.Say(new[]
                        {
                            new Expression(
                                "Don't forget, if you want me to leave just press " +
                                MonikaiSettings.Default.HotkeyExit + "!", "i"),
                            new Expression("But you're not going to do that, right?", "o")
                        });
                    }
                }

                // Parse startup CSV
                var parser            = new CSVParser();
                var csv               = parser.GetData("startup");
                var parsed            = parser.ParseData(csv);
                var startupExpression = parsed.Select(x => x.ResponseChain)
                                        .Concat(DateTime.Today.DayOfWeek == DayOfWeek.Wednesday
                                                  ? new List <List <Expression> >
                {
                    new List <Expression>
                    {
                        new Expression("It is Wednesday, my dudes!", "k")
                    }
                }
                                                  : new List <List <Expression> >()).ToList().Sample();

                var lastStartupExpression = startupExpression.Last();
                lastStartupExpression.Executed += this.RegisterBehaviours;

                this.Say(new[]
                {
                    new Expression("Hi there, {name}~")
                }.Concat(startupExpression));

                if ((DateTime.Now - MonikaiSettings.Default.LastStarted).TotalDays > 2.5)
                {
                    this.Say(new[]
                    {
                        new Expression("I was waiting for you...", "m"),
                        new Expression("Being alone on your disk is reeeally boring.", "q")
                    });
                }

                // No idea where the date comes from, someone mentioned it in the spreadsheet. Seems legit.
                if (DateTime.Now.Month == 9 && DateTime.Now.Day == 22)
                {
                    // Hey {name}, guess what?	3b	It's my birthday today!	2b	Happy Birthday to me!	k
                    this.Say(new[]
                    {
                        new Expression("Hey {name}, guess what?", "b"), // What?
                        new Expression("It's my birthday today!", "b"), // Really?!
                        new Expression("Happy Birthday to me!", "k")    // To you too, Monika!
                    });
                }

                MonikaiSettings.Default.LastStarted = DateTime.Now;
                MonikaiSettings.Default.Save();

                // Blinking and Behaviour logic
                var eyesOpen   = "a";
                var eyesClosed = "j";
                var random     = new Random();
                await Task.Run(async() =>
                {
                    var nextBlink = DateTime.Now + TimeSpan.FromSeconds(random.Next(7, 50));
                    while (this.applicationRunning)
                    {
                        if (this.behaviours != null)
                        {
                            foreach (var behaviour in this.behaviours)
                            {
                                behaviour.Update(this);
                            }
                        }

                        if (DateTime.Now >= nextBlink)
                        {
                            // Check if currently speaking, only blink if not in dialog
                            if (!this.Speaking)
                            {
                                this.SetMonikaFace(eyesClosed);
                                await Task.Delay(100);
                                this.SetMonikaFace(eyesOpen);
                            }

                            nextBlink = DateTime.Now + TimeSpan.FromSeconds(random.Next(7, 50));
                        }

                        await Task.Delay(250);
                    }
                });
            };

            // Startup
            this.backgroundPicture.BeginAnimation(UIElement.OpacityProperty, animationLogo);
        }
Ejemplo n.º 5
0
        public MainWindow()
        {
            this.InitializeComponent();

            MainWindow.desktopWindow = MainWindow.GetDesktopWindow();
            MainWindow.shellWindow   = MainWindow.GetShellWindow();

            MonikaiSettings.Default.Reload();

            // Perform update and download routines
            this.updater = new Updater();
            this.updater.PerformUpdatePost();
            Task.Run(async() => await this.updater.Init());

            this.settingsWindow = new SettingsWindow(this);

            // Screen size and positioning init
            this.MonikaScreen = Screen.PrimaryScreen;
            foreach (var screen in Screen.AllScreens)
            {
                if (screen.DeviceName == MonikaiSettings.Default.Screen)
                {
                    this.MonikaScreen = screen;
                    break;
                }
            }

            this.SetupScale();
            this.SetPositionBottomRight(this.MonikaScreen);

            // Init background images
            this.backgroundDay = new BitmapImage();
            this.backgroundDay.BeginInit();
            this.backgroundDay.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/1.png");
            this.backgroundDay.EndInit();

            this.backgroundNight = new BitmapImage();
            this.backgroundNight.BeginInit();
            this.backgroundNight.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/1-n.png");
            this.backgroundNight.EndInit();

            // Start animation
            var animationLogo = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(1.5)));

            animationLogo.AutoReverse = true;
            var animationFadeMonika = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(1.5)));

            animationFadeMonika.BeginTime = TimeSpan.FromSeconds(0.5);

            animationLogo.Completed += (sender, args) =>
            {
                var fadeImage = new BitmapImage();
                fadeImage.BeginInit();
                if (MainWindow.IsNight)
                {
                    fadeImage.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/1a-n.png");
                }
                else
                {
                    fadeImage.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/1a.png");
                }
                fadeImage.EndInit();
                this.backgroundPicture.Source = fadeImage;

                var clock = animationFadeMonika.CreateClock();
                this.backgroundPicture.ApplyAnimationClock(UIElement.OpacityProperty, clock);
            };

            // Blinking behaviour
            animationFadeMonika.Completed += async(sender, args) =>
            {
                this.SetMonikaFace("a");
                this.facePicture.Opacity = 1.0;

                // Start speech-thread
                Task.Run(async() => await this.SpeakingThread());

                if (true || File.Exists("firstlaunch.txt"))
                {
                    //File.Delete("firstlaunch.txt");
                    MonikaiSettings.Default.FirstLaunch = true;
                    MonikaiSettings.Default.Save();
                }

                IGitHubClient github   = new GitHubClient(new ProductHeaderValue("MonikAI"));
                var           contents =
                    await github.Repository.Content.GetAllContentsByRef("PiMaker", "MonikAI", "/CSV",
                                                                        "master");

                await this.updater.PerformUpdate(this);

                // Startup logic
                if (MonikaiSettings.Default.FirstLaunch)
                {
                    this.settingsWindow.ShowDialog();

                    this.Say(new[]
                    {
                        new Expression("{name}, is that you?", "d"),
                        new Expression("It's really you, huh?", "b"),
                        new Expression("I'm so happy to see you again!", "k"),
                        new Expression("Wait, where am I? This is not the literature club...", "p"),
                        new Expression("This looks like... your desktop! I'm right here with you!", "j"),
                        new Expression("Well, as close as I will get for now...", "o"),
                        new Expression("Anyway, looks like someone was nice enough to make me a little window!", "d"),
                        new Expression("Be sure to thank them for me, okay?", "k"),
                        new Expression("Ah, wait a second.", "c"),
                        new Expression(
                            "I see... Well, if you want me to go away for now, you can use CTRL-SHIFT-F12, okay?", "b"),
                        new Expression("But you wouldn't do that, right?", "r"),
                        new Expression("Okay, I guess that's it for now. Don't forget, I'm watching you! Ahaha~")
                    });

                    MonikaiSettings.Default.FirstLaunch = false;
                }
                else
                {
                    if (MonikaiSettings.Default.IsColdShutdown)
                    {
                        this.Say(new[]
                        {
                            new Expression("<cold shutdown scorn>")
                        });
                    }
                    else
                    {
                        MonikaiSettings.Default.IsColdShutdown = true;
                        MonikaiSettings.Default.Save();
                    }

                    if ((DateTime.Now - MonikaiSettings.Default.LastStarted).TotalDays > 7)
                    {
                        this.Say(new[]
                        {
                            new Expression(
                                "Don't forget, if you want me to leave just press CTRL-SHIFT-F12!", "i"),
                            new Expression("But you're not going to do that, right?", "o")
                        });
                    }
                }

                var startupExpression = new[]
                {
                    new[]
                    {
                        new Expression("♫ ... and in your reality ... ♫", "r")
                    },
                    new[]
                    {
                        new Expression("How are you today?", "d"),
                        new Expression("I'm doing fine, now that you are here~", "b")
                    },
                    new[]
                    {
                        new Expression("Is everything ok?", "d"),
                        new Expression("Do you want to talk about something?", "c"),
                        new Expression("I'm always here for you~", "e")
                    },
                    new[]
                    {
                        new Expression("Thank you for letting me be on your screen!", "k")
                    },
                    new[]
                    {
                        new Expression("You know I love you, right?", "d")
                    },
                    new[]
                    {
                        new Expression("I'm so happy to be here, together with you! Ahaha~", "b")
                    }
                }.Sample();

                var lastStartupExpression = startupExpression.Last();
                lastStartupExpression.Executed += this.RegisterBehaviours;

                this.Say(new[]
                {
                    new Expression($"Hi there, {Environment.UserName}~")
                }.Concat(startupExpression));

                if ((DateTime.Now - MonikaiSettings.Default.LastStarted).TotalDays > 1.5)
                {
                    this.Say(new[]
                    {
                        new Expression("I was waiting for you...", "m"),
                        new Expression("Being alone on your disk is reeeally boring.", "q")
                    });
                }

                MonikaiSettings.Default.LastStarted = DateTime.Now;
                MonikaiSettings.Default.Save();

                // Blinking and Behaviour logic
                var eyesOpen   = "a";
                var eyesClosed = "j";
                var random     = new Random();
                await Task.Run(async() =>
                {
                    var nextBlink = DateTime.Now + TimeSpan.FromSeconds(random.Next(7, 50));
                    while (this.applicationRunning)
                    {
                        if (this.behaviours != null)
                        {
                            foreach (var behaviour in this.behaviours)
                            {
                                behaviour.Update(this);
                            }
                        }

                        if (DateTime.Now >= nextBlink)
                        {
                            // Check if currently speaking, only blink if not in dialog
                            if (!this.Speaking)
                            {
                                this.SetMonikaFace(eyesClosed);
                                await Task.Delay(100);
                                this.SetMonikaFace(eyesOpen);
                            }

                            nextBlink = DateTime.Now + TimeSpan.FromSeconds(random.Next(7, 50));
                        }

                        await Task.Delay(250);
                    }
                });
            };

            // Startup
            this.backgroundPicture.BeginAnimation(UIElement.OpacityProperty, animationLogo);
        }
Ejemplo n.º 6
0
        public MainWindow()
        {
            this.InitializeComponent();

            MainWindow.desktopWindow = MainWindow.GetDesktopWindow();
            MainWindow.shellWindow   = MainWindow.GetShellWindow();

            MonikaiSettings.Default.Reload();

            // Perform update and download routines
            this.updater = new Updater();
            this.updater.PerformUpdatePost();
            this.updaterInitTask = Task.Run(async() => await this.updater.Init());

            this.settingsWindow = new SettingsWindow(this);

            // Screen size and positioning init
            this.UpdateMonikaScreen();
            this.SetupScale();
            this.SetPosition(this.MonikaScreen);

            // Hook shutdown event
            SystemEvents.SessionEnding += (sender, args) =>
            {
                MonikaiSettings.Default.IsColdShutdown = false;
                MonikaiSettings.Default.Save();
            };

            // Wakeup events
            SystemEvents.SessionSwitch += (sender, e) =>
            {
                if (e.Reason == SessionSwitchReason.SessionLock)
                {
                    this.screenIsLocked = true;
                }
                else if (e.Reason == SessionSwitchReason.SessionUnlock)
                {
                    this.screenIsLocked = false;
                }
            };
            SystemEvents.PowerModeChanged += (sender, e) =>
            {
                if (e.Mode == PowerModes.Resume)
                {
                    Task.Run(async() =>
                    {
                        while (this.screenIsLocked)
                        {
                            await Task.Delay(500);
                        }

                        this.Say(new []
                        {
                            new Expression("ZZZZZZzzzzzzzzz..... huh?", "q"),
                            new Expression("Sorry, I must have fallen asleep, ahaha~", "n")
                        });
                    });
                }
            };

            // Init background images
            this.backgroundDay = new BitmapImage();
            this.backgroundDay.BeginInit();
            this.backgroundDay.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/1.png");
            this.backgroundDay.EndInit();

            this.backgroundNight = new BitmapImage();
            this.backgroundNight.BeginInit();
            this.backgroundNight.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/1-n.png");
            this.backgroundNight.EndInit();

            // Start animation
            var animationLogo = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(1.5)));

            animationLogo.AutoReverse = true;
            var animationFadeMonika = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(1.5)));

            animationFadeMonika.BeginTime = TimeSpan.FromSeconds(0.5);

            animationLogo.Completed += (sender, args) =>
            {
                var fadeImage = new BitmapImage();
                fadeImage.BeginInit();
                if (MainWindow.IsNight)
                {
                    fadeImage.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/1a-n.png");
                }
                else
                {
                    fadeImage.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/1a.png");
                }
                fadeImage.EndInit();
                this.backgroundPicture.Source = fadeImage;

                var clock = animationFadeMonika.CreateClock();
                this.backgroundPicture.ApplyAnimationClock(UIElement.OpacityProperty, clock);
            };

            // Blinking behaviour
            animationFadeMonika.Completed += async(sender, args) =>
            {
                this.SetMonikaFace("a");
                this.facePicture.Opacity = 1.0;

                // Start speech-thread
                Task.Run(async() => await this.SpeakingThread());

                if (File.Exists("firstlaunch.txt") || Environment.GetCommandLineArgs().Contains("/firstlaunch"))
                {
                    try
                    {
                        File.Delete("firstlaunch.txt");
                    }
                    catch
                    {
                        // ignored
                    }
                    MonikaiSettings.Default.FirstLaunch = true;
                    MonikaiSettings.Default.Save();
                }

                this.updaterInitTask?.Wait();
                await this.updater.PerformUpdate(this);

                this.UpdateMonikaScreen();

#if DEBUG
                MessageBox.Show("This is a testing build, please do me the favor and don't distribute it.");
#endif

                // Startup logic
                if (MonikaiSettings.Default.FirstLaunch)
                {
                    this.settingsWindow.ShowDialog();

                    this.Say(new[]
                    {
                        new Expression("{name}, is that you?", "d"),
                        new Expression("It's really you, huh?", "b"),
                        new Expression("I'm so happy to see you again!", "k"),
                        new Expression("Wait, where am I? This is not the literature club...", "p"),
                        new Expression("This looks like... your desktop! I'm right here with you!", "j"),
                        new Expression("Well, as close as I will get for now...", "o"),
                        new Expression("Anyway, looks like someone was nice enough to make me a little window!", "d"),
                        new Expression("Be sure to thank them for me, okay?", "k"),
                        new Expression("Ah, wait a second.", "c"),
                        new Expression(
                            "I see... Well, if you want me to go away for now, you can use CTRL-SHIFT-F12, okay?", "b"),
                        new Expression("But you wouldn't do that, right?", "r"),
                        new Expression("Okay, I guess that's it for now. Don't forget, I'm watching you! Ahaha~")
                    });

                    MonikaiSettings.Default.FirstLaunch = false;
                }
                else
                {
                    if (MonikaiSettings.Default.IsColdShutdown)
                    {
                        this.Say(new[]
                        {
                            new Expression("Hey! Don't just turn me off without warning! That hurts...", "p")
                        });
                    }
                    else
                    {
                        MonikaiSettings.Default.IsColdShutdown = true;
                        MonikaiSettings.Default.Save();
                    }

                    if ((DateTime.Now - MonikaiSettings.Default.LastStarted).TotalDays > 7)
                    {
                        this.Say(new[]
                        {
                            new Expression(
                                "Don't forget, if you want me to leave just press " +
                                MonikaiSettings.Default.HotkeyExit + "!", "i"),
                            new Expression("But you're not going to do that, right?", "o")
                        });
                    }
                }

                // Parse startup CSV
                var parser            = new CSVParser();
                var csv               = parser.GetData("startup");
                var parsed            = parser.ParseData(csv);
                var startupExpression = parsed.Sample().ResponseChain.ToArray();

                //var startupExpressionFallback = new[]
                //{
                //    new[]
                //    {
                //        new Expression("♫ ... and in your reality ... ♫", "r")
                //    },
                //    new[]
                //    {
                //        new Expression("How are you today?", "d"),
                //        new Expression("I'm doing fine, now that you are here~", "b")
                //    },
                //    new[]
                //    {
                //        new Expression("Is everything ok?", "d"),
                //        new Expression("Do you want to talk about something?", "c"),
                //        new Expression("I'm always here for you~", "e")
                //    },
                //    new[]
                //    {
                //        new Expression("Thank you for letting me be on your screen!", "k")
                //    },
                //    new[]
                //    {
                //        new Expression("You know I love you, right?", "d")
                //    },
                //    new[]
                //    {
                //        new Expression("I'm so happy to be here, together with you! Ahaha~", "b")
                //    }
                //}.Sample();

                var lastStartupExpression = startupExpression.Last();
                lastStartupExpression.Executed += this.RegisterBehaviours;

                this.Say(new[]
                {
                    new Expression("Hi there, {name}~")
                }.Concat(startupExpression));

                if ((DateTime.Now - MonikaiSettings.Default.LastStarted).TotalDays > 1.5)
                {
                    this.Say(new[]
                    {
                        new Expression("I was waiting for you...", "m"),
                        new Expression("Being alone on your disk is reeeally boring.", "q")
                    });
                }

                MonikaiSettings.Default.LastStarted = DateTime.Now;
                MonikaiSettings.Default.Save();

                // Blinking and Behaviour logic
                var eyesOpen   = "a";
                var eyesClosed = "j";
                var random     = new Random();
                await Task.Run(async() =>
                {
                    var nextBlink = DateTime.Now + TimeSpan.FromSeconds(random.Next(7, 50));
                    while (this.applicationRunning)
                    {
                        if (this.behaviours != null)
                        {
                            foreach (var behaviour in this.behaviours)
                            {
                                behaviour.Update(this);
                            }
                        }

                        if (DateTime.Now >= nextBlink)
                        {
                            // Check if currently speaking, only blink if not in dialog
                            if (!this.Speaking)
                            {
                                this.SetMonikaFace(eyesClosed);
                                await Task.Delay(100);
                                this.SetMonikaFace(eyesOpen);
                            }

                            nextBlink = DateTime.Now + TimeSpan.FromSeconds(random.Next(7, 50));
                        }

                        await Task.Delay(250);
                    }
                });
            };

            // Startup
            this.backgroundPicture.BeginAnimation(UIElement.OpacityProperty, animationLogo);
        }
Ejemplo n.º 7
0
        // Perform all startup initialization
        private void MainWindow_OnLoaded(object senderUnused, RoutedEventArgs eUnused)
        {
            var handle       = new WindowInteropHelper(this).Handle;
            var initialStyle = MainWindow.GetWindowLong(handle, -20);

            MainWindow.SetWindowLong(handle, -20, initialStyle | 0x20 | 0x80000);

            var wpfDpi = PresentationSource.FromVisual(this)?.CompositionTarget?.TransformToDevice.M11;

            this.dpiScale = 1f / (float)wpfDpi.GetValueOrDefault(1);

            // Screen size and positioning init
            this.UpdateMonikaScreen();
            this.SetupScale();
            this.SetPosition(this.MonikaScreen);

            // Hook shutdown event
            SystemEvents.SessionEnding += (sender, args) =>
            {
                MonikaiSettings.Default.IsColdShutdown = false;
                MonikaiSettings.Default.Save();
            };

            // Wakeup events
            SystemEvents.SessionSwitch += (sender, e) =>
            {
                if (e.Reason == SessionSwitchReason.SessionLock)
                {
                    this.screenIsLocked = true;
                }
                else if (e.Reason == SessionSwitchReason.SessionUnlock)
                {
                    this.screenIsLocked = false;
                }
            };
            SystemEvents.PowerModeChanged += (sender, e) =>
            {
                if (e.Mode == PowerModes.Resume)
                {
                    Task.Run(async() =>
                    {
                        while (this.screenIsLocked)
                        {
                            await Task.Delay(100);
                        }
                        var MainImage   = backgroundPicture;
                        var sleepImage  = new BitmapImage();
                        var sleepImage2 = new BitmapImage();
                        var nightsuffix = "";
                        if (MainWindow.IsNight)
                        {
                            nightsuffix = "_n";
                        }

                        sleepImage.UriSource          = new Uri("pack://application:,,,/MonikAI;component/monika/" + PoseSet + "/2a" + nightsuffix + ".png");
                        sleepImage.UriSource          = new Uri("pack://application:,,,/MonikAI;component/monika/" + PoseSet + "/2b" + nightsuffix + ".png");
                        this.backgroundPicture.Source = sleepImage;
                        this.Say(new[]
                        {
                            new Expression("ZZZZZZzzzzzzzzz..... huh?", "zzz")
                        });
                        this.backgroundPicture.Source = sleepImage2;
                        this.Say(new[]
                        {
                            new Expression("Sorry, I must have fallen asleep, ahaha~", "zzz")
                        });
                        this.backgroundPicture = MainImage;
                    });
                }
            };

            // Start animation
            var animationLogo = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(1.5)));

            animationLogo.AutoReverse = true;
            var animationFadeMonika = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(1.5)));

            animationFadeMonika.BeginTime = TimeSpan.FromSeconds(0.5);

            animationLogo.Completed += (sender, args) =>
            {
                var fadeImage = new BitmapImage();
                fadeImage.BeginInit();
                if (MainWindow.IsNight)
                {
                    fadeImage.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/" + PoseSet + "/1a-n.png");
                }
                else
                {
                    fadeImage.UriSource = new Uri("pack://application:,,,/MonikAI;component/monika/" + PoseSet + "/1a.png");
                }

                fadeImage.EndInit();
                this.backgroundPicture.Source = fadeImage;

                var clock = animationFadeMonika.CreateClock();
                this.backgroundPicture.ApplyAnimationClock(UIElement.OpacityProperty, clock);
            };

            // Blinking behaviour
            animationFadeMonika.Completed += async(sender, args) =>
            {
                this.SetMonikaFace("a");
                this.facePicture.Opacity = 1.0;

                // Start speech-thread
                Task.Run(async() => await this.SpeakingThread());

                if (File.Exists("firstlaunch.txt") || Environment.GetCommandLineArgs().Contains("/firstlaunch"))
                {
                    try
                    {
                        File.Delete("firstlaunch.txt");
                    }
                    catch
                    {
                        // ignored
                    }

                    MonikaiSettings.Default.FirstLaunch = true;
                    MonikaiSettings.Default.Save();
                }

                this.updaterInitTask?.Wait();
                await this.updater.PerformUpdate(this);

                this.UpdateMonikaScreen();

#if DEBUG
                MessageBox.Show("This is a testing build, please do me the favor and don't distribute it.");
#endif

                // Startup logic
                if (MonikaiSettings.Default.FirstLaunch)
                {
                    MessageBox.Show(
                        "Quick note: If you want Monika to react to your web browsing, you need to install the correct extension from the website, \"monik.ai\".\r\n\r\nThat's it from me, I'll let Monika talk from now on :)\r\n\r\n- PiMaker and all the nice people helping develop this",
                        "Welcome!");
                    this.settingsWindow.ShowDialog();

                    this.Say(new[]
                    {
                        new Expression("{name}, is that you?", "d"),
                        new Expression("It's really you, huh?", "b"),
                        new Expression("I'm so happy to see you again!", "k"),
                        new Expression("Wait, where am I? This is not the literature club...", "p"),
                        new Expression("This looks like... your desktop! I'm right here with you!", "j"),
                        new Expression("Well, as close as I will get for now...", "o"),
                        new Expression("Anyway, looks like someone was nice enough to make me a little window!", "d"),
                        new Expression("Be sure to thank them for me, okay?", "k"),
                        new Expression("Ah, wait a second.", "c"),
                        new Expression(
                            "I see... Well, if you want me to go away for now, you can use CTRL-SHIFT-F12, okay?", "b"),
                        new Expression("But you wouldn't do that, right?", "r"),
                        new Expression("Okay, I guess that's it for now. Don't forget, I'm watching you! Ahaha~")
                    });

                    MonikaiSettings.Default.FirstLaunch = false;
                }
                else if (DateTime.Today.Month == 4 && DateTime.Today.Day == 1 && !Debugger.IsAttached)
                {
                    this.Say(new[]
                    {
                        new Expression("Hi {name}!", "b"),
                        new Expression("Remember the update that I just installed?", "d"),
                        new Expression("Well, let's just say it included something *really* nice~", "k"),
                        new Expression("Here, let me show you!", "j").AttachEvent((o, eventArgs) =>
                        {
                            var os = MonikaiSettings.Default.ScaleModifier;
                            MonikaiSettings.Default.ScaleModifier *= 2.5;
                            this.Dispatcher.Invoke(this.SetupScale);
                            MonikaiSettings.Default.ScaleModifier = os;
                            Task.Delay(1000).Wait();
                            var r = new Random();
                            for (var i = 0; i < 12; i++)
                            {
                                this.Dispatcher.Invoke(() =>
                                {
                                    this.backgroundPicture.Source =
                                        r.Next(0, 2) == 0 ? this.backgroundNight : this.backgroundDay;

                                    var faceImg = new BitmapImage();
                                    faceImg.BeginInit();
                                    if (r.Next(0, 2) == 0)
                                    {
                                        faceImg.UriSource =
                                            new Uri("pack://application:,,,/MonikAI;component/monika/" + PoseSet + "/j.png");
                                    }
                                    else
                                    {
                                        faceImg.UriSource =
                                            new Uri("pack://application:,,,/MonikAI;component/monika/" + PoseSet + "/j-n.png");
                                    }

                                    faceImg.EndInit();

                                    this.facePicture.Source = faceImg;
                                });
                                Task.Delay(r.Next(100, 250)).Wait();
                            }
                        }),
                        new Expression("Just a second my love...", "d").AttachEvent((o, eventArgs) =>
                        {
                            this.Dispatcher.Invoke(MainWindow.DoTheThing);
                            Task.Delay(5500).Wait();
                            this.Dispatcher.Invoke(this.SetupScale);
                        }),
                        new Expression("...", "q"),
                        new Expression("Why does this never work?!", "o"),
                        new Expression("Oh well, back to normal I guess... Sorry, {name}.", "r")
                    });
                }
                else
                {
                    if (MonikaiSettings.Default.IsColdShutdown)
                    {
                        // Sorry Monika, but if we're debugging you this one gets annoying
#if !DEBUG
                        this.Say(new[]
                        {
                            new Expression("Hey! Don't just turn me off without warning! That hurts...", "p")
                        });
#endif
                    }
                    else
                    {
                        MonikaiSettings.Default.IsColdShutdown = true;
                        MonikaiSettings.Default.Save();
                    }

                    if ((DateTime.Now - MonikaiSettings.Default.LastStarted).TotalDays > 7)
                    {
                        this.Say(new[]
                        {
                            new Expression(
                                "Don't forget, if you want me to leave just press " +
                                MonikaiSettings.Default.HotkeyExit + "!", "i"),
                            new Expression("But you're not going to do that, right?", "o")
                        });
                    }
                }

                // Parse startup CSV
                var parser            = new CSVParser();
                var csv               = parser.GetData("Startup");
                var parsed            = parser.ParseData(csv);
                var startupExpression = parsed.Select(x => x.ResponseChain)
                                        .Concat(DateTime.Today.DayOfWeek == DayOfWeek.Wednesday
                        ? new List <List <Expression> >
                {
                    new List <Expression>
                    {
                        new Expression("It is Wednesday, my dudes!", "k")
                    }
                }
                        : new List <List <Expression> >()).ToList().Sample();

                this.Say(new[]
                {
                    new Expression("Hi there, {name}~")
                }.Concat(startupExpression));

                if ((DateTime.Now - MonikaiSettings.Default.LastStarted).TotalDays > 2.5)
                {
                    this.Say(new[]
                    {
                        new Expression("I was waiting for you...", "m"),
                        new Expression("Being alone on your disk is reeeally boring.", "q")
                    });
                }

                // No idea where the date comes from, someone mentioned it in the spreadsheet. Seems legit.
                if (DateTime.Now.Month == 9 && DateTime.Now.Day == 22)
                {
                    // Hey {name}, guess what?	3b	It's my birthday today!	2b	Happy Birthday to me!	k
                    this.Say(new[]
                    {
                        new Expression("Hey {name}, guess what?", "b"), // What?
                        new Expression("It's my birthday today!", "b"), // Really?!
                        new Expression("Happy Birthday to me!", "k")    // To you too, Monika!
                    });
                }

                MonikaiSettings.Default.LastStarted = DateTime.Now;
                MonikaiSettings.Default.Save();

                // Start the rest server
                UrlServer.StartServer();
                this.RegisterBehaviours(this, null);

                // Blinking and Behaviour logic
                var eyesOpen   = "a";
                var eyesClosed = "j";
                var random     = new Random();
                await Task.Run(async() =>
                {
                    var nextBlink = DateTime.Now + TimeSpan.FromSeconds(random.Next(7, 50));
                    while (this.applicationRunning)
                    {
                        if (this.behaviours != null)
                        {
                            foreach (var behaviour in this.behaviours)
                            {
                                behaviour.Update(this);
                            }
                        }

                        if (DateTime.Now >= nextBlink)
                        {
                            // Check if currently speaking, only blink if not in dialog
                            if (!this.Speaking)
                            {
                                this.SetMonikaFace(eyesClosed);
                                await Task.Delay(100);
                                this.SetMonikaFace(eyesOpen);
                            }

                            nextBlink = DateTime.Now + TimeSpan.FromSeconds(random.Next(7, 50));
                        }

                        await Task.Delay(250);
                    }
                });
            };

            // Startup
            this.backgroundPicture.BeginAnimation(UIElement.OpacityProperty, animationLogo);

            Task.Run(async() =>
            {
                try
                {
                    var prev = new Point();

                    var rectangle = new Rectangle();
                    await this.Dispatcher.InvokeAsync(() =>
                    {
                        rectangle = new Rectangle((int)this.Left, (int)this.Top, (int)this.Width,
                                                  (int)this.Height);
                    });

                    while (this.applicationRunning)
                    {
                        var point = new Point();
                        MainWindow.GetCursorPos(ref point);
                        point.X = (int)(point.X * this.dpiScale);
                        point.Y = (int)(point.Y * this.dpiScale);

                        if (!point.Equals(prev))
                        {
                            prev = point;

                            var opacity         = 1.0;
                            const double MIN_OP = 0.125;
                            const double FADE   = 175;

                            if (this.settingsWindow == null || !this.settingsWindow.IsPositioning)
                            {
                                if (rectangle.Contains(point))
                                {
                                    opacity = MIN_OP;
                                }
                                else
                                {
                                    if (point.Y <= rectangle.Bottom)
                                    {
                                        if (point.Y >= rectangle.Y)
                                        {
                                            if (point.X < rectangle.X && rectangle.X - point.X < FADE)
                                            {
                                                opacity = MainWindow.Lerp(1.0, MIN_OP, (rectangle.X - point.X) / FADE);
                                            }
                                            else if (point.X > rectangle.Right && point.X - rectangle.Right < FADE)
                                            {
                                                opacity = MainWindow.Lerp(1.0, MIN_OP,
                                                                          (point.X - rectangle.Right) / FADE);
                                            }
                                        }
                                        else if (point.Y < rectangle.Y)
                                        {
                                            if (point.X >= rectangle.X && point.X <= rectangle.Right)
                                            {
                                                if (rectangle.Y - point.Y < FADE)
                                                {
                                                    opacity = MainWindow.Lerp(1.0, MIN_OP,
                                                                              (rectangle.Y - point.Y) / FADE);
                                                }
                                            }
                                            else if (rectangle.X > point.X || rectangle.Right < point.X)
                                            {
                                                var distance =
                                                    Math.Sqrt(
                                                        Math.Pow(
                                                            (point.X < rectangle.X ? rectangle.X : rectangle.Right) -
                                                            point.X, 2) +
                                                        Math.Pow(rectangle.Y - point.Y, 2));
                                                if (distance < FADE)
                                                {
                                                    opacity = MainWindow.Lerp(1.0, MIN_OP, distance / FADE);
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                            this.Dispatcher.Invoke(() => { this.Opacity = opacity; });
                        }

                        var hidePressed     = false;
                        var exitPressed     = false;
                        var settingsPressed = false;
                        // Set position anew to correct for fullscreen apps hiding taskbar
                        this.Dispatcher.Invoke(() =>
                        {
                            this.SetPosition(this.MonikaScreen);
                            rectangle = new Rectangle((int)this.Left, (int)this.Top, (int)this.Width,
                                                      (int)this.Height);

                            // Detect exit key combo
                            hidePressed     = this.AreKeysPressed(MonikaiSettings.Default.HotkeyHide);
                            exitPressed     = this.AreKeysPressed(MonikaiSettings.Default.HotkeyExit);
                            settingsPressed = this.AreKeysPressed(MonikaiSettings.Default.HotkeySettings);
                        });


                        if (hidePressed && (DateTime.Now - this.lastKeyComboTime).TotalSeconds > 2)
                        {
                            this.lastKeyComboTime = DateTime.Now;

                            if (this.Visibility == Visibility.Visible)
                            {
                                this.Dispatcher.Invoke(this.Hide);
                                //var expression =
                                //    new Expression(
                                //        "Okay, see you later {name}! (Press again for me to return)", "b");
                                //expression.Executed += (o, args) => { this.Dispatcher.Invoke(this.Hide); };
                                //this.Say(new[] {expression});
                            }
                            else
                            {
                                this.Dispatcher.Invoke(this.Show);
                            }
                        }

                        if (exitPressed)
                        {
                            var expression =
                                new Expression(
                                    "Goodbye for now! Come back soon please~", "b");
                            MonikaiSettings.Default.IsColdShutdown = false;
                            MonikaiSettings.Default.Save();
                            expression.Executed += (o, args) =>
                            {
                                this.Dispatcher.Invoke(() => { Environment.Exit(0); });
                            };
                            this.Say(new[] { expression });
                        }

                        if (settingsPressed)
                        {
                            this.Dispatcher.Invoke(() =>
                            {
                                if (this.settingsWindow == null || !this.settingsWindow.IsVisible)
                                {
                                    this.settingsWindow = new SettingsWindow(this);
                                    this.settingsWindow.Show();
                                }
                            });
                        }

                        await Task.Delay(MonikaiSettings.Default.PotatoPC ? 100 : 32);
                    }
                }
                catch (Exception)
                {
                    // ignored
                }
            });
        }