jvcleave / ofxImGui

Use ImGui in openFrameworks
296 stars 124 forks source link

how to prevent events from passing to app #26

Closed memo closed 8 years ago

memo commented 8 years ago

how can we block events from passing to the app? e.g. when using ofApp::mousePressed etc and we want to ignore events which are handled by the ImGui, or when using ofEasyCam etc?

jvcleave commented 8 years ago

Any way you could provide a small app just so we have a base to talk around?

jvcleave commented 8 years ago

ok, I see what you are saying - here is what I am playing with

#include "ofMain.h"
#include "ofxImGui.h"

class ofApp : public ofBaseApp{

public:
    ofEasyCam easyCam;
    ofxImGui gui;
    float floatValue;
    ofColor backgroundColor;

    void setup()
    {
        //
        easyCam.setDistance(100);
        gui.setup();
        floatValue = 0.0f;
        backgroundColor = ofColor(114, 144, 154);

    }

    void update()
    {

    }

    void draw()
    {
        ofSetBackgroundColor(backgroundColor);
        ofPushStyle();

        ofEnableDepthTest();
        easyCam.begin();
            ofNoFill();
            ofDrawBox(30);
        easyCam.end();
        ofPopStyle();
        ofDisableDepthTest();

        gui.begin();
        ImGui::Text("Hello, world!");
        ImGui::SliderFloat("Float", &floatValue, 0.0f, 1.0f);

        //this will change the app background color
        ImGui::ColorEdit3("Background Color", (float*)&backgroundColor);

        gui.end();
    }

    void keyPressed(int key)
    {

    }

    void keyReleased(int key)
    {

    }

    void mouseMoved(int x, int y )
    {

    }

    void mouseDragged(int x, int y, int button)
    {

    }

    void mousePressed(int x, int y, int button)
    {

    }

    void mouseReleased(int x, int y, int button)
    {

    }

};

//========================================================================
int main( ){
    ofSetupOpenGL(1024,768,OF_WINDOW);          // <-------- setup the GL context

    // this kicks off the running of my app
    // can be OF_WINDOW or OF_FULLSCREEN
    // pass in width and height too:
    ofRunApp(new ofApp());

}
memo commented 8 years ago

yes sorry, that's exactly what I meant. This is a problem I've always had with guis in OF :) not sure if it can be addressed without structural changes to the way events are handled in the core?

jvcleave commented 8 years ago

This seems to work ok

void draw()
    {
        ofSetBackgroundColor(backgroundColor);
        ofPushStyle();

        ofEnableDepthTest();

        bool isHovering = ImGui::IsPosHoveringAnyWindow(ofVec2f(ofGetMouseX(), ofGetMouseY()));
        ofLogVerbose() << "isHovering: " << isHovering;
        if(isHovering)
        {
            easyCam.disableMouseInput();
        }else
        {
            easyCam.enableMouseInput();
        }

        easyCam.begin();
            ofNoFill();
            ofDrawBox(30);
        easyCam.end();
        ofPopStyle();
        ofDisableDepthTest();

        gui.begin();
        ImGui::Text("Hello, world!");
        ImGui::SliderFloat("Float", &floatValue, 0.0f, 1.0f);

        //this will change the app background color
        ImGui::ColorEdit3("Background Color", (float*)&backgroundColor);

        gui.end();
    }
memo commented 8 years ago

oh wow that's smart thanks. still need a more generic solution. e.g. when typing in a text field, the key events are still sent to the ofApp::keyPressed. So would need to add a similar check for key events. but this is great!

jvcleave commented 8 years ago

Cool - The hover check may actually still apply with textfields as well. If not there is probably a focus check

memo commented 8 years ago

yup this is cool and works, thx

ocornut commented 7 years ago

@jvcleave IsPosHoveringAnyWindow() happens to be broken (and was always broken depending on the call timing), and anyway it isn't what you want to use, I think you need to use io.WantCaptureMouse for that purpose. io.WantCaptureMouse will handle more use cases and behaviors, should as clicking on a drag/slider widget and moving the mouse outside the imgui window (you still want to be capturing mouse in this case).

moebiussurfing commented 3 years ago

hey @ocornut , (not sure if It's better to write into your ImGui repo...)

I would like to check if the mouse is inside a specific widget, like a text input. How can I do this?

For the moment I am checking if the mouse it's inside any ImGui window doing this:

// draw()
mouseOverGui = ImGuiDraw();
mouseOverGui = ofxImGui::IsMouseOverGui();

if (mouseOverGui != mouseOverGui_PRE)// changed
{
    mouseOverGui_PRE = mouseOverGui;
    ofLog() << "mouseOverGui: " << (mouseOverGui ? " Going InSide" : " Going outSide");
}

//-----------

// ImGuiDraw()
std::string _text = "type here";

char tab2[32];
strncpy(tab2, _text.c_str(), sizeof(tab2));
tab2[sizeof(tab2) - 1] = 0;

if (ImGui::InputText("", tab2, IM_ARRAYSIZE(tab2)))
{
    ofLog() << "InputText:" << ofToString(tab2);
    _text = ofToString(tab2);
}
moebiussurfing commented 3 years ago
bool ofxImGui::IsMouseOverGui()
{
    return ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow);
}

I see this:

// Flags for ImGui::IsItemHovered(), ImGui::IsWindowHovered()
// Note: if you are trying to check whether your mouse should be dispatched to imgui or to your app, you should use the 'io.WantCaptureMouse' boolean for that. Please read the FAQ!
// Note: windows with the ImGuiWindowFlags_NoInputs flag are ignored by IsWindowHovered() calls.
enum ImGuiHoveredFlags_
{
    ImGuiHoveredFlags_None                          = 0,        // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them.
    ImGuiHoveredFlags_ChildWindows                  = 1 << 0,   // IsWindowHovered() only: Return true if any children of the window is hovered
    ImGuiHoveredFlags_RootWindow                    = 1 << 1,   // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy)
    ImGuiHoveredFlags_AnyWindow                     = 1 << 2,   // IsWindowHovered() only: Return true if any window is hovered
    ImGuiHoveredFlags_AllowWhenBlockedByPopup       = 1 << 3,   // Return true even if a popup window is normally blocking access to this item/window
    //ImGuiHoveredFlags_AllowWhenBlockedByModal     = 1 << 4,   // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet.
    ImGuiHoveredFlags_AllowWhenBlockedByActiveItem  = 1 << 5,   // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns.
    ImGuiHoveredFlags_AllowWhenOverlapped           = 1 << 6,   // Return true even if the position is obstructed or overlapped by another window
    ImGuiHoveredFlags_AllowWhenDisabled             = 1 << 7,   // Return true even if the item is disabled
    ImGuiHoveredFlags_RectOnly                      = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped,
    ImGuiHoveredFlags_RootAndChildWindows           = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows
};
ocornut commented 3 years ago

I would like to check if the mouse is inside a specific widget, like a text input.

You can use IsItemHovered()...

moebiussurfing commented 3 years ago

sorry, but where must be placed? I tried inside and / or after the InputText but is not appearing...

if (ImGui::InputText("", tab2, IM_ARRAYSIZE(tab2)))
{
    //if (ImGui::IsItemHovered())
    //  ImGui::SetTooltip("I am a tooltip");

    textInput_temp = ofToString(tab2);
}

if (ImGui::IsItemHovered()) {
    ImGui::SetTooltip("I am a tooltip");
}
ocornut commented 3 years ago

Read the comments and search how it is used in the demo (in about a hundred places).

moebiussurfing commented 3 years ago

solved. Thanks.

if (ImGui::InputText("", tab, IM_ARRAYSIZE(tab)))
{
  textInput_New = ofToString(tab);
  ofLog() << "textInput_New:" << textInput_New;
}

bool b = bTextInputActive;
bTextInputActive = ImGui::IsItemActive();
if (bTextInputActive != b) // hover into textInput changed
  ofLog() << "TextInput : " << (bTextInputActive?"ACTIVE":"DISABLED");