February 7th, 2010 | 0 comments

I’ve spent a good amount of the weekend thinking up designs that would allow me to quickly add new UI types into Shader Toy to support all sorts of parameter types. I think I’ve finally got something that works fairly well. What I’ve done is create a very simple interface that represents what a given UI must support:

public interface IParameterControl
{
	EffectParameter Parameter { get; set; }

	void CopyValue();
	void PasteValue();
}

Like I said, very simple. Each UI control must allow me to get and set the EffectParameter it is editing as well as supporting copy/paste functionality. Next I created a mapping for matching a parameter type to a control type, taking into account annotations. Right now I don’t have much but this is the part that will fill up as time goes on:

private readonly Dictionary<Type, Dictionary<string, Type>> parameterEditorTypes =
	new Dictionary<Type, Dictionary<string, Type>>
	{
		{
			typeof(Vector4),
			new Dictionary<string, Type>
			{
				{ "color", typeof(ColorChooser) }
			}
		}
	};

Basically what that means is that we first look up what type the parameter is. In this case a float4/Vector4. Next we look up the “UIType” annotation on the parameter and use that to find what Type of control we need. In this case that’s a ColorChooser UI. Obviously we’d also want some defaults and lots more in here, but this is just where I’m starting.

Finally the meat of the operation. I have this method wired up for when I select a new item in my parameter list:

private void listBox1_SelectedValueChanged(object sender, EventArgs e)
{
	groupBox1.Controls.Clear();

	if (listBox1.SelectedIndex < 0)
	{
		currentParameter = null;
		currentControl = null;
		groupBox1.Text = "{No Parameter Selected}";
		return;
	}

	currentParameter = parameters[listBox1.SelectedIndex];
	groupBox1.Text = currentParameter.Name;

	bool isArray = currentParameter.Elements.Count > 1;
	int arraySize = currentParameter.Elements.Count;

	Type currentParameterType;

	switch (currentParameter.ParameterType)
	{
		case EffectParameterType.Bool:
			currentParameterType = isArray ? typeof(bool[]) : typeof(bool);
			break;
		case EffectParameterType.Int32:
			currentParameterType = isArray ? typeof(int[]) : typeof(int);
			break;
		case EffectParameterType.Single:
		{
			if (currentParameter.RowCount == 1)
			{
				switch (currentParameter.ColumnCount)
				{
					case 1:
						currentParameterType = isArray ? typeof(float[]) : typeof(float);
						break;
					case 2:
						currentParameterType = isArray ? typeof(Vector2[]) : typeof(Vector2);
						break;
					case 3:
						currentParameterType = isArray ? typeof(Vector3[]) : typeof(Vector3);
						break;
					case 4:
						currentParameterType = isArray ? typeof(Vector4[]) : typeof(Vector4);
						break;
					default:
						currentParameterType = null;
						break;
				}
			}
			else
			{
				currentParameterType = isArray ? typeof(Matrix[]) : typeof(Matrix);
			}
			break;
		}
		case EffectParameterType.String:
		currentParameterType = typeof(string);
			break;
		case EffectParameterType.Texture:
		case EffectParameterType.Texture2D:
			currentParameterType = typeof(Texture2D);
			break;
		default:
			currentParameterType = null;
			break;
	}

	if (currentParameterType == null)
		return;

	string uiType = string.Empty;

	foreach (var annotation in currentParameter.Annotations)
	{
		if (annotation.Name == "UIType")
		{
			uiType = annotation.GetValueString().ToLower();
			break;
		}
	}

	Type editorType = null;
	Dictionary<string, Type> editorMatch = null;
	if (parameterEditorTypes.TryGetValue(currentParameterType, out editorMatch) &&
		editorMatch.TryGetValue(uiType, out editorType))
	{
		currentControl = Activator.CreateInstance(editorType) as IParameterControl;
		currentControl.Parameter = currentParameter;
		Control c = currentControl as Control;
		c.Location = new Point(12, 24);
		groupBox1.Controls.Add(c);
	}
}

That goes and figures out exactly what type of parameter we have, then we find the UIType annotation, and lastly we use those two pieces of information to figure out what type of control we want to use. We create an instance, set the parameter, position it, and add it to the group box. I’ll have to see if this holds up as I go, but for just colors right now it works quite well.

The idea behind all of this is to reduce the effort for implementing more UI for other parameter types. Before I had all sorts of hard coded types and different code paths based on type. With this new system, I just have to implement the new UI types and add them to my big dictionary mapping and this method will automatically work for the new UI. Should allow me to finally get down to making more UI for editing parameters.

And of course, what post on Shader Toy would be complete without yet another video. You’ll see the new color UI as well as me using copy/paste. Otherwise it’s nothing all that amazing. I just like making videos. :)


Possibly Related Posts

(Automatically Generated)
Starting parameter editing for Shader Toy
Naming your content
IDictionary + XmlSerializer = Epic FAIL
Default parameter saving in Shader Toy
XmlSerializer Misconceptions Part 1

February 7th, 2010 | 1 comment

One thing I want to support in Shader Toy is the idea of formulaic parameters. For example, any float parameter might define itself in the UI as:

time * 2 + otherParameter^2

Where ‘time’ is a value supplied by my editor for the total running time of the editor and ‘otherParameter’ is some other parameter in the shader code. I want this to work. It’s fairly trivial to do value substitution, replacing those names with other numbers, but to evaluate that at runtime is something that, using just C#, is quite non-trivial.

I started off doing some internet searches to see what can be done. I found that Mono has an Evaluator class built in to leverage the C# compiler and evaluate arbitrary C# code at runtime without the mess of handling your own compiler instance and so forth. Really cool (and I wish Microsoft’s .NET supported that), but a bit overkill for my needs, plus I’d rather not switch runtimes.

Then I found a quick blurb on leveraging JavaScript from C# and using the ‘eval’ method in that language. I gave this a try and am surprised at the simplicity of the solution when you realize what you’re able to do. I decided to test this out by making a command line calculator.

Calculator

First thing you want to do is create an Evaluator.js file and fill it with this code:

package Evaluator
{
  class JSEvaluator
  {
    public static function Eval(expr : String) : String
    {
      return eval(expr);
    }
  }
}

That’s it. It’s the most simplistic wrapper one could imagine. Next, open up a Visual Studio command line or XNA Game Studio command line (both are found in the Start menu in their respective folders). Navigate to your js file and run this command:

jsc /target:library Evaluator.js

That will compile your JavaScript file into a .NET usable DLL file.

Now create a new Windows Console Application project in Visual Studio. First add a reference to Microsoft.JScript.dll which gives us the JavaScript runtime. Then add a reference to the Evaluator.dll file we produced earlier. Next, drop this code into your Program.cs file:

using System;
using Evaluator;

namespace Calculator
{
	class Program
	{
		static void Main(string[] args)
		{
			Console.WriteLine("Calculator");
			Console.WriteLine("Enter a mathematical formula for evaluation.");
			Console.WriteLine("Type 'exit' to quit.");
			Console.WriteLine();

			string line = string.Empty;

			do
			{
				Console.Write("> ");

				line = Console.ReadLine();

				if (line == "exit")
					break;

				Console.WriteLine(JSEvaluator.Eval(line));

			} while (true);
		}
	}
}

That’s it. We just call into our JSEvaluator class’s static Eval method and write out the results. Now give it a try and play around, it’s really quite fun. I’m not sure exactly how much it handles, and of course I do no exception handling so it’ll likely break if you give it weird stuff, but it’s fun as a little calculator.

Now I just need to implement it into my Shader Toy. :P


Possibly Related Posts

(Automatically Generated)
sspack your images
Expanding animated Gif images
Sprite Sheet Packer Tool – XNA GS Example
Dynamically Refreshed Assets in XNA
Editing The Default XNA Game Studio Project Templates

February 6th, 2010 | 0 comments

I made a bit of progress on my parameter editing today. I have the app fully parsing down parameters and retrieving their values from the shader, and have the starts of the UI for editing in place. I’m using attributes (specifically a UIType string) to instruct what UI should appear. I also plan to use UIType for other things, such as a UIType of “Position” placing something in the 3D view that can be manipulated directly in 3D space.

I need to figure out how to deal with the editor and the shader’s default values. Right now any change to the effect blows away changes to parameters. One solution is to simply store the mapping of parameters and their values such that after a new compilation I can set the correct values. Another idea is to somehow have the changes made in the UI update your effect code such that it writes the new values into the code. Not sure how doable that really is.

Thoughts? Leave ‘em in the comments.


Possibly Related Posts

(Automatically Generated)
Default parameter saving in Shader Toy
Generic UI for parameter editing
Shader Toy – Parameters and Annotations
Adding basic features to Shader Toy
Shader Toy

February 6th, 2010 | 0 comments

Decided to add a little bit of extra features onto Shader Toy before plunging into the next big step of editing parameters. Basically those features boil down to your standard new/open/save File menu, options for choosing one of a few basic primitives for the model (eventually I’ll support imported meshes, but not yet), a split-pane so you can choose how you want your code/view sized, camera controls, and an error display at the bottom so you can fix your broken code (inspired by my own issues figuring out what I did wrong in my shaders to cause them to not compile). As per usual, a video:


Possibly Related Posts

(Automatically Generated)
Shader Toy
Starting parameter editing for Shader Toy
Default parameter saving in Shader Toy
Shader Toy – Parameters and Annotations
Basic Handling of Multiple Controllers

February 5th, 2010 | 4 comments

Yesterday I started work on getting parameters and annotations from the shader in the hopes of eventually generating a UI with which one can modify them. Annotations will be used much like other shader apps giving hints to the UI such as min/max values, UI types, and other things.

So far it’s coming along, slowly but surely. Hopefully this weekend I can get the parameter editing up and running. Until then, watch this demo showing the list of parameters and annotations building as I type. :)


Possibly Related Posts

(Automatically Generated)
Starting parameter editing for Shader Toy
Default parameter saving in Shader Toy
Adding basic features to Shader Toy
Shader Toy
Generic UI for parameter editing

February 2nd, 2010 | 0 comments

A few of my colleagues were discussing F# today and when/where/how it is/isn’t better than C#. I haven’t ever really used F# beyond a very, very brief look at the syntax, so tonight I decided to see what it was all about. As a little project, I decided to make Pong with XNA Game Studio using F# with Visual Studio 2010. :P

F# Pong

I will say that I’ve determined that F# probably has good uses, but my mind is still riding the object oriented train so it’s pretty hard to see how I could do more functional programming for game development. Even my F# is very much standard OO but with a new syntax. In that respect it’s hardly worth showing off, but in the interest of humor (I’ll go with that), I’ve decided to go ahead and talk about the project and the issues to overcome.

First I wanted to use VS 2010. This immediately means no (easy) way to build content. Therefore I needed to do any graphics in code. Not a terribly big deal until I wanted to display a score, but I opted to just show dots representing points (which, by the way, are not clamped in my game so I’m sure after a dozen or two there’ll be a mess up there).

Next I wanted to target .NET 4.0 (since that’s a good part of the reason to use VS 2010). But since the XNA Framework is compiled with the .NET 2.0 CLR in mind and .NET 4.0 has a whole new CLR, there’s a bit of an issue right out of the game if you add your XNA references and hit build. This is easily solved by adding an App.config file with the following in it:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<startup useLegacyV2RuntimeActivationPolicy="true">
		<supportedRuntime version="v4.0"/>
	</startup>
</configuration>

I’m not a CLR person, but from what I’ve read, this allows me to use v2 runtime libraries with a v4 runtime (and no, there is no v3 runtime from what I’ve read; .NET 3.0 and 3.5 use the v2 runtime. But again, I’m not a big CLR person so correct me if I’m wrong :) ).

From there it was all just hacking away. Keeping in mind I learned F# just a few hours ago, here’s the entirety of my code, with no syntax highlighting since my code pasting stuff doesn’t support F#:

open System
open Microsoft.Xna.Framework
open Microsoft.Xna.Framework.Graphics
open Microsoft.Xna.Framework.Input

type Paddle(posX : int, posY : int) =
    let speed = 5
    let x = posX
    let mutable y = posY

    static member W = 10
    static member H = 80

    member this.X with get() = x
    member this.Y with get() = y and set v = y <- v
    member this.Bounds
        with get() = new Rectangle(x - Paddle.W / 2, y - Paddle.H / 2, Paddle.W, Paddle.H)

    member this.Move (keyUp : Keys) (keyDown : Keys) =
        let ks = Keyboard.GetState()
        if ks.IsKeyDown(keyUp)
            then y <- y - speed
        if ks.IsKeyDown(keyDown)
            then y <- y + speed

type Ball() =
    let mutable x = 0
    let mutable y = 0

    let mutable vx = 0
    let mutable vy = 0

    static member W = 10
    static member H = 10

    member this.X with get() = x and set v = x <- v
    member this.Y with get() = y and set v = y <- v
    member this.Bounds
        with get() = new Rectangle(x - Ball.W / 2, y - Ball.H / 2, Ball.W, Ball.H)

    member this.BounceX() = vx <- -vx
    member this.BounceY() = vy <- -vy

    member this.Start (velX : int) (velY : int) =
        vx <- velX
        vy <- velY

    member this.Update() =
        x <- x + vx
        y <- y + vy

    member this.Collide (p : Paddle) = this.Bounds.Intersects(p.Bounds)

type Game1() as this =
    inherit Game()
    let graphics = new GraphicsDeviceManager(this)

    let mutable spriteBatch = null
    let mutable texture = null

    let left = new Paddle(Paddle.W * 2, 300)
    let right = new Paddle(800 - (Paddle.W * 2), 300)
    let ball = new Ball()

    let rand = new Random()

    let mutable leftScore = 0
    let mutable rightScore = 0

    let clampY x : int =
        if x < Paddle.H / 2 then Paddle.H / 2
        else if x > 600 - (Paddle.H / 2) then 600 - (Paddle.H / 2)
        else x

    let reset (b : Ball) =
        let mutable x = 0
        let mutable y = 0

        if rand.Next() % 2 = 0 then x <- -3 else x <- 3
        if rand.Next() % 2 = 0 then y <- -3 else y <- 3

        b.X <- 400
        b.Y <- 300
        b.Start x y

    let bounce (b : Ball) =
        if b.X < Ball.W / 2 then
            rightScore <- rightScore + 1
            reset b
        else if b.X > 800 - Ball.W / 2 then
            leftScore <- leftScore + 1
            reset b

        if b.Y < Ball.H / 2 then
            b.Y <- Ball.H / 2
            b.BounceY()
        else if b.Y > 600 - Ball.H / 2 then
            b.Y <- 600 - Ball.H / 2
            b.BounceY()

    override Game.LoadContent() =
        spriteBatch <- new SpriteBatch(this.GraphicsDevice)
        texture <- new Texture2D(this.GraphicsDevice, 1, 1);
        texture.SetData([| Color.White |])
        reset ball

    override Game.Update gameTime =
        left.Move Keys.Q Keys.A
        right.Move Keys.O Keys.L
        ball.Update()
        bounce ball
        left.Y <- clampY left.Y
        right.Y <- clampY right.Y

        if ball.Collide(left) || ball.Collide(right) then
            ball.BounceX()

    override Game.Draw gameTime =
        this.GraphicsDevice.Clear(Color.Black)
        spriteBatch.Begin()
        spriteBatch.Draw(texture, left.Bounds, Color.Lime)
        spriteBatch.Draw(texture, right.Bounds, Color.Lime)
        spriteBatch.Draw(texture, ball.Bounds, Color.Lime)

        for i in 1 .. leftScore do
            let r = new Rectangle(50 + i * 10, 5, 5, 5)
            spriteBatch.Draw(texture, r, Color.White);
        for i in 1 .. rightScore do
            let r = new Rectangle(750 - i * 10 - 5, 5, 5, 5)
            spriteBatch.Draw(texture, r, Color.White);

        spriteBatch.End()
        base.Draw(gameTime)

let g = new Game1()
try g.Run()
finally g.Dispose()

So there you go. If you’ve ever wanted to make a game with XNA Game Studio using F#, it can be done. It’s interesting, to say the least, but I’m sticking with my C# for now. :)


Possibly Related Posts

(Automatically Generated)
Editing The Default XNA Game Studio Project Templates
XNA Game Studio 3.0 Dated for October 30th
Sprite Sheet Packer Tool – XNA GS Example
How Not To Write A Game – The Reports of the Xbox 360 GC Are Greatly Exaggerated
Dynamically Refreshed Assets in XNA

January 31st, 2010 | 6 comments

Today I decided to start doing more with VS2010 and .NET 4.0. But I also wanted to do something with the XNA Framework. Sadly you can’t really use VS2010 to make a game using XNA Game Studio since it isn’t supported in VS2010. So I figured I’d make some sort of WinForm editor tool. I decided to make a shader editor since I want to start playing more with shaders.

A few hours later and I have something basically workable. I wrote my own XnaPanel for the graphics (slightly based on the WinForms samples, but largely my own stuff) and hooked up the rest. Basically as you type, it will try to compile your shader with every character stroke. If it compiles, it updates the view instantly so you can play around more freely without having to manually click any buttons to get an update.

Currently no support for textures or custom parameters, but these are all things I’m thinking about how to implement moving forward. I’m excited to have a project, even if it isn’t a game.

Here’s a video of my toy in action:


Possibly Related Posts

(Automatically Generated)
Default parameter saving in Shader Toy
Adding basic features to Shader Toy
Shader Toy – Parameters and Annotations
Starting parameter editing for Shader Toy
Visual Studio 2010, XNA, and you

January 23rd, 2010 | 0 comments

After seeing a post on the XNA forums about adapting an algorithm for generating random spaceships, I decided to give it a go myself. It was pretty fun and now I have to figure out whether I want to make a retro shooter using random spaceships. Here’s a video of my app generating a bunch of the space ships.


Possibly Related Posts

(Automatically Generated)
I do too much
I made a Flash game!