openframeworks / openFrameworks

openFrameworks is a community-developed cross platform toolkit for creative coding in C++.
http://openframeworks.cc
Other
9.98k stars 2.55k forks source link

ofxButton: distinguish button from Toggle visually with circle vs square #8144

Closed artificiel closed 1 month ago

artificiel commented 1 month ago

It is a bit confusing that the visual representation of an ofxButton is the same as the ofxToggle, as it is not possible to pre-determine that the widget will behave differently without clicking it. Even once clicked, it looks like an active toggle so you only know if if it's going to "stick" or not upon release.

This changes the representation of the Button to a rounded rectangle, completely filled when clicked (much like buttons do, in most environments). it is close enough to the original square to not disturb the visual ambiance of a populated ofxPanel, but still conveys it's operational status clearly.

It does not affect usage or API, nor adds methods or memory requirements as it simply implement it's own generateDraw over the one inherited by ofxToggle, by copying the ofxToggle::generatedDraw integrally and changing a few draw calls -- no changes in code logic).

https://github.com/user-attachments/assets/f8aacf15-85ff-4075-b079-efeae56584a4

roymacdonald commented 1 month ago

I agree. This seems like a good idea. Although I think it is a good idea to optimize its drawing by caching the geometries instead of having to generate each time. I can guess that this would be beneficial for low power systems such as a raspberrypi. And the button does not change its size, only where it gets drawn, so it is quite easy to generate once and then just draw.

artificiel commented 1 month ago

i agree with the caching but this code is a simply copy-paste from the ofxToggle with 3 changes lines (the method is otherwise inherited as-is from ofxToggle) -- the principle you describe should be implemented within ofxToggle (and perhaps others, for instance the text region of all elements?). but that is a much deeper dive and seems risky/out-of-scope versus a simple tweak of what is currently in place?

roymacdonald commented 1 month ago

i agree with the caching but this code is a simply copy-paste from the ofxToggle with 3 changes lines (the method is otherwise inherited as-is from ofxToggle) - sure, but the difference is that for a square you draw 4 vertices while for a rounded rect or circle you end up drawing a lot more.

There is already caching for the text, and some of the geometries. I digged into it a while ago, so I can't tell from the top of my head. I can check how to optimize this

artificiel commented 1 month ago

ah but i just verified and this generateDraw() is only called when the geometry or name changes (or whatever bumps needsRedraw). so maybe it is the caching you're thinking of.

https://github.com/openframeworks/openFrameworks/blob/2bd8b4564e9448c745459dd3f6190c253b411e18/addons/ofxGui/src/ofxBaseGui.cpp#L152-L160

roymacdonald commented 1 month ago

I was actually recalling what goes on here which is used in ofxSlider but not in ofxToggle (which I guess it should, as it currently uses an ofPath). Drawing an ofPath is more expensive than drawing an ofMesh, as the ofPath will teselate, generate a mesh, and then draw. Drawing a circle is more expensive than drawing a square. But, maybe I am getting to picky.

artificiel commented 1 month ago

tesselate() is called within draw(), but the tessellation is cached at the ofPath level (until bNeedsTessellation, and there is a similar check with bNeedsPolylinesGeneration):

https://github.com/openframeworks/openFrameworks/blob/2bd8b4564e9448c745459dd3f6190c253b411e18/libs/openFrameworks/graphics/ofPath.cpp#L642-L652

so unless the user drags ofxPanel around, the mesh is is not refreshed.