“New” technologies (Discovering the TI world)

Today’s post describes my adventure into the world of TI (Texas Instruments) programming. A little bit out of its time but nevertheless interesting to anyone who likes to learn new things and open their horizons.

My cousin is a few months away of completing his Civil engineering degree and is really interested in TI programming, doing scripts that help him solve problems really fast instead of having to do them manually (most useful in exams). He does all the programming in TI-Basic, a language similar to Basic but specific to TI calculators and like most (if not all) of these interpreted languages, they don’t provide any security if you want to sell your programs. Thus he turned to C programming. Now, C is a whole new beast when compared with this TI-Basic language and it’s much harder to start doing some interesting things without your programs crashing all over the place.

He asked me for help but having no knowledge of this TI-Basic or C tools/libraries/APIs available for these calculators and without access to internet and limited documentation and samples I wasn’t able to get complete the program although I did manage to make half of it. This was a 4 hour marathon that started around 22h30 till 2h30 and I had to admit defeat at the time since I was very tired but I promised to help him to finish the program. I don’t have a TI calculator so I needed to find a way to test it in my PC and fortunately there is an IDE along with an emulator and ROM image available for free on the internet. I’ll list what’s needed to be able to run and the debug C programs for TI calculators because it took me a while to get everything up and running due to incompatible versions of software.

  1. Download and install TIGCC 0.96 beta 8 (Unofficial version)
  2. Download and install TiEmu 3.02a
  3. Download TI Voyage 200 ROM image (my cousin’s model)
  4. Create a project in TIGCC
  5. Run the project (Debug –> Run)
  6. When the TiEmu wizard appears select “You have downloaded a FLASH upgrade on the TI website”
  7. Then select the TI Voyage 200 ROM image you’ve downloaded before.

Voilà! If everything went well you should see the program running on the emulator.

If you want to debug your project, follow these steps:

  1. Project –> Options
  2. Select the “Compilation” tab and then the option “Generate debug information”
  3. Run the project (Debug –> Run)

You should see new windows open if you followed these steps. These are the debug windows that will help you find your bugs.

Here are a few snippets I had to discover here and there through samples / documentation:

/* Retrieves strings passed into the program */
ESI argptr;
int argtype;
char *str;
InitArgPtr (argptr);
while ((argtype = GetArgType (argptr)) != END_TAG)
{
  if (argtype == STR_TAG)
  {
    str = GetStrnArg(argptr);
    printf("%s", str);
  }
  else
    break;
}
/* Get a variable from TI-Basic into C */
SYM_ENTRY *sym_entry = SymFindPtr (SYMSTR ("variableName"), 0);
if (!sym_entry)
  return FALSE;
ESI expr = HToESI(sym_entry->handle);
int argType = GetArgType(expr); /* Retrieves the type of the expression */
long num = GetIntArg(expr); /* Retrieves an integer if the expression holds an integer (positive or negative) */
/* Directly from TIGCC documentation: Run a TI-Basic program or statement from C */
char fname[25];
HANDLE h;
strcpy (fname, name);
strcat (fname, "()");
push_parse_text (fname);
h = HS_popEStack ();
TRY
  NG_execute (h, FALSE);
FINALLY
  HeapFree (h);
ENDFINAL

Including tigcclib.h will make sure that you have all the TI library functions available in C. For the last snippet you need to follow these steps if you have an error regarding push_parse_text function:

  1. go to Project->Options
  2. select the “Compilation” tab
  3. click on “Program Options…”
  4. select the “Operating System” tab
  5. and set the “Minimum AMS Version” as 1.01

Kinect Calibration

This program adjusts Kinect to better see the user, this way the user doesn’t have to move back or forward (unless Kinect’s angles aren’t enough to see the user). I think this is a useful thing to have when you start your Kinect application.

The code is very simple to follow. Use Kinect’s elevation angle to change the Kinect’s “view” and track the user in sight. For each angle count how many joints Kinect is tracking and save that angle as the best if we reach a new maximum number of tracked joints.

void KinectSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
	// Get skeleton information
	using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
	{
		if (skeletonFrame != null && m_skeletonData != null)
		{
			skeletonFrame.CopySkeletonDataTo(m_skeletonData);
		}
	}

	m_curTime = m_watch.ElapsedMilliseconds;

	if (m_calibrationState == CalibrateState.GoingDown)
	{
		// If the sensor reach its lowest angle, let's do a full scan from min angle to max angle.
		if (m_curTime >= WaitTime)
		{
			m_watch.Reset();
			m_watch.Start();

			m_bestAngle = m_kinect.MinElevationAngle;
			m_maxNumTracked = 0;

			m_calibrationState = CalibrateState.GoingUp;
			m_kinect.ElevationAngle = m_angles[m_curAngleIndex++];
		}
	}
	else if (m_calibrationState == CalibrateState.GoingUp)
	{
		if (m_curTime >= WaitTimeGoingUp)
		{
			m_watch.Reset();
			m_watch.Start();

			// If we scanned all the angles, lets adjust kinect to the best angle.
			if (m_curAngleIndex > m_angles.Length - 1)
			{
				m_calibrationState = CalibrateState.GoingBest;
				m_kinect.ElevationAngle = m_bestAngle;
				return;
			}

			m_kinect.ElevationAngle = m_angles[m_curAngleIndex++];
		}

		// For each skeleton, count the number of tracked joints and save the best
		// angle when the number of tracked joints is greater than previous values.
		foreach (Skeleton skeleton in m_skeletonData)
		{
			if (skeleton == null)
				continue;

			if (skeleton.TrackingState == SkeletonTrackingState.Tracked)
			{
				//TODO: Improve algorithm by using the number of inferred joints.
				int numTracked = 0;
				int numInferred = 0;
				foreach (Joint joint in skeleton.Joints)
				{
					if (joint.TrackingState == JointTrackingState.Tracked)
						numTracked++;
					else if (joint.TrackingState == JointTrackingState.Inferred)
						numInferred++;
				}

				if (numTracked >= m_maxNumTracked)
				{
					m_maxNumTracked = numTracked;
					m_bestAngle = m_kinect.ElevationAngle;
				}
			}
		}
	}
	else if (m_calibrationState == CalibrateState.GoingBest)
	{
		// Just wait until kinect adjusts itself to match the best angle.
		if (m_curTime >= WaitTime)
		{
			m_watch.Reset();

			m_calibrationState = CalibrateState.Idle;
			m_kinect.SkeletonFrameReady -= KinectSkeletonFrameReady;

			// Reset Kinect state.
			DisableStreams();
			EnableStreams();

			// Signal that we finished the calibration.
			if (OnCalibrationComplete != null)
				OnCalibrationComplete();
		}
	}
}

You may notice two things about the code:

  • First is that I’m using time to control between Kinect movements. The reason for this is that if we try to compare Kinect with the angle we set, we might not get the same value for different reasons (Kinect sensor is not 100% accurate or it couldn’t physically rotate the sensor to that exact angle).
  • And second is the fact that I’m only scanning the skeleton for some angles. I don’t know if this is a Kinect’s limitation or if I did something wrong in the code but I couldn’t track any joints while Kinect was moving. So what I did was move the sensor between some angles and wait there a bit to count the bones for each one of those angles.

Known limitations:

  • it only supports 1 user at this moment;
  • the scanning process is not ideal.

Download:

Kinect Calibration (13Kb)

Kinect Slide Tutorial

Part of my Kinect Portfolio presentation had slides controlled by gestures. This short tutorial explains how I made it work. As I said in the other post, I used a Gesture Library to help with the gesture recognition, Kinect SDK Dynamic Time Warping (DTW) Gesture Recognition. This is a great project that is available on CodePlex and uses a cool algorithm called Dynamic Time Warping which is pretty cool for pattern recognition such as gestures or voice, among others. If you’re curious like me and want to know how this algorithm works, take a look at this link.

But onto the slide tutorial. I started by taking the core files to handle the gesture recognition and plug it in with my project. After a couple of little changes mostly to call an event handler when a gesture is recognized and to work with the final Kinect SDK 1.0., I used the original program to generate the gestures file which contains the information needed to detect gestures. I actually recorded two different gestures for each “SlideLeft” and “SlideRight” gesture just to make sure that different gestures done by different people would be caught by the algorithm.

The next step was to figure out how to animate the slides. I didn’t have experience with WPF animations but I arrived at this solution which works but might not be the best.

VisualStates and their transitions

I created 3 visual states to handle the slide left and slide right: previous (VisualState 1), current (VisualState 2) and next (VisualState 3). There are 2 visual transitions (left and right) between each 2 states and every time we change from one visual state to another we update the “next” target with new slides.

To automatize the transitions I decided to create a SlideManager that starts by reading all the “slides” (Grid elements) under a parent element and initializing the visual states by adding the event handlers. I created a simple structure to keep track of slides and transitions between slides because initially I wanted to include vertical transitions by ended up not doing them.

// Initialize slides.
for (int i = 0; i < mainSlideContainer.Children.Count; i++)
{
	Grid slide = mainSlideContainer.Children[i] as Grid;
	if(slide == null)
		continue;

	Slide s = new Slide()
				            {
				                Name = slide.Name,
				                GUIElement = slide,
				            };

	m_slides.Add(s);
}

for (int i = 0; i < m_slides.Count; i++)
{
	Slide nSlide = null;
	Slide pSlide = null;

	if (i < m_slides.Count - 1)
		nSlide = m_slides[i + 1];
 	if (i > 0)
		pSlide = m_slides[i];

	Slide s = m_slides[i];
	s.Transitions = new Dictionary();
	if(nSlide != null)
		s.Transitions.Add(Transition.RightToLeft, nSlide);
	if (pSlide != null)
		s.Transitions.Add(Transition.LeftToRight, pSlide);
}

There are two other important methods that change slides: MoveToNextSlide() and MoveToPrevSlide(). Each method checks if the current slide has the transition we want to perform, updates the current slide and visual state attribute members and calls the method that actually performs the transition.

public void MoveToNextSlide()
{
	if(m_inTransition)
		return;

	Slide nextSlide;
	if (m_curSlide.Transitions.TryGetValue(Transition.RightToLeft, out nextSlide))
	{
		m_prevSlideIndex = m_curSlideIndex;

		m_curSlideIndex = Math.Min(m_curSlideIndex + 1, m_slides.Count - 1);
		m_curSlide = m_slides[m_curSlideIndex];
		m_curVSIndex = (m_curVSIndex + 1) % m_visualStates.Count;
		m_curVS = m_visualStates[m_curVSIndex];

		m_inTransition = true;
		ExtendedVisualStateManager.GoToElementState(m_vsManagerContainer, m_curVS.Name, true);
	}
}

Another part of the code that is worth mentioning is the two event handlers at the end of this manager: Storyboard_Completed and VSGCurrentStateChanged.

private void Storyboard_Completed(object sender, EventArgs e)
{
	m_slides[m_curSlideIndex].GUIElement.Opacity = 1;
	m_slides[m_curSlideIndex].GUIElement.Visibility = Visibility.Visible;

	if (m_prevSlideIndex != m_curSlideIndex)
	{
		m_slides[m_prevSlideIndex].GUIElement.Opacity = 0;
		m_slides[m_prevSlideIndex].GUIElement.Visibility = Visibility.Collapsed;
	}
}

The visual state transitions do the slide movement and the storyboard controls the opacity and visibility of the element in that state. Whenever we change from one state to the other we have to reset the opacity and visibility properties so that the next time we do the transitions the new slides have the correct properties.

private void VSGCurrentStateChanged(object sender, VisualStateChangedEventArgs e)
{
	VisualState nvs = m_curVS;

	// update the next visual state time line (only if necessary)
	if (m_curSlideIndex < m_slides.Count - 1)
	{
		Timeline tl = FindObjectByName(nvs.Storyboard.Children, nvs.Name + "_next" + TLOpacName);
		if (tl != null)
			tl.SetValue(Storyboard.TargetNameProperty, m_slides[m_curSlideIndex + 1].Name);

		tl = FindObjectByName(nvs.Storyboard.Children, nvs.Name + "_next" + TLVisName);
		if (tl != null)
			tl.SetValue(Storyboard.TargetNameProperty, m_slides[m_curSlideIndex + 1].Name);
	}

	m_inTransition = false;
}

The same goes for the storyboard target name property, whenever we change to a new state we have to update the next slide. I also used a flag to prevent it from starting a new transition while we’re still doing the animation from the current transition.

The KinectManager is a simple class to handle the Kinect’s initialization that I adapted from the samples. It’s far from complete as it is but it serves well for this tutorial.

You may ask yourself why go through all this trouble when there is PowerPoint and Kinect applications to do the slide animation controls? Firstly, because it is fun to explore and learn new things and secondly because there are parts of the complete interactive portfolio that weren’t so easy to do in PowerPoint such as the particle system or the pong game.

Note: The transitions between texts were programmed in a similar way but instead of using 3 Visual States I only used 2, one for display the text and the other and to hide it, then it’s just a matter of setting the right text when you do the transitions.

Download
Kinect Slide Tutorial (requires: .Net4, Kinect SDK 1.0, VS2010 and up)

Windows Phone 7 – Tips for programming games

Puzzle Jumble started as an experiment to test and learn a little bit about XNA and Windows Phone 7. I decided to write some tips to help those who like me started experimenting with XNA and WP7.

Stencil

The stencil was used to cut the hole for doors so that pieces would appear to be sliding over the doors but under the board. The stencil was active in every frame which lowered the frame rate quite a lot (18-20 FPS). The solution was to activate the stencil only when a piece is going to leave through a door, so be careful when using the stencil buffer on the WP7.

DXT

GPUs like the DXT format and the WP7 is no exception, but unlike desktop’s GPUs the WP7 processor only loads DXTs that are power of two. My regret is not using DXT from the beginning when I started working on Puzzle Jumble. When I changed all my textures to DXT I had to change a lot of code, all the draw calls where I was using a position to draw a sprite had to be changed to a rectangle because the textures had a different resolution (power of two).
But the change was very useful:
– I gain some FPS;
– the memory footprint was reduced from 95MB (total peak) to about 45MB;
– the XAP file was reduced from 25MB to 9MB;
– thus, as a consequence reduced the loading times.

Floats (culture)

When parsing floats it’s easy to add bugs in your application if you ignore the culture format. Make sure to use the correct format provider or at least use the culture independent System.Globalization.NumberFormatInfo.InvariantInfo.

Float precision

Another problem that I found when using floats was that this comparison: if(a < float.Epsilon) (when a = 0) would work everywhere except on the WP7 device itself where it would always return false.

HTML page requests

This is not a WP7 specific problem but I thought it was worth mentioning it. Since Microsoft didn’t provide us with an API for leader boards I implemented an online score system using our servers to keep track of the users’ scores and best times.
The system was working fine to post data online but there was a problem when retrieving it. The first time the data was retrieved everything was fine but the subsequent retrievals would always be the same as if the data was cached somewhere.
After searching for a while I found out that the problem was that the HTTP request was being cached since the URL didn’t change, it would cache the result for that URL. The solution was to add a random attribute to the URL so that the the request couldn’t be cached. Not pretty but it was the only way I found to make it work.

And those were the problems that I found during the Puzzle Jumble’s development phase. I hope this useful for you!

VSX: How to detect when Property Pages (Project Properties) window is closed

I posted a thread on the MSDN forums to seek for help in detecting when the property pages window (accessible through project->properties) in Visual Studio is closed. You can follow up the thread here: Detect when project properties window is closed. Ziwei Chen was really helpful and could find me a way to achieve this in C# projects but to my surprise, to achieve the same results for C++ projects proved to be harder than I thought.

I decided to write this short tutorial to help those who have the same problem in future.

First of we need to detect when the user click in any project->properties menu selection. Put this code where you initialize your add-in:

m_commandEventsAfterExecuteProperties1 =
    m_applicationObject.DTE.Events.get_CommandEvents("{5EFC7975-14BC-11CF-9B2B-00AA00573819}", 396);
m_commandEventsAfterExecuteProperties1.AfterExecute +=
    new _dispCommandEvents_AfterExecuteEventHandler(CommandEvents_AfterExecuteProperties);

m_commandEventsAfterExecuteProperties2 =
    m_applicationObject.DTE.Events.get_CommandEvents("{5EFC7975-14BC-11CF-9B2B-00AA00573819}", 397);
m_commandEventsAfterExecuteProperties2.AfterExecute +=
    new _dispCommandEvents_AfterExecuteEventHandler(CommandEvents_AfterExecuteProperties);

These command events ids were found using the technique described in this post: How to find Visual Studio command bars. When registering the event handlers be careful with this: Visual Studio .NET events being disconnected from add-in. So declare these as member attributes and not as method variables:

private CommandEvents m_commandEventsAfterExecuteProperties1;
private CommandEvents m_commandEventsAfterExecuteProperties2;

Now, lets dig into some rather awful code to get our property pages handle. Property pages in .NET projects are document windows but, unfortunately, if we try to call the ActiveDocument property directly through the ActiveEnvDTE library, it will throw an exception. So, with the precious help of Chen, this is the code came up with:

// For C# projects the property pages is a document window, lets try to find it.
// I was unable to get a handle using the EnvDTE library which could have eased things a bit.
bool propertyPagesFound = false;

IVsWindowFrame[] frames = new IVsWindowFrame[1];
uint numFrames;

IEnumWindowFrames ppenum;
m_uiShell.GetDocumentWindowEnum(out ppenum);

while (ppenum.Next(1, frames, out numFrames) == VSConstants.S_OK && numFrames == 1)
{
	m_frame = frames[0] as IVsWindowFrame;
	object title;
	m_frame.GetProperty((int)__VSFPROPID.VSFPROPID_Caption, out title);

	// I really don't like the way I'm using to retrieve the property pages handle.
	//TODO: CHANGE IF BETTER SOLUTION IS FOUND.
	if ((title as String).ToLowerInvariant() == GetStartupProject().Name.ToLowerInvariant())
	{
		propertyPagesFound = true;
		((IVsWindowFrame2)m_frame).Advise(this, out m_cookieWindowFrameNotify);
	}
}

First, all document windows are retrieved to the ppenum variable and next we go one by one and test its caption name to see if it’s equal to the project’s name. After we got our desired window frame we register the IVsWindowNotifyFrame event handler.

In the C++ case, things are a bit different. The property pages window isn’t an instance of document or frame, it’s a dialog window. To catch the dialog window events we use an auxiliary class that listens for the destroy message in the WndProc method.

// If we didn't find any property pages before then we need to go and search for a C++ one since they're
// different from C# property pages.
if (!propertyPagesFound)
{
	//NOTE: This might not work well if we happen to have two Visual Studio instances with the same
	//      project names.
	//TODO: TRY TO FIND A WAY TO FIX IT.
	//HACK: Go through all windows to find the project properties dialog window that matters.
	FindWindowLike.Window[] list =
	    FindWindowLike.Find(IntPtr.Zero, GetStartupProject().Name.ToLowerInvariant() + " property pages", "");
	
	// Release any handle we might have.
	if (m_subclassedMainWindow != null)
	{
		m_subclassedMainWindow.ReleaseHandle();
		m_subclassedMainWindow = null;
	}

	if (m_subclassedMainWindow == null && list != null && list.Length >= 1)
	{
		m_subclassedMainWindow = new SubclassedWindow(list[0].Handle);
	}
}

Apart from that FindWindowLike that we’ll check later, I think the code is pretty simple to understand. I really don’t like to have to search through all windows in the system but apparently the dialog window couldn’t be found under the dte’s MainWindow.HWnd hierarchy.

 

As for the event implementations, here is the C# first:

public int OnShow(int fShow)
{
	switch (fShow)
	{
		case (int)__FRAMESHOW.FRAMESHOW_TabDeactivated:
			// Property pages lost focus, put your code here!
			((IVsWindowFrame2)m_frame).Unadvise(m_cookieWindowFrameNotify);
			m_cookieWindowFrameNotify = 0;
			break;

		default:
			break;

	}

	return VSConstants.S_OK;
}

We need to implement the IVsWindowFrameNotify interface and in the OnShow you can check when the tab is closed. I used the FRAMESHOW_TabDeactivated because it is called when the tab loses focus and also when the tab closes.

Now for the C++ version:

/// 
/// Auxiliary window to intercept messages sent to the property pages dialog window.
/// 
public class SubclassedWindow : NativeWindow
{
	private const int WM_NCDESTROY = 0x0082;

	public SubclassedWindow(IntPtr hWnd)
	{
		AssignHandle(hWnd);
	}

	protected override void WndProc(ref Message m)
	{
		if (m.Msg == WM_NCDESTROY)
		{
			// Property pages window was closed, put your code here!
		}
		base.WndProc(ref m);
	}
}

As explained before, in this case we have an auxiliary window to catch the destroy event for the dialog window.

I found this script over at FindWindowLike for C# and changed it a bit to fit my needs. I modified the code that compared the window title; created a new class and changed p/invoke methods’ signature just to keep VS quiet about some warnings.

/// <summary>
/// Now we have to declare p/invoke methods in a class called NativeMethods (or similar) to
/// shut up some VS warnings.
/// </summary>
internal static class NativeMethods
{
	[DllImport("user32")]
	internal static extern IntPtr GetWindow(IntPtr hwnd, int wCmd);

	[DllImport("user32")]
	internal static extern IntPtr GetDesktopWindow();

	[DllImport("user32", EntryPoint = "GetWindowLongW")]
	internal static extern int GetWindowLong(IntPtr hwnd, int nIndex);

	[DllImport("user32")]
	internal static extern IntPtr GetParent(IntPtr hwnd);

	[DllImport("user32", EntryPoint = "GetClassNameW", CharSet = CharSet.Unicode)]
	internal static extern int GetClassName(IntPtr hWnd, [Out] StringBuilder lpClassName, int nMaxCount);

	[DllImport("user32", EntryPoint = "GetWindowTextW", CharSet = CharSet.Unicode)]
	internal static extern int GetWindowText(IntPtr hWnd, [Out] StringBuilder lpString, int nMaxCount);
}

// FROM: http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_21611201.html
// Just changed the way it checked strings.
internal class FindWindowLike
{
	internal class Window
	{
		public string Title;
		public string Class;
		public IntPtr Handle;
	}

	private const int GWL_ID = (-12);
	private const int GW_HWNDNEXT = 2;
	private const int GW_CHILD = 5;

	public static Window[] Find(IntPtr hwndStart, string findText, string findClassName)
	{
		ArrayList windows = DoSearch(hwndStart, findText, findClassName);

		return (Window[])windows.ToArray(typeof(Window));

	} //Find


	private static ArrayList DoSearch(IntPtr hwndStart, string findText, string findClassName)
	{
		ArrayList list = new ArrayList();

		if (hwndStart == IntPtr.Zero)
			hwndStart = NativeMethods.GetDesktopWindow();

		IntPtr hwnd = NativeMethods.GetWindow(hwndStart, GW_CHILD);
		while (hwnd != IntPtr.Zero)
		{
			// Recursively search for child windows.
			list.AddRange(DoSearch(hwnd, findText, findClassName));

			StringBuilder text = new StringBuilder(255);
			int rtn = NativeMethods.GetWindowText(hwnd, text, 255);
			string windowText = text.ToString();
			windowText = windowText.Substring(0, rtn);

			StringBuilder cls = new StringBuilder(255);
			rtn = NativeMethods.GetClassName(hwnd, cls, 255);
			string className = cls.ToString();
			className = className.Substring(0, rtn);

			if (NativeMethods.GetParent(hwnd) != IntPtr.Zero)
				rtn = NativeMethods.GetWindowLong(hwnd, GWL_ID);

			if (windowText.Length > 0 &&
				windowText.ToUpperInvariant().Contains(findText.ToUpperInvariant()) &&
				(className.Length == 0 ||
					className.ToUpperInvariant().Contains(findClassName.ToUpperInvariant())))
			{
				Window currentWindow = new Window();

				currentWindow.Title = windowText;
				currentWindow.Class = className;
				currentWindow.Handle = hwnd;

				list.Add(currentWindow);
			}

			hwnd = NativeMethods.GetWindow(hwnd, GW_HWNDNEXT);
		}

		return list;
	} //DoSearch
} //Class

And that’s it! I’d really appreciate if someone could tell me how to improve some of this code, mostly the parts where I have TODOs and/or HACK.
Thank you and I hope you find this useful!

Thanks to:

I wanted to thank Ziwei Chen for the excellent help at the forums.

References

VSSDK IDE Sample: Combo Box
Detect when project properties window is closed
I need FindWindowLike for C#
How to find Visual Studio command bars
Visual Studio .NET events being disconnected from add-in

Links:

Visual Studio Extensibility Forum
VSX Home on Code Gallery
Visual Studio on MSDN

Don’t be nervous

Reading an interesting article about comedy in games at GDC I found something rather interesting and wanted to share it with you:

Tim: When we started on Monkey Island, I don’t know about Dave [Grossman], but I thought we were writing the temporary dialogue for that game. Cause we were really new, and there was a big company there with Lucasarts and George Lucas and everyone. So I was sure they’d have professionals come and write the dialogue. So we were just kind of goofing around and writing really silly dialogue. And it took the pressure off us cause we didn’t sit there and wonder, “Is this good enough?” We were just making each other laugh in the office. And then, as it went on, Ron said, “No, no, no. This is the dialogue for the game.” And I was like, “Oh, god.”

And we never wrote anything funny after that.

Folder Creator

A few days ago a friend asked me if I had or knew a program that would create folders given a two numbers. Example: if we put 01 – 04 it would create folders from 01 to 04 and so on. Well, I didn’t have nor knew any program that did what was asked so I just thought: this is pretty simple, why not do it myself? And after a hour or so I had the first version. The program asks where you want to create your folders, the base folder name and the number range.
Folder Creator

Instructions:

  • Insert/Choose the base folder. You may enter a folder manually or you can double click the field to open a folder browser dialog an choose a folder. The base folder indicates where the folders will be created. Example: c:\test\
  • Insert a base name (not required). The base name will serve as the name which will be appended by the number of each folder. Example: inserting folder in the base directory textbox will create folders in the path: c:\test\folderXXX where XXX is a number.
  • Insert a start number. Start number is the starting number of the range (start-end) that will be appended to the base name (if there is one). Continuing with our example: 003 will create folder in the path: c:\test\folder003 and so one until we reach the end number.
  • Insert an end number. End number is the number that ends the range (start-end) which will be end appended to the base name (if there is one). Again, in our example: 010 will create folders in the path: c:\test\folder003 (which was our start number), c:\test\folder004 … an so on … ending with c:\test\folder010.
  • Escape key closes the application.

Note: The start number must be less than or equal to the end number.

The program hasn’t been fully tested so it’s most likely that you’ll find bugs in the program. If you find some please report them to me. With time I may add more things if needed, so feel free to suggest new features.

You’re free to use this code as long as you don’t blame me for any changes/bugs, as well as, don’t demand anything from me. Download folder creator here and/or download source code here.

Let me know if you have any bugs/questions/comments/suggestions.

Before I go, I want to thank Victor Romão for the idea for this program.

Diagramming for dummies

Hi, in the past months I’ve been working with the .Net framework either in C# and in C++/CLI. I’ve been more focused in the GUI part of the framework playing with controls and developing some simple ones. Now I needed to make a more challenging control that would draw diagrams, so I went looking for references and I found this great article http://www.codeproject.com/cs/miscctrl/NetronLight.asp by NetronProject. I liked the design of the code and decided to use it and make some modifications to my needs. Below you can find the modifications I did to the code.

Changelog (2006-04-02):

  • Added scroll bars (maybe a bit more of tuning is needed.)
  • Added type for connectors (none, input, output. An input connector can’t connect to another input connector and the same goes for the output connector.)
  • Added a new type of shape (the actionbox that has some inputs, in green, and outputs, in blue.)
  • You can indicate if a shape allows internal connections, i.e., a connection from two connectors within the same shape.
  • Delete key deletes the selected component.
  • When deleting a component, it will delete all connections associated with it.
  • The controls gains focus automatically as the mouse passes over it. This was added so we can use the mouse whell (for scrolling the scrollbars) and keyboard keys, like Delete, more easily.
  • Mouse cursor changes to a resizer when hovering a shape and to a hand when hovering a connector.
  • Fixed some problems with the drawing/refreshing of shapes, connections and connectors.

These modifications haven’t been fully tested yet so it’s most likely that you’ll find bugs in the control. If you find some please report them to me. With time I may add more things as I need, so if you interested in this control, just check this page from time to time.
You’re free to use this code as long as you don’t blame me for any changes/bugs that were introduced and don’t demand anything from me. Just download it here if you accept these conditions.

If you have any bugs/questions/comments/suggestions just send me an e-mail.
Before I go, I want to thank NetronProject team for this great control and tutorial.

References:

http://www.codeproject.com/cs/miscctrl/NetronLight.asp – Diagramming for dummies – The Code Project – C# Controls

Regular Expressions (part 2)

The first regexp was thought after someone in the IRC asked for some help. They asked if anyone could remove the comments from a c++ source code file. I tried to help:

(/\*([^*]|[\n]|(\*+([^*/]|[\n])))*\*+/)|(//.*)

Note: this is not the exact expression that I came up at the time but this one is richer and better than the other one I answered at the time.

Let’s analyze it:

  1. /\* – to match with the beginning of any comment /*.
  2. [^*]|[\n] – to match any characters except the * or match with the new line character.
  3. \*+ – matches any number of * in the middle of comments.
  4. [^*/]|[\n] – to match with any character except these two * and / or match a new line.
  5. \*+/ – matches any number of * and the / character.
  6. //.* – matches // followed by any characters.

After matching with the first /* the expression becomes a bit harder to understand. What happens next is that we match anything (including new lines) except the * or we match one or more * followed by anything except the end of comment */. After we match with one ore more * followed by a /.
The second part matches only 1 line comments in C++.

Have you ever received an email full of HTML garbage? It happened to me more than once and it’s extremely annoying having to filter the text in the middle of the HTML. I remembered to create a regular expression that would help me remove this kind of garbage. If you didn’t understand what I meant by garbage, here is an example of these emails:

<html><div style='background-color:'><DIV>
<DIV>
<P class=MsoNormal><FONT color=navy face=Impact size=5><SPAN style="BACKGROUND: #f7f7f7; COLOR: navy;
FONT-FAMILY: Impact; FONT-SIZE: 18pt">This is extremely&nbsp</SPAN></FONT><FONT color=#9966ff
face=Impact size=5 FAMILY="SANSSERIF"> <SPAN style="BACKGROUND: #f7f7f7; COLOR: #9966ff; FONT-FAMILY: Impact;
FONT-SIZE: 18pt">annoying&nbsp;</SPAN></FONT> <FONT color=navy face=Tahoma FAMILY="SANSSERIF">
<SPAN style="BACKGROUND: #f7f7f7; COLOR: navy; FONT-FAMILY: Tahoma">&nbsp;</SPAN></FONT>

In this case I used this regexp:

(\<[^\<]*\>)|&nbsp;

It’s quite pretty to grasp this one, we just grab everything that is between two < > but we have to put a safe guard to exclude a possible < since regular expressions are pretty greedy and like to match whatever they can.
The &nbsp; match the HTML code for space characters serve. We could filter other similar characters but this one seems to do the trick in most situations.

Regular Expressions (part 1)

A while ago I was refactoring the #include’s of c++ project and I needed to know which project files were including STL files (in our case it meant that the included files wouldn’t have the .h). So, I decided to make a regular expression to find these files:

\#include:b*\<.+[^\.h]\>

If you insert this simple expression in the search box of the Visual Studio you can get a list of all #include’s that don’t have the .h in the name of the file. Now I’ll break the regular expression and try to explain it step by step:

  1. \#include – to match with any #include expression.
  2. :b* – to match with any number of spaces or tabs.
  3. \< – to match with the < character.
  4. .+ – to match one or more characters.
  5. [^\.h] – exclude the .h characters.
  6. \> – match with the > character.

Meaning of the characters in the expression:

  • \ – escape a character, the character after this symbol is treated as a normal character instead of a special character used in regular expressions.
  • :b – space or tab.
  • * – 0 or more times.
  • + – 1 or more times.
  • . – any character except the end of line.
  • [] – any set of characters inside the [].

Note: this regular expression might not be compatible with other programs because it uses specific expressions of the VS, such as the :b that matches a space or tab.

Another example, remove the initial characters (garbage) from actual lines code:

1.          #include <iostream>
2.             using namespace std;
3.         int main()
4.           {
5.           cout << "Hello World!";
6.        return 0;
7.         }

I’m sure you already found something like this and when you put it in the editor it’s really a pain in the ass to remove all that garbage line by line. Here’s another expression that will help in this task:

^[^a-zA-Z_$/{}\#"'\+\-]+

Again, let’s go step by step:

  1. ^ – this means that we’ll start to match only at the beginning of a line.
  2. [^…]+ – matches any character that is not in the set of characters that follows the ^.
  3. a-zA-Z_$/{}\#”‘\+\- – exclude the characters from a to z (same for uppercase letters) and the following characters: _, $, /, {, }, #, , , + and .

This means that this expression catches anything that starts with any character except the characters that are excluded. In the VS, replace this expression by an empty string to remove the garbage.
Note: It’s quite possible that the regular expressions presented here will fail (specially the second one), because it’s really complicated to test all the possibilities but in the general case, these should work.

I hope these two examples will make you see the power of regular expressions or even be useful to you ;) If you have any comments about this article or do you have any problems with a regular expression? Just let me know.