Release notes can be found on Github
The OPENRNDR template has been updated to use the latest versions of OPENRNDR and ORX.
Note: we have merged the openrndr-panel
project into ORX and it can now be found under orx-panel
.
Release notes can be found on Github
The OPENRNDR template has been updated to use the latest versions of OPENRNDR and ORX.
Note: we have merged the openrndr-panel
project into ORX and it can now be found under orx-panel
.
One major improvement in OPENRNDR 0.3.40 is how uncaught exceptions are now handled.
The following program will throw an exception whenever the slider is touched.
fun main() =
application {
program {
val cm = controlManager {
layout {
slider {
events.valueChanged.listen {
require(false) { "Pretty clear exception messages" }
}
}
}
}
extend(cm)
}
}
Prior to version 0.3.40, whever we would touch the slider we would see a very lengthy wall of text (which turns out to be a dump of the stack trace), that would require a lot of work to decode. First of all the order of the dump is in a way that the root cause is found near the top of the dump, which means we would have to scroll through several pages of text just to find the root cause. So we reversed the order.
We also added coloring to the dump and attempt to highlight the parts of the call stack that are in user code. User code nearest to the root cause now has an extra clear highlight.
The stack trace shows Kotlin classes and functions as JVM classes, those names look like Program01Kt$main$1$1cm$1$2
and are not easily understandable to the untrained user. The stack trace printer in version 0.3.40 attempts to decode the JVM class names to present an easier to read dump.
Here is what the error report and stack looks like:
Here some examples of what you can do with ShapeContour.offset
The first one produces something closer to what you might expect:
TestCurveOffset1.kt (1.5 KB)
Notice how it is calling .offset()
with SegmentJoin.BEVEL
as an argument. Other options are SegmentJoin.ROUND
and SegmentJoin.MITER
By having just one line of code:
extend(Screenshots())
you can press the [space] key to save a screenshot. When doing that the console informs you:
[main] INFO org.openrndr.extensions.Screenshots - [Screenshots] saved to: screenshots/TestCurveOffset1-2020-03-28-13.36.59.png
In this new version the image file name follows the name of the kotlin file that produced it: TestCurveOffset1
which helps a lot figure out which program produced a certain image.
A second, wilder example of using .offset()
with ROUND, BEVEL and MITER:
TestCurveOffset2.kt (1.6 KB)
Panel, now known as orx-panel
, gained a new control called XYPad
, that allows you to control a Vector2 value:
fun main() = application {
configure {
width = 400
height = 400
}
program {
val cm = ControlManager()
var pad: XYPad? = null
cm.body = layout(cm) {
pad = xyPad {
minX = 0.0
maxX = width.toDouble()
minY = 0.0
maxY = height.toDouble()
invertY = false
}
}
extend(cm)
extend {
drawer.background(ColorRGBa.BLACK)
drawer.circle(pad!!.value, 50.0)
}
}
}
It can also be used in orx-gui
using XYParameter
:
fun main() = application {
configure {
width = 800
height = 800
}
program {
val gui = GUI()
val settings = @Description("Vector parameter!") object {
@XYParameter("Position", 0.0, 800.0, 0.0, 800.0,
precision = 2,
invertY = true,
showVector = true)
var position: Vector2 = Vector2(0.0,0.0)
}
gui.add(settings)
extend(gui)
extend {
drawer.circle(settings.position, 50.0)
}
}
}
The Program
's keyboard
now has a pressedKeys
property, a Set<String>
which keeps track of the keys currently being held.
Here it is used to move a circle with the WASD or arrow keys:
fun main() = application {
configure {
width = 800
height = 800
}
program {
var position = drawer.bounds.center
val speed = 10.0
extend {
keyboard.pressedKeys.let {
if (it.contains("arrow-up") || it.contains("w")) {
position = Vector2(position.x, position.y - speed)
}
if (it.contains("arrow-down") || it.contains("s")) {
position = Vector2(position.x, position.y + speed)
}
if (it.contains("arrow-left") || it.contains("a")) {
position = Vector2(position.x - speed, position.y)
}
if (it.contains("arrow-right") || it.contains("d")) {
position = Vector2(position.x + speed, position.y)
}
}
drawer.circle(position, 100.0)
}
}
}
orx-shapes
adds the roundedRectangle()
method to Drawer
, so you can easily draw rounded rectangles.
fun main() = application {
configure {
width = 800
height = 800
}
program {
extend {
drawer.roundedRectangle(width/2.0 - 100.0, height/2.0 - 100.0, 200.0, 200.0, radius = sin(seconds) * 50 + 50)
}
}
}
ORX 0.3.50 adds new filters to orx-fx
and orx-jumpflood
.
To orx-fx
the new filters additions are: StretchWaves, PerspectivePlane, DisplaceBlend and FishEye
To orx-jumpflood
which is an extra that adds distance transform based functionality the additions are: OuterGlow and InnerGlow
OPENRNDR 0.3.40 adds short-hand functions rgb
, rgba
and hsv
, hsva
to make it a bit simpler to define colors.
Before one would write:
val color = ColorRGBa(0.2, 0.3, 0.6)
now one can write:
val color = rgb(0.2, 0.3, 0.6)
With ORX 0.3.50 the orx-compositor
extension saw the introduction of 2 new features: mask
and use
.
mask
allows defining a mask within a layer, f.ex:val c = compose {
layer {
post(Checkers())
}
layer {
// invertMask = false // <--
draw {
drawer.imageFit(image, 0.0, 0.0, w , h, fitMethod = FitMethod.Contain)
}
mask {
drawer.circles(circles)
}
}.addTo(gui, "Image")
}
Or inverted via invertMask
:
use
lets you re-use easily the buffer from another layer, f.ex:val c = compose {
layer {
post(Checkers())
}
layer {
val imageLayer = layer {
draw {
drawer.imageFit(image, 0.0, 0.0, w , h, fitMethod = FitMethod.Contain)
}
mask {
drawer.circles(circles)
}
}.addTo(gui, "Image")
layer {
use(imageLayer) // <--
post(Sepia()) {
amount = 1.0
}
post(BlockRepeat().addTo(gui))
}.addTo(gui, "Image Copy")
}
}