Physical Interaction with Digital Interfaces.
At the last evening of us flash geeks getting together at the monthly London Flash Platform User Group little over a week ago, Adam Robertson and Leif Løvgreen displayed some really inspiring stuff. Adam, of FWiidom, focussed on the WiiMote - Nintendo's Wii motion sensing controller - and how to make it work with flash on both PC and Wii, complete with an overview of what's supported and some tips on best APIs ( WiiFlash, GlovePie and Flosc )out there. Leif showed some really cool sensory input being converted into some lovely and interactive flash output using the makingthings kit.
I couldn't help myself and, with my bluetooth enabled little laptop, I decided to go out and get myself a WiiMote controller to try some of this stuff out for myself. After a little confusion at first on how to connect the WiiMote to the laptop, - I couldn't get it to work on my office-laptop with Belkin bluetooth dongle without installing the BlueSoleil drivers, so resorted to my personal laptop which worked without too much hassle -, I got it to work with GlovePie. The WiiFlash server doesn't work for me yet, so I'll have to do a little more fiddling with that before I can used 'the preferred' solution.
I'm also still without Flash CS3, so no AS3 for me yet.. So I just started playing with some of the GlovePIE scripts to control my laptop with the WiiMote for now, and I have to say, it's a lot of fun! GlovePIE's scripting language is a bit odd at first, very forgiving, but after reading through the documentation it started to make more sense.
I've started with reading through some of the scripts and shortly after, combining them - rewriting most of the code them so they're more consistent with ECMA, making them just that bit more sensible - and adding my own bits to make the controller do what I want it too. There's a few bugs in it still - just some keyboard keys that can't be unset -, but it works quite nicely, displaying the batterylevel, and 3 different modes for mouse emulation, media controls and presentation (powerpoint) controls.
I'm looking forward to start integrating the Flosc bit, and writing some AS2 code to connect - if anybody has a nice few AS2 Flosc classes, I'm happy to hear from you -.
Other things I'd like to look into are the Lego Mindstorms NXT sensors and the 3dconnexion space navigator..
Anyway, if you have GlovePIE, a WiiMote and a compatible bluetooth enabled PC, give this script try...
-
// customized from MouseAccel.PIE
-
// 3 modes (4th browser mode todo)
-
// 1. mouse mode, for moving the mouse around the screen,
-
// with left, right buttons, scroll and cursor control
-
// 2. presentation mode, for controlling powerpoint
-
// open slideshow, click through slides, pen control, quick slide menu
-
// note: ctrl button is buggy, fix with clicking ctrl on the keyboard
-
// 3. media mode, for controlling media devices
-
// play/pause, prev and next, volume and mute support
-
// voice confirmation of the selected mode
-
// visual feedback through leds
-
// batterylevel indication
-
-
// initiate script
-
-
if (var.inited == false){
-
var.inited = true;
-
//precision settings for mouse movement
-
var.sense0 = 500
-
var.thresh0x = 5
-
var.thresh0y = 2
-
var.sense1 = 300
-
var.thresh1x = 10
-
var.thresh1y = 5
-
var.sense2 = 100
-
var.thresh2x = 15
-
var.thresh2y = 8
-
var.sense3 = 50
-
var.thresh3x = 20
-
var.thresh3y = 12
-
// default delays for
-
var.longInterval = 200 ms;
-
var.shortInterval = 50 ms;
-
// wait for PIE to find WiiMote orientation
-
wait(var.longInterval);
-
// set initial zero point
-
var.initx = WiiMote.RawForceX;
-
var.inity = WiiMote.RawForceY;
-
var.initz = WiiMote.RawForceZ;
-
// wii control modes
-
var.mouseMode_id = 1;
-
var.mouseMode_say = "mouse";
-
var.pptMode_id = 2;
-
var.pptMode_say = "presentayshun";
-
var.penEnabled= false;
-
var.mediaMode_id = 3;
-
var.mediaMode_say = "media";
-
// todo
-
//var.browsemode = 4
-
//var.browsemodestr = "browser"
-
var.numModes = 3;
-
var.mode_say = " mode";
-
//set mouseMode_id as default
-
var.wiiMode_id = var.mouseMode_id;
-
WiiMote.leds = (2^var.wiiMode_id) - (2^(var.wiiMode_id-1));
-
var.wiiMode_say = var.mouseMode_say;
-
say var.wiiMode_say + var.mode_say;
-
var.showBatteryLevel = false;
-
wait(1000 ms);
-
var.showBatteryLevel = true;
-
}
-
-
// switch control mode by pressing the home key
-
if (pressed(WiiMote.Home)){
-
-
var.showBatteryLevel = false;
-
// select next mode id
-
var.tmode = var.wiiMode_id + 1;
-
-
if (var.tmode> var.numModes){
-
var.tmode = 1;
-
}
-
-
//rumble to give feedback on change mode
-
WiiMote.Rumble= true;
-
wait(var.shortInterval);
-
WiiMote.Rumble= false;
-
var.wiiMode_id = var.tmode;
-
//light the led indicating the selected mode
-
var.led_id = (2^var.wiiMode_id) - (2^(var.wiiMode_id-1));
-
WiiMote.leds = var.led_id;
-
-
//select the string to say
-
if(var.wiiMode_id == var.mouseMode_id){
-
var.wiiMode_say = var.mouseMode_say;
-
} else if(var.wiiMode_id == var.pptMode_id){
-
var.wiiMode_say = var.pptMode_say ;
-
}else if(var.wiiMode_id == var.mediaMode_id){
-
var.wiiMode_say = var.mediaMode_say;
-
}else if(var.wiiMode_id == var.browsemode){
-
var.wiiMode_say = var.browsemodestr;
-
}
-
-
//say the current mode
-
say(var.wiiMode_say + var.mode_say);
-
wait(1000 ms);
-
var.showBatteryLevel = true;
-
}
-
-
// default key mapping for up, down, left, right
-
if (WiiMote.Up){
-
Key.Up = true;
-
wait(var.longInterval);
-
Key.Up = false;
-
} else if (WiiMote.Down){
-
Key.Down = true;
-
wait(var.longInterval);
-
Key.Down = false;
-
}
-
-
if (WiiMote.Left){
-
Key.Left = true;
-
wait(var.longInterval);
-
Key.Left = false;
-
} else if (WiiMote.Right){
-
Key.Right = true;
-
wait(var.longInterval);
-
Key.Right = false;
-
}
-
-
// assign custom actions for each mode
-
if (var.wiiMode_id == var.mouseMode_id){
-
// mouse mode
-
if (pressed(WiiMote.A)){
-
Mouse.LeftButton = true;
-
wait(var.longInterval);
-
Mouse.LeftButton = false;
-
}
-
-
if (WiiMote.B){
-
var.mouseMoveEnabled = true;
-
}else{
-
var.mouseMoveEnabled = false;
-
}
-
-
if (pressed(WiiMote.Minus)) {
-
Key.Enter = true;
-
wait(var.longInterval);
-
Key.Enter = false;
-
}
-
-
if (pressed(WiiMote.Plus)){
-
Mouse.RightButton = true;
-
wait(var.longInterval);
-
Mouse.RightButton = false;
-
}
-
-
Mouse.WheelUp = WiiMote.One
-
-
Mouse.WheelDown = WiiMote.Two
-
-
}else if (var.wiiMode_id == var.pptMode_id){
-
//directional buttons:
-
//left & up to go back one slide
-
//right & down to go to the next slide and move trought the dialog window
-
// Press A to start the slide show &
-
// and to go to the next slide
-
if (WiiMote.A){
-
// press and hold B to move the mouse
-
if (WiiMote.B){
-
// A is left mouse button when in mouse mode
-
Mouse.LeftButton = true;
-
wait(var.longInterval);
-
Mouse.LeftButton = false;
-
}else {
-
// if the mouse is not moving, reassign A to the Enter Key
-
Key.Enter = true;
-
wait(var.longInterval);
-
Key.Enter = false;
-
}
-
}
-
-
// press and hold B to move the mouse
-
if (WiiMote.B){
-
var.mouseMoveEnabled = true;
-
}else{
-
var.mouseMoveEnabled = false;
-
}
-
-
// start slideshow / go to the first slide
-
if (pressed(WiiMote.Minus)) {
-
Key.Home = true;
-
Key.F5 = true;
-
wait(var.shortInterval);
-
Key.Home = false;
-
Key.F5 = false;
-
}
-
-
// show contextmenu
-
if (pressed(WiiMote.Plus)){
-
Mouse.RightButton = true;
-
wait(var.shortInterval);
-
Mouse.RightButton = false;
-
}
-
-
// press '1' to show the select slide dialog
-
// (press A to select)
-
if (WiiMote.One) {
-
Key.Ctrl = true;
-
Key.S = true;
-
wait(var.shortInterval);
-
Key.S = false;
-
Key.Ctrl = false; // ctrl doesn't get unset properly, so press ctrl if you experience problems while or after running thie PIE
-
}
-
-
// switch penEnabled
-
if (WiiMote.Two)
-
if(var.penEnabled == false){
-
var.penEnabled = true;
-
Key.Ctrl = true;
-
Key.P = true;
-
wait(var.shortInterval);
-
Key.P = false;
-
Key.Ctrl = false;
-
}else if(var.penEnabled == true){
-
var.penEnabled = false;
-
Key.Ctrl = true;
-
Key.A = true;
-
wait(var.shortInterval);
-
Key.A = false;
-
Key.Ctrl = false; // ctrl doesn't get unset properly, so press ctrl if you experience problems while or after running thie PIE
-
}
-
}
-
-
wait(var.longInterval);
-
Key.Ctrl = false;
-
-
}else if (var.wiiMode_id == var.mediaMode_id){
-
//Plus and Minus handle Volume
-
if (WiiMote.One){
-
Key.VolumeUp = true;
-
wait(var.shortInterval);
-
Key.VolumeUp = false;
-
}
-
-
if (WiiMote.Two){
-
Key.VolumeDown = true;
-
wait(var.shortInterval);
-
Key.VolumeDown = false;
-
}
-
-
if (pressed(WiiMote.A)){
-
Key.PlayPause = true;
-
wait(var.longInterval);
-
Key.PlayPause = false;
-
}
-
-
Key.Mute = WiiMote.B;
-
if (pressed(WiiMote.Minus)){
-
Key.Prevtrack = true;
-
wait(var.longInterval);
-
Key.Prevtrack = false;
-
}
-
-
if (pressed(WiiMote.Plus)){
-
Key.NextTrack = true;
-
wait(var.longInterval);
-
Key.NextTrack = false;
-
}
-
}
-
-
//If the mouse reaches the end, rumble for 200 milliseconds
-
if (var.mouseX == 0 or var.mouseX == 1 or var.mouseY == 0 or var.mouseY == 1){
-
if (var.rmbl == false){
-
WiiMote.Rumble = true;
-
wait(var.longInterval);
-
WiiMote.Rumble = false;
-
}
-
var.rmbl = true;
-
}else{
-
var.rmbl = false;
-
}
-
-
// ##taken from WiiMouseAccel.PIE##
-
// set these to the offsets when the WiiMote is at rest
-
// will be different for each WiiMote most likely
-
var.posX = WiiMote.RawForceX - var.initx //trim to 0
-
var.posY = WiiMote.RawForceY - var.inity // trim to 0
-
var.posZ = WiiMote.RawForceZ - var.initz //trim to 0
-
-
if (var.mouseMoveEnabled == true){
-
//first sensitivity setting
-
//xaxis
-
var.mouseX = Mouse.x;
-
var.mouseY = Mouse.y;
-
if (var.posX> var.thresh0x){
-
var.mouseX = var.mouseX - 1/var.sense0;
-
}else if (var.posX <-var.thresh0x){
-
var.mouseX = var.mouseX + 1/var.sense0;
-
}
-
-
//yaxis
-
if (var.posZ> var.thresh0y){
-
var.mouseY = var.mouseY - 1/var.sense0;
-
}else if (var.posZ <-var.thresh0y){
-
var.mouseY = var.mouseY + 1/var.sense0;
-
}
-
-
//second sensitivity setting
-
//xaxis
-
if (var.posX> var.thresh1x){
-
var.mouseX = var.mouseX - 1/var.sense1;
-
}else if (var.posX <-var.thresh1x){
-
var.mouseX = var.mouseX + 1/var.sense1;
-
}
-
-
//yaxis
-
if (var.posZ> var.thresh1y) {
-
var.mouseY = var.mouseY - 1/var.sense1;
-
}else if (var.posZ <-var.thresh1y){
-
var.mouseY = var.mouseY + 1/var.sense1;
-
}
-
-
//third sensitivity setting
-
//xaxis
-
if (var.posX> var.thresh2x){
-
var.mouseX = var.mouseX - 1/var.sense2;
-
}else if (var.posX <-var.thresh2x){
-
var.mouseX = var.mouseX + 1/var.sense2;
-
}
-
-
//yaxis
-
if (var.posZ> var.thresh2y){
-
var.mouseY = var.mouseY - 1/var.sense2;
-
}else if (var.posZ <-var.thresh2y){
-
var.mouseY = var.mouseY + 1/var.sense2;
-
}
-
-
//fourth sensitivity setting