MOUSECLICK/OVER AND SOUND

Our chalenge at this lesson is to capture the click of a button and open or close a door of a "wall-door".

We would like also that when the pointer is "over" the button, the cursor changes to "hand".

And also we would like that when the door opens or closes there will be a sound!

The Avalon API has the method VisualTreeHelper.HitTest that can be used to capture when the user clicks a 3D piece or a "mouse-over" a piece.

Imagine that the Camera is out of the Monitor.

When we click a point in the screen, imagine that a ray goes from the Camera to the point and go ahead.

Everytime the ray cross an object it fires an event that we can capture using:

 Model3D modelHit = (myresult  as RayHitTestResult).ModelHit;

You can see at the downloadable material that ResultsOfHit works like a loop presenting the "modelhiteds".

When the "modelhited" is the model we are testing for click (at our case: the button) we stop the loop.

...
if (modelHit  != null){
   GeometryModel3D gm3D = modelHit as GeometryModel3D; 
   if(gm3D.Geometry == TheCanvas.Resources["buttonG"]){
     //do something...
    }
    return HitTestResultBehavior.Stop;//Exit
   }
...

Remember that we have defined the Geometry of our button in the file Window1.xaml:

...
<Canvas Name="TheCanvas"...
...
< MeshGeometry3D x:Key="buttonG"...
...

After this explanation, look all the part of our code-behind (better to download and analise all the code...)

...
 private void buttonDownHandler(object Sender, MouseButtonEventArgs e){
  Point p = e.GetPosition(VP);
  VisualTreeHelper.HitTest(VP, null, new HitTestResultCallback(ResultsOfHit), new PointHitTestParameters(p));
 } 
 private HitTestResultBehavior ResultsOfHit(HitTestResult myresult ){
     Model3D modelHit = (myresult as RayHitTestResult).ModelHit;
  if (modelHit == null) return HitTestResultBehavior.Stop;//Exit
  if (modelHit  != null){
   GeometryModel3D gm3D = modelHit as GeometryModel3D; 
   if(gm3D.Geometry == TheCanvas.Resources["buttonG"]){
    if(op==0){
     open001();
     op=1;
    }
    else{
     close001();
     op=0;
    }
    return HitTestResultBehavior.Stop;//Exit
   }
  }
  return HitTestResultBehavior.Continue;
 }
...

The capture of "mouse-over" is similar. We use the points of each "mouse-move".

We need to do many things for all this "magic" to work:

1 - At the tag Window we nedd to add:

 MouseLeftButtonDown="buttonDownHandler"
 MouseMove="OnMouseMove" 

2 - The Canvas needs to have a Name now: "TheCanvas" .

3 - We need to "define" and "install" the pieces: "button" and "door".

4 - We need to add:

using System.Media
because we will have sound.

5 - We need to define two objects SoundPlayer (refering the sound files) and a flag:

...
 SoundPlayer doorSound = new SoundPlayer(@"door.wav");
  SoundPlayer boingSound = new SoundPlayer(@"boing1.wav");
  Double op=0;
...

6 - We create the methods to open or close the door (by a jump to a new point, not an animation - we will learn animations later):

...
 public  void open001(){
  Matrix3D open001 = new Matrix3D(0.1,0,0,0,0,0.1,0,0,0,0,0.1,0,-9,0,-5.5,1); 
  MatrixTransform3D mopen001= new MatrixTransform3D(open001);
  ModelVisual3D mv3D = VP.Children[0] as ModelVisual3D;
  Model3DGroup  m3Dg = mv3D.Content as  Model3DGroup;
  m3Dg.Children[7].Transform= mopen001  ;
  doorSound.Play();  
 }
 public  void close001(){
  Matrix3D close001 = new Matrix3D(0.1,0,0,0,0,0.1,0,0,0,0,0.1,0,-5, 0, -5.5,1); 
  MatrixTransform3D mclose001= new MatrixTransform3D(close001);
  ModelVisual3D mv3D = VP.Children[0] as ModelVisual3D;
  Model3DGroup  m3Dg = mv3D.Content as  Model3DGroup;
  m3Dg.Children[7].Transform= mclose001  ;
  doorSound.Play();  
}

...

7 - You need to "include" the sound files in the .CSPROJ.

8 - There will be sound also when the avatar collides against the wall.

9 - We need to make the point crossing the door conditional for the avatar use.

...
//To avoid   the avatar to go to forbiden points
 
 if ((TheZ==-3 && TheX==-4)|| 
  (TheZ==-3 && TheX==-3)||
  (TheZ==-3 && TheX==-2)|| 
  (TheZ==-3 && TheX==-1)|| 
  (TheZ==-8 && TheX==-4)|| 
  (TheZ==-8 && TheX==-3)|| 
  (TheZ==-8 && TheX==-2)|| 
  (TheZ==-8 && TheX==-1) || 
  (TheZ==-3 && TheX==-5 && op==0)||  
  (TheZ==-8 && TheX==-5 && op==0)      
 ){ 
  //return to the previous point
boingSound.Play();
  mtrans= new MatrixTransform3D(transold);
...

IMPORTANT: For the sound to be downloaded to the client the .CSPROJ lines for .WAV files need to be:

...
 <Resource Include="door.png" />
 <Content Include="door.wav">
      <FileStorage>loose</FileStorage>
      <Localizable>False</Localizable>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
  <Content Include="boing1.wav">
      <FileStorage>loose</FileStorage>
      <Localizable>False</Localizable>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
   </Content>
...

OK. I don't know if I talk about everything. Better that you do the download, run the application, analise the code, try to change something etc.

Create a folder having the name of the .ZIP file and download it - right-clicking the link - and unzip inside the folder :

tu14v.zip

Liberate the firewall and play this web3d application:

We are doing our tests at a: Notebook DELL Latitude D600 - Intel Pentium M755 2.0 GHZ - Memory: 512 MB - VideoCard ATI Radeon 9000 32MB DDR 4xAGP - Resolution 1400x1050 - Communication: ADSL 256 kbps (Download: 45 kBps, Upload: 14 kBps)


PREVIOUS LESSON NEXT LESSON
T.CONTENTS HOMEPAGE