Looking at the dependencies, I noticed that you also wrote a binding to SDL_ttf
.
I am wondering if it would be enough to provide a SDL-based reimplementation of the Graphics
library (with exactly the same interface)? It could be a nice way to have a pedagogical graphical API which is just a front-end for a full graphical library.
Yes, I think it would be fairly easy.
Looking at the Graphics
API, the only things that are not included in SDL
+SDL_ttf
+SDL_image
are graphics primitives like (filled) ellipses and (filled) polygons. One could write bindings to SDL_gfx
(*) for these, but it’s more fun to program them directly in ocaml
(*) in fact they already exist, GitHub - fccm/tsdl-gfx: OCaml SDL2_gfx bindings to go with Tsdl
I’m drawing things like this using the graphics library (for now)
So I’m just drawing circles, lines from a point to another and text.
Would it be possible to add a widget in which I could draw this kind of things to a Bogue window with other widgets ?
Yes, absolutely. The Box
widget can contain an arbitrary SDL texture, and hence you may use all SDL drawing functions onto that texture. Unfortunately, this is not documented yet (simply because my strategy is to add to the .mli
file only functions that are tested in examples). But I can add this to the next release
That would be awesome, thanks ! Do you know how I can be notified for the next release ?
I will announce the next releases in this thread
Sounds nice ! You could even release a standalone project that would only provide this API in a single window, as an alternative to graphics : that would be a godsend imo, because the api of graphics really is terrible
In fact, for this, using the already existing Bogue version, one can use Labels
with a round background. This gives the following picture: it would just remain to implement lines…
Here is the complete code, for the curious ones:
open Bogue
module W = Widget
module L = Layout
let n = 15 (* number of discs *)
let radius = 20
let width = 800
let height = 600
let c = Draw.find_color "#e5b92c"
let disc_style = Style.(
create ~border:(
mk_border ~radius (mk_line ~color:Draw.(opaque c) ~width:1 ~style:Solid ()))
~background:(color_bg Draw.(transp c)) ())
let background = L.style_bg Style.(
of_bg (gradient ~angle:45. Draw.[opaque grey; opaque black]))
let fg = Draw.(opaque white)
let create_disc i (x,y) =
let w = 2*radius + 1 in
let bg = Box.create ~style:disc_style ~width:w ~height:w () in
W.label ~fg (string_of_int i)
|> L.resident ~background:(L.box_bg bg) ~x:(x-radius) ~y:(y-radius) ~w ~h:w
let random_center _ =
radius + Random.int (width - 2*radius),
radius + Random.int (height - 2*radius)
let area =
let box = L.resident (W.box ~w:width ~h:height ()) in
let centers = Array.init n random_center in
let discs = Array.mapi create_disc centers |> Array.to_list in
L.superpose ~w:width ~h:height ~background (box :: discs)
let board = Bogue.make [] [area]
let () = Bogue.run board
I’m not sure I understand what you have in mind. If you want to do graphics in a window with the SDL library, you can just import the tsdl
, tsdl-image
and tstl-ttf
packages and you’re good to go.
Nice ! Should I use boxes for lines ?
In theory indeed you could make a horizontal line with a thin box and then use Layout.rotate
.
but I think it make sense (for me) to propose a new, dedicated Line
widget.
Hmm OK, I’ll wait for your next release then. Thanks again !
Hi! Can you point me to the documentation about setting up themes? When I do
$ boguex 0
I get
Loading Bogue 20220101 with config dir /home/rsmith/.opam/4.12.1/lib/bogue/../../share/bogue/themes/default
INFO: Using SDL 2.0.14
0 = Just a check button.
Fatal error: exception Failure("SDL ERROR: Couldn't open /home/rsmith/.opam/4.12.1/lib/bogue/../../share/bogue/themes/default/check_on.png")
I’m excited about testing this.
sorry for this, this is what my post [ANN] Bogue, the OCaml GUI - #4 by sanette was about: you have to install the github version for now…
(download, cd bogue
and opam install .
should be enough)
EDIT: Doing
export BOGUE_THEME=default
should also work
Yeah, but having a dedicated library for beginner that hides this would be useful in my opinion.
Hi @Regis_Smith the new version in opam
should fix this issue.
(version 20220115)
It should also work on Mac Retina screens, thanks to the help of @nilsbecker!
EDIT: the doc about Theming is here: Bogue.Theme
Hi, some new developments. I have implemented a new Sdl_area
widget where one can conveniently issue any SDL function (from the SDL Renderer API).
Here is (below) the new ‘labelled graph’ example. In this example I am using regular “label” widgets for creating the nodes, and I am using an Sdl_area for drawing the lines.
The nice things for labels to be regular widgets is that one can click on them. To demonstrate this, in this example they react to a click by jumping to another random location (with animation).
open Bogue
module W = Widget
module L = Layout
let n = 15 (* number of discs *)
let radius = 20
let width = 800
let height = 600
let c = Draw.find_color "#e5b92c"
let cb = Draw.find_color "#7b6b35"
let disc_style = Style.(
create ~border:(
mk_border ~radius (mk_line ~color:Draw.(opaque c) ~width:1 ~style:Solid ()))
~background:(color_bg Draw.(opaque cb)) ())
let background = L.style_bg Style.(
of_bg (gradient ~angle:45. Draw.[opaque grey; opaque black]))
let fg = Draw.(opaque white)
let create_disc i (x,y) =
let w = 2*radius + 1 in
let bg = Box.create ~style:disc_style ~width:w ~height:w () in
W.label ~fg (string_of_int i)
|> L.resident ~background:(L.box_bg bg) ~x:(x-radius) ~y:(y-radius) ~w ~h:w
let move_disc (x,y) d =
let (x0, y0) = L.xpos d, L.ypos d in
L.animate_x d (Avar.fromto x0 x);
L.animate_y d (Avar.fromto y0 y)
let random_center _ =
radius + Random.int (width - 2*radius),
radius + Random.int (height - 2*radius)
let area =
let sdlw = W.sdl_area ~w:width ~h:height () in
let sdla = W.get_sdl_area sdlw in
let centers = Array.init n random_center in
let color = Draw.(opaque grey) in
let draw_lines renderer = let open Draw in
for i = 0 to n - 2 do
let x0, y0 = to_pixels centers.(i) in
let x1, y1 = to_pixels centers.(i+1) in
line renderer ~color ~thick:6 ~x0 ~y0 ~x1 ~y1
done in
Sdl_area.add sdla draw_lines;
let discs = Array.mapi create_disc centers |> Array.to_list in
(* move the disc when click on it *)
List.iteri (fun i d ->
W.on_click ~click:(fun _ ->
centers.(i) <- random_center 0;
Sdl_area.update sdla;
let x,y = centers.(i) in
move_disc (x - radius, y - radius) d) (L.widget d))
discs;
L.superpose ~w:width ~h:height ~background (L.resident sdlw :: discs)
let board = Bogue.make [] [area]
let () = Bogue.run board
Thank you so much, I look forward to implementing this in my current project!
I’ll let you know how it goes
Cool. Is it possible with this API to wait with drawing the new connecting lines to the randomized label until the animation has finished?
Yes, it is possible, because Avar.fromto
has an ending
parameter.
You would simply have to replace the line containing L.animate_x
by
L.animate_x d (Avar.fromto x0 x ~ending:(fun () ->
Sdl_area.update sdla;
Update.push sdlw));
add sdla
and sdlw
as parameters to the move_disc
function (in fact only sdlw
is necessary), and remove the line with Sdl_area.update sdla
below.