mirror of
https://gitlab.com/cc-ru/ocelot/ocelot-desktop.git
synced 2026-01-06 19:22:38 +01:00
Draw connections between nodes
This commit is contained in:
parent
a5d6f3de58
commit
a2f63af646
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 ]"
|
||||
}
|
||||
@ -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]"
|
||||
}
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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()
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)))
|
||||
}
|
||||
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user