<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Salty Dog Digital]]></title><description><![CDATA[imagine // create // play]]></description><link>http://saltydog.digital/</link><generator>Ghost 0.7</generator><lastBuildDate>Fri, 24 Apr 2026 23:37:42 GMT</lastBuildDate><atom:link href="http://saltydog.digital/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Fourtex Jugo launches on Steam April 13th!]]></title><description><![CDATA[<p>We are truly excited to announce that Fourtex Jugo will be leaving Steam Early Access, and launching fully and in its complete form on April 13th!</p>

<p>Jugo is unlike any puzzle game you've played before:</p>

<ul>
<li><p>Various play modes allow self-selection of difficulty on a particular level. On each level, you</p></li></ul>]]></description><link>http://saltydog.digital/jugo-launches-april-13/</link><guid isPermaLink="false">bbf57cd2-cec2-43ce-8da4-aa75c44d41bb</guid><category><![CDATA[fourtex jugo]]></category><dc:creator><![CDATA[Robert Wahler]]></dc:creator><pubDate>Fri, 07 Apr 2017 13:11:11 GMT</pubDate><media:content url="http://saltydog.digital/content/images/2017/04/jugo_capsule_616x353.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://saltydog.digital/content/images/2017/04/jugo_capsule_616x353.jpg" alt="Fourtex Jugo launches on Steam April 13th!"><p>We are truly excited to announce that Fourtex Jugo will be leaving Steam Early Access, and launching fully and in its complete form on April 13th!</p>

<p>Jugo is unlike any puzzle game you've played before:</p>

<ul>
<li><p>Various play modes allow self-selection of difficulty on a particular level. On each level, you can shoot for 1, 2 or 3 stars, each getting increasingly more difficult, or you can just shoot for the high score.</p></li>
<li><p>The AI is, along with every other aspect of play, 100% deterministic. So, you can plan accordingly, but plan you must, or risk your pie getting eaten.</p></li>
<li><p>The rules are simple combine the particles to achieve the highest score possible. But, doing so while avoiding the claws will be a satisfying challenge.</p></li>
</ul>

<p>Lorin has put together a pair of developer Let's Play videos for players to reference ahead of next week's release as well:</p>

<h3 id="fourtexjugoletsplaywiththegamedesignerep1youtubehttpswwwyoutubecomwatchv20lq2n0yje4">Fourtex Jugo Lets Play with the Game Designer Ep #1 <a href="https://www.youtube.com/watch?v=20lQ2N0YJE4">YouTube</a></h3>

<iframe width="640" height="360" src="https://www.youtube.com/embed/20lQ2N0YJE4?rel=0&amp;controls=0&amp;showinfo=0" frameborder="0" allowfullscreen></iframe>

<h3 id="fourtexjugoletsplaywiththegamedesignerep2youtubehttpswwwyoutubecomwatchvjm6t2sbmbki">Fourtex Jugo Lets Play with the Game Designer Ep #2 <a href="https://www.youtube.com/watch?v=Jm6t2SbMBKI">YouTube</a></h3>

<iframe width="640" height="360" src="https://www.youtube.com/embed/Jm6t2SbMBKI?rel=0&amp;controls=0&amp;showinfo=0" frameborder="0" allowfullscreen></iframe>

<p>While Fourtex Jugo will be essentially complete after next week's launch, this will be far from the end. The game will keep on getting better and richer for as long as possible. There are many new ideas, and puzzles that we hope to bring about in later updates.</p>

<p>Look out for more info over the coming weeks -- thank you so much for your support and feedback during early access!</p>]]></content:encoded></item><item><title><![CDATA[Jugo in space]]></title><description><![CDATA[<h3 id="screenshots">Screenshots</h3>

<div class="row">  
  <div class="col-md-12">

 <div id="jugo-landscape-screenshots" class="screenshots">

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v6a.jpg" class="screenshot" data-size="1000x680">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Jugo-v6a.png" alt="">
          <figure></figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v7a.jpg" class="screenshot" data-size="1000x680">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Jugo-v7a.png" alt="">
          <figure></figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v8d.jpg" class="screenshot" data-size="1000x680">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Jugo-v8d.png" alt="">
          <figure></figure>
        </a>


        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v3a.jpg" class="screenshot" data-size="1000x680">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Jugo-v3a.png" alt="">
          <figure></figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v4d.jpg" class="screenshot" data-size="1000x680">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Jugo-v4d.png" alt="">
          <figure></figure>
        </a>

         <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v9a.jpg" class="screenshot" data-size="1000x563">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Jugo-v9a.png" alt="">
          <figure></figure>
        </a>
    </div>

  </div>
</div>

<p>It may be premature to write an extensive history of Jugo, but for those interested in the look and feel of the game and how they have changed and may change again, here are… pictures. Whee!</p>

<p>Our current prototype had two primary paths of evolution:  the game-play itself, and</p>]]></description><link>http://saltydog.digital/jugo-in-space/</link><guid isPermaLink="false">f666fe3b-83de-42ed-8fed-1c496cb78032</guid><category><![CDATA[screenshots]]></category><dc:creator><![CDATA[Lorin Drum]]></dc:creator><pubDate>Thu, 03 Mar 2016 19:32:05 GMT</pubDate><media:content url="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v8d.jpg" medium="image"/><content:encoded><![CDATA[<h3 id="screenshots">Screenshots</h3>

<div class="row">  
  <div class="col-md-12">

 <div id="jugo-landscape-screenshots" class="screenshots">

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v6a.jpg" class="screenshot" data-size="1000x680">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Jugo-v6a.png" alt="Jugo in space">
          <figure></figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v7a.jpg" class="screenshot" data-size="1000x680">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Jugo-v7a.png" alt="Jugo in space">
          <figure></figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v8d.jpg" class="screenshot" data-size="1000x680">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Jugo-v8d.png" alt="Jugo in space">
          <figure></figure>
        </a>


        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v3a.jpg" class="screenshot" data-size="1000x680">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Jugo-v3a.png" alt="Jugo in space">
          <figure></figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v4d.jpg" class="screenshot" data-size="1000x680">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Jugo-v4d.png" alt="Jugo in space">
          <figure></figure>
        </a>

         <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v9a.jpg" class="screenshot" data-size="1000x563">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Jugo-v9a.png" alt="Jugo in space">
          <figure></figure>
        </a>
    </div>

  </div>
</div>

<img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/Jugo-v8d.jpg" alt="Jugo in space"><p>It may be premature to write an extensive history of Jugo, but for those interested in the look and feel of the game and how they have changed and may change again, here are… pictures. Whee!</p>

<p>Our current prototype had two primary paths of evolution:  the game-play itself, and the artwork.</p>

<p>Our talented artist Steve came up with many cool layout versions while we pondered what the game was supposed to do. Several had a space-based them, with a dark background that soon became filled with space-stuff like a nebula, or more than one nebula, i.e. nebulae. And claws.</p>

<p>I think we all really liked the stone backgrounds. They were abandoned due to technical reasons, primarily the time element for making the graphics and any animations work correctly. Now that game-play is fully worked out, however, there is a chance we may all get together and say...let there be rock. </p>

<p>The last screenshots show various early versions of game play, which at one time was apparently pretty complicated. Still, there are probably one or two different versions that might be fun, so we are hoping some day we have a chance and a reason to explore some alternate play modes.</p>

<p>Jugo is now trying to make its way through the Greenlight process on Steam, so we encourage any of you who haven’t done so yet to head over there and give Jugo a vote. </p>

<iframe src="http://steamcommunity.com/sharedfiles/widget/614602755" width="336" height="137" frameborder="0" scrolling="no"></iframe>]]></content:encoded></item><item><title><![CDATA[Usage Pattern for a Type-Safe Unity Event System]]></title><description><![CDATA[<h3 id="eventmanageroverview">EventManager Overview</h3>

<p>A <a href="https://en.wikipedia.org/wiki/Type_safety">type-safe</a> event system for <a href="https://unity3d.com/">Unity</a> based on the event listener pattern was originally described by Will Miller here <a href="http://www.willrmiller.com/?p=87">http://www.willrmiller.com/?p=87</a>. We use this pattern at Salty Dog. We made a few minor modifications, added some unit tests and example code, and published it</p>]]></description><link>http://saltydog.digital/usage-pattern-for-a-type-safe-unity-event-system/</link><guid isPermaLink="false">69025fe4-7e44-4cd8-a4dd-40c89b22aa22</guid><dc:creator><![CDATA[Robert Wahler]]></dc:creator><pubDate>Tue, 23 Feb 2016 13:29:35 GMT</pubDate><media:content url="http://saltydog.digital/content/images/2016/02/EventManager.png" medium="image"/><content:encoded><![CDATA[<h3 id="eventmanageroverview">EventManager Overview</h3>

<img src="http://saltydog.digital/content/images/2016/02/EventManager.png" alt="Usage Pattern for a Type-Safe Unity Event System"><p>A <a href="https://en.wikipedia.org/wiki/Type_safety">type-safe</a> event system for <a href="https://unity3d.com/">Unity</a> based on the event listener pattern was originally described by Will Miller here <a href="http://www.willrmiller.com/?p=87">http://www.willrmiller.com/?p=87</a>. We use this pattern at Salty Dog. We made a few minor modifications, added some unit tests and example code, and published it as the asset <em>EventManager</em>. The full MIT licensed source code is located here <a href="https://github.com/robertwahler/EventManager">https://github.com/robertwahler/EventManager</a>.</p>

<p>This pattern is useful when you want to keep your codebase <a href="https://en.wikipedia.org/wiki/Loose_coupling">loosely coupled</a>. Publishers and subscribers don't need to know anything about each other. This is not a solution for exposing callbacks in the Unity Editor, Unity's own EventSystem may be more appropriate for that use case.</p>

<h3 id="features">Features</h3>

<ul>
<li><a href="https://en.wikipedia.org/wiki/Loose_coupling">Loosely coupled</a></li>
<li><a href="https://en.wikipedia.org/wiki/Type_safety">Type-safe</a></li>
<li>Avoids breaking changes when new event parameters are added</li>
</ul>

<h3 id="exampleusage">Example Usage</h3>

<p>The <a href="http://www.willrmiller.com/?p=87">original article</a> does a good job of explaining the purpose and the inner workings of this event system.  This usage example, <em>Colors Clicker</em> (shown in screenshot above) will walk through a simple use case. The example scene, full code, and installation instructions are available in the <a href="https://github.com/robertwahler/EventManager">EventManager repository</a>.</p>

<h4 id="createevents">Create Events</h4>

<p>Events are straight-up C# classes based on <code>SDD.Events.Event</code></p>

<pre><code class="language-C#">namespace SDD.Events {

  /// &lt;summary&gt;
  /// Base event for all EventManager events.
  /// &lt;/summary&gt;
  public class Event {
  }
}
</code></pre>

<p><a href="https://github.com/robertwahler/EventManager/blob/master/Assets/EventManager/Source/Event.cs">View on GitHub</a></p>

<p>The <code>Colors.Events.ButtonClickEvent</code> descends from <code>SDD.Events.Event</code> and has a single simple property reference to <code>Colors.ButtonHandler</code>. Events can have zero to as many properties as needed.  This simple flexibility permits easily adding properties to events as a project evolves without breaking existing functionality.</p>

<pre><code class="language-C#">namespace Colors.Events {

  /// &lt;summary&gt;
  /// Raised event signals a button was clicked
  /// &lt;/summary&gt;
  public class ButtonClickEvent : SDD.Events.Event {

    public ButtonHandler ButtonHandler { get; set; }

    /// &lt;summary&gt;
    /// Return a string
    /// &lt;/summary&gt;
    public override string ToString(){
      return string.Format("{0}, ButtonHandler {1}", base.ToString(), ButtonHandler);
    }

  }
}
</code></pre>

<p><a href="https://github.com/robertwahler/EventManager/blob/master/Assets/Examples/Colors/Events/ButtonClickEvent.cs">View on GitHub</a></p>

<h4 id="implementieventhandler">Implement IEventHandler</h4>

<p>EventManager provides a generic interface to allow MonoBehaviours to add and remove listener delegates.</p>

<pre><code class="language-C#">namespace SDD.Events {

  /// &lt;summary&gt;
  ///  Interface for event handlers
  /// &lt;/summary&gt;
  public interface IEventHandler {

    /// &lt;summary&gt;
    /// Subscribe to events
    ///
    /// @example
    ///   Events.AddListener&lt;MoveResolvedEvent&gt;(OnMoveResolved);
    ///     or
    ///   EventManager.OnSetRule += OnSetRule;
    /// &lt;/summary&gt;
    void SubscribeEvents();

    /// &lt;summary&gt;
    /// Unsubscribe from events
    ///
    /// @example
    ///   Events.RemoveListener&lt;MoveResolvedEvent&gt;(OnMoveResolved);
    ///     or
    ///   EventManager.OnSetRule -= OnSetRule;
    /// &lt;/summary&gt;
    void UnsubscribeEvents();

  }
}
</code></pre>

<p><a href="https://github.com/robertwahler/EventManager/blob/master/Assets/EventManager/Source/IEventHandler.cs">View on GitHub</a></p>

<h4 id="colorclickereventhandlerabstractclass">Color Clicker EventHandler Abstract Class</h4>

<p>This class is used as a base class for all event event handlers in the project. The implementation ensures event listeners are added and removed appropriately when MonoBehviours are added and destoyed.</p>

<pre><code class="language-C#">using UnityEngine;  
using SDD.Events;

namespace Colors.Events {

  /// &lt;summary&gt;
  /// Event handler
  /// &lt;/summary&gt;
  public abstract class EventHandler : MonoBehaviour, IEventHandler {

    /// &lt;summary&gt;
    /// Subscribe to events
    ///
    /// @example
    ///   EventManager.Instance.AddListener&lt;MoveResolvedEvent&gt;(OnMoveResolved);
    /// &lt;/summary&gt;
    public abstract void SubscribeEvents();

    /// &lt;summary&gt;
    /// Unsubscribe from events
    ///
    /// @example
    ///   EventManager.Instance.RemoveListener&lt;MoveResolvedEvent&gt;(OnMoveResolved);
    /// &lt;/summary&gt;
    public abstract void UnsubscribeEvents();

    protected virtual void OnEnable() {
      SubscribeEvents();
    }

    protected virtual void OnDisable() {
      UnsubscribeEvents();
    }

  }
}
</code></pre>

<p><a href="https://github.com/robertwahler/EventManager/blob/master/Assets/Examples/Colors/Events/EventHandler.cs">View on GitHub</a></p>

<h4 id="concreteeventhandlerimplementation">Concrete EventHandler Implementation</h4>

<p>This header text handler responds to events by displaying text at the top of the screen. See screenshot above.</p>

<pre><code class="language-C#">using UnityEngine;  
using UnityEngine.UI;  
using SDD.Events;

using Colors.Events;

namespace Colors {

  /// &lt;summary&gt;
  /// Header text handler
  /// &lt;/summary&gt;
  public class HeaderText : EventHandler {

    /// &lt;summary&gt;
    /// Header text. Assign in IDE.
    /// &lt;/summary&gt;
    public Text text;

    public override void SubscribeEvents() {
      Debug.Log(string.Format("HeaderText.SubscribeEvents() name {0}", name));

      EventManager.Instance.AddListener&lt;ButtonClickEvent&gt;(OnButtonClickEvent);
      EventManager.Instance.AddListener&lt;ButtonRemovedEvent&gt;(OnButtonRemovedEvent);
    }

    public override void UnsubscribeEvents() {
      Debug.Log(string.Format("HeaderText.UnsubscribeEvents() name {0}", name));

      EventManager.Instance.RemoveListener&lt;ButtonClickEvent&gt;(OnButtonClickEvent);
      EventManager.Instance.RemoveListener&lt;ButtonRemovedEvent&gt;(OnButtonRemovedEvent);
    }

    /// &lt;summary&gt;
    /// A button in the scene was clicked
    /// &lt;/summary&gt;
    public void OnButtonClickEvent(ButtonClickEvent e) {
      Debug.Log(string.Format("HeaderText.OnClick({0})", e));

      string caption = string.Format("{0} '{1}' was clicked.\nEventManager.DelegateLookupCount is {2}", e.ButtonHandler.kind, e.ButtonHandler.name, EventManager.Instance.DelegateLookupCount);
      text.text = caption;
    }

    /// &lt;summary&gt;
    /// A button in the scene was destroyed
    /// &lt;/summary&gt;
    public void OnButtonRemovedEvent(ButtonRemovedEvent e) {
      Debug.Log(string.Format("HeaderText.OnButtonRemoved({0})", e));

      string caption = string.Format("'{0}' was removed.", e.Name);
      text.text = caption;
    }

  }
}
</code></pre>

<p><a href="https://github.com/robertwahler/EventManager/blob/master/Assets/Examples/Colors/HeaderText.cs">View on GitHub</a></p>

<h4 id="raisingevents">Raising Events</h4>

<p>Events can be raised anywhere without knowing any details of the listening behaviours.  Here is a snippet from the Unity EventSystem OnClick handler for the big colored buttons. This snippet creates the ButtonClickEvent each time it raises the event. This is fine for seldom raised events but can create a garbage collection issue if the event is raised often. Create a reference cache to prevent memory allocations after initialization. See the field <a href="https://github.com/robertwahler/EventManager/blob/master/Assets/Examples/Colors/ButtonHandler.cs">buttonRemovedEvent</a> for an example of zero allocations after initialization.</p>

<pre><code class="language-C#">/// &lt;summary&gt;
/// OnClick handler for the button on this specific GameObject
/// &lt;/summary&gt;
public void OnClick() {  
  Debug.Log(string.Format("ButtonHandler.OnClick() name {0}", name));

  EventManager.Instance.Raise(new ButtonClickEvent(){ ButtonHandler=this });
}
</code></pre>

<p><a href="https://github.com/robertwahler/EventManager/blob/master/Assets/Examples/Colors/ButtonHandler.cs">View on GitHub</a></p>

<h3 id="simpleandflexible">Simple and Flexible</h3>

<p>There you have it. Thanks for reading! We think EventManager is simple and flexible and makes event system maintenance and trouble-shooting about as easy as it gets in a fully decoupled architecture.</p>

<p>If you have appreciated this article or would like to see the games we are creating with this event system, please visit our <a href="http://steamcommunity.com/sharedfiles/filedetails/?id=614602755">Steam Greenlight</a> page.  </p>

<p>Our released game <a href="http://saltydog.digital/zen">Fourtex Zen</a> also uses this event system. </p>

<iframe src="http://steamcommunity.com/sharedfiles/widget/614602755" width="336" height="137" frameborder="0" scrolling="no"></iframe>]]></content:encoded></item><item><title><![CDATA[Fourtex Jugo on Steam Greenlight]]></title><description><![CDATA[<h3 id="steamgreenlight">Steam Greenlight</h3>

<p>Salty is beside himself with the excitement! Fourtex Jugo is on Steam Greenlight.  Please visit our <a href="http://steamcommunity.com/sharedfiles/filedetails/?id=614602755">Steam Greenlight</a> page and let us know what you think.</p>

<iframe src="http://steamcommunity.com/sharedfiles/widget/614602755" width="336" height="137" frameborder="0" scrolling="no"></iframe>

<h3 id="screenshots">Screenshots</h3>

<div class="row">  
  <div class="col-md-12">

 <div id="jugo-landscape-screenshots" class="screenshots">

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Level1.png" class="screenshot" data-size="1920x1080">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Level1.png" alt="">
          <figure>Level 1</figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Start.png" class="screenshot" data-size="1920x1080">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Start.png" alt="">
          <figure>Start screen</figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Level3.png" class="screenshot" data-size="1920x1080">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Level3.png" alt="">
          <figure>Level 3</figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Level4A.png" class="screenshot" data-size="1920x1080">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Level4A.png" alt="">
          <figure>Level 4</figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Menu.png" class="screenshot" data-size="1920x1080">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Menu.png" alt="">
          <figure>In-game menu</figure>
        </a>

    </div>

  </div>
</div>

<p><a href="http://steamcommunity.com/sharedfiles/filedetails/?id=614602755"> <br>
  <img src="http://saltydog.digital/content/images/screenshots/jugo/Jugo-Steam-512.gif" class="image-responsive" alt="Jugo Greenlight GIF"> <br>
</a></p>]]></description><link>http://saltydog.digital/fourtex-jugo-on-steam-greenlight/</link><guid isPermaLink="false">99d0990c-2ce8-4e8f-83a7-a1bf7e1f24f1</guid><category><![CDATA[screenshots]]></category><category><![CDATA[fourtex jugo]]></category><dc:creator><![CDATA[Robert Wahler]]></dc:creator><pubDate>Wed, 17 Feb 2016 14:17:55 GMT</pubDate><media:content url="http://saltydog.digital/content/images/screenshots/jugo/landscape/Level1.png" medium="image"/><content:encoded><![CDATA[<h3 id="steamgreenlight">Steam Greenlight</h3>

<img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/Level1.png" alt="Fourtex Jugo on Steam Greenlight"><p>Salty is beside himself with the excitement! Fourtex Jugo is on Steam Greenlight.  Please visit our <a href="http://steamcommunity.com/sharedfiles/filedetails/?id=614602755">Steam Greenlight</a> page and let us know what you think.</p>

<iframe src="http://steamcommunity.com/sharedfiles/widget/614602755" width="336" height="137" frameborder="0" scrolling="no"></iframe>

<h3 id="screenshots">Screenshots</h3>

<div class="row">  
  <div class="col-md-12">

 <div id="jugo-landscape-screenshots" class="screenshots">

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Level1.png" class="screenshot" data-size="1920x1080">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Level1.png" alt="Fourtex Jugo on Steam Greenlight">
          <figure>Level 1</figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Start.png" class="screenshot" data-size="1920x1080">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Start.png" alt="Fourtex Jugo on Steam Greenlight">
          <figure>Start screen</figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Level3.png" class="screenshot" data-size="1920x1080">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Level3.png" alt="Fourtex Jugo on Steam Greenlight">
          <figure>Level 3</figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Level4A.png" class="screenshot" data-size="1920x1080">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Level4A.png" alt="Fourtex Jugo on Steam Greenlight">
          <figure>Level 4</figure>
        </a>

        <a href="http://saltydog.digital/content/images/screenshots/jugo/landscape/Menu.png" class="screenshot" data-size="1920x1080">
          <img src="http://saltydog.digital/content/images/screenshots/jugo/landscape/small/Menu.png" alt="Fourtex Jugo on Steam Greenlight">
          <figure>In-game menu</figure>
        </a>

    </div>

  </div>
</div>

<p><a href="http://steamcommunity.com/sharedfiles/filedetails/?id=614602755"> <br>
  <img src="http://saltydog.digital/content/images/screenshots/jugo/Jugo-Steam-512.gif" class="image-responsive" alt="Fourtex Jugo on Steam Greenlight"> <br>
</a></p>]]></content:encoded></item><item><title><![CDATA[List the fonts in a Gimp XCF file]]></title><description><![CDATA[Editing text layers in Gimp is hit or miss if the font isn’t installed.  You can find out the fonts used in an XCF file from the command line.]]></description><link>http://saltydog.digital/list-the-fonts-in-a-gimp-xcf-file/</link><guid isPermaLink="false">c08fe034-17fb-4e4a-a0a1-f436f56b163a</guid><category><![CDATA[Graphics]]></category><category><![CDATA[Gimp]]></category><dc:creator><![CDATA[Robert Wahler]]></dc:creator><pubDate>Tue, 17 Nov 2015 14:03:32 GMT</pubDate><media:content url="http://saltydog.digital/content/images/2015/09/Screen-Shot-2015-09-28-at-9-14-51-AM.png" medium="image"/><content:encoded><![CDATA[<img src="http://saltydog.digital/content/images/2015/09/Screen-Shot-2015-09-28-at-9-14-51-AM.png" alt="List the fonts in a Gimp XCF file"><p>Editing text layers in Gimp is hit or miss if the font isn’t installed. You can tell it isn’t installed because when you click on the text with the text tool, no font name or size is listed.</p>

<h3 id="findthefont">Find the font</h3>

<p>Requires the GNU CLI utilities.</p>

<pre><code class="language-bash">strings jugo-artwork-alt.xcf | grep font  
</code></pre>

<p>Install the font before opening the XCF file.  </p>]]></content:encoded></item><item><title><![CDATA[Dynamic Unity UI Layout Groups]]></title><description><![CDATA[Give your layout groups some smarts.   This DynamicLayoutGroup group switches orientation automatically between landscape and portrait layouts. ]]></description><link>http://saltydog.digital/dynamic-unity-ui-layoutgroups/</link><guid isPermaLink="false">c4b29cda-1f55-45b3-9af6-5649d4f6ac18</guid><category><![CDATA[Unity]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[UI]]></category><category><![CDATA[Landscape]]></category><category><![CDATA[Portrait]]></category><category><![CDATA[Orientation]]></category><dc:creator><![CDATA[Robert Wahler]]></dc:creator><pubDate>Tue, 03 Nov 2015 15:44:00 GMT</pubDate><media:content url="http://saltydog.digital/content/images/2015/10/Zen-Poem-Vertical.png" medium="image"/><content:encoded><![CDATA[<img src="http://saltydog.digital/content/images/2015/10/Zen-Poem-Vertical.png" alt="Dynamic Unity UI Layout Groups"><p>Give your layout groups some smarts.   This <code>DynamicLayoutGroup</code> group switches orientation automatically between landscape and portrait layouts. It acts like a VerticalLayoutGroup (screenshot above) or a HorizontalLayoutGroup (screenshot below) depending the current aspect ratio of the screen.</p>

<h3 id="thewhy">The Why</h3>

<p>These screenshots are from an upcoming 2.0 update to <a href="http://saltydog.digital/zen">Fourtex Zen</a>. The game shipped with a fixed landscape orientation. We recently moved to Unity 5 and decided that updating Fourtex Zen would be a good way to learn the new UI system.  We wanted the game playable regardless of screen orientation. The poem panels stack the poetry text in portrait and place it side-by-side in landscape (there are 64 poems given as in-game rewards).</p>

<p><img src="http://saltydog.digital/content/images/2015/10/Zen-Poem-Horizontal.png" alt="Dynamic Unity UI Layout Groups"></p>

<h3 id="thecode">The Code</h3>

<p>The <code>DynamicLayoutGroup</code> class inherits directly from the Unity 5 <code>HorizontalOrVerticalLayoutGroup</code> base class and provides a simple mechanism to determine screen orientation and shift its layout accordingly. It can be used anywhere you would normally use a <code>VerticalLayoutGroup</code> or <code>HorizontalLayoutGroup</code>.</p>

<pre><code>using UnityEngine;  
using UnityEngine.UI;  
using UnityEngine.EventSystems;  
using System.Collections;  
using System.Collections.Generic;

namespace SDD.UI {

  /// &lt;summary&gt;
  /// Layout group switches orientation automatically between landscape and
  /// portrait layouts so it either acts like a VerticalLayoutGroup or a
  /// HorizontalLayoutGroup.
  /// &lt;/summary&gt;
  [AddComponentMenu("Layout/Dynamic Layout Group", 150)]
  public class DynamicLayoutGroup : HorizontalOrVerticalLayoutGroup {

    /// &lt;summary&gt;
    /// When is the layout vertical? In portrait or landscape?
    /// &lt;/summary&gt;
    [SerializeField]
    public ScreenOrientation verticalWhen = ScreenOrientation.Portrait;

    public bool IsVertical { get { return GetIsVertical(); }}

    private bool GetIsVertical() {
      bool isVertical;

      if (UnityEngine.Screen.width &gt; UnityEngine.Screen.height) {
        //orientation = ScreenOrientation.Landscape;
        isVertical = (verticalWhen == ScreenOrientation.Landscape) ? true : false;
      }
      else {
        //orientation = ScreenOrientation.Portrait;
        isVertical = (verticalWhen == ScreenOrientation.Portrait) ? true : false;
      }

      //Log.Debug(string.Format("DynamicLayoutGroup.OnRectTransformDimensionsChange() isVertical={0}a, ID={1}", isVertical, GetInstanceID()));
      return isVertical;
    }

    public override void CalculateLayoutInputHorizontal() {
      //Log.Debug(string.Format("DynamicLayoutGroup.CalculateLayoutInputHorizontal() IsVertical={0}, ID={1}", IsVertical, GetInstanceID()));

      base.CalculateLayoutInputHorizontal();
      CalcAlongAxis(0, isVertical: IsVertical);
    }

    public override void CalculateLayoutInputVertical() {
      //Log.Debug(string.Format("DynamicLayoutGroup.CalculateLayoutInputVertical() IsVertical={0}, ID={1}", IsVertical, GetInstanceID()));

      CalcAlongAxis(1, isVertical: IsVertical);
    }

    public override void SetLayoutHorizontal() {
      //Log.Debug(string.Format("DynamicLayoutGroup.SetLayoutHorizontal() IsVertical={0}, ID={1}", IsVertical, GetInstanceID()));

      SetChildrenAlongAxis(0, isVertical: IsVertical);
    }

    public override void SetLayoutVertical() {
      //Log.Debug(string.Format("DynamicLayoutGroup.SetLayoutVertical() IsVertical={0}, ID={1}", IsVertical, GetInstanceID()));

      SetChildrenAlongAxis(1, isVertical: IsVertical);
    }
  }
}
</code></pre>

<pre><code>using UnityEditor;  
using UnityEngine;  
using UnityEngine.UI;

namespace SDD.UI {

  /// &lt;summary&gt;
  /// Override the Unity UI custom editor for HorizontalOrVerticalLayoutGroup
  /// and do exactly nothing. The only purpose of this class is to expose the
  /// public ```VerticalWhen```. The inherited editor prevents editing new
  /// publics in descendant classes without doing a full widget layout here
  /// (too much work!).
  /// &lt;/summary&gt;
  /// &lt;remarks&gt;
  /// Place in ```Editor``` folder
  /// &lt;/remarks&gt;
  [CustomEditor(typeof(SDD.UI.DynamicLayoutGroup), true)]
  [CanEditMultipleObjects]
  public class DynamicLayoutGroupEditor : UnityEditor.Editor {
  }
}
</code></pre>

<pre><code>namespace SDD {

  /// &lt;summary&gt;
  /// Orientation of the screen regardless of which way is up
  /// &lt;/summary&gt;
  public enum ScreenOrientation {
    Landscape,
    Portrait
  }
</code></pre>

<p><a href="https://gist.github.com/robertwahler/016a820af52521a5cb0d">GitHub Gist</a></p>]]></content:encoded></item><item><title><![CDATA[Fourtex Jugo]]></title><description><![CDATA[Fourtex Jugo is strategy-based single-player puzzler with two players, because Jugo is always there, watching and waiting for your mistake.]]></description><link>http://saltydog.digital/jugo/</link><guid isPermaLink="false">4b984098-6c2d-47bf-9a13-019b63331817</guid><category><![CDATA[fourtex jugo]]></category><dc:creator><![CDATA[Stephen Ashurst]]></dc:creator><pubDate>Sat, 17 Oct 2015 21:00:00 GMT</pubDate><media:content url="http://saltydog.digital/content/images/2015/09/jugo-artwork-colour-1000.jpg" medium="image"/><content:encoded><![CDATA[<h3 id="strategybasedpuzzler">Strategy-based Puzzler</h3>

<img src="http://saltydog.digital/content/images/2015/09/jugo-artwork-colour-1000.jpg" alt="Fourtex Jugo"><p>Fourtex Jugo is strategy-based single-player puzzler with two players, because Jugo is always there, watching and waiting for your mistake.</p>

<p>Each level has a target score which may be relatively easy to beat, or not. Some are quite difficult. Can you beat them all? Can you play a perfect game, when Jugo is always ready to capitalize on any opportunity to ruin your perfect game?</p>

<div class="row">  
  <div class="col-md-12">
    <iframe src="http://store.steampowered.com/widget/499560/" frameborder="0" width="646" height="190"></iframe>
  </div>
</div>

<p><img src="http://saltydog.digital/content/images/2016/02/Particles.png" alt="Fourtex Jugo"></p>

<h3 id="pieandnoms">Pie and Noms</h3>

<p>In Fourtex Jugo you progress through a level by combining the three particle types with each other to create higher-value particles, or to create void. Number particles combine to make Pie particles. Pie particles combine to make Nom ("nominal") particles, and noms combine to make void. In the void, there are ... claws!</p>

<p><img src="http://saltydog.digital/content/images/2016/02/Pies.png" alt="Fourtex Jugo"></p>

<h3 id="jugodoesntdomath">Jugo doesn't do Math</h3>

<p>The number particles combine with each other in just two ways:  two of the same number will combine to make the next higher particle, or two numbers that add to 15 will combine to make a pie particle. Any two pies will combine, and the two opposite color nom particles combine to make void. The claws that live in the void like the pies and noms and will try to grab them if they can. The strategy in Fourtex Jugo usually involves keeping the claws away from your pies and noms until you can beat the target score.</p>

<h3 id="howdoyouwin">How do you Win?</h3>

<p>When you complete a level . . . and have more points than Jugo, you get a star. If you reached the target score you have won the game and get two stars. If you have won without giving a particle to Jugo or having Jugo's claws grab a pie or nom, you get all three stars-- you have played a perfect game! There are levels of various difficulty, but getting three stars is usually quite challenging.</p>

<p>Each designed level is unique and so each level has a leader-board for competing against yourself or other players. Jugo himself also has a leaderboard. Don't think of it as just a hall of shame-- it can be a slightly different way to play the game in trying deliberately to get a high score for Jugo.</p>

<p>Fourtex Jugo has controller support as well as keyboard or mouse support, and has simple configuration menus for adjusting audio and other parameters.</p>

<p><img src="http://saltydog.digital/content/images/2016/02/LevelsA.png" alt="Fourtex Jugo"></p>

<h3 id="features">Features:</h3>

<ul>
<li>Play casually just to complete a level, or play to achieve a high score, or play to get a perfect game</li>
<li>Levels are handcrafted by humans</li>
<li>Additional daily randomized levels</li>
<li>Original art and audio</li>
<li>Leaderboards, achievements, stats</li>
</ul>

<p><img src="http://saltydog.digital/content/images/2016/02/LevelsB.png" alt="Fourtex Jugo"></p>

<h4 id="fourtexjugoisavailablenowonsteam">Fourtex Jugo is available now on Steam:</h4>

<h4 id="httpstoresteampoweredcomapp499560"><a href="http://store.steampowered.com/app/499560/">http://store.steampowered.com/app/499560/</a></h4>

<h4 id="fourtexjugoextendedplayyoutubehttpswwwyoutubecomwatchvrc_37y73kym">Fourtex Jugo | Extended Play <a href="https://www.youtube.com/watch?v=rc_37y73KYM">YouTube</a></h4>

<iframe width="800" height="450" src="https://www.youtube.com/embed/rc_37y73KYM?rel=0&amp;controls=0&amp;showinfo=0" frameborder="0" allowfullscreen></iframe>]]></content:encoded></item><item><title><![CDATA[Dynamically Ignoring Unity Unit Tests the Fast Way]]></title><description><![CDATA[You can statically ignore Unity unit tests by applying the [Ignore] attribute.  There is a better way: Try compiler defines.]]></description><link>http://saltydog.digital/dynamically-ignoring-unity-unit-tests-the-fast-way/</link><guid isPermaLink="false">ed5a896c-92f0-4a8a-86a3-15156bdf51af</guid><category><![CDATA[Unity]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Robert Wahler]]></dc:creator><pubDate>Tue, 13 Oct 2015 17:03:36 GMT</pubDate><media:content url="http://saltydog.digital/content/images/2015/08/unity-unit-tests.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://saltydog.digital/content/images/2015/08/unity-unit-tests.jpg" alt="Dynamically Ignoring Unity Unit Tests the Fast Way"><p>You can statically ignore Unity unit tests by applying the <code>[Ignore]</code> attribute. That works fine if you only have a few work-in-progress tests to ignore. What about the use case where you have hundreds of tests that need to be ignored? This use case is very common when you have a single code framework that supports multiple games on multiple platforms. </p>

<p>Here at Salty Dog, we’ve tried a couple of different methods to dynamically ignore unit tests. We've tried the slow way using <code>Assert.Ignore</code> and a faster method using compiler defines.  </p>

<p>The example code snippets below are from our multiple product code base used by our Fourtex products.</p>

<h3 id="theslowapproachassertignore">The Slow Approach: Assert.Ignore</h3>

<p>This approach executes the <code>[Setup]</code> method for each test class before the test class is ignored. Test time really adds up when you have good test coverage.   </p>

<p>An additional downside to this approach is that filtering by <code>Assert.Ignore</code> is not implemented for dynamically ignored tests.  You can end up with hundreds of ignored tests in the IDE and no way to hide them.</p>

<p>Here's our example code.  </p>

<pre><code>…

using SDD.Players;  
using SDD.Campaigns;  
using SDD.Campaigns.Zen;

namespace SDD.Test.Zen {

  [TestFixture]
  [Category("Campaigns")]
  public class CampaignTest : UnitTest {

    private Campaign campaign;

    [SetUp]
    public void Before() {
</code></pre>

<pre><code>      if (Settings.ProductCode != ProductCode.Zen) {
        Assert.Ignore("These tests are for 'ProductCode.Zen'");
      }
</code></pre>

<pre><code>      campaign = new MainCampaign();
    }
…
</code></pre>

<h3 id="thefastapproachcompilerdefines">The Fast Approach: Compiler Defines</h3>

<p>Wrap the <code>[Ignore]</code> attribute in compiler defines. This method is filterable in the Unity IDE. Better and Faster! Wee!</p>

<pre><code>…
using SDD.Players;  
using SDD.Campaigns;  
using SDD.Campaigns.Zen;

namespace SDD.Test.Zen {
</code></pre>

<pre><code>  #if !SDD_PRODUCT_ZEN
  [Ignore]
  #endif
</code></pre>

<pre><code>  [TestFixture]
  [Category("Campaigns")]
  public class CampaignTest : UnitTest {

    private Campaign campaign;

    [SetUp]
    public void Before() {
      campaign = new MainCampaign();
    }
…
</code></pre>

<p>How do you handle this?  Tweet me. See below.</p>]]></content:encoded></item><item><title><![CDATA[More Unity Shortcut Keys]]></title><description><![CDATA[<p>The Unity Test Tools don't have shortcut keys to run your test suites. All the interesting methods are private. The following code adds shortcuts for running both unit and integration tests.</p>

<p>NOTE: This is a followup article to article <a href="http://saltydog.digital/unity-shortcuts-via-reflection/">Unity Shortcuts via Reflection</a></p>

<pre><code class="language-cs">using UnityEditor;  
using UnityEngine;  
using UnityTest;  
using</code></pre>]]></description><link>http://saltydog.digital/unity-test-tools-shortcut-keys/</link><guid isPermaLink="false">ba593255-0c15-4b4c-a4f8-76672387e1ec</guid><category><![CDATA[Unity]]></category><dc:creator><![CDATA[Robert Wahler]]></dc:creator><pubDate>Tue, 06 Oct 2015 13:06:06 GMT</pubDate><media:content url="http://saltydog.digital/content/images/2015/10/Screen-Shot-2015-10-03-at-4-00-40-PM.png" medium="image"/><content:encoded><![CDATA[<img src="http://saltydog.digital/content/images/2015/10/Screen-Shot-2015-10-03-at-4-00-40-PM.png" alt="More Unity Shortcut Keys"><p>The Unity Test Tools don't have shortcut keys to run your test suites. All the interesting methods are private. The following code adds shortcuts for running both unit and integration tests.</p>

<p>NOTE: This is a followup article to article <a href="http://saltydog.digital/unity-shortcuts-via-reflection/">Unity Shortcuts via Reflection</a></p>

<pre><code class="language-cs">using UnityEditor;  
using UnityEngine;  
using UnityTest;  
using System.Collections.Generic;  
using System.Linq;  
using System.Reflection;

namespace SDD.Editor {

  /// &lt;summary&gt;
  /// Salty Dog Digital Unity IDE shortcuts
  /// &lt;/summary&gt;
  public class Shortcuts : MonoBehaviour {

    /// &lt;summary&gt;
    /// Auto running unit tests after each recompile getting you down?  Add a
    /// shortcut.
    /// &lt;/summary&gt;
    [MenuItem("Unity Test Tools/Run Unit Tests %u")]
    static void RunUnitTests() {
      EditorApplication.ExecuteMenuItem("Unity Test Tools/Unit Test Runner");

      System.Type type = typeof(UnitTestView);
      FieldInfo info = type.GetField("s_Instance", BindingFlags.NonPublic | BindingFlags.Static);
      UnitTestView unitTestView = (UnitTestView) info.GetValue(null);
      // find overloaded method "RunTests()"
      MethodInfo methodInfo = unitTestView.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(method =&gt; method.Name == "RunTests" &amp;&amp; method.GetParameters().Count() == 0);
      methodInfo.Invoke(unitTestView, null);
    }

    [MenuItem("Unity Test Tools/Run Unit Tests (Selected) %#u")]
    static void RunUnitTestsSelected() {
      EditorApplication.ExecuteMenuItem("Unity Test Tools/Unit Test Runner");

      System.Type type = typeof(UnitTestView);
      FieldInfo info = type.GetField("s_Instance", BindingFlags.NonPublic | BindingFlags.Static);
      UnitTestView unitTestView = (UnitTestView) info.GetValue(null);

      info = type.GetField("m_TestLines", BindingFlags.NonPublic | BindingFlags.Instance);
      UnitTestRendererLine m_TestLines = (UnitTestRendererLine) info.GetValue(unitTestView);
      m_TestLines.RunSelectedTests();
    }

    [MenuItem("Unity Test Tools/Run Unit Tests (Failed) %&amp;u")]
    static void RunUnitTestsFailed() {
      EditorApplication.ExecuteMenuItem("Unity Test Tools/Unit Test Runner");

      System.Type type = typeof(UnitTestView);
      FieldInfo info = type.GetField("s_Instance", BindingFlags.NonPublic | BindingFlags.Static);
      UnitTestView unitTestView = (UnitTestView) info.GetValue(null);

      info = type.GetField("m_TestLines", BindingFlags.NonPublic | BindingFlags.Instance);
      UnitTestRendererLine m_TestLines = (UnitTestRendererLine) info.GetValue(unitTestView);

      info = type.GetField("m_ResultList", BindingFlags.NonPublic | BindingFlags.Instance);
      List&lt;UnitTestResult&gt; m_ResultList = (List&lt;UnitTestResult&gt;) info.GetValue(unitTestView);
      Debug.Log(m_ResultList);

      m_TestLines.RunTests(m_ResultList.Where(result =&gt; result.IsFailure || result.IsError).Select(l =&gt; l.FullName).ToArray());
    }

    [MenuItem("Unity Test Tools/Run Integration Tests %t")]
    static void RunIntegrationTests() {
      EditorApplication.ExecuteMenuItem("Unity Test Tools/Integration Test Runner");

      System.Type type = typeof(IntegrationTestsRunnerWindow);
      FieldInfo info = type.GetField("s_Instance", BindingFlags.NonPublic | BindingFlags.Static);
      IntegrationTestsRunnerWindow testRunner = (IntegrationTestsRunnerWindow) info.GetValue(null);
      MethodInfo methodInfo = testRunner.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(method =&gt; method.Name == "RunTests");
      object[] objArray = new object[1];
      objArray[0] = TestComponent.FindAllTestsOnScene().Cast&lt;ITestComponent&gt;().ToList();
      methodInfo.Invoke(testRunner, objArray);
    }

    [MenuItem("Unity Test Tools/Run Integration Tests (Selected) %#t")]
    static void RunIntegrationTestsSelected() {
      EditorApplication.ExecuteMenuItem("Unity Test Tools/Integration Test Runner");

      System.Type type = typeof(IntegrationTestsRunnerWindow);
      FieldInfo info = type.GetField("s_Instance", BindingFlags.NonPublic | BindingFlags.Static);
      IntegrationTestsRunnerWindow testRunner = (IntegrationTestsRunnerWindow) info.GetValue(null);
      MethodInfo methodInfo = testRunner.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(method =&gt; method.Name == "RunTests");
      object[] objArray = new object[1];
      objArray[0] = Selection.gameObjects.Select(t =&gt; t.GetComponent(typeof(TestComponent))).Cast&lt;ITestComponent&gt;().ToList();
      methodInfo.Invoke(testRunner, objArray);
    }

  }
}
</code></pre>

<p><a href="https://gist.github.com/robertwahler/ea0de59a5b525ffaa87c">GitHub Gist</a></p>]]></content:encoded></item><item><title><![CDATA[Unity Shortcuts via Reflection]]></title><description><![CDATA[Unity 3D editor code to add a menu item and hotkey to load and run unit tests manually.]]></description><link>http://saltydog.digital/unity-shortcuts-via-reflection/</link><guid isPermaLink="false">e88b4472-21a0-4097-8f30-a2fafb743608</guid><category><![CDATA[Unity]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Robert Wahler]]></dc:creator><pubDate>Tue, 15 Sep 2015 14:11:00 GMT</pubDate><media:content url="http://saltydog.digital/content/images/2015/08/unity-unit-tests.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://saltydog.digital/content/images/2015/08/unity-unit-tests.jpg" alt="Unity Shortcuts via Reflection"><p>Auto running unit tests after each recompile getting you down?  Take control, reflect a bit, and add a shortcut.  </p>

<p>Auto running unit tests is a great idea...as long as it happens in a separate process or in the cloud.  The Unity unit test runner is a private mouse only affair and it will take focus until all the tests are complete. The following editor code will add a menu item and hotkey to load and run unit tests manually.</p>

<p>NOTE: There is a followup to this article with additional shortcut keys <a href="http://saltydog.digital/unity-test-tools-shortcut-keys/">More Unity Shortcut Keys</a></p>

<pre><code class="language-cs">using UnityEditor;  
using UnityEngine;  
using UnityTest;  
using System.Linq;  
using System.Reflection;

namespace SDD.Editor {

  /// &lt;summary&gt;
  /// Salty Dog Digital Unity IDE shortcuts
  /// &lt;/summary&gt;
  public class Shortcuts : MonoBehaviour {

    /// &lt;summary&gt;
    /// Auto running unit tests after each recompile getting you down?  Add a
    /// shortcut to the private method "RunTests".
    /// &lt;/summary&gt;  
    [MenuItem("Unity Test Tools/Run Unit Tests %u")]
    static void RunUnitTests() {
      // make sure the runner is open
      EditorApplication.ExecuteMenuItem("Unity Test Tools/Unit Test Runner");

      System.Type type = typeof(UnitTestView);
      FieldInfo info = type.GetField("s_Instance", BindingFlags.NonPublic | BindingFlags.Static);
      UnitTestView unitTestView = (UnitTestView) info.GetValue(null);
      // find overloaded method "RunTests()"
      MethodInfo methodInfo = unitTestView.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(method =&gt; method.Name == "RunTests" &amp;&amp; method.GetParameters().Count() == 0);
      methodInfo.Invoke(unitTestView, null);
    }

  }
}
</code></pre>

<p><a href="https://gist.github.com/robertwahler/ea0de59a5b525ffaa87c">GitHub Gist</a></p>

<p>This is where someone tells me there already is a unit test hotkey.</p>]]></content:encoded></item><item><title><![CDATA[National Dog Day - 2015]]></title><description><![CDATA[<h3 id="nationaldogday">National Dog Day</h3>

<p>August 26th is National Dog Day in the US</p>

<h4 id="woofsaltysays">WoofSalty says</h4>

<blockquote>
  <p>Take your dog to the beach!</p>
</blockquote>]]></description><link>http://saltydog.digital/national-dog-day-2015/</link><guid isPermaLink="false">5b246be7-d5e0-4613-9f1b-3bf3fcb07f72</guid><dc:creator><![CDATA[Robert Wahler]]></dc:creator><pubDate>Tue, 25 Aug 2015 17:52:00 GMT</pubDate><media:content url="http://saltydog.digital/content/images/2015/08/dog-surfing.jpg" medium="image"/><content:encoded><![CDATA[<h3 id="nationaldogday">National Dog Day</h3>

<img src="http://saltydog.digital/content/images/2015/08/dog-surfing.jpg" alt="National Dog Day - 2015"><p>August 26th is National Dog Day in the US</p>

<h4 id="woofsaltysays">WoofSalty says</h4>

<blockquote>
  <p>Take your dog to the beach!</p>
</blockquote>]]></content:encoded></item><item><title><![CDATA[No. 20 Resolve in Despair]]></title><description><![CDATA[<p>Late 9th or early 10th century. Prince Motoyoshi was son of Yōzei (poem no. 13). The Prince has been caught having a forbidden intimate relationship, and this poem expresses his despair of the situation. Bay of Naniwa means Bay of the Swift Waves.</p>

<h3 id="resolveindespair">Resolve In Despair</h3>

<pre><code class="language-nohighlight">Now, in dire distress,</code></pre>]]></description><link>http://saltydog.digital/no-20-resolve-in-despair/</link><guid isPermaLink="false">344aef65-5873-449c-8e9d-a683cf0b1b50</guid><category><![CDATA[poetry]]></category><dc:creator><![CDATA[Louise Wasilewski]]></dc:creator><pubDate>Sat, 20 Jun 2015 20:49:58 GMT</pubDate><media:content url="http://saltydog.digital/content/images/2015/08/slider-screen3.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://saltydog.digital/content/images/2015/08/slider-screen3.jpg" alt="No. 20 Resolve in Despair"><p>Late 9th or early 10th century. Prince Motoyoshi was son of Yōzei (poem no. 13). The Prince has been caught having a forbidden intimate relationship, and this poem expresses his despair of the situation. Bay of Naniwa means Bay of the Swift Waves.</p>

<h3 id="resolveindespair">Resolve In Despair</h3>

<pre><code class="language-nohighlight">Now, in dire distress,  
  It is all the same to me!
So, then, let us meet  
  Even though it costs my life
  In the Bay of Naniwa.

Prince Motoyoshi

Wabinureba  
  Ima hata onaji
Naniwa naru  
  Mi wo tsukushite mo
  Awanu to zo omou.

Motoyoshi Shinnō  
</code></pre>]]></content:encoded></item><item><title><![CDATA[No. 19 A Lover's Reproach]]></title><description><![CDATA[<p>9th century. The writer, the Lady of Ise, was the daughter of the governor of <a href="http://www.japan-guide.com/e/e4301.html">Ise</a>, on Honshu, and the mother of a Prince, and a scholar in her own right.</p>

<h3 id="aloversreproach">A Lover’s Reproach</h3>

<pre><code class="language-nohighlight">Even for a space,  
  Short as joint of tiny reed  
From Naniwa’s marsh,  
  We</code></pre>]]></description><link>http://saltydog.digital/no-19-a-lovers-reproach/</link><guid isPermaLink="false">18cf0b5f-76ce-477d-a956-eecb08ea1cd4</guid><category><![CDATA[poetry]]></category><dc:creator><![CDATA[Louise Wasilewski]]></dc:creator><pubDate>Sat, 06 Jun 2015 21:26:51 GMT</pubDate><media:content url="http://saltydog.digital/content/images/2015/08/slider-screen4.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://saltydog.digital/content/images/2015/08/slider-screen4.jpg" alt="No. 19 A Lover's Reproach"><p>9th century. The writer, the Lady of Ise, was the daughter of the governor of <a href="http://www.japan-guide.com/e/e4301.html">Ise</a>, on Honshu, and the mother of a Prince, and a scholar in her own right.</p>

<h3 id="aloversreproach">A Lover’s Reproach</h3>

<pre><code class="language-nohighlight">Even for a space,  
  Short as joint of tiny reed  
From Naniwa’s marsh,  
  We must never meet again  
  In this life? This, do you ask?

Lady of Ise

Naniwagata  
  Mijikaki ashi no  
Fushi no ma mo  
  Awade kono yo wo  
  Sugushite yo to ya.

Ise  
</code></pre>]]></content:encoded></item><item><title><![CDATA[No.18 Secret Love]]></title><description><![CDATA[<p>A classic poet, the author died aged only 27 years old, yet still is designated as one of the Thirty-six Poetry Immortals.</p>

<h3 id="secretlove">Secret Love</h3>

<pre><code class="language-nohighlight">Lo! the gathered waves  
  On the shore of Sumi’s bay!  
 E’en in gathered night,  
  When in dreams I go to thee,  
  I must shun</code></pre>]]></description><link>http://saltydog.digital/no-18-secret-love/</link><guid isPermaLink="false">4c1bd81f-313f-42a1-992e-7e1980747798</guid><category><![CDATA[poetry]]></category><dc:creator><![CDATA[Louise Wasilewski]]></dc:creator><pubDate>Sat, 16 May 2015 14:53:33 GMT</pubDate><content:encoded><![CDATA[<p>A classic poet, the author died aged only 27 years old, yet still is designated as one of the Thirty-six Poetry Immortals.</p>

<h3 id="secretlove">Secret Love</h3>

<pre><code class="language-nohighlight">Lo! the gathered waves  
  On the shore of Sumi’s bay!  
 E’en in gathered night,  
  When in dreams I go to thee,  
  I must shun the eyes of men.

Ason Toshiyuki

Suminoe no  
  Kishi ni yoru nami  
 Yoru sae ya  
  Yume no kayoiji  
  Hito me yokuran.

Fujiwara no Toshiyuki Ason  
</code></pre>]]></content:encoded></item><item><title><![CDATA[No. 17 Autumn At Tatta River]]></title><description><![CDATA[<p>9th century. Narihira is known as one of the six best waka poets, and one of the thirty six poet immortals. His affair with <a href="http://en.wikipedia.org/w/index.php?title=Fujiwara_no_Takaiko&amp;action=edit&amp;redlink=1" title="Fujiwara no Takaiko (page does not exist)">Fujiwara no Takaiko</a>, a consort to the Emperor was a big scandal, referred to in the Tales of Ise. <a href="http://www.amazon.com/Tales-Ise-Lyrical-Episodes-Tenth-Century/dp/0804706530">http://www.amazon.com/Tales-Ise-Lyrical-Episodes-Tenth-Century/dp/0804706530</a></p>]]></description><link>http://saltydog.digital/no-17-autumn-at-tatta-river/</link><guid isPermaLink="false">506e7f6a-46f2-4fb1-a5c5-cd9f89487407</guid><category><![CDATA[poetry]]></category><dc:creator><![CDATA[Louise Wasilewski]]></dc:creator><pubDate>Sat, 09 May 2015 19:56:21 GMT</pubDate><content:encoded><![CDATA[<p>9th century. Narihira is known as one of the six best waka poets, and one of the thirty six poet immortals. His affair with <a href="http://en.wikipedia.org/w/index.php?title=Fujiwara_no_Takaiko&amp;action=edit&amp;redlink=1" title="Fujiwara no Takaiko (page does not exist)">Fujiwara no Takaiko</a>, a consort to the Emperor was a big scandal, referred to in the Tales of Ise. <a href="http://www.amazon.com/Tales-Ise-Lyrical-Episodes-Tenth-Century/dp/0804706530">http://www.amazon.com/Tales-Ise-Lyrical-Episodes-Tenth-Century/dp/0804706530</a></p>

<h3 id="autumnattattariver">Autumn At Tatta River</h3>

<pre><code class="language-nohighlight">I have never heard  
  That, e’en when the gods held sway
In the ancient days,  
  E’er was water bound with red
  Such as here in Tatta’s stream.

Ason Narihira


Chihayaburu  
  Kami yo mo kikazu
Tatsuta gawa  
  Kara-kurenai ni
  Mizu kukuru to wa.

Ariwara no Narihira Ason  
</code></pre>]]></content:encoded></item></channel></rss>