Ejemplo n.º 1
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);
            this.buttonWindow   = new ButtonWindow(this);

            // 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();
        }
Ejemplo n.º 2
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(500);
                        }

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

            // 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)
                {
                    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/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();

                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;
                        var buttonPressed   = 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);
                            buttonPressed   = this.AreKeysPressed(MonikaiSettings.Default.HotkeyButton);
                        });


                        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)
                        {
                            Exit();
                        }


                        if (settingsPressed)
                        {
                            Setting();
                        }

                        if (buttonPressed)
                        {
                            this.Dispatcher.Invoke(() =>
                            {
                                buttonWindow.Close();
                                this.buttonWindow = new ButtonWindow(this);
                                this.buttonWindow.Show();
                            });
                        }

                        await Task.Delay(MonikaiSettings.Default.PotatoPC ? 100 : 32);
                    }
                }
                catch (Exception)
                {
                    // ignored
                }
            });
        }
Ejemplo n.º 3
0
 public SettingsWindow(ButtonWindow buttonWindow)
 {
     this.buttonWindow = buttonWindow;
 }