Skip to content

Commit

Permalink
Add Window.takeScreenshot API (#225)
Browse files Browse the repository at this point in the history
* Integrate Window.takeScreenshot into examples

* Add Window.takeScreenshot

* Change screen capture example

* Fix formatting
  • Loading branch information
OhadRau authored Jan 31, 2019
1 parent 8616a97 commit f773acd
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 4 deletions.
8 changes: 4 additions & 4 deletions examples/Examples.re
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,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",
Expand Down Expand Up @@ -95,10 +96,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 => {
Expand Down
78 changes: 78 additions & 0 deletions examples/ScreenCapture.re
Original file line number Diff line number Diff line change
@@ -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),
];
<Clickable style=wrapperStyle onClick>
<Text style=textHeaderStyle text=name />
</Clickable>;
});

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)];

<View style=viewStyle>
<ActionButton name="Take a screenshot!" onClick=capture />
{switch (file) {
| None => <View />
| Some(src) => <Image style=imageStyle src />
}}
</View>;
});

let createElement = (~w, ~children as _, ()) => React.element(make(w));
};

let render = w => <CaptureArea w />;
20 changes: 20 additions & 0 deletions src/Core/Window.re
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit f773acd

Please sign in to comment.