I'm writing a Haskell program with click-and-drag functionality, so with each mouse movement event an update gets painted to the window. At the moment I'm using
renderWithDrawable myCanvas update
However this is flickering a lot. My understanding is that I need to create a separate drawable (a "surface"?), render to that, and then blit it onto the screen window in a single operation. However I'm confused as to the right way to do this.
I've found drawWindowBeginPaintRegion, which talks about eliminating flicker.
However it is removed in Gtk3 according to the Haddock docs. So I'm not sure if I should use this, as it seems to be deprecated.
I've also found renderWithSimilarSurface in Cairo, which seems to do something similar.
I'm also not sure how these functions relate to renderWithDrawable: do I have to use them inside that function, or what?
What is the right way to do this?
Edit
This seems to be a known thing in Cairo. I'm trying to figure out how to handle this in Haskell.
Explanation and solution in Python
Description of how to handle this issue in raw C
The right way to do this is to make sure all your drawing comes from within expose events, and operates on the draw window provided by the event. You can mark a region as "dirty" and trigger a synthetic expose event using drawWindowInvalidateRect, drawWindowInvalidateRegion, or widgetQueueDraw.
A quick worked example of setting up the drawing pipeline follows. It is excerpted from a custom Viewport type, which does Google-maps style panning with smooth motions on drag-and-release operations, that I built for a side-project some time ago. To support that, it has to redraw on mouse motion events, so it addresses a similar use case to your described problem. I've elided irrelevant stuff with ... to highlight the important bits. I've uploaded the complete project to github just now, so you can browse the repo to see the full details of Viewport. (It's been years though, so there's probably a fair bit of bitrot -- don't expect the project to just build and run with modern GHCs/packages.)
viewportNew :: Viewport -> IO DrawingArea
viewportNew v = do
da <- drawingAreaNew
-- ...
on da exposeEvent $ exposeViewport posRef (draw v)
-- ...
exposeViewport :: IORef Position -> RegionRenderer -> EventM EExpose Bool
exposeViewport posRef draw = do
dw <- eventWindow
region <- eventRegion >>= liftIO . regionGetRectangles
-- ...
liftIO . renderWithDrawable dw $ do
-- Cairo () action goes here
-- can reference region to decide which things to draw
draw region
return True -- see documentation of exposeEvent for what this means
This template should take advantage of gtk's built-in double-buffering and work with both the gtk and gtk3 packages.
Related
So I have an instanced scene that is supposed to be the child of a colour rect in my tree. I want to randomly generate the nodes, but I also want parts of the view to be cut off if the texture no longer is above the main section. I know you can render nodes below their parents, but I don't know if stopping part of them from rendering is physically possible.
In this image I want the bottom circle to remain the same, but the top circle to not show anything above the dark purple box
This is the node tree in the editor
Is there any way to do this directly, or am I gonna have to use a viewport of some variety?
I believe what you want is to set rect_clip_content to true on the ColorRect (or whatever Control). Making invisible any part of its children outside of it.
From Godot's documentation:
bool rect_clip_content
Enables whether rendering of CanvasItem based children should be clipped to this control's rectangle. If true, parts of a child which would be visibly outside of this control's rectangle will not be rendered.
If what you want is the opposite, perhaps you can use z_index to have something render on top, occluding the parts you don't want visible.
There is also a trick you can use with lights (including 2D lights):
Make a light that matches the area you want things to be visible.
Set a custom material that will be transparent by default, but visible on the light pass. The simpler way to do this is to set the light_mode of the material to "Light Only". You could also do it with a custom shader instead.
Making something disappear with light, in 2D, is impossible. In 3D, you can use flags_use_shadow_to_opacity. That is how you make a shadow catcher.
But, there is one more trick: you can use a mask. This should give you full control of when to show or hide things. So, if none of the above solutions works for you, use a mask. I have an explanation in a different answer. See also: How to crop sprite in a non-rectangular form?.
Mighty Mochi Games recently (2022-03-30) made a compilation of the different approaches in video form: Mask Methods Collection - Godot 3.x - 2D
.
I'm trying to load an image into a fltkhs box widget and do some image processing on it and I'd like to get the coordinates when the mouse click on a point on the image.
I couldn't find any part of fltkhs that can handle mouse events.
Anyone could give any suggestions?
Glancing through the documentation yielded this page:
https://hackage.haskell.org/package/fltkhs-0.5.4.1/docs/Graphics-UI-FLTK-LowLevel-FL.html
It has a function with the following signature:
getMouse :: IO Position
I suppose it's FLTKHS's analogue for get_mouse
I've been looking around for an answer for this. I seem to gather that some sort of X11 (or a virtual frame buffer) is always required for plotting.
However I do not understand why that is needed for SVG graphics, seems like I should even be able to create them manually, so why does R seem to always need the X11?
I imagine that the X11 performs some functionality, like selecting colors from a palette or something like that. Is that the case? if not, how can I avoid the X11 completely.
I'm using ggplot2 to make a plot and gridSVG to extract it as in:
plot <- ggplot(data=data, aes(...)) + ...
print(plot)
mysvg <- grid.export()
I'm making a game using gtk/cairo in haskell, and I'm looking for a way to completely clear the drawing area (a widget of type drawingArea). When a widget resizes for instance, the drawing area is cleared automatically. I'm looking for a way to clear it manually.
Any suggestions?
First get the DrawWindow of the DrawingArea using the function widgetGetDrawWindow, then call drawWindowClear with the DrawWindow as the argument.
I'm building a Container using code and now I want to set the Styleusing one UnselectedStyle from the Resource Editor.
I'm doing this because, I don't find the way to add a LinearBackground color and a RoundBorder to my Container. When I put the two properties to the Style, the background color has gone.
So I finally add this Style using the UIManager.getInstance().addThemeProps(String name ThemeFromResource); and later the setUIID(String nameStyle). Is working fine...my Containergets the Style, but the app lose the navigation, the back Commandhas gone.
How can do this? I would like to do with my first way...creating the lineargradient and the border and adding it to the style, but I don't find the way.
I would strongly suggest against doing that.
Border's override other forms of background, round border tries to respect some of them but is REALLY inefficient about that. It effectively draws the background on a mutable image then draws the round border on another mutable image, gets the RGB for both and performs a NOT operation to crop the background into a round image. This (as you might understand) is REALLY expensive in terms of performance, while the image is then cached it is still expensive in the longer term.
You should use image borders which are MUCH faster.