F# and DirectX - Jack Palevich's Tutorial

F# is a research project from Microsoft Research. It is not a Microsoft product. All opinions are my own. All content is provided "AS IS" with no warranties, and confers no rights.

Jack Palevich has just emailed to the F# list recently with a very cool tutorial on using F# with DirectX. (the link has been updated now, and now includes Tutorial 3 as well.) 

I've got the feeling that F# and DirectX will turn out to be an excellent combination - I've been playing with some DirectX samples recently, but Jack's is clearer and more to the point, and what's more is actually up on the web rather than being somewhere on my computer :-).  

I've suggested some refinements to Jack's code for the first tutorial (I'll do the same for the later tutorials soon) - this is exactly the kind of situation where F#'s "value recursion" comes in handy to create mutually referential objects without using "null" pointers. Note how this removes both the 'null' value and the extra record type that Jack had to use (nb. the record type may come in handy for larger samples)

let rec device : Device =
let presentParams = new PresentParameters() in
presentParams.Windowed <- true;
presentParams.SwapEffect <- SwapEffect.Discard;
new Device(0, DeviceType.Hardware, (form :> Control),
CreateFlags.SoftwareVertexProcessing,
[|presentParams|])

and form : Form =
{ new Form()
with OnPaint(e) =
device.Clear(ClearFlags.Target, System.Drawing.Color.Blue, 1.0f, 0);
device.BeginScene();
device.EndScene();
device.Present()
}

and do
form.Text <- "F# 2.0 D3D Tutorial 01: CreateDevice";
form.ClientSize <- new Size(400, 300)

let main() =
do Application.Run(form)

do main()

I'll add that I hit some interesting issues when writing my DirectX samples. Firstly it was these samples that made me finally do more work on Intellisense. Secondly, in the currently released version of F# it can be awkward to access protected/family members on base classes, since the most natutral way to write the F# code doesn't necessarily end up with the accesses being in the lexical scope of the object expressions. For example, accessing System.Windows.Forms.Form.SetStyle is only permitted from within the lexical scope of the object expression defining an extension to a Form. This is a thorny issue: F# has a very clean and simple notion of accessibility (signatures and scoping), and I hardly want to pollute the language with arcane rule about what is accessible from where. I've prototyped a solution to this problem - it allows your F# code to get rid of the issue once and for all whenever you hit it. You simply use a special declaration that generates a new class definition (e.g. a MyForm, extending System.Windows.Form).  

type MyForm = GenerateMaximallyAccessibleDerivedClass<Form>

// now you can access MyForm.SetStyle and the rest of Form's
// "protected" functionality from anywhere in your assembly

The name is kind of long, but it helps to explain what's going on. F# generates the type MyForm for you and ensures that it looks identical to its base class but where all the methods, events and properties arel now be public (they are newslot methods that immediately call the base class). This is safe because the protected members will only be accessible for instances of MyForm, and if necessary we can restrict the visiblity of MyForm by F#'s existing mechanisms (i.e. hide it using a signature). This leaves the vast majority of your F# programming uncomplicated by issues like accessibility rules, and gives you a way to eliminate the complexities of "protected" accessiblity whenever you hit them. I'll describe the mechanism in more detail when the next release comes out.