Hit test example

Hi everyone! Its been a while!

Is there any hit test simple example in the of examples?
I thought that would be useful for everyone.

Best,
j

Hello Jordi! please explain better what a hit test example would be

Hi Dimitre!
I mean an example where you click and select objects (square, circle, polygons) and drag them around the screen. Maybe rotate them and scale them… like a drawing tool.
I would like to see a simple example about that. But maybe it’s a bit too much code for an example? where to start?

Best,
j

There are some resources that might help - this is something I use a lot:

Its a handy class that uses events for mouse over, click, rolloff etc.

The ofRectangle class has an inside() function to know if a point is inside it
https://openframeworks.cc/documentation/types/ofRectangle/#show_inside

As does ofPolyline (for knowing if a point is inside a more complex shape):
https://openframeworks.cc/documentation/graphics/ofPolyline/#show_inside

This is a simple addon that utilises the ofxMSAInteractiveObject to create draggable objects

For something more advanced there is a pointPickerExample in the 3D section, for picking points in a mesh.

Using addons may well be overkill for your needs (and although it makes things simple, it is not always the best way to go), but this selection should give you a bit of a showcase of different ways to acheive a few different interaction based goals.

1 Like

Hi @Jordi !
I use a lot the ofRectangle class which has the inside(…) method that returns a bool. Receives a 2d coordinate and returns true if it is inside of the rectangle.
I have this old but still functional addon which makes use of such. GitHub - roymacdonald/ofxScaleDragRect: openFrameworks addon. adds interactive scale and dragging to the ofRectangle class.
for something like a draggable point I would often use a simple class as the following

#pragma once

#include "ofMain.h"

class Draggable: public glm::vec2{
public:
    Draggable(){}
    Draggable(float x, float y){
        this->x = x;
        this->y = y;
    }
    
    void draw(){
        if(state == OFX_DRAGGABLE_OVER || state == OFX_DRAGGABLE_DRAGGING){
            ofSetColor(ofColor::black);
            ofDrawCircle(this->x, this->y, radius+ 4);
        }
        if(state == OFX_DRAGGABLE_DRAGGING){
            ofSetColor(ofColor::red);
        }else{
            ofSetColor(ofColor::white);
        }
        ofDrawCircle(this->x, this->y, radius);
    }
    
    void enableMouse(){
        listeners.unsubscribeAll();
        listeners.push(ofEvents().mouseMoved.newListener(this, &Draggable::mouseMoved));
        listeners.push(ofEvents().mouseDragged.newListener(this, &Draggable::mouseDragged));
        listeners.push(ofEvents().mousePressed.newListener(this, &Draggable::mousePressed));
        listeners.push(ofEvents().mouseReleased.newListener(this, &Draggable::mouseReleased));


    }
    void disableMouse(){
        listeners.unsubscribeAll();
    }
    bool isMouseEnabled(){
        return !listeners.empty();
    }
    
private:
    virtual void mouseMoved( ofMouseEventArgs & mouse ){
        if(glm::distance(*this, mouse) <= radius ){
            state =OFX_DRAGGABLE_OVER;
        }else{
            state =OFX_DRAGGABLE_NONE;
        }
    }
    virtual void mouseDragged( ofMouseEventArgs & mouse ){
        if(state == OFX_DRAGGABLE_DRAGGING){
            this->x = mouse.x - pressOffset.x;
            this->y = mouse.y - pressOffset.y;
        }
    }
    virtual void mousePressed( ofMouseEventArgs & mouse ){
        if(glm::distance(*this, mouse) <= radius ){
            pressOffset = mouse - *this;
            state =OFX_DRAGGABLE_DRAGGING;
        }
    }
    virtual void mouseReleased(ofMouseEventArgs & mouse){
        if(glm::distance(*this, mouse) <= radius ){
            state =OFX_DRAGGABLE_OVER;
        }else{
            state =OFX_DRAGGABLE_NONE;
        }
    }
    
    float radius = 10;// change this if you want to
    
    enum DraggableState{
        OFX_DRAGGABLE_NONE = 0,
        OFX_DRAGGABLE_OVER,
        OFX_DRAGGABLE_DRAGGING
    } state = OFX_DRAGGABLE_NONE;
    
    glm::vec2 pressOffset; // store the press offset (difference between this object's position and the mouse position when pressed) so it does not make an ugly jump when moving.
    
    ofEventListeners listeners;
    
};

class ofApp : public ofBaseApp{

	public:
		void setup();
		void draw();
		
    vector<unique_ptr<Draggable>> draggables;
    
};

//--------------------------------------------------------------
void ofApp::setup(){
    
    for(size_t i = 0; i < 100; i++){
        draggables.emplace_back(make_unique<Draggable>(ofRandomWidth(), ofRandomHeight()));
        draggables.back()->enableMouse();
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    for(auto& d: draggables){
        d->draw();
    }
}
2 Likes

Actually it could be a good thing to add some examples like this. I can easily make this. What do you think @theo @zach ?

1 Like

Hey an example with some drawing tools might make a fantastic example. And some of the tools could tie in with the Graphics chapter from ofBook too.

1 Like

Hello everyone,

Thank you for your replies. I did know about ofRectangle and ofPolyline inside functions. Also about memo’s addon. Its good that you specified them in this thread.

I agree that having an example about that would be great. I would be please to contribute.

All the best,
j

1 Like

This design pattern has come up in the forum recently. If there isn’t an example of it already, I love the thought of including it in a new “drawing tools” example.

1 Like

I have a bunch of tools for drawing like that, rotating, scaling etc. I feel that it is a bit more complex than the usual OF examples. But I still could give it a try and transform these into some sort of example

1 Like