From 0a120f6ff28c8fc7ee75e81b00cdb2ff78cfac1c Mon Sep 17 00:00:00 2001 From: katu07 Date: Wed, 13 Jan 2016 15:12:35 -0700 Subject: [PATCH] Support for all languages! (letters and numbers). Shapes and colors supported for Russian. Upgraded to .NET 4.6.1. --- BabySmash.csproj | 49 +- BabySmash.sln | 8 +- Controller.cs | 983 +++++++++++++++++-------------- Extensions/ObjectExtensions.cs | 71 +++ MainWindow.xaml.cs | 12 +- Properties/Resources.Designer.cs | 2 +- Properties/Settings.Designer.cs | 10 +- Resources/Strings/en-EN.json | 21 + Resources/Strings/ru-RU.json | 21 + Shapes/BabySmashShape.cs | 15 + Shapes/FigureGenerator.cs | 155 ++--- app.config | 2 +- packages.config | 4 + 13 files changed, 826 insertions(+), 527 deletions(-) create mode 100644 Extensions/ObjectExtensions.cs create mode 100644 Resources/Strings/en-EN.json create mode 100644 Resources/Strings/ru-RU.json create mode 100644 Shapes/BabySmashShape.cs create mode 100644 packages.config diff --git a/BabySmash.csproj b/BabySmash.csproj index 9e52b32..2029182 100644 --- a/BabySmash.csproj +++ b/BabySmash.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,14 +10,14 @@ Properties BabySmash BabySmash - v3.5 + v4.6.1 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 E4355A6B46BE61300D217B56C346651E03BEB47F private.pfx true - true + false false App.ico @@ -56,6 +56,7 @@ 4 x86 AllRules.ruleset + false pdbonly @@ -65,9 +66,34 @@ prompt 4 AllRules.ruleset + false + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + AllRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + AllRules.ruleset + + + + packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll + True + 3.0 @@ -78,9 +104,10 @@ - 3.0 + ..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Speech.dll + 3.5 @@ -275,14 +302,23 @@ Resources.Designer.cs Designer - + + Designer + + SettingsSingleFileGenerator Settings.Designer.cs + + Always + + + Always + @@ -360,9 +396,8 @@ --> - - + \ No newline at end of file diff --git a/BabySmash.sln b/BabySmash.sln index 6bb4042..8e3c5ab 100644 --- a/BabySmash.sln +++ b/BabySmash.sln @@ -1,20 +1,26 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BabySmash", "BabySmash.csproj", "{FB378E07-FDE4-4FC7-9210-68F80B561164}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {FB378E07-FDE4-4FC7-9210-68F80B561164}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FB378E07-FDE4-4FC7-9210-68F80B561164}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB378E07-FDE4-4FC7-9210-68F80B561164}.Debug|x64.ActiveCfg = Debug|x64 + {FB378E07-FDE4-4FC7-9210-68F80B561164}.Debug|x64.Build.0 = Debug|x64 {FB378E07-FDE4-4FC7-9210-68F80B561164}.Release|Any CPU.ActiveCfg = Release|Any CPU {FB378E07-FDE4-4FC7-9210-68F80B561164}.Release|Any CPU.Build.0 = Release|Any CPU + {FB378E07-FDE4-4FC7-9210-68F80B561164}.Release|x64.ActiveCfg = Release|x64 + {FB378E07-FDE4-4FC7-9210-68F80B561164}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Controller.cs b/Controller.cs index a4a4fcf..4b6fdd7 100644 --- a/Controller.cs +++ b/Controller.cs @@ -5,7 +5,6 @@ using System.Deployment.Application; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; -using System.Speech.Synthesis; using System.Threading; using System.Windows; using System.Windows.Controls; @@ -22,498 +21,622 @@ using WinForms = System.Windows.Forms; namespace BabySmash { - public class Controller - { - [DllImport("user32.dll")] - private static extern IntPtr SetFocus(IntPtr hWnd); + using System.Globalization; + using System.IO; + using System.Speech.Synthesis; + using System.Text; - [DllImport("user32.dll")] - private static extern bool SetForegroundWindow(IntPtr hWnd); + using Newtonsoft.Json; - private static Controller instance = new Controller(); - - public bool isOptionsDialogShown { get; set; } - private bool isDrawing = false; - private readonly SpeechSynthesizer objSpeech = new SpeechSynthesizer(); - private readonly List windows = new List(); + public class Controller + { + [DllImport("user32.dll")] + private static extern IntPtr SetFocus(IntPtr hWnd); - private DispatcherTimer timer = new DispatcherTimer(); - private Queue ellipsesQueue = new Queue(); - private Dictionary> figuresUserControlQueue = new Dictionary>(); - private ApplicationDeployment deployment = null; - private WordFinder wordFinder = new WordFinder("Words.txt"); + [DllImport("user32.dll")] + private static extern bool SetForegroundWindow(IntPtr hWnd); - /// Prevents a default instance of the Controller class from being created. - private Controller() { } + private static Controller instance = new Controller(); - public static Controller Instance - { - get { return instance; } - } + public bool isOptionsDialogShown { get; set; } + private bool isDrawing = false; + private readonly SpeechSynthesizer objSpeech = new SpeechSynthesizer(); + private readonly List windows = new List(); - void deployment_CheckForUpdateCompleted(object sender, CheckForUpdateCompletedEventArgs e) - { - if (e.Error == null && e.UpdateAvailable) - { - try - { - MainWindow w = this.windows[0]; - w.updateProgress.Value = 0; - w.UpdateAvailableLabel.Visibility = Visibility.Visible; + private DispatcherTimer timer = new DispatcherTimer(); + private Queue ellipsesQueue = new Queue(); + private Dictionary> figuresUserControlQueue = new Dictionary>(); + private ApplicationDeployment deployment = null; + private WordFinder wordFinder = new WordFinder("Words.txt"); - deployment.UpdateAsync(); - } - catch (InvalidOperationException ex) - { - Debug.WriteLine(ex.ToString()); - MainWindow w = this.windows[0]; - w.UpdateAvailableLabel.Visibility = Visibility.Hidden; - } - } - } + /// Prevents a default instance of the Controller class from being created. + private Controller() { } - void deployment_UpdateProgressChanged(object sender, DeploymentProgressChangedEventArgs e) - { - MainWindow w = this.windows[0]; - w.updateProgress.Value = e.ProgressPercentage; - } + public static Controller Instance + { + get { return instance; } + } - void deployment_UpdateCompleted(object sender, AsyncCompletedEventArgs e) - { - if (e.Error != null) - { - Debug.WriteLine(e.ToString()); - return; - } - MainWindow w = this.windows[0]; - w.UpdateAvailableLabel.Visibility = Visibility.Hidden; - } + void deployment_CheckForUpdateCompleted(object sender, CheckForUpdateCompletedEventArgs e) + { + if (e.Error == null && e.UpdateAvailable) + { + try + { + MainWindow w = this.windows[0]; + w.updateProgress.Value = 0; + w.UpdateAvailableLabel.Visibility = Visibility.Visible; - public void Launch() - { - timer.Tick += new EventHandler(timer_Tick); - timer.Interval = new TimeSpan(0, 0, 1); - int Number = 0; + deployment.UpdateAsync(); + } + catch (InvalidOperationException ex) + { + Debug.WriteLine(ex.ToString()); + MainWindow w = this.windows[0]; + w.UpdateAvailableLabel.Visibility = Visibility.Hidden; + } + } + } - if (ApplicationDeployment.IsNetworkDeployed) - { - deployment = ApplicationDeployment.CurrentDeployment; - deployment.UpdateCompleted += new System.ComponentModel.AsyncCompletedEventHandler(deployment_UpdateCompleted); - deployment.UpdateProgressChanged += deployment_UpdateProgressChanged; - deployment.CheckForUpdateCompleted += deployment_CheckForUpdateCompleted; - try - { - deployment.CheckForUpdateAsync(); - } - catch (InvalidOperationException e) - { - Debug.WriteLine(e.ToString()); - } - } + void deployment_UpdateProgressChanged(object sender, DeploymentProgressChangedEventArgs e) + { + MainWindow w = this.windows[0]; + w.updateProgress.Value = e.ProgressPercentage; + } - foreach (WinForms.Screen s in WinForms.Screen.AllScreens) - { - MainWindow m = new MainWindow(this) - { - WindowStartupLocation = WindowStartupLocation.Manual, - Left = s.WorkingArea.Left, - Top = s.WorkingArea.Top, - Width = s.WorkingArea.Width, - Height = s.WorkingArea.Height, - WindowStyle = WindowStyle.None, - Topmost = true, - AllowsTransparency = Settings.Default.TransparentBackground, - Background = (Settings.Default.TransparentBackground ? new SolidColorBrush(Color.FromArgb(1, 0, 0, 0)) : Brushes.WhiteSmoke), - Name = "Window" + Number++.ToString() - }; + void deployment_UpdateCompleted(object sender, AsyncCompletedEventArgs e) + { + if (e.Error != null) + { + Debug.WriteLine(e.ToString()); + return; + } + MainWindow w = this.windows[0]; + w.UpdateAvailableLabel.Visibility = Visibility.Hidden; + } - figuresUserControlQueue[m.Name] = new List(); + public void Launch() + { + timer.Tick += new EventHandler(timer_Tick); + timer.Interval = new TimeSpan(0, 0, 1); + int Number = 0; - m.Show(); - m.MouseLeftButtonDown += HandleMouseLeftButtonDown; - m.MouseWheel += HandleMouseWheel; - m.WindowState = WindowState.Maximized; - windows.Add(m); - } + if (ApplicationDeployment.IsNetworkDeployed) + { + deployment = ApplicationDeployment.CurrentDeployment; + deployment.UpdateCompleted += new System.ComponentModel.AsyncCompletedEventHandler(deployment_UpdateCompleted); + deployment.UpdateProgressChanged += deployment_UpdateProgressChanged; + deployment.CheckForUpdateCompleted += deployment_CheckForUpdateCompleted; + try + { + deployment.CheckForUpdateAsync(); + } + catch (InvalidOperationException e) + { + Debug.WriteLine(e.ToString()); + } + } - //Only show the info label on the FIRST monitor. - windows[0].infoLabel.Visibility = Visibility.Visible; + foreach (WinForms.Screen s in WinForms.Screen.AllScreens) + { + MainWindow m = new MainWindow(this) + { + WindowStartupLocation = WindowStartupLocation.Manual, + Left = s.WorkingArea.Left, + Top = s.WorkingArea.Top, + Width = s.WorkingArea.Width, + Height = s.WorkingArea.Height, + WindowStyle = WindowStyle.None, + Topmost = true, + AllowsTransparency = Settings.Default.TransparentBackground, + Background = (Settings.Default.TransparentBackground ? new SolidColorBrush(Color.FromArgb(1, 0, 0, 0)) : Brushes.WhiteSmoke), + Name = "Window" + Number++.ToString() + }; - //Startup sound - Win32Audio.PlayWavResourceYield("EditedJackPlaysBabySmash.wav"); + figuresUserControlQueue[m.Name] = new List(); - string[] args = Environment.GetCommandLineArgs(); - string ext = System.IO.Path.GetExtension(System.Reflection.Assembly.GetExecutingAssembly().CodeBase); + m.Show(); + m.MouseLeftButtonDown += HandleMouseLeftButtonDown; + m.MouseWheel += HandleMouseWheel; + m.WindowState = WindowState.Maximized; + windows.Add(m); + } - if (ApplicationDeployment.IsNetworkDeployed && (ApplicationDeployment.CurrentDeployment.IsFirstRun || ApplicationDeployment.CurrentDeployment.UpdatedVersion != ApplicationDeployment.CurrentDeployment.CurrentVersion)) - { - //if someone made us a screensaver, then don't show the options dialog. - if ((args != null && args[0] != "/s") && String.CompareOrdinal(ext, ".SCR") != 0) - { - ShowOptionsDialog(); - } - } + //Only show the info label on the FIRST monitor. + windows[0].infoLabel.Visibility = Visibility.Visible; + + //Startup sound + Win32Audio.PlayWavResourceYield("EditedJackPlaysBabySmash.wav"); + + string[] args = Environment.GetCommandLineArgs(); + string ext = System.IO.Path.GetExtension(System.Reflection.Assembly.GetExecutingAssembly().CodeBase); + + if (ApplicationDeployment.IsNetworkDeployed && (ApplicationDeployment.CurrentDeployment.IsFirstRun || ApplicationDeployment.CurrentDeployment.UpdatedVersion != ApplicationDeployment.CurrentDeployment.CurrentVersion)) + { + //if someone made us a screensaver, then don't show the options dialog. + if ((args != null && args[0] != "/s") && String.CompareOrdinal(ext, ".SCR") != 0) + { + ShowOptionsDialog(); + } + } #if !false - timer.Start(); + timer.Start(); #endif - } + } - void timer_Tick(object sender, EventArgs e) - { - if (isOptionsDialogShown) - { - return; - } + void timer_Tick(object sender, EventArgs e) + { + if (isOptionsDialogShown) + { + return; + } - try - { - IntPtr windowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle; - SetForegroundWindow(windowHandle); - SetFocus(windowHandle); - } - catch (Exception) - { - //Wish me luck! - } - } + try + { + IntPtr windowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle; + SetForegroundWindow(windowHandle); + SetFocus(windowHandle); + } + catch (Exception) + { + //Wish me luck! + } + } - public void ProcessKey(FrameworkElement uie, KeyEventArgs e) - { - bool Alt = (Keyboard.Modifiers & ModifierKeys.Alt) != 0; - bool Control = (Keyboard.Modifiers & ModifierKeys.Control) != 0; - bool Shift = (Keyboard.Modifiers & ModifierKeys.Shift) != 0; + public void ProcessKey(FrameworkElement uie, KeyEventArgs e) + { + bool Alt = (Keyboard.Modifiers & ModifierKeys.Alt) != 0; + bool Control = (Keyboard.Modifiers & ModifierKeys.Control) != 0; + bool Shift = (Keyboard.Modifiers & ModifierKeys.Shift) != 0; - if (uie.IsMouseCaptured) - { - uie.ReleaseMouseCapture(); - } + if (uie.IsMouseCaptured) + { + uie.ReleaseMouseCapture(); + } - //TODO: Might be able to remove this: http://www.ageektrapped.com/blog/using-commands-in-babysmash/ - if (Alt && Control && Shift && e.Key == Key.O) - { - ShowOptionsDialog(); - e.Handled = true; - return; - } + //TODO: Might be able to remove this: http://www.ageektrapped.com/blog/using-commands-in-babysmash/ + if (Alt && Control && Shift && e.Key == Key.O) + { + ShowOptionsDialog(); + e.Handled = true; + return; + } - char displayChar = GetDisplayChar(e.Key); - AddFigure(uie, displayChar); - } + char displayChar = GetDisplayChar(e.Key); + AddFigure(uie, displayChar); + } - private char GetDisplayChar(Key key) - { - // If a letter was pressed, display the letter. - if (key >= Key.A && key <= Key.Z) - { - return (char)('A' + key - Key.A); - } + private char GetDisplayChar(Key key) + { + // If a number on the normal number track is pressed, display the number. + if (key >= Key.D0 && key <= Key.D9) + { + return (char)('0' + key - Key.D0); + } - // If a number on the normal number track is pressed, display the number. - if (key >= Key.D0 && key <= Key.D9) - { - return (char)('0' + key - Key.D0); - } + // If a number on the numpad is pressed, display the number. + if (key >= Key.NumPad0 && key <= Key.NumPad9) + { + return (char)('0' + key - Key.NumPad0); + } - // If a number on the numpad is pressed, display the number. - if (key >= Key.NumPad0 && key <= Key.NumPad9) - { - return (char)('0' + key - Key.NumPad0); - } + try + { + return char.ToUpperInvariant(TryGetLetter(key)); + } + catch (Exception ex) + { + Debug.Assert(false, ex.ToString()); + return '*'; + } + } - // Otherwise, display a random shape. - return '*'; - } + public enum MapType : uint + { + MAPVK_VK_TO_VSC = 0x0, + MAPVK_VSC_TO_VK = 0x1, + MAPVK_VK_TO_CHAR = 0x2, + MAPVK_VSC_TO_VK_EX = 0x3, + } - private void AddFigure(FrameworkElement uie, char c) - { - FigureTemplate template = FigureGenerator.GenerateFigureTemplate(c); - foreach (MainWindow window in this.windows) - { - UserControl f = FigureGenerator.NewUserControlFrom(template); - window.AddFigure(f); + [DllImport("user32.dll")] + public static extern int ToUnicode( + uint wVirtKey, + uint wScanCode, + byte[] lpKeyState, + [Out, MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 4)] + StringBuilder pwszBuff, + int cchBuff, + uint wFlags); - var queue = figuresUserControlQueue[window.Name]; - queue.Add(f); + [DllImport("user32.dll")] + public static extern bool GetKeyboardState(byte[] lpKeyState); - // Letters should already have accurate width and height, but others may them assigned. - if (double.IsNaN(f.Width) || double.IsNaN(f.Height)) - { - f.Width = 300; - f.Height = 300; - } + [DllImport("user32.dll")] + public static extern uint MapVirtualKey(uint uCode, MapType uMapType); - Canvas.SetLeft(f, Utils.RandomBetweenTwoNumbers(0, Convert.ToInt32(window.ActualWidth - f.Width))); - Canvas.SetTop(f, Utils.RandomBetweenTwoNumbers(0, Convert.ToInt32(window.ActualHeight - f.Height))); + private static char TryGetLetter(Key key) + { + char ch = ' '; - Storyboard storyboard = Animation.CreateDPAnimation(uie, f, - UIElement.OpacityProperty, - new Duration(TimeSpan.FromSeconds(Settings.Default.FadeAfter)), 1, 0); - if (Settings.Default.FadeAway) storyboard.Begin(uie); + int virtualKey = KeyInterop.VirtualKeyFromKey(key); + byte[] keyboardState = new byte[256]; + GetKeyboardState(keyboardState); - IHasFace face = f as IHasFace; - if (face != null) - { - face.FaceVisible = Settings.Default.FacesOnShapes ? Visibility.Visible : Visibility.Hidden; - } + uint scanCode = MapVirtualKey((uint)virtualKey, MapType.MAPVK_VK_TO_VSC); + StringBuilder stringBuilder = new StringBuilder(2); - if (queue.Count > Settings.Default.ClearAfter) - { - window.RemoveFigure(queue[0]); - queue.RemoveAt(0); - } - } + int result = ToUnicode((uint)virtualKey, scanCode, keyboardState, stringBuilder, stringBuilder.Capacity, 0); + switch (result) + { + case -1: + break; + case 0: + break; + case 1: + { + ch = stringBuilder[0]; + break; + } + default: + { + ch = stringBuilder[0]; + break; + } + } + return ch; + } - // Find the last word typed, if applicable. - string lastWord = this.wordFinder.LastWord(figuresUserControlQueue.Values.First()); - if (lastWord != null) - { - foreach (MainWindow window in this.windows) - { - this.wordFinder.AnimateLettersIntoWord(figuresUserControlQueue[window.Name], lastWord); - } + private void AddFigure(FrameworkElement uie, char c) + { + FigureTemplate template = FigureGenerator.GenerateFigureTemplate(c); + foreach (MainWindow window in this.windows) + { + UserControl f = FigureGenerator.NewUserControlFrom(template); + window.AddFigure(f); - SpeakString(lastWord); - } - else - { - PlaySound(template); - } - } + var queue = figuresUserControlQueue[window.Name]; + queue.Add(f); - //private static DoubleAnimationUsingKeyFrames ApplyZoomOut(UserControl u) - //{ - // Tweener.TransitionType rt1 = Tweener.TransitionType.EaseOutExpo; - // var ani1 = Tweener.Tween.CreateAnimation(rt1, 1, 0, TimeSpan.FromSeconds(0.5)); - // u.RenderTransformOrigin = new Point(0.5, 0.5); - // var group = new TransformGroup(); - // u.RenderTransform = group; + // Letters should already have accurate width and height, but others may them assigned. + if (double.IsNaN(f.Width) || double.IsNaN(f.Height)) + { + f.Width = 300; + f.Height = 300; + } - // ani1.Completed += new EventHandler(ani1_Completed); + Canvas.SetLeft(f, Utils.RandomBetweenTwoNumbers(0, Convert.ToInt32(window.ActualWidth - f.Width))); + Canvas.SetTop(f, Utils.RandomBetweenTwoNumbers(0, Convert.ToInt32(window.ActualHeight - f.Height))); - // group.Children.Add(new ScaleTransform()); - // group.Children[0].BeginAnimation(ScaleTransform.ScaleXProperty, ani1); - // group.Children[0].BeginAnimation(ScaleTransform.ScaleYProperty, ani1); - // return ani1; - //} + Storyboard storyboard = Animation.CreateDPAnimation(uie, f, + UIElement.OpacityProperty, + new Duration(TimeSpan.FromSeconds(Settings.Default.FadeAfter)), 1, 0); + if (Settings.Default.FadeAway) storyboard.Begin(uie); - //static void ani1_Completed(object sender, EventArgs e) - //{ - // AnimationClock clock = sender as AnimationClock; - // Debug.Write(sender.ToString()); - // UserControl foo = sender as UserControl; - // UserControl toBeRemoved = queue.Dequeue() as UserControl; - // Canvas container = toBeRemoved.Parent as Canvas; - // container.Children.Remove(toBeRemoved); - //} + IHasFace face = f as IHasFace; + if (face != null) + { + face.FaceVisible = Settings.Default.FacesOnShapes ? Visibility.Visible : Visibility.Hidden; + } - void HandleMouseWheel(object sender, MouseWheelEventArgs e) - { - UserControl foo = sender as UserControl; //expected this on Sender! - if (foo != null) - { - if (e.Delta < 0) - { - Animation.ApplyZoom(foo, new Duration(TimeSpan.FromSeconds(0.5)), 2.5); - } - else - { - Animation.ApplyZoom(foo, new Duration(TimeSpan.FromSeconds(0.5)), 0.5); - } - } - } + if (queue.Count > Settings.Default.ClearAfter) + { + window.RemoveFigure(queue[0]); + queue.RemoveAt(0); + } + } - void HandleMouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - UserControl f = e.Source as UserControl; - if (f != null && f.Opacity > 0.1) //can it be seen? - { - isDrawing = true; //HACK: This is a cheat to stop the mouse draw action. - Animation.ApplyRandomAnimationEffect(f, Duration.Automatic); - PlayLaughter(); //Might be better to re-speak the name, color, etc. - } - } + // Find the last word typed, if applicable. + string lastWord = this.wordFinder.LastWord(figuresUserControlQueue.Values.First()); + if (lastWord != null) + { + foreach (MainWindow window in this.windows) + { + this.wordFinder.AnimateLettersIntoWord(figuresUserControlQueue[window.Name], lastWord); + } - public void PlaySound(FigureTemplate template) - { - if (Settings.Default.Sounds == "Laughter") - { - PlayLaughter(); - } - if (objSpeech != null && Settings.Default.Sounds == "Speech") - { - if (template.Letter != null && template.Letter.Length == 1 && Char.IsLetterOrDigit(template.Letter[0])) - { - SpeakString(template.Letter); - } - else - { - SpeakString(Utils.ColorToString(template.Color) + " " + template.Name); - } - } - } + SpeakString(lastWord); + } + else + { + PlaySound(template); + } + } - private void PlayLaughter() - { - Win32Audio.PlayWavResource(Utils.GetRandomSoundFile()); - } + //private static DoubleAnimationUsingKeyFrames ApplyZoomOut(UserControl u) + //{ + // Tweener.TransitionType rt1 = Tweener.TransitionType.EaseOutExpo; + // var ani1 = Tweener.Tween.CreateAnimation(rt1, 1, 0, TimeSpan.FromSeconds(0.5)); + // u.RenderTransformOrigin = new Point(0.5, 0.5); + // var group = new TransformGroup(); + // u.RenderTransform = group; - private void SpeakString(string s) - { - ThreadedSpeak ts = new ThreadedSpeak(s); - ts.Speak(); - } + // ani1.Completed += new EventHandler(ani1_Completed); - private class ThreadedSpeak - { - private string Word = null; - SpeechSynthesizer SpeechSynth = new SpeechSynthesizer(); - public ThreadedSpeak(string Word) - { - this.Word = Word; - SpeechSynth.Rate = -1; - SpeechSynth.Volume = 100; - } - public void Speak() - { - Thread oThread = new Thread(new ThreadStart(this.Start)); - oThread.Start(); - } - private void Start() - { - try - { - SpeechSynth.Speak(Word); - } - catch (Exception e) - { - System.Diagnostics.Trace.WriteLine(e.ToString()); - } - } - } + // group.Children.Add(new ScaleTransform()); + // group.Children[0].BeginAnimation(ScaleTransform.ScaleXProperty, ani1); + // group.Children[0].BeginAnimation(ScaleTransform.ScaleYProperty, ani1); + // return ani1; + //} - private void ShowOptionsDialog() - { - bool foo = Settings.Default.TransparentBackground; - isOptionsDialogShown = true; - var o = new Options(); - Mouse.Capture(null); - foreach (MainWindow m in this.windows) - { - m.Topmost = false; - } - o.Topmost = true; - o.Focus(); - o.ShowDialog(); - Debug.Write("test"); - foreach (MainWindow m in this.windows) - { - m.Topmost = true; - //m.ResetCanvas(); - } - isOptionsDialogShown = false; + //static void ani1_Completed(object sender, EventArgs e) + //{ + // AnimationClock clock = sender as AnimationClock; + // Debug.Write(sender.ToString()); + // UserControl foo = sender as UserControl; + // UserControl toBeRemoved = queue.Dequeue() as UserControl; + // Canvas container = toBeRemoved.Parent as Canvas; + // container.Children.Remove(toBeRemoved); + //} - if (foo != Settings.Default.TransparentBackground) - { - MessageBoxResult result = MessageBox.Show( - "You've changed the Window Transparency Option. We'll need to restart BabySmash! for you to see the change. Pressing YES will restart BabySmash!. Is that OK?", - "Need to Restart", MessageBoxButton.YesNo, MessageBoxImage.Question); - if (result == MessageBoxResult.Yes) - { - Application.Current.Shutdown(); - System.Windows.Forms.Application.Restart(); - } - } - } + void HandleMouseWheel(object sender, MouseWheelEventArgs e) + { + UserControl foo = sender as UserControl; //expected this on Sender! + if (foo != null) + { + if (e.Delta < 0) + { + Animation.ApplyZoom(foo, new Duration(TimeSpan.FromSeconds(0.5)), 2.5); + } + else + { + Animation.ApplyZoom(foo, new Duration(TimeSpan.FromSeconds(0.5)), 0.5); + } + } + } - public void MouseDown(MainWindow main, MouseButtonEventArgs e) - { - if (isDrawing || Settings.Default.MouseDraw) return; + void HandleMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + UserControl f = e.Source as UserControl; + if (f != null && f.Opacity > 0.1) //can it be seen? + { + isDrawing = true; //HACK: This is a cheat to stop the mouse draw action. + Animation.ApplyRandomAnimationEffect(f, Duration.Automatic); + PlayLaughter(); //Might be better to re-speak the name, color, etc. + } + } - // Create a new Ellipse object and add it to canvas. - Point ptCenter = e.GetPosition(main.mouseCursorCanvas); - MouseDraw(main, ptCenter); - isDrawing = true; - main.CaptureMouse(); + public void PlaySound(FigureTemplate template) + { + if (Settings.Default.Sounds == "Laughter") + { + PlayLaughter(); + } + if (objSpeech != null && Settings.Default.Sounds == "Speech") + { + if (template.Letter != null && template.Letter.Length == 1 && Char.IsLetterOrDigit(template.Letter[0])) + { + SpeakString(template.Letter); + } + else + { + SpeakString(GetLocalizedString(Utils.ColorToString(template.Color)) + " " + template.Name); + } + } + } - Win32Audio.PlayWavResource("smallbumblebee.wav"); - } + /// + /// Returns if value or culture is not found. + /// + public static string GetLocalizedString(string key) + { + CultureInfo keyboardLanguage = System.Windows.Forms.InputLanguage.CurrentInputLanguage.Culture; + string culture = keyboardLanguage.Name; + string path = $@"Resources\Strings\{culture}.json"; + string path2 = @"Resources\Strings\en-EN.json"; + string jsonConfig = null; + if (File.Exists(path)) + { + jsonConfig = File.ReadAllText(path); + } + else if (File.Exists(path2)) + { + jsonConfig = File.ReadAllText(path2); + } + + if (jsonConfig != null) + { + Dictionary config = JsonConvert.DeserializeObject>(jsonConfig); + if (config.ContainsKey(key)) + { + return config[key].ToString(); + } + } + else + { + System.Diagnostics.Debug.Assert(false, "No file"); + } - public void MouseWheel(MainWindow main, MouseWheelEventArgs e) - { - if (e.Delta > 0) - { - Win32Audio.PlayWavResourceYield("rising.wav"); - } - else - { - Win32Audio.PlayWavResourceYield("falling.wav"); - } - } + return key; + } - public void MouseUp(MainWindow main, MouseButtonEventArgs e) - { - isDrawing = false; - if (Settings.Default.MouseDraw) return; - main.ReleaseMouseCapture(); - } + private void PlayLaughter() + { + Win32Audio.PlayWavResource(Utils.GetRandomSoundFile()); + } - public void MouseMove(MainWindow main, MouseEventArgs e) - { - if (isOptionsDialogShown) - { - main.ReleaseMouseCapture(); - return; - } - if (Settings.Default.MouseDraw && main.IsMouseCaptured == false) - main.CaptureMouse(); + private void SpeakString(string s) + { + ThreadedSpeak ts = new ThreadedSpeak(s); + ts.Speak(); + } - if (isDrawing || Settings.Default.MouseDraw) - { - MouseDraw(main, e.GetPosition(main)); - } + private class ThreadedSpeak + { + private string Word = null; + SpeechSynthesizer SpeechSynth = new SpeechSynthesizer(); + public ThreadedSpeak(string Word) + { + this.Word = Word; + CultureInfo keyboardLanguage = System.Windows.Forms.InputLanguage.CurrentInputLanguage.Culture; + InstalledVoice neededVoice = this.SpeechSynth.GetInstalledVoices(keyboardLanguage).FirstOrDefault(); + if (neededVoice == null) + { + //http://superuser.com/questions/590779/how-to-install-more-voices-to-windows-speech + https://msdn.microsoft.com/en-us/library/windows.media.speechsynthesis.speechsynthesizer.voice.aspx + http://stackoverflow.com/questions/34776593/speechsynthesizer-selectvoice-fails-with-no-matching-voice-is-installed-or-th + this.Word = "Unsupported Language"; + } + else if (!neededVoice.Enabled) + { + this.Word = "Voice Disabled"; + } + else + { + try + { + this.SpeechSynth.SelectVoice(neededVoice.VoiceInfo.Name); + } + catch (Exception ex) + { + Debug.Assert(false, ex.ToString()); + } + } - // Cheesy, but hotkeys are ignored when the mouse is captured. - // However, if we don't capture and release, the shapes will draw forever. - if (Settings.Default.MouseDraw && main.IsMouseCaptured) - main.ReleaseMouseCapture(); - } + SpeechSynth.Rate = -1; + SpeechSynth.Volume = 100; + } + public void Speak() + { + Thread oThread = new Thread(new ThreadStart(this.Start)); + oThread.Start(); + } + private void Start() + { + try + { + SpeechSynth.Speak(Word); + } + catch (Exception e) + { + System.Diagnostics.Trace.WriteLine(e.ToString()); + } + } + } - private void MouseDraw(MainWindow main, Point p) - { - //randomize at some point? - Shape shape = new Ellipse - { - Stroke = SystemColors.WindowTextBrush, - StrokeThickness = 0, - Fill = Utils.GetGradientBrush(Utils.GetRandomColor()), - Width = 50, - Height = 50 - }; + private void ShowOptionsDialog() + { + bool foo = Settings.Default.TransparentBackground; + isOptionsDialogShown = true; + var o = new Options(); + Mouse.Capture(null); + foreach (MainWindow m in this.windows) + { + m.Topmost = false; + } + o.Topmost = true; + o.Focus(); + o.ShowDialog(); + Debug.Write("test"); + foreach (MainWindow m in this.windows) + { + m.Topmost = true; + //m.ResetCanvas(); + } + isOptionsDialogShown = false; - ellipsesQueue.Enqueue(shape); - main.mouseDragCanvas.Children.Add(shape); - Canvas.SetLeft(shape, p.X - 25); - Canvas.SetTop(shape, p.Y - 25); + if (foo != Settings.Default.TransparentBackground) + { + MessageBoxResult result = MessageBox.Show( + "You've changed the Window Transparency Option. We'll need to restart BabySmash! for you to see the change. Pressing YES will restart BabySmash!. Is that OK?", + "Need to Restart", MessageBoxButton.YesNo, MessageBoxImage.Question); + if (result == MessageBoxResult.Yes) + { + Application.Current.Shutdown(); + System.Windows.Forms.Application.Restart(); + } + } + } - if (Settings.Default.MouseDraw) - Win32Audio.PlayWavResourceYield("smallbumblebee.wav"); + public void MouseDown(MainWindow main, MouseButtonEventArgs e) + { + if (isDrawing || Settings.Default.MouseDraw) return; - if (ellipsesQueue.Count > 30) //this is arbitrary - { - Shape shapeToRemove = ellipsesQueue.Dequeue(); - main.mouseDragCanvas.Children.Remove(shapeToRemove); - } - } + // Create a new Ellipse object and add it to canvas. + Point ptCenter = e.GetPosition(main.mouseCursorCanvas); + MouseDraw(main, ptCenter); + isDrawing = true; + main.CaptureMouse(); - //private static void ResetCanvas(MainWindow main) - //{ - // main.ResetCanvas(); - //} + Win32Audio.PlayWavResource("smallbumblebee.wav"); + } - public void LostMouseCapture(MainWindow main, MouseEventArgs e) - { - if (Settings.Default.MouseDraw) return; - if (isDrawing) isDrawing = false; - } - } + public void MouseWheel(MainWindow main, MouseWheelEventArgs e) + { + if (e.Delta > 0) + { + Win32Audio.PlayWavResourceYield("rising.wav"); + } + else + { + Win32Audio.PlayWavResourceYield("falling.wav"); + } + } + + public void MouseUp(MainWindow main, MouseButtonEventArgs e) + { + isDrawing = false; + if (Settings.Default.MouseDraw) return; + main.ReleaseMouseCapture(); + } + + public void MouseMove(MainWindow main, MouseEventArgs e) + { + if (isOptionsDialogShown) + { + main.ReleaseMouseCapture(); + return; + } + if (Settings.Default.MouseDraw && main.IsMouseCaptured == false) + main.CaptureMouse(); + + if (isDrawing || Settings.Default.MouseDraw) + { + MouseDraw(main, e.GetPosition(main)); + } + + // Cheesy, but hotkeys are ignored when the mouse is captured. + // However, if we don't capture and release, the shapes will draw forever. + if (Settings.Default.MouseDraw && main.IsMouseCaptured) + main.ReleaseMouseCapture(); + } + + private void MouseDraw(MainWindow main, Point p) + { + //randomize at some point? + Shape shape = new Ellipse + { + Stroke = SystemColors.WindowTextBrush, + StrokeThickness = 0, + Fill = Utils.GetGradientBrush(Utils.GetRandomColor()), + Width = 50, + Height = 50 + }; + + ellipsesQueue.Enqueue(shape); + main.mouseDragCanvas.Children.Add(shape); + Canvas.SetLeft(shape, p.X - 25); + Canvas.SetTop(shape, p.Y - 25); + + if (Settings.Default.MouseDraw) + Win32Audio.PlayWavResourceYield("smallbumblebee.wav"); + + if (ellipsesQueue.Count > 30) //this is arbitrary + { + Shape shapeToRemove = ellipsesQueue.Dequeue(); + main.mouseDragCanvas.Children.Remove(shapeToRemove); + } + } + + //private static void ResetCanvas(MainWindow main) + //{ + // main.ResetCanvas(); + //} + + public void LostMouseCapture(MainWindow main, MouseEventArgs e) + { + if (Settings.Default.MouseDraw) return; + if (isDrawing) isDrawing = false; + } + } } \ No newline at end of file diff --git a/Extensions/ObjectExtensions.cs b/Extensions/ObjectExtensions.cs new file mode 100644 index 0000000..4474944 --- /dev/null +++ b/Extensions/ObjectExtensions.cs @@ -0,0 +1,71 @@ +namespace BabySmash.Extensions +{ + using System; + using System.Diagnostics.CodeAnalysis; + using System.Reflection; + + /// + /// Contains extension methods for objects + /// + public static class ObjectExtensions + { + /// + /// Uses reflection to find a private field and validate its type. + /// + /// The type that declares the field. FlattenHierarchy doesn't work for private fields, so you have to pass the base type that declares the field. + /// Expected field type. + /// Name of the field to read. + /// Field information. + /// + /// When field is not found or it is of incorrect type. + + public static FieldInfo GetField(this Type ownerType, Type valueType, string fieldName) + { + FieldInfo field = ownerType.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); + if (field == null) + { + throw new ArgumentException($"Failed to find field '{fieldName}' on type {ownerType.FullName}."); + } + + if (!valueType.IsAssignableFrom(field.FieldType)) + { + throw new ArgumentException($"Field '{fieldName}' on type {ownerType.FullName} is {field.FieldType.FullName}, but expected {valueType.FullName}."); + } + + return field; + } + + /// + /// Uses reflection to read a value of a private field. + /// + /// The type that declares the field. FlattenHierarchy doesn't work for private fields, so you have to pass the base type that declares the field. + /// Expected field type. + /// The instance to read the field value from. + /// Name of the field to read. + /// Field value. + /// + /// When field is not found or it is of incorrect type. + [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "ReadField", Justification = "'Read' is a clear verb and 'field value' is the subject.")] + public static TValue ReadFieldValue(this TOwner owner, string fieldName) + { + FieldInfo field = GetField(typeof(TOwner), typeof(TValue), fieldName); + return (TValue)field.GetValue(owner); + } + + /// + /// Uses reflection to set a value of a private field. + /// + /// The type that declares the field. FlattenHierarchy doesn't work for private fields, so you have to pass the base type that declares the field. + /// Expected field type. + /// The instance to write the field value to. + /// Name of the field to write. + /// The value to set. + /// + /// When field is not found or it is of incorrect type. + public static void WriteFieldValue(this TOwner owner, string fieldName, TValue value) + { + FieldInfo field = GetField(typeof(TOwner), typeof(TValue), fieldName); + field.SetValue(owner, value); + } + } +} \ No newline at end of file diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index 45095a7..ab38991 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -1,16 +1,8 @@ -using System; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Diagnostics; -using System.Speech.Synthesis; + using System.Windows; using System.Windows.Controls; -using System.Windows.Data; using System.Windows.Input; -using System.Windows.Navigation; -using System.Windows.Shapes; -using BabySmash.Properties; + using System.Windows.Media; namespace BabySmash diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs index f88aa91..202ab18 100644 --- a/Properties/Resources.Designer.cs +++ b/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.18444 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs index 1daf447..7c003da 100644 --- a/Properties/Settings.Designer.cs +++ b/Properties/Settings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.18444 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -12,7 +12,7 @@ namespace BabySmash.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -50,12 +50,12 @@ namespace BabySmash.Properties { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool UseEffects { + public bool BitmapEffects { get { - return ((bool)(this["UseEffects"])); + return ((bool)(this["BitmapEffects"])); } set { - this["UseEffects"] = value; + this["BitmapEffects"] = value; } } diff --git a/Resources/Strings/en-EN.json b/Resources/Strings/en-EN.json new file mode 100644 index 0000000..a243d1a --- /dev/null +++ b/Resources/Strings/en-EN.json @@ -0,0 +1,21 @@ +{ + "Circle": "Circle", + "Oval": "Oval", + "Rectangle": "Rectangle", + "Hexagon": "Hexagon", + "Trapezoid": "Trapezoid", + "Star": "Star", + "Square": "Square", + "Triangle": "Triangle", + "Heart": "Heart", + + "Red": "Red", + "Blue": "Blue", + "Yellow": "Yellow", + "Green": "Green", + "Purple": "Purple", + "Pink": "Pink", + "Orange": "Orange", + "Tan": "Tan", + "Gray": "Gray" +} \ No newline at end of file diff --git a/Resources/Strings/ru-RU.json b/Resources/Strings/ru-RU.json new file mode 100644 index 0000000..8c47701 --- /dev/null +++ b/Resources/Strings/ru-RU.json @@ -0,0 +1,21 @@ +{ + "Circle": "Круг", + "Oval": "Овал", + "Rectangle": "Прямоугольник", + "Hexagon": "Шестиугольник", + "Trapezoid": "Трапеция", + "Star": "Звезда", + "Square": "Квадрат", + "Triangle": "Треугольник", + "Heart": "Сердце", + + "Red": "красный", + "Blue": "синий", + "Yellow": "желтый", + "Green": "зеленый", + "Purple": "фиолетовый", + "Pink": "розовый", + "Orange": "оранжевый", + "Tan": "желтовато-коричневый", + "Gray": "серый" +} \ No newline at end of file diff --git a/Shapes/BabySmashShape.cs b/Shapes/BabySmashShape.cs new file mode 100644 index 0000000..6df41b2 --- /dev/null +++ b/Shapes/BabySmashShape.cs @@ -0,0 +1,15 @@ +namespace BabySmash.Shapes +{ + public enum BabySmashShape + { + Circle, + Oval, + Rectangle, + Hexagon, + Trapezoid, + Star, + Square, + Triangle, + Heart + } +} \ No newline at end of file diff --git a/Shapes/FigureGenerator.cs b/Shapes/FigureGenerator.cs index ef90544..ed94fb5 100644 --- a/Shapes/FigureGenerator.cs +++ b/Shapes/FigureGenerator.cs @@ -6,86 +6,97 @@ using System.Windows.Media; using System.Windows.Media.Effects; using BrushControlFunc = System.Func; using BabySmash.Properties; +using BabySmash.Shapes; namespace BabySmash { - public class FigureTemplate - { - public Brush Fill { get; set; } - public Color Color { get; set; } - public BrushControlFunc GeneratorFunc { get; set; } - public Effect Effect { get; set; } - public string Name { get; set; } - public string Letter { get; set; } - } + public class FigureTemplate + { + public Brush Fill { get; set; } + public Color Color { get; set; } + public BrushControlFunc GeneratorFunc { get; set; } + public Effect Effect { get; set; } + public string Name { get; set; } + public string Letter { get; set; } + } - public class FigureGenerator - { - private static readonly List> hashTableOfFigureGenerators = new List> - { - new KeyValuePair("Circle", x => new CoolCircle(x) ), - new KeyValuePair("Oval", x => new CoolOval(x) ), - new KeyValuePair("Rectangle", x => new CoolRectangle(x) ), - new KeyValuePair("Hexagon", x => new CoolHexagon(x) ), - new KeyValuePair("Trapezoid", x => new CoolTrapezoid(x) ), - new KeyValuePair("Star", x => new CoolStar(x) ), - new KeyValuePair("Square", x => new CoolSquare(x) ), - new KeyValuePair("Triangle", x => new CoolTriangle(x) ), - new KeyValuePair("Heart", x => new CoolHeart(x) ) - }; + public class FigureGenerator + { + private static readonly List> hashTableOfFigureGenerators = new List> + { + new KeyValuePair(BabySmashShape.Circle, x => new CoolCircle(x) ), + new KeyValuePair(BabySmashShape.Oval, x => new CoolOval(x) ), + new KeyValuePair(BabySmashShape.Rectangle, x => new CoolRectangle(x) ), + new KeyValuePair(BabySmashShape.Hexagon, x => new CoolHexagon(x) ), + new KeyValuePair(BabySmashShape.Trapezoid, x => new CoolTrapezoid(x) ), + new KeyValuePair(BabySmashShape.Star, x => new CoolStar(x) ), + new KeyValuePair(BabySmashShape.Square, x => new CoolSquare(x) ), + new KeyValuePair(BabySmashShape.Triangle, x => new CoolTriangle(x) ), + new KeyValuePair(BabySmashShape.Heart, x => new CoolHeart(x) ) + }; - public static UserControl NewUserControlFrom(FigureTemplate template) - { - UserControl retVal = null; - - if (template.Letter.Length == 1 && Char.IsLetterOrDigit(template.Letter[0])) - { - retVal = new CoolLetter(template.Fill.Clone(), template.Letter[0]); - } - else - { - retVal = template.GeneratorFunc(template.Fill.Clone()); - } + public static UserControl NewUserControlFrom(FigureTemplate template) + { + UserControl retVal = null; - var randomTransition1 = (Tweener.TransitionType)Utils.RandomBetweenTwoNumbers(1, (int)Tweener.TransitionType.EaseOutInBounce); - var ani1 = Tweener.Tween.CreateAnimation(randomTransition1, 0, 1, new TimeSpan(0, 0, 0, 1), 30); - var randomTransition2 = (Tweener.TransitionType)Utils.RandomBetweenTwoNumbers(1, (int)Tweener.TransitionType.EaseOutInBounce); - var ani2 = Tweener.Tween.CreateAnimation(randomTransition2, 360, 0, new TimeSpan(0, 0, 0, 1), 30); - retVal.RenderTransformOrigin = new Point(0.5, 0.5); - var group = new TransformGroup(); - group.Children.Add(new ScaleTransform()); - group.Children.Add(new RotateTransform()); - retVal.RenderTransform = group; - group.Children[0].BeginAnimation(ScaleTransform.ScaleXProperty, ani1); - group.Children[0].BeginAnimation(ScaleTransform.ScaleYProperty, ani1); - group.Children[1].BeginAnimation(RotateTransform.AngleProperty, ani2); + if (template.Letter.Length == 1 && Char.IsLetterOrDigit(template.Letter[0])) + { + retVal = new CoolLetter(template.Fill.Clone(), template.Letter[0]); + } + else + { + retVal = template.GeneratorFunc(template.Fill.Clone()); + } - if (Settings.Default.UseEffects) - { - retVal.Effect = template.Effect.Clone(); - } - - return retVal; - } + var randomTransition1 = (Tweener.TransitionType)Utils.RandomBetweenTwoNumbers(1, (int)Tweener.TransitionType.EaseOutInBounce); + var ani1 = Tweener.Tween.CreateAnimation(randomTransition1, 0, 1, new TimeSpan(0, 0, 0, 1), 30); + var randomTransition2 = (Tweener.TransitionType)Utils.RandomBetweenTwoNumbers(1, (int)Tweener.TransitionType.EaseOutInBounce); + var ani2 = Tweener.Tween.CreateAnimation(randomTransition2, 360, 0, new TimeSpan(0, 0, 0, 1), 30); + retVal.RenderTransformOrigin = new Point(0.5, 0.5); + var group = new TransformGroup(); + group.Children.Add(new ScaleTransform()); + group.Children.Add(new RotateTransform()); + retVal.RenderTransform = group; + group.Children[0].BeginAnimation(ScaleTransform.ScaleXProperty, ani1); + group.Children[0].BeginAnimation(ScaleTransform.ScaleYProperty, ani1); + group.Children[1].BeginAnimation(RotateTransform.AngleProperty, ani2); - //TODO: Should this be in XAML? Would that make it better? - //TODO: Should I change the height, width and stroke to be relative to the screen size? - //TODO: Where can I get REALLY complex shapes like animal vectors or custom pics? Where do I store them? + if (Settings.Default.BitmapEffects) + { + retVal.Effect = template.Effect.Clone(); + } - public static FigureTemplate GenerateFigureTemplate(char displayChar) - { - Color c = Utils.GetRandomColor(); + return retVal; + } - var nameFunc = hashTableOfFigureGenerators[Utils.RandomBetweenTwoNumbers(0, hashTableOfFigureGenerators.Count - 1)]; - return new FigureTemplate - { - Color = c, - Name = Char.IsLetterOrDigit(displayChar) ? displayChar.ToString() : nameFunc.Key, - GeneratorFunc = nameFunc.Value, - Fill = Utils.GetGradientBrush(c), - Letter = displayChar.ToString(), - Effect = Animation.GetRandomBitmapEffect() - }; - } - } + //TODO: Should this be in XAML? Would that make it better? + //TODO: Should I change the height, width and stroke to be relative to the screen size? + //TODO: Where can I get REALLY complex shapes like animal vectors or custom pics? Where do I store them? + + public static FigureTemplate GenerateFigureTemplate(char displayChar) + { + Color c = Utils.GetRandomColor(); + + string name = null; + KeyValuePair nameFunc = hashTableOfFigureGenerators[Utils.RandomBetweenTwoNumbers(0, hashTableOfFigureGenerators.Count - 1)]; + if (Char.IsLetterOrDigit(displayChar)) + { + name = displayChar.ToString(); + } + else + { + name = Controller.GetLocalizedString(nameFunc.Key.ToString()); + } + + return new FigureTemplate + { + Color = c, + Name = name, + GeneratorFunc = nameFunc.Value, + Fill = Utils.GetGradientBrush(c), + Letter = displayChar.ToString(), + Effect = Animation.GetRandomBitmapEffect() + }; + } + } } \ No newline at end of file diff --git a/app.config b/app.config index 1cb2e9d..979f4c6 100644 --- a/app.config +++ b/app.config @@ -58,5 +58,5 @@ - + diff --git a/packages.config b/packages.config new file mode 100644 index 0000000..d18d9b1 --- /dev/null +++ b/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file