Custom shaped NSButton - cocoa

I am trying to create eight custom buttons (NSButton) in Xcode 4.6.3. Those are the segments of a circle. I used a standard rectangular button for each of them, adding a custom image for each segment. However, when I put the pieces together in one circle, there is no way to click some of these buttons, as the rectangular areas around each of them overlap, and prevent from reaching the other half of the buttons.
I was wondering if there is any way to make the button shape at least triangular, such that I can click on all of these buttons?

From the documentation "View Programming Guide":
Note: For performance reasons, Cocoa does not enforce clipping among sibling views or guarantee correct invalidation and drawing behavior when sibling views overlap. If you want a view to be drawn in front of another view, you should make the front view a subview (or descendant) of the rear view.
In other words, you can't expect overlapping views to process mouse events properly. There's no way of getting around the fact that views occupy rectangular frames. You have to make a single view which performs the work of all of your circle segments (including drawing and event handling, and optionally mouse moved events). YOu will have to use trigonometry to calculate which segment a mouse click occurs in, and respond appropriately as though a button were pressed, by re-drawing the segment and invoking the desired action.

Related

Render UI element in front of others programmatically without sibling index (2D)

I have a grid of buttons (3 by 3 for this example). When a button is clicked, it rotates 180 degrees. As it rotates towards 90 degrees, it increases in scale. Once it passes 90 degrees and rotates towards 180, it decreases back to it's original size.
Unfortunately, this is a 2D game so it seems that the layers are determined by the hierarchy, which is created in the order the buttons are spawned. This causes some ugly overlap issues when the tiles scale up, when I really just want whatever button is clicked to be brought to the front.
The common solution seems to be to set the sibling index, but that will not work in this case because the buttons are held in a canvas using a Grid Layout Group, and changing the sibling index causes the buttons to be reordered.
Add a canvas component to your button and use sortOrder to modify the rendering order of it.

React Native: pass touch events through ScrollView to elements lower in the z plane

I'm trying to write a parallax element that has multiple panes which scroll at different rates.
To achieve this, I have multiple View absolutely positioned and stacked in the z plane, with a ScrollView on top to capture the drag events, from which I'll animate the top position and opacity of the lower panes. (Reason for using a ScrollView is to benefit from the bouncing and momentum animation that gives us.)
However, the lower panes may contain elements that want to accept touches (as opposed to scrolls). The problem I'm having is that the ScrollView captures these touches, and there doesn't seem to be a mechanism to pass them on. Basically, I want the ScrollView to respond to drags, but the lower elements to respond to touches.
Is there a way to achieve that?
I've successfully used https://github.com/rome2rio/react-native-touch-through-view for that on iOS.
However on Android, somehow click events are not getting trough while swiping works for underlying view.

NSScrollView with massive contentView causing terrible performance on scroll

I'm trying to draw a large waveform/graph that is an NSView placed inside of a NSScrollView. That way, the user can scroll horizontally and parts of it at a time.
The waveform view can be very large (technically, infinitely wide).
If the entire waveform is drawn, the scrolling performance is unusable. I'm unsure why NSScrollView is attempting to redraw the entire view rather than just the visible rect - but I suspect I will need to implement this logic myself.
What is the most efficient way to implement this to have a good scrolling experience?
You could tile the contents of your scroll view into several small NSView instances, each one representing a small part of your graph and placed right beside one another.
However, I am not sure to what extent the views that are clipped off-screen still consume resources and affect performance.
A better apporach would be similar to the above, but relying on the built-in functionality of a Collection View. Its machinery definitely takes care of displaying only the cells that should be visible (not clipped by the scroll view).

NSView -drawRect and mouse hover performance

I have a custom NSView that draws (with -drawRect) a graph. It also tracks the mouse position (with -mouseMoved and the like) and draws the cursor position/coordinates relative to the axes.
The graph is big and (potentially) slow to draw, and doesn't depend on the mouse position. The mouse-over effect is tiny, and always fast to draw. I don't want to have to redraw everything when the mouse moves a couple pixels, because it feels sluggish.
I'm sure I can make my own private graphics context (doubled in size, if on a 2x display), draw the chart data into that once, and then have -drawRect simply blit that into the view's drawing context. Alternatively, I could split my NSView subclass into two classes, and have one just the chart data, and one just the overlay, and place them exactly on top of each other (though they have to share a bit of data, so this seems awkward).
Is there a built-in method to make this easier, or is there a more idiomatic way of handling this?
Take a look at these NSWindow methods:
Bracketing Drawing Operations
– cacheImageInRect:
– restoreCachedImage
– discardCachedImage
Normally, with a view, you define a drawRect: method that draws contents on-demand. You can, however, do on the spot drawing in a view as result of events for example, by locking focus on the view, performing the drawing, then unlocking focus. The missing link in this on-the-spot drawing, is somehow undoing it without calling your potentially heavy drawRect: via setNeedsDisplay:
This is where the Bracketed drawing operations on NSWindow come into play. Before locking focus on the view and doing some on-the-spot drawing, cache an image of the view in the area you intend to draw. When you next want to update your drawing (while tracking events, perhaps) then restore the cached image, rinse, and repeat.

Warping GUI elements in Unity's OnGUI

I am using Unity3D, and I have a function which is being called inside of OnGUI to lay out the various gui components of my application. Ordinarily, the labels and buttons are all inside of a certain Rect that I supply, which is centered on the screen.
No problem there... however, what I want to is sometime render the exact same gui elements, which can be dynamic, and thus not just put into a prefabbed texture, into a trapezoid-shaped area off to the side, looking as if that gui were actually on a flat plane, pushed away from the center of the screen, and rotated slightly. All gui buttons that were drawn in the function should still respond normally.
I was rather hoping I could just specify some values in GUI.matrix to map the rectangle to a trapezoid, but my initial exploration seems to show that the gui elements don't appear to use homogenous coordinates, and everything still shows up as rectangular.
Is there any way to do this with Unity, ideally without requiring access to pro-only features?
Since now Unity3D GUI system isn't very flexible. The new GUI system is one of the features still not released in Unity 4 (we are all waiting for it).
From my point of view it has several problems, particularly:
You are forced to layout components using the flow of the code, instead of having a more declarative (or at least a more structured) way to do that.
It's quite inefficient (at least one draw call for button).
It isn't flexible at all. Add, Remove, Enable/Disable buttons can be come quick a painful operation when the number of buttons increase.
however, what I want to is sometime render the exact same gui
elements, which can be dynamic, and thus not just put into a prefabbed
texture, into a trapezoid-shaped area off to the side, looking as if
that gui were actually on a flat plane, pushed away from the center of
the screen, and rotated slightly. All gui buttons that were drawn in
the function should still respond normally.
This is quite hard if not impossible to obtain using Unity's GUI classes.
I see 2 possibilities:
Don't use GUI classes to do that. If your GUI is simple enough, you can implement your own (even 3d) buttons using for example:
A mesh (a plane or a trapezoid mesh) with a texture for the button background
TextMesh for drawing 3D text
RayCasting to check if a button has been pressed
Use a library that implements a more advanced GUI system like NGUI
When I ran into the same problem, I just used normal 3D GameObjects cubes with textures and called OnMouseDown(PC/Mac) or RayCasting(Android/iOS) on them. I guess that's how everyone does it.

Resources