VSLab update and measure units sample

by cisterni 30. October 2008 23:29

Ok, it is some time since the last update of VSLab, but today I decided to update the installer and commit several changes I did to improve stability and support for events. I finally managed to go through the whole Viewlet definition and fully document supported and unsupported events inherited from UserControl. I also managed to fix several bugs in this respect.

 This is term period and in the Graphical interfaces courses I'm teaching using F# (interactively). Today to discuss animations I've implemented a simple application with balls moving around and quickly converted into a viewlet! The nice thing about this application is the use of unit measures in a graphical application to estimate velocity (<px/s>). Once you run the viewlet you can create a new ball by simply clicking in the client area and drag the initial velocity vector. Here is a screenshot:

 

and here it is the code:

#light

open System.Drawing

open System.Windows.Forms [<Measure>] type px

[<Measure>] type s

open VSLab

let ballsz = new SizeF(25.0f, 25.0f)

type Ball(ipx: float<px>, ipy:float<px>, ivx:float<px/s>, ivy:float<px/s>) =

  let mutable vx = ivx

  let mutable vy = ivy

  let mutable px = ipx

  let mutable py = ipy

  let sz = ballsz

  member x.Update(interval:float<s>) =

    px <- px + vx * interval

    py <- py + vy * interval

  member x.Size

    with get() = sz

  member x.Position     with get() = (px, py)

 

  member x.CenterPosition

    with get() = ((px + 1.0<px> * (float (sz.Width / 2.0f))), (py + 1.0<px> * (float (sz.Height / 2.0f))))

 

  member x.Velocity

    with get() = (vx, vy)

    and set (v:float<px/s>*float<px/s>) =

      vx <- fst v

      vy <- snd v

type SampleViewlet() as x =

  inherit Viewlet()

  let balls = new ResizeArray<Ball>()

  let framerate = 0.02<s>

  let t = new Timer()

  let mutable newball:Option<Ball> = None

  let mutable mousepos = (0, 0)

 

  do

    t.Interval <- int(framerate * 1000.0)

    t.Tick.Add(fun _ ->

    balls |> ResizeArray.iter (fun b ->

      b.Update(framerate)

      let px, py = b.Position

      let pxi = (int px)

      let pyi = (int py)      let mutable vx, vy = b.Velocity

 

      if (pxi < 0 || pxi > x.ClientSize.Width - (int b.Size.Width)) then

        vx <- vx * -1.0

      if (pyi < 0 || pyi > x.ClientSize.Height - (int b.Size.Height)) then

        vy <- vy * -1.0

 

      b.Velocity <- (vx, vy)

      )

 

      x.Invalidate()

    )

    t.Start()

    x.Text <- "Animate!"

  override x.OnMouseDown e =

    mousepos <- (e.X, e.Y)

    let px = 1.0<px>*((float e.X) - ((float ballsz.Width) / 2.0))

    let py = 1.0<px>*((float e.Y) - ((float ballsz.Height) / 2.0))

    let b = new Ball(px, py, 0.0<px/s>, 0.0<px/s>)

    balls.Add(b)

    newball <- Some(b)

  override x.OnMouseMove e =

    if newball.IsSome then

      mousepos <- (e.X, e.Y)

  override x.OnMouseUp e =

    if newball.IsSome then

      let px, py = newball.Value.Position

      let vx = (float (fst mousepos - (int px)))*1.0<px/s>

      let vy = (float (snd mousepos - (int py)))*1.0<px/s>

      newball.Value.Velocity <- (vx, vy)

      newball <- None

  override x.OnPaint e =    let g = e.Graphics

    g.SmoothingMode <- Drawing2D.SmoothingMode.AntiAlias

    balls |> ResizeArray.iter (fun b ->

    let px, py = b.Position

    g.FillEllipse(Brushes.Blue, (single px), (single py), ballsz.Width, ballsz.Height))

    if newball.IsSome then

      let px, py = newball.Value.CenterPosition

      let ipx = (int px)

      let ipy = (int py)

      let mx, my = mousepos

      use p = new Pen(Color.Black)

      p.EndCap <- Drawing2D.LineCap.ArrowAnchor

      g.DrawLine(p, ipx, ipy, mx, my)

 

  override x.OnViewletVisibilityChange e =

  t.Enabled <- e

let v = new SampleViewlet()

v.Show()

v.Close()

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

General | Viewlets

Massage yourself with VSLab

by cisterni 6. October 2008 19:53

I just ordered the Gaming Jacket from TNGames  and guess what? I couldn't resist to implement a F#/VSLab library for controlling the gaming Jacket from F#.

I compiled a C++ DLL that simply exposes the API and defined F# PInvoke statements in a module. A class is used to expose the Jacket to F# programs including to the F# interactive.

This is an example of usage:

#light

#r @"ManagedJacket.dll"

open ManagedJacket

open System

let j = new Jacket()

let sequence = [| Actuator.BackBottomLeft; Actuator.FrontBottomLeft; Actuator.BackBottomRight; Actuator.FrontBottomRight; Actuator.BackTopLeft; Actuator.FrontTopLeft; Actuator.BackTopRight; Actuator.FrontTopRight |]

for i in 1..10 do

  for v in sequence do

    j.SetAirCell 5uy v

System.Threading.Thread.Sleep 100

(j :> IDisposable).Dispose()

 This code performs a very simple form of massage. Now we are considering to use blasts when you do bad coding in Visual Studio!!!

I include the definition of the library that maps one on one on the functionality of the SDK.

This is the content of the interop.fs file:

#light

module ManagedJacket.Interop

open System.Runtime.InteropServices

[<DllImport("JacketDLL.dll")>]

extern int internal Jacket_SetUpJacket()

[<DllImport("JacketDLL.dll")>]

extern void internal Jacket_TearDownJacket()

[<DllImport("JacketDLL.dll")>]

extern int internal Jacket_SetEffect(int nEffect)

[<DllImport("JacketDLL.dll")>]

extern int internal Jacket_SetEffect2(int speed,int actuator)

[<DllImport("JacketDLL.dll")>]

extern void internal Jacket_FlushBuffer(int actuator)

[<DllImport("JacketDLL.dll")>]

extern int internal Jacket_GetErrorCode()

And this is the public definition of the library (jacket.fs):

#light

namespace ManagedJacket

open ManagedJacket.Interop

type Effect =

| MachinegunFront = 0

| MachinegunBack = 1

| BigBlastFront = 2

| BigBlastBack = 3

| SmallBlastFront = 4

| SmallBlastBack = 5

| PistolFront = 6

| PunchFront = 7

| StabFront = 8

| ShotgunFront = 9

| RifleFront = 10

| PistolBack = 11

| PunchBack = 12

| StabBack = 13

| ShotgunBack = 14

| RifleBack = 15

| LeftSideHit = 16

| RightSideHit = 17

| Acceleration = 18

| Deceleration = 19

| Leftturn = 20

| Rightturn = 21

| AccelerationStop = 22

| DecelerationStop = 23

| LeftturnStop = 24

| RightturnStop = 25

type Actuator =

| FrontTopRight = 1

| FrontTopLeft = 2

| FrontBottomRight = 3

| FrontBottomLeft = 4

| BackTopRight = 5

| BackTopLeft = 6

| BackBottomRight = 7

| BackBottomLeft = 8

type Jacket() =

  do

    if Jacket_SetUpJacket() <> 0 then failwith "Error connecting with Jacket"

 

  member x.SetPredefinedEffect(e:Effect) =

    if Jacket_SetEffect (int e) <> 0 then failwith "Error activating effect"

 

  member x.SetAirCell (speed:byte) (actuator:Actuator) =

    if Jacket_SetEffect2((int speed), (int actuator)) <> 0 then failwith "Error activating effect"

 

  member x.FlushBuffer (actuator:Actuator) =

    Jacket_FlushBuffer(int actuator)

 

  interface System.IDisposable with

    member x.Dispose() =

      Jacket_TearDownJacket()

A video will follow.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Applications | General

VSLab Visual Tutorial updated!

by cisterni 5. October 2008 19:38
I finally managed to update the VSLab visual tutorial. Now I have to go through the rest of the documentation and update it. Then I can move on further development. Nevertheless during this process I'm writing unit and regression tests for viewlets.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

General

Powered by BlogEngine.NET 1.4.0.0
Theme by Mads Kristensen

VSLab blog

VSLab is a Visual Studio extension designed to support Visual Studio interaction from F# interactive. It is a Microsoft product developed at University of Pisa, by a team lead by Antonio Cisternino.

Resources

Recent comments

Comment RSS

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in  anyway.

© Copyright 2008