Giter Club home page Giter Club logo

Comments (20)

clwe avatar clwe commented on August 15, 2024 2

Thanks a lot for your time and help! I haven't found the time yet to implement it as above, will do ASAP. The issue can be closed - mouse up events are received as advertised!

from vstgui.

clwe avatar clwe commented on August 15, 2024 1

After more testing I found that this problem is not linux related at all - but is host specific: It happens in Reaper and Bitwig, but the problem does not show in Ableton Live.
My gut feeling says, it could be something related with the automation recording or state saving capabilities of the host(?)

from vstgui.

scheffle avatar scheffle commented on August 15, 2024 1

Hi, I think it is not a good idea to inherit from a control class which implements a special behavior like the CAnimKnob and implement another behavior into it like a kick button as in your case.
I've drafted a version of what you want and how I would implement it:

class CKickButtonHover : public CControl
{
public:
	CKickButtonHover (const CRect& r, IControlListener* l, int32_t tag) : CControl (r, l, tag) { std::fill (bitmaps.begin (), bitmaps.end (), nullptr); }

	void setBitmaps (CBitmap* inactive, CBitmap* hover, CBitmap* clicked)
	{
		bitmaps[UIState::Inactive] = inactive;
		bitmaps[UIState::Hover] = hover;
		bitmaps[UIState::Clicked] = clicked;
	}

	void draw (CDrawContext* context) override
	{
		if (auto bitmap = bitmaps[state])
			bitmap->draw (context, getViewSize ());
		setDirty (false);
	}

	void onMouseDownEvent (MouseDownEvent& event) override
	{
		beginEdit ();
		setValue (1.);
		valueChanged ();
		
		state = UIState::Clicked;
		invalid ();
		event.consumed = true;
	}
	void onMouseUpEvent (MouseUpEvent& event) override
	{
		setValue (0.);
		valueChanged ();
		endEdit ();
		if (getViewSize().pointInside(event.mousePosition))
			state = UIState::Hover;
		else
			state = UIState::Inactive;
		invalid ();
		event.consumed = true;
	}
	void onMouseCancelEvent (MouseCancelEvent& event) override
	{
		if (isEditing ())
			endEdit ();
		state = UIState::Inactive;
		invalid ();
	}
	void onMouseEnterEvent (MouseEnterEvent& event) override
	{
		if (isEditing ())
			return;
		state = UIState::Hover;
		invalid ();
	}
	void onMouseExitEvent (MouseExitEvent& event) override
	{
		if (isEditing ())
			return;
		state = UIState::Inactive;
		invalid ();
	}

	CLASS_METHODS_NOCOPY (CKickButtonHover, CControl)
private:
	enum UIState
	{
		Inactive,
		Hover,
		Clicked,
		
		Count
	};

	UIState state {UIState::Inactive};
	std::array<SharedPointer<CBitmap>, UIState::Count> bitmaps;
};

from vstgui.

scheffle avatar scheffle commented on August 15, 2024

@mxa , can you provide a little bit more information, which kind of project (standalone, vst3), which host, etc... Thank you

from vstgui.

clwe avatar clwe commented on August 15, 2024

Hello @scheffle,

We build a VST3, the issue was tested with Bitwig Studio 4.3.10 on Linux.
I subclassed CAnimKnob and implemented the mouse functions as follows:

namespace VSTGUI {

    CKickButtonHover::CKickButtonHover(const VSTGUI::CRect& size, IControlListener* listener, int32_t tag, CBitmap* background, CBitmap* triggerBitmap, const CPoint& offset)
    : CAnimKnob(size, listener, tag, background, offset)
    {}

    CMouseEventResult CKickButtonHover::onMouseDown (CPoint& where, const CButtonState& buttons)
    {
        LOG_DEBUG("mouse down on trigger view \n");
        if (!(buttons & kLButton))
            return kMouseEventNotHandled;

        value = 1.0;
        if (isDirty ())
        {
            invalid ();
            valueChanged ();
        }
        beginEdit ();
        return onMouseMoved(where, buttons);
    }

    CMouseEventResult CKickButtonHover::onMouseUp (CPoint& where, const CButtonState& buttons)
    {
        LOG_DEBUG("mouse up on trigger view \n");
        if (!(buttons & kLButton))
            return kMouseEventNotHandled;

        value = 0.5;
        if (isDirty ())
        {
            invalid ();
            valueChanged ();
        }
        endEdit ();
        return kMouseEventHandled;
    }

    CMouseEventResult CKickButtonHover::onMouseEntered (CPoint& where, const CButtonState& buttons)
    {
        LOG_DEBUG("mouse entered trigger view \n");
        value = 0.5;
        if (isDirty ())
        {
            invalid ();
            valueChanged ();
        }
		
        return kMouseEventHandled;
    }

    CMouseEventResult CKickButtonHover::onMouseExited (CPoint& where, const CButtonState& buttons)
    {
        LOG_DEBUG("mouse exited trigger view \n");
        value = 0.0;
        if (isDirty ())
        {
            invalid ();
            valueChanged ();
        }
		
        return kMouseEventHandled;
    }

    bool CKickButtonHover::onWheel (const CPoint& where, const CMouseWheelAxis& axis, const float &distance, const CButtonState &buttons)
    {   
        return false;
    }
}

I just re-tested after changes to the order of isDirty(), invalid() and valueChanged() and the mouse up event is correctly received. But the value of 1.0 of this event somehow doesn't get properly received in the GUI.

from vstgui.

scheffle avatar scheffle commented on August 15, 2024

Hi @clwe , do you get mouse ups on normal CAnimKnobs?

from vstgui.

clwe avatar clwe commented on August 15, 2024

Sorry, the edit of my comment from yesterday didn't get saved. As stated above:

I just re-tested after changes to the order of isDirty(), invalid() and valueChanged() and the mouse up event is correctly received. But the value of 1.0 of this event somehow doesn't get properly received in the GUI.

The problem might to be somewhere else, not in this part of the code. The strange thing is that this code works perfectly fine on Mac OS and Windows. We implement a hovering function with CAnimknob with three bitmaps:

  • value = 0.0 -> button inactive (bitmap 0)
  • value = 0.5 -> button hover (bitmap 1)
  • value = 1.0 -> button clicked (bitmap 2)

The strange behaviour on linux is the following:

  • On first mouse down we see bitmap number 0 - corresponding to value = 0.0 (erratic behavior)
  • On all succeeding mouse downs we see bitmap number 2 - corresponding to value = 1.0 (expected behavior)

from vstgui.

scheffle avatar scheffle commented on August 15, 2024

@clwe , it still is interesting if unmodified CAnimKnobs work in those hosts. Error analysis will be much easier if this is known.

from vstgui.

clwe avatar clwe commented on August 15, 2024

Yes, we use several animation knobs as shipped with the sdk and they work as expected in all the mentioned DAWs (but do not implement hovering by default).

from vstgui.

scheffle avatar scheffle commented on August 15, 2024

OK, just reread your stuff. You use the CControl::value member in your subclass to select bitmaps. Don't do this, add your own member variable to do this.

from vstgui.

clwe avatar clwe commented on August 15, 2024

OK. How do I inform the host, that my member variable changed?

from vstgui.

scheffle avatar scheffle commented on August 15, 2024

Why does the host need to know that you have switched bitmaps?

from vstgui.

scheffle avatar scheffle commented on August 15, 2024

Should your subclass still be used as a knob?

from vstgui.

clwe avatar clwe commented on August 15, 2024

You are right, the host doesn't need to know. But the UI needs to update the bitmap according to my member variable somehow. (I don't know the inner workings of CAnimknob.)
It's used as a trigger button actually. It has three states as mentioned above.

from vstgui.

scheffle avatar scheffle commented on August 15, 2024

Whenever you want to change the bitmap, you call invalid() and set your own class member to the index depending on the situation. Your draw methods will be called a little bit later where you then draw the bitmap according to the index you previously have set in your class member.

from vstgui.

clwe avatar clwe commented on August 15, 2024

Aha, thanks!
So I would have to re-implement this function:

void CAnimKnob::draw (CDrawContext *pContext)
{
	if (getDrawBackground ())
	{
		CPoint where (0, 0);
		float val = getValueNormalized ();
		if (val >= 0.f && heightOfOneImage > 0.)
		{
			CCoord tmp = heightOfOneImage * (getNumSubPixmaps () - 1);
			if (bInverseBitmap)
				where.y = floor ((1. - val) * tmp);
			else
				where.y = floor (val * tmp);
			where.y -= (int32_t)where.y % (int32_t)heightOfOneImage;
		}

		getDrawBackground ()->draw (pContext, getViewSize (), where);
	}
	setDirty (false);
}

What is the index you were referring to? How do I add my class to the index?
Also, do I have to implement setDirty() as well?

from vstgui.

clwe avatar clwe commented on August 15, 2024

Hmm. I changed the code slightly and don't call onMouseMoved() anymore. I also call beginEdit() and endEdit() directly in sequence and it works! The graphics get displayed correctly now.

CMouseEventResult CKickButtonHover::onMouseDown (CPoint& where, const CButtonState& buttons)
    {
        if (!(buttons & kLButton))
            return kMouseEventNotHandled;

        value = 1.0;
        if (isDirty ())
        {
            invalid ();
            valueChanged ();
        }
        beginEdit ();
        endEdit ();
        return kMouseEventHandled; // onMouseMoved(where, buttons);
    }

    CMouseEventResult CKickButtonHover::onMouseUp (CPoint& where, const CButtonState& buttons)
    {
        if (!(buttons & kLButton))
            return kMouseEventNotHandled;

        value = 0.5;
        if (isDirty ())
        {
            invalid ();
            valueChanged ();
        }
        return kMouseEventHandled;
    }

Is there any side effect that I don't know of?

from vstgui.

clwe avatar clwe commented on August 15, 2024

 Well, not exactly. If I press down and drag the mouse, then the bitmap gets stuck in the pressed state (value=1) until you press or exit the hover area. So I guess I will need to go the longer way and re-implement the methods.

from vstgui.

mxa avatar mxa commented on August 15, 2024

It would be nice to have usable examples for these basic things. My snarky comment from 2 years ago still holds.

from vstgui.

scheffle avatar scheffle commented on August 15, 2024

VSTGUI is open source, it lives from the participation of its users. When no one provides "usable examples", then there are no "usable examples".
And it's always discussable what "usable" actually means.
Can we close this issue now, or are you still have issue with mouse up events?

from vstgui.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.