Draw connections between nodes

This commit is contained in:
LeshaInc 2019-09-02 14:43:05 +03:00
parent a5d6f3de58
commit a2f63af646
No known key found for this signature in database
GPG Key ID: B4855290FC36DE72
10 changed files with 105 additions and 23 deletions

View File

@ -15,6 +15,8 @@ case class Rect2D(var x: Float, var y: Float, var w: Float, var h: Float) {
def size: Size2D = Size2D(w, h)
def extent: Vector2D = Vector2D(w / 2f, h / 2f)
def collides(b: Rect2D): Boolean = {
val a = this
a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y
@ -30,7 +32,7 @@ case class Rect2D(var x: Float, var y: Float, var w: Float, var h: Float) {
var minDist = math.abs(point.x - min.x)
var boundsPoint = Vector2D(min.x, point.y)
if (math.abs(max.x - point.x) < minDist) {
if (math.abs(max.x - point.x) < minDist) {
minDist = Math.abs(max.x - point.x)
boundsPoint = Vector2D(max.x, point.y)
}
@ -47,4 +49,20 @@ case class Rect2D(var x: Float, var y: Float, var w: Float, var h: Float) {
boundsPoint
}
def inflate(addition: Float): Rect2D = Rect2D(x - addition, y - addition, w + addition * 2, h + addition * 2)
def center: Vector2D = {
min + (size * 0.5f).toVector
}
def centerPoints: Array[Vector2D] = Array(
Vector2D(x + w / 2f, y),
Vector2D(x + w, y + h / 2f),
Vector2D(x + w / 2f, y + h),
Vector2D(x, y + h / 2f))
def distanceTo(that: Rect2D): Float = {
((center - that.center).abs - (extent + that.extent)).max(Vector2D(0, 0)).length
}
}

View File

@ -26,5 +26,7 @@ case class Size2D(var width: Float, var height: Float) {
def +(that: Size2D): Size2D = Size2D(width + that.width, height + that.height)
def *(mul: Float): Size2D = Size2D(width * mul, height * mul)
override def toString: String = f"Size2D [ $width%8.2f x $height%8.2f ]"
}

View File

@ -37,7 +37,7 @@ case class Vector2D(var x: Float, var y: Float) {
def *(that: Vector2D): Float = x * that.x + y * that.y
def length: Float = math.sqrt(lengthSquared).asInstanceOf
def length: Float = math.sqrt(lengthSquared).toFloat
def lengthSquared: Float = this.x * this.x + this.y * this.y
@ -51,9 +51,9 @@ case class Vector2D(var x: Float, var y: Float) {
if (l > 0) this /= this.length
}
def rounded(): Vector2D = Vector2D(x.round, y.round)
def rounded: Vector2D = Vector2D(x.round, y.round)
def angle: Float = math.atan2(this.y, this.x).asInstanceOf
def angle: Float = math.atan2(this.y, this.x).toFloat
def angle(that: Vector2D): Float = angle - that.angle
@ -64,9 +64,13 @@ case class Vector2D(var x: Float, var y: Float) {
def rotate(angle: Float): Unit = {
val (s, c) = (math.sin(angle), math.cos(angle))
x = (c * x - s * y).asInstanceOf
y = (s * x + c * y).asInstanceOf
x = (c * x - s * y).toFloat
y = (s * x + c * y).toFloat
}
def abs: Vector2D = Vector2D(x.abs, y.abs)
def max(that: Vector2D): Vector2D = Vector2D(x.max(that.x), y.max(that.y))
override def toString: String = s"Vector2D [$x, $y]"
}

View File

@ -1,7 +1,7 @@
package ocelot.desktop.graphics
import ocelot.desktop.color.{Color, RGBAColorNorm}
import ocelot.desktop.geometry.Transform2D
import ocelot.desktop.geometry.{Transform2D, Vector2D}
import ocelot.desktop.graphics.mesh.{Mesh, MeshInstance}
import ocelot.desktop.graphics.render.InstanceRenderer
import ocelot.desktop.util.{Font, Spritesheet}
@ -140,6 +140,16 @@ class Graphics extends Logging {
transform(Transform2D.translate(x, y))
}
def rotate(angle: Float): Unit = {
transform(Transform2D.rotate(angle))
}
def origin: Vector2D = stack.head.origin
def origin_=(origin: Vector2D): Unit = {
stack.head.origin = origin
}
def text(x: Float, y: Float, text: String): Unit = {
var ox = x
val fontSize = fontSizeMultiplier * _font.fontSize
@ -194,20 +204,43 @@ class Graphics extends Logging {
def rect(x: Float, y: Float, width: Float, height: Float, rotation: Float = 0f): Unit = {
val uvTransform =
Transform2D.translate(spriteRect.x, spriteRect.y) >>
Transform2D.scale(spriteRect.w, spriteRect.h)
Transform2D.scale(spriteRect.w, spriteRect.h - 0.3f / 512)
val origin = stack.head.origin
val transform =
stack.head.transform >>
Transform2D.translate(x, y) >>
Transform2D.scale(width, height) >>
Transform2D.translate(0.5f, 0.5f) >>
Transform2D.rotate(rotation * 0.0174532925f) >>
Transform2D.translate(-0.5f, -0.5f)
Transform2D.translate(-origin.x, -origin.y) >>
Transform2D.rotate(rotation) >>
Transform2D.translate(origin.x, origin.y) >>
Transform2D.scale(width, height)
rectRenderer.schedule(MeshInstance(stack.head.foreground, z, transform, uvTransform))
z += 1
}
def line(x1: Float, y1: Float, x2: Float, y2: Float, thickness: Float): Unit = {
save()
origin = Vector2D(0.0, 0.5)
sprite = "Empty"
val dy = x2 - x1
val dx = y2 - y1
val length = math.sqrt(dx * dx + dy * dy).toFloat
val inclination = math.atan2(dy, dx).toFloat
translate(x1, y1)
rotate(-inclination + (math.Pi * 0.5).toFloat)
rect(-thickness * 0.25f, -thickness * 0.5f, length + thickness * 0.25f, thickness)
restore()
}
def line(start: Vector2D, end: Vector2D, thickness: Float = 4): Unit = {
line(start.x, start.y, end.x, end.y, thickness)
}
def flush(): Unit = {
Spritesheet.texture.bind()
rectRenderer.flush()

View File

@ -1,11 +1,12 @@
package ocelot.desktop.graphics
import ocelot.desktop.color.RGBAColorNorm
import ocelot.desktop.geometry.Transform2D
import ocelot.desktop.geometry.{Transform2D, Vector2D}
case class GraphicsState(var foreground: RGBAColorNorm = RGBAColorNorm(0f, 0f, 0f),
var background: RGBAColorNorm = RGBAColorNorm(1f, 1f, 1f),
var fontSizeMultiplier: Float = 1f,
var sprite: String = "Empty",
var scissor: Option[(Int, Int, Int, Int)] = None,
var transform: Transform2D = Transform2D.identity)
var transform: Transform2D = Transform2D.identity,
var origin: Vector2D = Vector2D(0, 0))

View File

@ -56,6 +56,7 @@ object UiHandler extends Logging {
GLFW.glfwDefaultWindowHints()
GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE)
GLFW.glfwWindowHint(GLFW.GLFW_RESIZABLE, GLFW.GLFW_TRUE)
GLFW.glfwWindowHint(GLFW.GLFW_SAMPLES, 16)
windowSize = root.size.copy()

View File

@ -140,7 +140,7 @@ class LinearLayout(widget: Widget,
child.position.y = widget.position.y + widget.size.height / 2 - child.size.height / 2
}
child.position = child.position.rounded()
child.position = child.position.rounded
}
}
}

View File

@ -1,6 +1,5 @@
package ocelot.desktop.ui.widget
import ocelot.desktop.color.RGBAColor
import ocelot.desktop.ui.layout.LinearLayout
import totoro.ocelot.brain.entity.Screen
@ -10,7 +9,7 @@ class RootWidget(screen: Screen) extends Widget {
val screenWidget = new ScreenWidget(screen)
children :+= new WorkspaceView
// children :+= new ScrollView(new WorkspaceView)
//
// children :+= new ScrollView(new CenterBox(screenWidget, background = RGBAColor(30, 30, 30)))
// children :+= new ScrollView(new WorkspaceView)
//
// children :+= new ScrollView(new CenterBox(screenWidget, background = RGBAColor(30, 30, 30)))
}

View File

@ -1,5 +1,6 @@
package ocelot.desktop.ui.widget
import ocelot.desktop.color.RGBAColor
import ocelot.desktop.geometry.{Size2D, Vector2D}
import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.UiHandler
@ -85,11 +86,33 @@ class WorkspaceView extends Widget {
node.position -= penetrationVector
}
private def drawConnection(g: Graphics, a: Node, b: Node): Unit = {
g.foreground = RGBAColor(150, 150, 150)
val aBounds = a.bounds
val bBounds = b.bounds
val dist = aBounds.distanceTo(bBounds) / 2f
val addition = if (dist < 100) {
40.56077 + (2.219244 - 40.56077) / math.pow(1 + math.pow(dist / 22949.13, 2.598411), 14930690)
} else 40
val aRect = aBounds.inflate(addition.toFloat)
val bRect = bBounds.inflate(addition.toFloat)
val pairs = for (a <- aRect.centerPoints; b <- bRect.centerPoints) yield (a, b)
val pair = pairs.minBy(pair => (pair._1 - pair._2).length.toInt)
val (start, end) = pair
g.line(start, end)
g.line(start, a.bounds.center)
g.line(end, b.bounds.center)
}
override def draw(g: Graphics): Unit = {
g.save()
val backgroundOffsetX = if (cameraOffset.x > 0) 304f - cameraOffset.x % 304f else -cameraOffset.x % 304f
val backgroundOffsetY = if (cameraOffset.y > 0) 304f - cameraOffset.y % 304f else -cameraOffset.y % 304f
val backgroundOffsetX = if (cameraOffset.x > 0) 304 - cameraOffset.x.toInt % 304 else -cameraOffset.x.toInt % 304
val backgroundOffsetY = if (cameraOffset.y > 0) 304 - cameraOffset.y.toInt % 304 else -cameraOffset.y.toInt % 304
val numRepeatsX = math.ceil((size.width + backgroundOffsetX) / 304f).asInstanceOf[Int]
val numRepeatsY = math.ceil((size.height + backgroundOffsetY) / 304f).asInstanceOf[Int]
@ -97,13 +120,14 @@ class WorkspaceView extends Widget {
for (x <- 0 to numRepeatsX) {
for (y <- 0 to numRepeatsY) {
g.sprite("BackgroundPattern", x * 304f, y * 304f, 304f, 304f)
g.sprite("BackgroundPattern", x * 304, y * 304, 304, 304)
}
}
g.restore()
g.translate(cameraOffset.x + position.x, cameraOffset.y + position.y)
drawConnection(g, nodes(0), nodes(1))
nodes.foreach(_.draw(g))
}
}

View File

@ -3,7 +3,7 @@ package ocelot.desktop.util
object Easing {
def linear(t: Float): Float = t
def easeInQuad(t: Float): Float = t
def easeInQuad(t: Float): Float = t * t
def easeOutQuad(t: Float): Float = t * (2 - t)