Page 1 of 1

[Unity] Using PathGeometry for a circular cooldown effect

Posted: 21 Jan 2015, 21:46
by Scherub
Hi,

I'm currently working on an RPG Interaction test scene. Each usable item has a cooldown and I want to display a kind of circular progressbar that fills the whole rectangle where the item is placed inside. I created this in WPF with PathGeometry first and tried it then in Noesis but nothing appeared. Is this not supported or is there a different way to achieve this? :)

Re: [Unity] Using PathGeometry for a circular cooldown effec

Posted: 22 Jan 2015, 18:01
by sfernandez
Hi,

Unfortunately PathGeometry is not implemented in NoesisGUI so path animations can't be done directly in the xaml. But there are alternatives, one I can think now is to have an attached property that you can animate, and in the property changed callback you can regenerate the StreamGeometry associated with the Path that renders the cool down effect:
// Using 1.2 API
static class CoolDownPathAnimation
{
  public static DependencyProperty RotationProperty = DependencyProperty.RegisterAttached(
    "Rotation", typeof(float), typeof(CoolDownPathAnimation),
    new PropertyMetadata(0.0f, new PropertyChangedCallback(OnRotationChanged));

  public static float GetRotation(DependencyObject element)
  {
    return (float)element.GetValue(RotationProperty);
  }
  public static void SetRotation(DependencyObject element, float rotation)
  {
    element.SetValue(RotationProperty, rotation);
  }

  private static void OnRotationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
    Path path = d as Path;
    if (path != null)
    {
      var geometry = path.Data as StreamGeometry;
      if (geometry == null)
      {
        geometry = new StreamGeometry();
        path.Data = geometry;
      }

      using (var context = geometry.Open())
      {
        float rotation = GetRotation(path);
        // generate cool down geometry with current rotation value...
      }
    }
  }      
}
And in the xaml, you will have something like this:
...
<Storyboard x:Key="CoolDownAnimation">
  <DoubleAnimation
    Storyboard.TargetName="CoolDownPath"
    Storyboard.TargetProperty="(local:CoolDownPathAnimation.Rotation)"
    From="0" To="360" Duration="0:0:5"/>
</Storyboard>
...
<Path x:Name="CoolDownPath" local:CoolDownPathAnimation.Rotation="0" Fill="#80000000"/>
...

Re: [Unity] Using PathGeometry for a circular cooldown effec

Posted: 22 Jan 2015, 18:12
by movra
On a sidenote, Noesis.DependencyPropertyChangedEventArgs doesn't contain NewValue and OldValue, does it?

https://msdn.microsoft.com/en-us/librar ... deventargs

https://msdn.microsoft.com/en-us/librar ... .110).aspx

Re: [Unity] Using PathGeometry for a circular cooldown effec

Posted: 22 Jan 2015, 18:22
by sfernandez
On a sidenote, Noesis.DependencyPropertyChangedEventArgs doesn't contain NewValue and OldValue, does it?

https://msdn.microsoft.com/en-us/librar ... deventargs

https://msdn.microsoft.com/en-us/librar ... .110).aspx
Not yet, we are going to expose them for the 1.2 API.

Re: [Unity] Using PathGeometry for a circular cooldown effec

Posted: 22 Jan 2015, 18:28
by Scherub
@sfernandez: Thanks, I'll give it a try! :)

Re: [Unity] Using PathGeometry for a circular cooldown effec

Posted: 23 Jan 2015, 06:04
by ai_enabled
That's how this effect done in our game:
Image
Image

It's done by utilizing rectangle with semi-transparent fill and updating clip (StreamGeometry) for it every time the angle changed.

The update code maybe not very elegant, but works flawlessly and fast:
         float angleRad = // provide your angle in radians
			float angleDeg = angleRad * (float)(180f / Math.PI);

			var w = this.width;
			var h = this.height;

			Vector2 point = new Vector2(w / 2 + (w * 2 * Mathf.Cos(angleRad)), h / 2 + (h * 2) * Mathf.Sin(angleRad));

			using (StreamGeometryContext ctx = this.clipGeometry.Open())
			{
				ctx.BeginFigure(new Point(w / 2, 0), true);
				ctx.LineTo(new Point(w / 2, h / 2));
				ctx.LineTo(new Point(point.X, point.Y));

				if (angleDeg < 45)
				{
					ctx.LineTo(new Point(w, 0));
				}

				if (angleDeg < 180)
				{
					ctx.LineTo(new Point(w, h));
				}

				if (angleDeg < 270)
				{
					ctx.LineTo(new Point(0, h));
				}

				if (angleDeg < 315)
				{
					ctx.LineTo(new Point(0, 0));
				}
			}
			// all done
You need to add Rectange with name "Rectangle" to this control XAML, set some fill for it.
Then in OnPostInit you need to set clip for it:
                var rectangle = this.FindName("Rectangle").As<Rectangle>();
                this.clipGeometry = new StreamGeometry();
                rectangle.Clip = this.clipGeometry;

Re: [Unity] Using PathGeometry for a circular cooldown effec

Posted: 26 Jan 2015, 18:39
by Scherub
Hi,

I've finally found the time to try your solution and it works very well. Thank you very much! :)

Re: [Unity] Using PathGeometry for a circular cooldown effec

Posted: 24 Feb 2015, 02:34
by elecman
Any update on supporting PathGeometry? I need it to get clipping paths to work which are exported from Inkscape.

Re: [Unity] Using PathGeometry for a circular cooldown effec

Posted: 24 Feb 2015, 17:14
by jsantos
Not for v1.2.0. This is low priority for now, mainly because PathGeometry is very inefficient. It is a lot better using StreamGeometry. Cannot you convert your geometry to a set of StreamGeometries that can be animated separately? Or do you need each segment to be animated independently?

Re: [Unity] Using PathGeometry for a circular cooldown effec

Posted: 24 Feb 2015, 17:50
by jsantos
Please, open a new thread for this. This one is closed and accepted.