diff --git a/examples/Examples.re b/examples/Examples.re index 64027c643..4c8b9a170 100644 --- a/examples/Examples.re +++ b/examples/Examples.re @@ -39,6 +39,7 @@ let state: state = { {name: "Input", render: w => InputExample.render(w)}, {name: "Radio Button", render: _ => RadioButtonExample.render()}, {name: "Game Of Life", render: _ => GameOfLife.render()}, + {name: "Screen Capture", render: w => ScreenCapture.render(w)}, {name: "Tree View", render: w => TreeView.render(w)}, ], selectedExample: "Animation", @@ -94,10 +95,9 @@ type action = | SelectExample(string); let reducer = (s: state, a: action) => { - let SelectExample(name) = a; - - let ret: state = {...s, selectedExample: name}; - ret; + switch (a) { + | SelectExample(name) => {...s, selectedExample: name} + }; }; let init = app => { diff --git a/examples/ScreenCapture.re b/examples/ScreenCapture.re new file mode 100644 index 000000000..d09f01f9d --- /dev/null +++ b/examples/ScreenCapture.re @@ -0,0 +1,78 @@ +open Revery.UI; +open Revery.UI.Components; +open Revery.Core; + +let backgroundColor = Color.hex("#212733"); +let activeBackgroundColor = Color.hex("#2E3440"); +let inactiveBackgroundColor = Color.hex("#272d39"); +let selectionHighlight = Color.hex("#90f7ff"); + +module ActionButton = { + let component = React.component("ActionButton"); + + let make = (~name, ~onClick, ()) => + component((_slots: React.Hooks.empty) => { + let wrapperStyle = + Style.[ + backgroundColor(selectionHighlight), + border(~width=4, ~color=activeBackgroundColor), + ]; + let textHeaderStyle = + Style.[ + color(Colors.black), + fontFamily("Roboto-Regular.ttf"), + fontSize(14), + margin(16), + ]; + + + ; + }); + + let createElement = (~children as _, ~name, ~onClick, ()) => + React.element(make(~name, ~onClick, ())); +}; + +module CaptureArea = { + let component = React.component("Capture Area"); + + let make = w => + component(slots => { + let (count, setCount, slots) = React.Hooks.state(0, slots); + let (file, setFile, _slots: React.Hooks.empty) = + React.Hooks.state(None, slots); + + let capture = () => { + let exed = Environment.getExecutingDirectory(); + let filename = Printf.sprintf("Scrot_%d.tga", count); + let fullname = exed ++ filename; + Window.takeScreenshot(w, fullname); + setCount(count + 1); + setFile(Some(filename)); + }; + + let viewStyle = + Style.[ + position(`Absolute), + left(0), + right(0), + top(0), + bottom(0), + flexDirection(`Column), + ]; + + let imageStyle = Style.[width(400), height(300)]; + + + + {switch (file) { + | None => + | Some(src) => + }} + ; + }); + + let createElement = (~w, ~children as _, ()) => React.element(make(w)); +}; + +let render = w => ; diff --git a/src/Core/Window.re b/src/Core/Window.re index db7a5e210..9464d2c04 100644 --- a/src/Core/Window.re +++ b/src/Core/Window.re @@ -323,6 +323,26 @@ let getDevicePixelRatio = (w: t) => { /. float_of_int(windowSizeInScreenCoordinates.width); }; +let takeScreenshot = (w: t, filename: string) => { + open Glfw; + + let width = w.framebufferWidth; + let height = w.framebufferHeight; + + let image = Image.create(~width, ~height, ~numChannels=4, ~channelSize=1); + let buffer = Image.getBuffer(image); + + /* WebGL is weird in that we can't capture with glReadPixels during + a render operation. Instead, we want to wait till it's over (we + can force this by triggering a new render) and then taking the + screenshot */ + render(w); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + + Image.save(image, filename); + Image.destroy(image); +}; + let destroyWindow = (w: t) => Glfw.glfwDestroyWindow(w.glfwWindow); let shouldClose = (w: t) => Glfw.glfwWindowShouldClose(w.glfwWindow);