Archive for the ‘Tutorials’ Category

Mac OS X on a Dell Vostro A90 (Mini 9)

Wednesday, August 19th, 2009

mac vostro openOver the summer I had a little argument with a coworker about the “Mac tax.” I was telling him that a Mac uses pretty much the same hardware you will find in a “PC” (that word, PC, used in that context annoys me because PC is Personal Computer, so technically as Mac is a PC, but marketing prevails I guess) but Mac’s are a lot more expensive. So in an attempt to prove my point, I tried to install Mac OSX on to my HP laptop. After about 15 tries, all I could get it to do was finish the installation. Never got it to boot. I gave up, moved to California, bought a MacBook Pro because I wanted a Mac and the USC Bookstore was having a sale.

Very happy with my MacBook Pro I did not pursue ihackintosh any more. Then after the netbook craze, I found a lovely Mac OSX netbook compatability chart and noticed everything works on the Dell Mini 9/Vostro A90 (they are the SAME computer). A Mac netbook, that would be cool!

I waited, trying to save up some splurging money. Meanwhile I helped two of my friends pick out netbooks for themselves (both were HP Mini 10, one with solid state and one without), which made me want to buy one. On top of that I found some Dell discounts from a friend, and I went to the Dell Outlet and bought a Vostro A90 with 16GB SSD and Ubuntu for $280 delivered.

Since I am going to be hacking and all that, I figured I would buy a nice retail copy of Mac OSX 10.5.6 (which I also got at the USC Bookstore, seeing as they sell it for $99).

With my new-to-me netbook and fresh retail copy of Mac OSX, I went home and stayed in on a Friday night, to bump up my geek cred!

This is not meant to be a full tutorial, there are many many online, but more of a checklist of items needed and the guide I followed, and some road blocks. And a little review of my Mac Vostro A90 at the end.

I only had one issue worth noting. After I booted off of the DellMiniBoot 8.02b1 and swapped the disc for the retail Mac OSX install disc it took a few tries for the OSX installer to load. The Vostro didn’t recognize the install disc right away after I swapped the discs. I had to wait about a 15 count before I hit ENTER on the boot screen after I put in the retail Mac OSX install disc. So if you get stuck and the intaller will not load, just keep trying! It took me about 10 minutes of fiddling before I go it to load the installer. Other than that, follow the guide to the letter, they do a very good job of outlining what you need to do.

UPDATE: To get to the BIOS hit 2 at boot up, and hit 0 to get to the boot menu.

UDPATE: ***For sleep to work you must deselect usb wake from sleep and usb legacy mode in bios***

mac vostro closed

Checklist:

I have been using my Dell Vostro for about 2 weeks now. I took it on a trip to Chicago, and it played about 4 hours of TV shows from a USB stick on the plane ride. Which is pretty good considering its a refurb and I know that batter is not at 100%. The computer is very small though. The screen is nice, but the resolution is only 1024 x 600. Most web pages look fine, and you kinda get used to it. It does have a VGA port if so you can hook up an external monitor. I got it to play relatively smooth streaming video from Hulu at 1280 x 1024 full screen. The biggest issue I have with the computer is the keyboard layout. The quote ( ‘ ) is not in the normal place by your right pinky, but down below the period next to the spacebar. So I hit enter instead of ‘, which is really annoying when you are IMing.

Most of the time I use it at work, I have Synergy installed on my work Windows XP machine, and SynergyKM installed on the Mac Vostro. Mich is great for testing websites. Just copy the URL and move my mouse down to the Mac Vostro and paste it in and see how it looks! Aside from that, everything works, runs quite smooth, and quiet. Overall, I am really happy with it.

AIR/Flex URLRequest: Sending Authentication Headers

Wednesday, June 17th, 2009

If the request requires authentication and URLRequest.authenticate is set to true (the default) the operating systems login window will popup asking for credentials. These will be automatically sent in the request. To manually set the username and password there are a few ways:

URL Request Defaults:

URLRequestDefaults.setLoginCredentialsForHost("www.domain.com",username,password);

Headers:

var encAuth:Base64Encoder = new Base64Encoder();
encAuth.encode(username+":"+password);
var header:URLRequestHeader = new URLRequestHeader("Authorization","Basic "+ encAuth.toString() );
var request:URLRequest = new URLRequest(url);
request.requestHeaders.push(header);

Under both ways, once a successful login occurs the credentials are remembered while the application is open and the user is not asked for username and password again.

Mac OS X Leopard and Windows XP File Sharing

Saturday, June 6th, 2009

I have a Windows XP Media Center 2005 computer, a MacBook Pro and a few other Windows and Mac computers stroll through my network from time to time. I have my Media Center PC streaming media to the XBOX 360, file server, printer etc. I had the Media Center machine before the MacBook Pro. So when I got my MacBook Pro, and hooked it into my network I was suprised that all my file shares were automatically picked up and I could read my movies and print, all as a Guest. Which is exactly how I wanted it. Login to change, but anyone can view a movie, listen to music, and print.

Then the Media Center PC mother board failed! So I got a new AMD Athlon 64 LE (45w cool-and-quiet, and yeah, it runs very cool and very quiet) and reinstalled. I setup my shares again, but this time I turned OFF simple file sharing.

I go to my MBP and connect to the MC PC. I try as guest. But I got this message:

“The file server does not allow Guest access.”

Huh? So I enable the guest account, which I do not remember having to enable before. Reboot. Try to connect again. Same error message: “The file server does not allow Guest access.” WTF?! And the other Windows machine (Windows Vista) could not print without loging in. Gah!

So I googled around, played with my Mac samba settings. Deleted my networking settings on my Mac. Tripple checked my shared settings on my PC. So I went back to the basics. Reading one Microsoft KB how to setup Windows XP file sharing. There it was, simple file sharing. A light bulb came on. So I re-enabled simple file sharing (My Computer->Tools->Folder Options…->View->Advanced settings:->User simple file sharing (Recommended)).

And it all worked!  Reading my media shares, printing as guest! Even from the Vista machine! I know there is some security risks leaving it so open, but I keep my private data separate.

Google App Engine and dynamic Django Forms

Wednesday, January 28th, 2009

Let me define dynamic form: a form that can have 0 to x number of entries for a field. For example a form that contains a list of items, like a grocery list. Its part of the same form but can have more than one entry. In PHP, they can be grouped by appending “[]” to their name attribute, and PHP stores them the $_POST variable as array (i.e. $_POST['list'][0]). I am working a project using Google App Engine, which uses Django forms, and I needed a dynamic form (list).  I found this can be done using the get_all() function of the self.request object (i.e. self.request.get_all(‘list’)) will return a list object.

Cool! But how do I use that with the Django form model with this list?  Make a list of form models. Loop through the posted list, create a form object with that data, append it to the form list, check if its valid and repeat.  If there was an error, just send the form list to the template, and loop through the forms displaying them with error messages. Else, the entire form is valid, save it to the data object.  Here is some code:

#main.py

import wsgiref.handlers
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.db import djangoforms

class Groceries(db.Model):
	quantity = db.IntegerProperty()
	name = db.StringProperty(required=True)

class GroceryForm(djangoforms.ModelForm):
	class Meta:
		model = Groceries

class MainHandler(webapp.RequestHandler):
	def get(self):
		groceryform = GroceryForm()
		values = {'groceriesformlist': [groceryform]}
		self.response.out.write(template.render('main.html',values))
	def post(self):
		postedQuantities = self.request.get_all('quantity')
		postedNames = self.request.get_all('name')
		groceriesList = []
		allGroceriesValid = True;
		n = 0;
		for i in self.request.get_all('quantity'):
			groc = GroceryForm(data={'quantity':postedQuantities[n],'name':postedNames[n]})
			allIngredientsValid = allIngredientsValid and groc.is_valid()
			groceriesList.append(groc)
			n += 1
		if allGroceriesValid:
			for grocerydata in groceriesList:
				grocery = grocerydata.save(commit=False)
				#do something with data
				grocery.put()
			self.redirect('/')
		else:
			values = {'groceriesformlist': groceriesList}
			self.response.out.write(template.render('main.html',values))
def main():
	application = webapp.WSGIApplication([('/', MainHandler)],debug=True)
	wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
	main()

The commit=False is useful when you do not want to save the data right away, like some other variable manipulation. Then there is the template file. There are numerous ways to output the form, it even has a built in table or paragraph method. If you wanted to just use the default table method to output the form, with errors, simple use <table>{{groceryform}}</table> (the output omits the table declartions, just the rows and columns) and your are done. I like a little more control, so to output the erros: {{ groceryform.quanity.errors }} and then output the input tag: {{groceryform.quantity}. Here is the template file, main.html:

<h3 class="form_headers">Groceries</h3>
<ol id="directions_form">
	{% for groceryform in groceriesformlist %}
		<li>{{ groceryform.quanity.errors }}{{groceryform.quantity}}{{ groceryform.name.errors }}{{groceryform.name}}</li>
	{% endfor %}
</ol>
<input type="button" value="+" id="add_btn" onclick="AddLi(this.previousSibling.previousSibling)" />

You also need to toss in some javascript for adding new grocery items:

function AddDirLi(ol)
{
	var li = ol.firstChild.nextSibling.cloneNode(true);
	ol.appendChild(li);
}

There are many ways to accomplish this, with AJAX or just posting items one at a time. But my project actually had a few sections of this nature and it this method seemed to work the best. I hope that made sense. The next post will cover Using Relationships with the Google App Engine Datastore. Creating and storing multiple grocery lists. The grocery list would be the the parent to many grocery items.

Reading and Writing Files in AIR – using a simple text editor

Monday, January 26th, 2009

Monstagon asked me if I ever saved or opened files in Adobe AIR. Yes. I have. I made a simple text editor to demonstrate the basics of reading files in (letting the user browse for a file on their machine) and writing a save (also letting the user specify where to save the new file).

Some issues I encountered with making the text editor were the different FileModes (READ, WRITE, UPDATE, and APPEND). UPDATE and APPEND basically just add whatever you write to the FileStream to the end of the file. WRITE deletes the destination and writes only what is sent to the FileStream. READ only opens the file for reading. After erasing some files accidentally by opening it with WRITE, I realized for the text editor to work, first READ the file in, close the FileStream. When the user hits Save, open the file in WRITE mode, and send the contents of the editor to the FileStream.

I also had to removeEventListener from the FileStream because it was listening for two Event.SELECT’s: user selects which file to open, and user selects where to save. This was throwing errors when the user selects where to save and the program tries to open a file that doesn’t exist.

If you just want to know how to read a file, look at private function Open() and follow the code. For writing, private function Save(). Note that in ActionScript, its all about event listeners. So reading the file contents into the TextArea is 3 function, because we have to wait until each step is ready. Else, if you don’t setup the Event Listeners nothing will happen.

<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.events.FileEvent;
private var stream:FileStream;
private var file:File = File.documentsDirectory;
private var newFile:Boolean = true;
private function New():void
{
	newFile = true;
	editor.text = '';
}
private function Open():void
{
	try
	{
	    file.browseForOpen("Open");
	    file.addEventListener(Event.SELECT, LoadFile);
	}
	catch (error:Error)
	{
	    trace("Failed:", error.message);
	}
}
private function LoadFile(evt:Event):void
{
	file.removeEventListener(Event.SELECT, LoadFile);
	file = evt.currentTarget as File;
	stream = new FileStream();
	stream.addEventListener(Event.COMPLETE, ReadFile);
	stream.openAsync(file,FileMode.READ);
}
private function ReadFile(evt:Event):void
{
	stream.removeEventListener(Event.COMPLETE,ReadFile);
	var str:String = stream.readUTFBytes(stream.bytesAvailable);
	editor.text = str;
	newFile = false;
	stream.close();
}
private function Save():void
{
	if(!newFile)
	{
		stream = new FileStream();
		stream.openAsync(file,FileMode.WRITE);
		stream.writeUTFBytes(editor.text);
		stream.close();
	}else
	{
		file.browseForSave("Save");
		file.addEventListener(Event.SELECT, SaveFile);
	}
}
private function SaveFile(evt:Event):void
{
	file.removeEventListener(Event.SELECT, SaveFile);
	var file:File = evt.currentTarget as File;
	stream = new FileStream();
	stream.openAsync(file,FileMode.WRITE);
	stream.writeUTFBytes(editor.text);
	stream.close();
	newFile = false;
}
]]>
</mx:Script>
<mx:VBox width="100%" height="100%">
<mx:HBox>
	<mx:Button label="New" click="New();" />
	<mx:Button label="Open" click="Open();" />
	<mx:Button label="Save" click="Save();" />
</mx:HBox>
	<mx:TextArea id="editor" width="100%" height="100%" />
</mx:VBox>
</mx:WindowedApplication>

Detecting Screen Resolution in Flex/AIR

Saturday, January 10th, 2009

Monstagon asked me how to scale and AIR application to the users screen resolution. There are
a few ways to achieve this: maximize(), StageDisplayState.FULLSCREEN, or Capabilities.screenResolutionX/Y.
Here is a little tutorial/sample of resizing a chomeless window to fit the screen
using all 3 methods.

Go open Flex Builder 3, and create a new AIR project. First, lest go chromeless.
Open the app.xml file to edit the application settings. We need to set
systemChrome and transparent to none and true
respectively.

<!-- Thetype of system chrome to use (either "standard" or "none"). Optional. Default standard. -->
<systemChrome>none</systemChrome>

<!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. -->
<transparent>true</transparent>

And now we need to set up the WindowedApplication properties showStatusBar,
showTitleBar, and just for effect backgroundAlpha to false,
false, and 0.5. Also set applicationComplete to the
startup function, in this case Init();. (I ran into some trouble accessing the stage
in the startup function when I was listening for the creationComplete event. We need to listen
for applicationComplete if we want to access stage and stage items, because when this event
is fired, everything is drawn and ready to go.
Understanding The Flex Application Startup Event Order)

	<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="Init();"
		showStatusBar="false" showTitleBar="false" backgroundAlpha="0.5" backgroundGradientAlphas="[1.0, 1.0]" backgroundGradientColors="[#000000, #5D7B68]">

Enough jabber, here is are the functions source code. Layout some buttons to activate which options you want to see.

<mx:Script>
	<![CDATA[
	import mx.events.FlexEvent;
	private function Init():void
	{
		addEventListener(MouseEvent.MOUSE_DOWN,InitMove);
	}
	private function CapabilitiesMax():void
	{
		width = Capabilities.screenResolutionX;
		height = Capabilities.screenResolutionY;
	}
	private function FullScreen():void
	{
		stage.displayState = StageDisplayState.FULL_SCREEN;
	}
	/* MOVE */
	private function InitMove(evt:MouseEvent):void
	{
		stage.nativeWindow.startMove();
	}
	]]>
</mx:Script>
<mx:VBox horizontalCenter="0" verticalCenter="0" horizontalAlign="center">
	<mx:Button label="stage.nativeWindow.maximize()" click="stage.nativeWindow.maximize();" />
	<mx:Button label="Resize to Screen Resolution" click="CapabilitiesMax();" />
	<mx:Button label="stage.nativeWindow.restore()" click="stage.nativeWindow.restore();" />
	<mx:Button label="Full Screen" click="FullScreen();" />
	<mx:Button label="Close" click="close();" />
</mx:VBox>

And that is the entire source code to demostrate how each option works. A thing to note,
when using the “Resize to Screen Resolution” the window is not centered, but stretched
from its current screen position. In most cases, I maximize(); would be the function
to use, or set it to full screen. And if you want to manually resize it to the screen resolution
and have the window centered, set the x and y of stage.nativeWindow to 0.
Here is the new CapabilitiesMax() function.

private function CapabilitiesMax():void
{
	width = Capabilities.screenResolutionX;
	height = Capabilities.screenResolutionY;
	stage.nativeWindow.x = 0;
	stage.nativeWindow.y = 0;
}

Hope that helps Monsta. And I would enjoy working on a project, and I want chocolate.

Client Side Script in a .NET Web Part

Tuesday, August 26th, 2008

Quick, a little snippet on adding client side scripts (javascript) in a web part or ASP.NET page. And the link to [MSDN](http://msdn.microsoft.com/en-us/library/ms948916.aspx “Creating a Web Part with Client-side Script”) where I found this wonderful information. My script was small, basically an alert to tell the user he/she is stupid. So I embedded the script in the Web Part. It worked. Here is my code snippet, since the one on MSDN was using old function to register the client script.

	private const string ByeByeIncludeScriptKey = "myByeByeIncludeScript";
    private const string EmbeddedScriptFormat =
          "<script language=javascript>alert('Bye Bye');</script> ";

    public WebPart_ClientScript()
    {
       this.PreRender += new EventHandler(WebPart_ClientScript_PreRender);
    }

    private void WebPart_ClientScript_PreRender(object sender , System.EventArgs e )
    {

          	if (!Page.ClientScript.IsClientScriptBlockRegistered(ByeByeIncludeScriptKey))
              Page.ClientScript.RegisterClientScriptBlock(typeOf(WebPart_ClientScript), ByeByeIncludeScriptKey, EmbeddedScriptFormat);
    }

Note that [James.ToString()](http://blogs.ipona.com/james/archive/2006/10/03/6710.aspx “Don’t user GetType()”) says not to use this.GetType but rather typeOf(ControlName) where control name is the web part. So the above just tosses up an alert that happens when the page loads. Although, if you did want a function in there, to have it be called, you add the OnClientClick attribute to the asp tag.

	<asp:Button runat="server" Text="Oh, Click me.." OnClientClick="ShowAlert()" />

And that “ShowAlert()” can be any function name. Simple enough.

SharePoint 2007 Web Part Deployment Tutorial

Monday, August 11th, 2008

There are a bunch of tutorials out there that use C# to create a class library and the put that in the GAC (Windows assemblies folder) etc. I could not get those to work for the life of me. The best way I have found to develop, test, and then deploy a custom SharePoint Web Part to the production server is with Visual Studio SharePoint Extensions, for VS 2005 or VS 2008. Except it seems you can only install this if you have Windows SharePoint Services 3.0 installed. And you can only install WSS 3.0 on Windows Server 2003 SP1. Sorry, no free download for that.

(more…)

Unity3d SQLite Basic 3D Visualization Tutorial

Wednesday, June 4th, 2008

At work we are trying to develop some ways to visualize data. Since game engines are great at making complicated math look cool, we are trying to use them to visualize data-sets. We wanted to test how many “dimensions” we could represent (x, y, z..size, direction, color, etc). So I made a little proof of concept with Unity3d, SQLite, and AIR. (The AIR part of will not be covered in this tutorial; but I basically used it as a simple form to input data-points, nothing crazy.)

Unity3d uses Mono which has an SQLite Library which I then modified to javascript (for some reason it worked better in javascript than C#).

In this tutorial, I will assume you already have a basic understanding of databases, scripting, and even Unity.

So the first thing we’ll do is create a new project in Unity. Then create an Empty Game Object, place it at (0,0,0), and name it 3DGraph. To create an axis, simply create a Cube, make it a child of 3DGraph by dragging it onto 3DGraph in the Hierarchy view. Lets name this X-Axis and place it at (0,0,0) and scale it (100,0.5,0.5). This should give us a nice long bar on the x axis. Repeat these steps for Y-Axis and Z-Axis, scaling the respective axis by 100 and the other by 0.5.

Once that is complete, we should have a nice X,Y,Z graph. Feel free to get fancy and add materials and colors, and add a point light or some other light source, but I will not cover how to do that. With that done, lets take a moment to go over our database.

I used SQLite Database Browser to create and manipulate the SQLite DB. Create a new table called points and save the SQLite DB file in the same directory as the Unity project, name the DB file “SqliteTest.db” or something. Here is the SQLite CREATE statement for tabel points.

CREATE TABLE points (
	id INTEGER PRIMARY KEY,
	name VARCHAR,
	x NUMERIC,
	y NUMERIC,
	z NUMERIC,
	scale NUMERIC,
	r NUMERIC,
	g NUMERIC,
	b NUMERIC,
	timeMod date
)

The name is whatever name the point has, x,y,z are the coordinates, scale is how much to scale the point (size), r,g,b are the color values, and timeMod is the date it was last modified. These are the 7 dimensions that we will visualize in this tutorial. Since it is SQLite, a TRIGGER is needed to keep the timeMod up to date when data is updated or inserted. Here is the TRIGGER statement.

CREATE TRIGGER insert_point_timeMod AFTER INSERT ON points
BEGIN
	UPDATE points SET timeMod = DATETIME('NOW') WHERE id = new.id;
END;

CREATE TRIGGER update_point_timeMod AFTER UPDATE ON points
BEGIN
	UPDATE points SET timeMod = DATETIME('NOW') WHERE id = new.id;
END;

Now that the DB is all setup perfectly, quit the SQLite Database Browser (or else you will get an error when Unity tries to access the DB). Now we need to create the script in Unity to access the DB (Project view…Create JavaSctipt). You will have to rename it to something useful, like “MySqlite” or “SQLiteUpdater”. Here is the code.

	import System;
	import Mono.Data.Sqlite;

	var pointObject : Transform;

	private var childArray : Array = new Array();
	private var graphClone : Object;

	function Start()
	{
		var connStrn : String = "URI=file:SqliteTest.db";

		var dbcon : SqliteConnection = new SqliteConnection(connStrn);
		dbcon.Open();

		GetTable(dbcon);
		//GetLatest(dbcon);

		dbcon.Close();
		dbcon = null;
	}

	function Update ()
	{
		var connStrn : String = "URI=file:SqliteTest.db";

		var dbcon : SqliteConnection = new SqliteConnection(connStrn);
		dbcon.Open();

		var rowCount : int = GetRowCount(dbcon);
			//DestroyPoints();
		if((rowCount != transform.childCount - 3) || NeedUpdate(dbcon))
		{
			DestroyPoints();
			//graphClone = Instantiate(transform,Vector3.zero,Quaternion.identity);
			GetTable(dbcon);
		}
		//Debug.Log("children: " + transform.childCount);

		dbcon.Close();
		dbcon = null;
	}

	function GetRowCount(dbcon) : int
	{
		var dbcmd : Object = dbcon.CreateCommand();
		dbcmd.CommandText = "SELECT count(*) as count FROM points";

		var reader : Object;
		try
		{
			reader = dbcmd.ExecuteReader();
		}catch(err)
		{
			Debug.LogError("cmd failed:" + err.Message);
		}
		reader.Read();
		var rowCount : int = reader.GetInt32(0);

		reader.Close();
		reader = null;
		//dbcmd.Close();
		//dbcmd = null;

		return rowCount;
	}
	private var lastUpdated : DateTime;

	//If no update needed, don't redraw everything
	//Format 2008-01-30 15:38:41
	//       0123,56,89,1112,1415,1718
	//DateTime(Int32, Int32, Int32, Int32, Int32, Int32) constructor
	function NeedUpdate(dbcon) : Boolean
	{
		var latest = false;
		var dbcmd : Object = dbcon.CreateCommand();
		dbcmd.CommandText = "SELECT timeMod FROM points ORDER BY timeMod DESC LIMIT 1;";

		var reader : Object = dbcmd.ExecuteReader();
		reader.Read();

		var timeMod = reader.GetString(0);
		//Debug.Log("timeMod: " + timeMod);

		var tempYear = parseInt(timeMod[0].ToString()+timeMod[1].ToString()+timeMod[2].ToString()+timeMod[3].ToString());
		var tempMonth = parseInt(timeMod[5].ToString()+timeMod[6].ToString());
		var tempDay = parseInt(timeMod[8].ToString()+timeMod[9].ToString());
		var tempHour = parseInt(timeMod[11].ToString()+timeMod[12].ToString());
		var tempMinute = parseInt(timeMod[14].ToString()+timeMod[15].ToString());
		var tempSecond = parseInt(timeMod[17].ToString()+timeMod[18].ToString());

		var sqlUpdate  = new DateTime(tempYear,tempMonth,tempDay,tempHour,tempMinute,tempSecond);

		if(DateTime.Compare(sqlUpdate,lastUpdated) > 0) //sqlUpdate > lastUpdated
		{

			lastUpdated = sqlUpdate; //new DateTime(tempYear,tempMonth,tempDay,tempHour,tempMinute,tempSecond);
			latest = true;
		}

		//var timeInt : int = parseInt(timeMod);
		//var timeDivided : Array = timeMod.Substring(" ");
		//var timeDate : Array = timeDivided[0].split("-");
		//var timeTime : Array = timeDivided[1].split(":");
		//Debug.Log(timeDivided.ToString());// + timeDate.ToString() + timeTime.ToString());
		//pareInt

		reader.Close();
		reader = null;
		//dbcmd.Close();
		//dbcmd = null;

		return latest;
	}

	function GetTable(dbcon) : void
	{
		var dbcmd : Object = dbcon.CreateCommand();
		dbcmd.CommandText = "SELECT * FROM points;";

		var reader : Object = dbcmd.ExecuteReader();

		while(reader.Read())
		{

			var pos : Vector3 = new Vector3(reader.GetFloat(2),reader.GetFloat(3),reader.GetFloat(4));
			var scale : Vector3 = new Vector3(reader.GetFloat(5),reader.GetFloat(5),reader.GetFloat(5));
			var colour : Color = new Color(reader.GetFloat(6),reader.GetFloat(7),reader.GetFloat(8),1);

			var newChild : Transform = Instantiate(pointObject,Vector3.zero,Quaternion.identity);
			newChild.parent = transform;
			newChild.localPosition = pos;
			newChild.localScale = scale;
			newChild.renderer.material.color = colour;

			childArray.Push(newChild);
			//result += reader.GetInt32(0) + " " + reader.GetString(1) + " " + reader.GetString(2) + ", ";
			//http://msdn2.microsoft.com/en-us/library/system.data.idatareader_methods.aspx
		}

		reader.Close();
		reader = null;
		//dbcmd.Close();
		//dbcmd = null;
	}

	//Erase them all so we can draw all the new ones and we won't get duplicates
	function DestroyPoints() : void
	{

		//Destroy(graphClone);
		//Can't remove Transform because MeshFilter, SphereCollider, MeshRenderer depend on it!
		//var points = GetComponentsInChildren(typeof(pointObject));
		while(childArray.length > 0)
		//for(var child : Object in points)
		{
			var child = childArray.Pop();

			var meshFilters = child.GetComponentsInChildren (MeshFilter);
			for (var meshF : MeshFilter in meshFilters) {
				DestroyImmediate(meshF);
			}

			var sphereColliders = child.GetComponentsInChildren (SphereCollider);
			for (var sphere : SphereCollider in sphereColliders) {
				DestroyImmediate(sphere);
			}

			var meshRenderers = child.GetComponentsInChildren (MeshRenderer);
			for (var meshR : MeshRenderer in meshRenderers) {
				DestroyImmediate(meshR);
			}

			DestroyImmediate(child);
			//Debug.Log("Children after destroy: " + transform.childCount);
		}
	}

Change the URI to point to your SQLite DB.

	var connStrn : String = "URI=file:SqliteTest.db";

Drag this script from the Project view onto the 3DGraph game object. All that is left is to create a point object. Lets just use a sphere, so create a new sphere object, call it GraphPoint, click on 3DGraph and drag GraphPoint onto the Point Object under the script settings. You should disable the source point object so its not confused with the ones created by the script. That should be all you need. The graph should plot the points in 3D space! Yay!

To make it more appealing, we added some controls, like zooming and flying the camera around with an XBOX360 controller. Maybe I will do that in Part 2, after I get back from Hawaii!!

Willy Makeit