Skip to content

Commit

Permalink
Brought over a couple more of my old BabySmash mods.
Browse files Browse the repository at this point in the history
* Hardware effects option was implemented; the options checkbox for it is no longer grayed out.
* Words! When a typed sequence of letters completes a recognized word, the letters will each animate into position to
  form the word, and the last synthesized speech will be of the word rather than the last-typed letter.  This may
  breath a little more life into the app, when the child is starting to read and write; allowing them to explore keys
  and find words.  The starting dictionary just demonstrates the feature, and ought to be replaced with a longer one,
  or the WordFinder class could be modified to use the OS dictionary, etc.  Extensions should think on how to handle
  rude words that we don't want to teach here, and avoid obscure words that aren't commonly used, etc.
  • Loading branch information
DavidRieman committed Mar 15, 2015
1 parent e7f6a0e commit 50b816a
Show file tree
Hide file tree
Showing 10 changed files with 326 additions and 92 deletions.
6 changes: 6 additions & 0 deletions BabySmash.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Compile Include="WordFinder.cs" />
<Reference Include="PresentationFramework.Luna">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
Expand Down Expand Up @@ -346,6 +347,11 @@
<Folder Include="Resources\Voices\Female\" />
<Folder Include="Resources\Voices\Male\" />
</ItemGroup>
<ItemGroup>
<Content Include="Words.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
121 changes: 75 additions & 46 deletions Controller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.ComponentModel;
using System.Deployment.Application;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Speech.Synthesis;
using System.Windows;
Expand Down Expand Up @@ -35,8 +36,9 @@ public class Controller

private DispatcherTimer timer = new DispatcherTimer();
private Queue<Shape> ellipsesQueue = new Queue<Shape>();
private Dictionary<string, Queue<UserControl>> ellipsesUserControlQueue = new Dictionary<string, Queue<UserControl>>();
private Dictionary<string, List<UserControl>> figuresUserControlQueue = new Dictionary<string, List<UserControl>>();
private ApplicationDeployment deployment = null;
private WordFinder wordFinder = new WordFinder("Words.txt");

void deployment_CheckForUpdateCompleted(object sender, CheckForUpdateCompletedEventArgs e)
{
Expand Down Expand Up @@ -101,35 +103,25 @@ public void Launch()
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()
};



ellipsesUserControlQueue[m.Name] = new Queue<UserControl>();
{
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()
};

figuresUserControlQueue[m.Name] = new List<UserControl>();

m.Show();
m.MouseLeftButtonDown += HandleMouseLeftButtonDown;
m.MouseWheel += HandleMouseWheel;

#if false
m.Width = 700;
m.Height = 600;
m.Left = 900;
m.Top = 500;
#else
m.WindowState = WindowState.Maximized;
#endif
windows.Add(m);
}

Expand Down Expand Up @@ -188,29 +180,54 @@ public void ProcessKey(FrameworkElement uie, KeyEventArgs e)
return;
}

string s = e.Key.ToString();
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);
}

// 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);
}

// Handle number keys, whose values are prefixed by "D" or "NumPad" (because enum names can't start with a digit)
if (s.StartsWith("NumPad")) s = s.Substring(6);
if ((s.Length == 2) && s.StartsWith("D")) s = s.Substring(1);
AddFigure(uie, s);
// Otherwise, display a random shape.
return '*';
}

private void AddFigure(FrameworkElement uie, string s)
private void AddFigure(FrameworkElement uie, char c)
{
FigureTemplate template = FigureGenerator.GenerateFigureTemplate(s);
foreach (MainWindow m in this.windows)
FigureTemplate template = FigureGenerator.GenerateFigureTemplate(c);
foreach (MainWindow window in this.windows)
{
UserControl f = FigureGenerator.NewUserControlFrom(template);
m.AddFigure(f);
window.AddFigure(f);

var queue = figuresUserControlQueue[window.Name];
queue.Add(f);

var queue = ellipsesUserControlQueue[m.Name];
queue.Enqueue(f);
// 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;
}

f.Width = 300;
f.Height = 300;
Canvas.SetLeft(f, Utils.RandomBetweenTwoNumbers(0, Convert.ToInt32(m.ActualWidth - f.Width)));
Canvas.SetTop(f, Utils.RandomBetweenTwoNumbers(0, Convert.ToInt32(m.ActualHeight - f.Height)));
Canvas.SetLeft(f, Utils.RandomBetweenTwoNumbers(0, Convert.ToInt32(window.ActualWidth - f.Width)));
Canvas.SetTop(f, Utils.RandomBetweenTwoNumbers(0, Convert.ToInt32(window.ActualHeight - f.Height)));

Storyboard storyboard = Animation.CreateDPAnimation(uie, f,
UIElement.OpacityProperty,
Expand All @@ -225,12 +242,26 @@ private void AddFigure(FrameworkElement uie, string s)

if (queue.Count > Settings.Default.ClearAfter)
{
UserControl u = queue.Dequeue() as UserControl;
m.RemoveFigure(u);
window.RemoveFigure(queue[0]);
queue.RemoveAt(0);
}
}

PlaySound(template);
// 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);
}

SpeakString(lastWord);
}
else
{
PlaySound(template);
}
}

//private static DoubleAnimationUsingKeyFrames ApplyZoomOut(UserControl u)
Expand Down Expand Up @@ -421,14 +452,12 @@ public void MouseMove(MainWindow main, MouseEventArgs e)
if (Settings.Default.MouseDraw && main.IsMouseCaptured == false)
main.CaptureMouse();

Debug.WriteLine(String.Format("MouseMove! {0} {1} {2}", Settings.Default.MouseDraw, main.IsMouseCaptured, isOptionsDialogShown));

if (isDrawing || Settings.Default.MouseDraw)
{
MouseDraw(main, e.GetPosition(main));
}

//Cheesy, but hotkeys are ignored when the mouse is captured.
// 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();
Expand Down
4 changes: 2 additions & 2 deletions Options.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -793,8 +793,8 @@
IsChecked="{Binding Path=Default.ForceUppercase, Mode=TwoWay}" Content="Force Letters to UPPERCASE" />
<CheckBox Style="{DynamicResource SimpleCheckBox}" Grid.Row="5" Grid.ColumnSpan="2" Grid.Column="0" Foreground="#FFD1D1D1" FontSize="14" FontFamily="Segoe UI"
IsChecked="{Binding Path=Default.FacesOnShapes, Mode=TwoWay}" Content="Faces on Shapes" />
<CheckBox Style="{DynamicResource SimpleCheckBox}" Grid.Row="6" Grid.ColumnSpan="2" Grid.Column="0" Foreground="#4CD1D1D1" FontSize="14" FontFamily="Segoe UI"
IsChecked="{Binding Path=Default.BitmapEffects, Mode=TwoWay}" IsEnabled="False" Content="Hardware Effects (DISABLED FOR NOW)"/>
<CheckBox Style="{DynamicResource SimpleCheckBox}" Grid.Row="6" Grid.ColumnSpan="2" Grid.Column="0" Foreground="#FFD1D1D1" FontSize="14" FontFamily="Segoe UI"
IsChecked="{Binding Path=Default.UseEffects, Mode=TwoWay}" Content="Hardware Effects"/>
<CheckBox Style="{DynamicResource SimpleCheckBox}" Grid.Row="7" Grid.ColumnSpan="2" Grid.Column="0" Foreground="#FFD1D1D1" FontSize="14" FontFamily="Segoe UI"
IsChecked="{Binding Path=Default.MouseDraw, Mode=TwoWay}" Content="Clickless Mouse Drawing" />
<CheckBox Style="{DynamicResource SimpleCheckBox}" x:Name="TransparentCheckBox" Grid.Row="8" Grid.ColumnSpan="3" Grid.Column="0" Foreground="#FFD1D1D1" FontSize="14" FontFamily="Segoe UI"
Expand Down
6 changes: 3 additions & 3 deletions Properties/Settings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 18 additions & 6 deletions Shapes/Animation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,33 @@ namespace BabySmash
{
class Animation
{
public static BitmapEffect GetRandomBitmapEffect()
public static Effect GetRandomBitmapEffect()
{
int e = Utils.RandomBetweenTwoNumbers(0, 3);
switch (e)
{
case 0:
return new BevelBitmapEffect();
// Just makes the figure blurry; maybe do this one less frequently?
return new BlurEffect
{
Radius = Utils.RandomBetweenTwoNumbers(5, 20),
RenderingBias = RenderingBias.Performance,
};
case 1:
return new DropShadowBitmapEffect();
// TODO: Maybe add a replacement for the deprecated EmbossBitmapEffect? For now, just fallthrough.
case 2:
return new EmbossBitmapEffect();
// TODO: Maybe add a replacement for the deprecated BevelBitmapEffect? For now, just fallthrough.
case 3:
return new OuterGlowBitmapEffect();
return new DropShadowEffect
{
ShadowDepth = 0,
Color = Utils.GetRandomColor(),
BlurRadius = Utils.RandomBetweenTwoNumbers(10, 50),
RenderingBias = RenderingBias.Performance,
};
}
return new BevelBitmapEffect();

return new DropShadowEffect();
}

public static void ApplyRandomAnimationEffect(FrameworkElement fe, Duration duration)
Expand Down
40 changes: 20 additions & 20 deletions Shapes/CoolLetter.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Media;
Expand All @@ -17,45 +18,44 @@ public CoolLetter()
this.InitializeComponent();
}

public CoolLetter(Brush x, string letter)
public CoolLetter(Brush x, char letter)
: this()
{
this.Character = letter;
this.letterPath.Fill = x;

this.letterPath.Data = MakeCharacterGeometry(GetLetterCharacter(letter));
this.Width = this.letterPath.Data.Bounds.Width + this.letterPath.Data.Bounds.X + this.letterPath.StrokeThickness / 2;
this.Height = this.letterPath.Data.Bounds.Height + this.letterPath.Data.Bounds.Y + this.letterPath.StrokeThickness / 2;
}

private static Geometry MakeCharacterGeometry(string t)
public char Character { get; private set; }

private static Geometry MakeCharacterGeometry(char character)
{
var fText = new FormattedText(
t,
var fontFamily = new FontFamily(Settings.Default.FontFamily);
var typeface = new Typeface(fontFamily, FontStyles.Normal, FontWeights.Heavy, FontStretches.Normal);
var formattedText = new FormattedText(
character.ToString(),
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface(
new FontFamily(Properties.Settings.Default.FontFamily),
FontStyles.Normal,
FontWeights.Heavy,
FontStretches.Normal),
typeface,
300,
Brushes.Black
);
return fText.BuildGeometry(new Point(0, 0)).GetAsFrozen() as Geometry;
Brushes.Black);
return formattedText.BuildGeometry(new Point(0, 0)).GetAsFrozen() as Geometry;
}

private static string GetLetterCharacter(string name)
private static char GetLetterCharacter(char name)
{
string nameToDisplay;
Debug.Assert(name == char.ToUpperInvariant(name), "Always provide uppercase character names to this method.");

if (Settings.Default.ForceUppercase)
{
nameToDisplay = name;
return name;
}
else
{
nameToDisplay = Utils.GetRandomBoolean() ? name : name.ToLowerInvariant();
}
return nameToDisplay;

// Return a random uppercase or lowercase letter.
return Utils.GetRandomBoolean() ? name : char.ToLowerInvariant(name);
}
}
}
Loading

0 comments on commit 50b816a

Please sign in to comment.