Creating an interactive object that responds to the mouse

In this recipe, we will create an InteractiveObject class for making graphical objects that interact with the mouse cursor and executes the following actions:

Action

Description

Pressed

The user pressed the mouse button while over the object.

Pressed outside

The user pressed the mouse button while outside the object.

Released

The mouse button is released after being pressed over the object and is still over the object.

Released outside

The mouse button is released outside the object.

Rolled over

The cursor moves over the object.

Rolled out

The cursor moves out of the object.

Dragged

The cursor is dragged while being over the object and after having pressed the object.

For each of the previous actions, a virtual method will be called, and it would change the color of the object been drawn.

This object can be used as a base class to create interactive objects with more interesting graphics, such as textures.

Getting ready

Create and add the following files to your project:

  • InteractiveObject.h
  • InteractiveObject.cpp

In the source file with your application class, include the InteractiveObject.h file and add the following using statements:

#include "InteractiveObject.h"
using namespace ci;
using namespace ci::app;
using namespace std;

How to do it…

We will create an InteractiveObject class and make it responsive to mouse events.

  1. Move to the file InteractiveObject.h and add the #pragma once directive and include the following files:
    #pragma once
    
    #include "cinder/Rect.h"
    #include "cinder/Color.h"
    #include "cinder/app/MouseEvent.h"
    #include "cinder/gl/gl.h"
    #include "cinder/app/App.h"
  2. Declare the class InteractiveObject:
    class InteractiveObject{
    public:
    InteractiveObject( const ci::Rectf& rect );
    virtual ~InteractiveObject();
    virtual void draw();
    virtual void pressed();
    virtual void pressedOutside();
    virtual void released();
    virtual void releasedOutside();
    virtual void rolledOver();
    virtual void rolledOut();
    virtual void dragged();
    void mouseDown( ci::app::MouseEvent& event );
    void mouseUp( ci::app::MouseEvent& event );
    void mouseDrag( ci::app::MouseEvent& event );
    void mouseMove( ci::app::MouseEvent& event );
    
    ci::Rectf rect;
    ci::Color pressedColor, idleColor, overColor, strokeColor;
    
    protected:
    bool mPressed, mOver;
    };
  3. Move on to the InteractiveObject.cpp file, and let's begin by including the InteractiveObject.h file and adding the following using statements:
    #include "InteractiveObject.h"
    
    using namespace ci;
    using namespace ci::app;
    using namespace std;
  4. Let's begin by implementing constructor and destructor.
    InteractiveObject::InteractiveObject( const Rectf& rect ){
      this->rect = rect;
      pressedColor = Color( 1.0f, 0.0f, 0.0f );
      idleColor = Color( 0.7f, 0.7f, 0.7f );
      overColor = Color( 1.0f, 1.0f, 1.0f );
      strokeColor = Color( 0.0f, 0.0f, 0.0f );
      mPressed = false;
      mOver = false;
    }
    
    InteractiveObject::~InteractiveObject(){    
    }
  5. In the InteractiveObject::draw method we will draw the rectangle using the appropriate colors:
    void InteractiveObject::draw(){
     if( mPressed ){
      gl::color( pressedColor );
     } else if( mOver ){
      gl::color( overColor );
     } else {
      gl::color( idleColor );
     }
     gl::drawSolidRect( rect );
     gl::color( strokeColor );
     gl::drawStrokedRect( rect );
    }
  6. In the pressed, released, rolledOver, rolledOut, and dragged methods we will simply output to the console on which the action just happened:
    void InteractiveObject::pressed(){
      console() << "pressed" << endl;
    }
    
    void InteractiveObject::pressedOutside(){
      console() << "pressed outside" << endl;
    }
    
    void InteractiveObject::released(){
      console() << "released" << endl;
    }
    
    void InteractiveObject::releasedOutside(){
      console() << "released outside" << endl;
    }
    
    void InteractiveObject::rolledOver(){
      console() << "rolled over" << endl;
    }
    
    void InteractiveObject::rolledOut(){
      console() << "rolled out" << endl;
    }
    
    void InteractiveObject::dragged(){
      console() << "dragged" << endl;
    }
  7. In the mouse event handlers we will check if the cursor is inside the object and update the mPressed and mOver variables accordingly. Every time the action is detected, we will also call the correspondent method.
    void InteractiveObject::mouseDown( MouseEvent& event ){
      if( rect.contains( event.getPos() ) ){
        mPressed = true;
        mOver = false;
        pressed();
      }else{
          pressedOutside();
      }
    }
    
    void InteractiveObject::mouseUp( MouseEvent& event ){
     if( rect.contains( event.getPos() ) ){
      if( mPressed ){
       mPressed = false;
       mOver = true;
       released();
      }
     } else {
      mPressed = false;
      mOver = false;
      releasedOutside();
     } 
    }
    
    void InteractiveObject::mouseDrag( MouseEvent& event ){
     if( mPressed && rect.contains( event.getPos() ) ){
      mPressed = true;
      mOver = false;
      dragged();
     } 
    }
    
    void InteractiveObject::mouseMove( MouseEvent& event ){
     if( rect.contains( event.getPos() ) ){
      if( mOver == false ){
       mPressed = false;
       mOver = true;
       rolledOver();
      }
     } else {
      if( mOver ){
       mPressed = false;
       mOver = false;
       rolledOut();
      } 
     }
  8. With our InteractiveObject class ready, let's move to our application's class source file. Let's begin by declaring an InteractiveObject object.
    shared_ptr<InteractiveObject> mObject;
  9. In the setup method we will initialize mObject.
    Rectf rect( 100.0f, 100.0f, 300.0f, 300.0f );
    mObject = shared_ptr<InteractiveObject>( new InteractiveObject( rect ) );
  10. We will need to declare the mouse event handlers.
    void mouseDown( MouseEvent event );	
    void mouseUp( MouseEvent event );
    void mouseDrag( MouseEvent event );
    void mouseMove( MouseEvent event );
  11. In the implementation of the previous methods we will simply call the corresponding method of mObject.
    void MyApp::mouseDown( MouseEvent event ){
      mObject->mouseDown( event );
    }
    
    void MyApp::mouseUp( MouseEvent event ){
      mObject->mouseUp( event );
    }
    
    void MyApp::mouseDrag( MouseEvent event ){
      mObject->mouseDrag( event );
    }
    
    void MyApp::mouseMove( MouseEvent event ){
      mObject->mouseMove( event );
    }
  12. In the implementation of the draw method, we will clear the background with black and call the draw method of mObject.
    gl::clear( Color( 0, 0, 0 ) ); 
    mObject->draw();
  13. Now build and run the application. Use the mouse to interact with the object. Whenever you press, release, or roll over or out of the object, a message will be sent to the console indicating the behavior.

How it works…

The InteractiveObject class is to be used as a base class for interactive objects. The methods pressed, released, rolledOver, rolledOut, and dragged are specifically designed to be overridden.

The mouse handlers of InteractiveObject call the previous methods whenever an action is detected. By overriding the methods, it is possible to implement specific behavior.

The virtual destructor is declared so that extending classes can have their own destructor.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.108.119