Comments (20)
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.
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.
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.
@mxa , can you provide a little bit more information, which kind of project (standalone, vst3), which host, etc... Thank you
from vstgui.
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.
Hi @clwe , do you get mouse ups on normal CAnimKnobs?
from vstgui.
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.
@clwe , it still is interesting if unmodified CAnimKnobs work in those hosts. Error analysis will be much easier if this is known.
from vstgui.
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.
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.
OK. How do I inform the host, that my member variable changed?
from vstgui.
Why does the host need to know that you have switched bitmaps?
from vstgui.
Should your subclass still be used as a knob?
from vstgui.
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.
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.
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.
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.
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.
It would be nice to have usable examples for these basic things. My snarky comment from 2 years ago still holds.
from vstgui.
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)
- Reintroduce setBackOffset() / getBackOffset() and respect the backOffset in all views / controls HOT 4
- FR - Linux HIDPI support HOT 9
- Requesting accessibility implementation, expose GUI controls to platform specific APIs HOT 7
- Use of new CMultiBitmap implementation in CAnimKnob is not backwards compatible HOT 1
- 4.12.1 cswitch.cpp fails compilation with VSTGUI_ENABLE_DEPRECATED_METHODS=0 HOT 1
- Unhandled exception when using vstgui HOT 2
- compile error after updating to Xcode 14.3: no member named 'move' in namespace 'std'
- getChildViewsOfType() with option 'deep' searches only one level deep HOT 1
- ui built on ver 4.11+ will flicker especially run on vst3plugintesthost 64bit HOT 8
- Issue when building with Xcode 14.3 HOT 1
- Segment Button segment names string gets replaced by parameter steps normalized value in Release build HOT 3
- Font drawing inconsistencies between Mac and Windows HOT 5
- [Windows] Cannot move window after a COptionMenu has been popped up HOT 2
- Standalone application crash with newest version of vst3sdk (3.7.9) on Windows when using transforms HOT 6
- std::unique_ptr of forward-declared types HOT 1
- COptionMenu().getMax() returns 18446744073709551616
- Build error while compiling vst3sdk on Fedora 40 HOT 2
- Mac Fails to compile generated project HOT 1
- Custom Fonts on Windows broken if ExitDll called but DLL not actually unloaded
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from vstgui.