From 2f4b7dd596a3e96814494001fee8a8a20dab65de Mon Sep 17 00:00:00 2001 From: LeshaInc Date: Sat, 30 May 2020 22:11:23 +0300 Subject: [PATCH] Major node selector improvements --- sprites/nodes/NewNode.png | Bin 0 -> 154 bytes .../resources/ocelot/desktop/spritesheet.png | Bin 55112 -> 55274 bytes .../resources/ocelot/desktop/spritesheet.txt | 15 ++-- .../ocelot/desktop/geometry/Rect2D.scala | 2 + .../ocelot/desktop/ui/widget/ScrollView.scala | 6 +- .../desktop/ui/window/NodeSelector.scala | 15 +++- .../desktop/ui/workspace/NodeRegistry.scala | 12 +++- .../desktop/ui/workspace/NodeType.scala | 2 +- .../desktop/ui/workspace/NodeTypeWidget.scala | 3 +- .../desktop/ui/workspace/WorkspaceView.scala | 66 ++++++++++++++---- .../scala/ocelot/desktop/util/DrawUtils.scala | 7 ++ 11 files changed, 97 insertions(+), 31 deletions(-) create mode 100644 sprites/nodes/NewNode.png diff --git a/sprites/nodes/NewNode.png b/sprites/nodes/NewNode.png new file mode 100644 index 0000000000000000000000000000000000000000..d164c91e50311c8d3df66a94dc03bd760441c80f GIT binary patch literal 154 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

HjJskJsBTX)3ASKlAIYG z!`yKMFCkQn{sAot#-Lhf(Q4oMm#F!tdYW&Y0pGa!R(W$PzdFQd5fGrKAVDgtP+zg7 z8LFN)J9g+e6=}QY@aAipg~ZU4EC90^t=IOdX!h&_ymg%Jl48#%m5$6qHDa2GELPk9 z&Juu2A%`w9fn%J7m0XoB-$rK2O7(((tO31PtjgOq0NmnrkO*m2D4Jhie&GfRcw_|} z@&{I$J@cf_2aGp@WVU?L8#d~^?bdub z=3NinTHH&bohi*uHeAto8`{R9HX+Y2QfX10U7#9^y`$F~ar{}UJ)dj5W&!bSwa^Bp zaXS#jsu_KHd~NKba1#XO*smWb?;iy{$xiM%oi-I&?a{m{yfXRC1A4{q`8&XqLVtipb@uTgK9un7$jC{pRjQVV;`Xr zuCMSg9l~7GIcV&Cs91G68d}ezaMlx&OnEzXfel_k;P?Aom)_{wm4SsrcMA2K zC@tP?lR)vs(ZT6eh^zMW`NhSB%RH80@JlY)rjq=eTRi>tRXH?{U^b9~wfU z7}}JV^ObpKJ=+(W0|)C`Er4vzhu$kZJJXkvV$W4&8vH~#wfkLDbz}AQd%v}!J&wPW~lyBF0h7bHUeyH$2e0@!} zP2!3&iqqiv_@=7GKUmiX7$Kx3E0}>~6T&SGAfDc%aUr|G>mW2$tPPUR&G+MU)!y^a z4ra4Ud4rEZ)i}x10m^=k+OfJ=h**f#DG1g40j;kEtVq$=Fu9;N0>kgM!xRkSGg;w~ zS2nt_4VwP{)vkYU%Dt@q4B=V6LN56ODhN$~cX2ODvmN6;^ny32qp}$Mr^)X%UYkaS zhp9Q6`&Jz`dzP0J-CU3p10Q;mZ0}B?2FCr4=sH?&7;Uf5BW4@<1F_dKgMhFvXVRt` zKd2CYH%-&O=OR1EV0B&{Rt5Y6{?fU)WQ0YJxYyw;<3S5Gzbzd9Z5si+_Hb-L-rv_X zjuG`GX0&xYBEp|Y@&is7kS}|NVN)K_zw`42XgP_3D5M*HYDq$qqsq= z)xN#xIP;Rn83hrt%TeAG&9ALX3>>P=f&`Qr1R^>xx*+!+L9@mmn%Lh$LR;6*p591{ zF*bu=h?z$=2tm8?;#UK!QkLe}5K;JEw7pK73WLx0T=L>^jea1(i8s5`rr!?I6 z&tyaRECi1+6`j#x?wo0C`d{EWQoz8bryx(nD4eH>$qwUi-UDot6TShe0K<@|9bE;5Z3O}*}l+qx0`o0+1SD$)rp`r(Sl-N^{hJf$&nb zSE?3MvqGgTzZo3#!Y6yvg_b{G;~e zmGJD-4^i>9*qiHdOFhXSrii8yN=TQf>LHKA+KXdk8D3Vln}k#Gt+t5)9eLuddVW;U zlVoU2=6Z{;DtbTx-edseEiiY37(N}ae_~pxS=Hgt{EzUc!AN%UD*1Rp>c7P_?Iu|tCjZ8H! zbcgl3#kX2R%*9sbZ3+j!z9JZibv(ppgI{-plC)+RqsZsO<|zp9KmGsmRs1uAvI1fr ztbKeRRoN-ehk_5$-wpFIBaI~o9*4q|&LS*04=>=mwg%j;VYp1i8ID8$_UgqK*hOcl zZWh2_1n{r0pa5f-3u7?Hoztr0s95tHVgW8E*+IKnStkCA`$(yR+_~JALoKuP^Eme_R;hW(-XGJf7zh!`6yD6KcdR7KXATv5yAMc zSNbx5Q96E=uVl5U>fY+UWoFcx?CI9*6Mt>*^$0pl2?v!^)>YD!3b5hY|o`?p799z^Tq(qDLuyy9+kLG(%Bo8OOA zg#Gp028c^fLQQiy2$5gPJdv^wbHp7&m2IlvjV`zhrPKF^O%c(l5Ep*B?zhoO0R3_& z3+72xK>^CZ$p@X2&eQktozwZ;Zz()dFql8G8CAe`qJKlu-7^%35c|(iv8C*@=4)8xx<^M?eKQg}lFSb#@=BjE|e}Ux|LiqrW+n+j8dicU` F{|ix3#7O`E delta 11785 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 QrvXRoj~^`CfA+8c1uic<00000 diff --git a/src/main/resources/ocelot/desktop/spritesheet.txt b/src/main/resources/ocelot/desktop/spritesheet.txt index ea04a11..db3ea9d 100644 --- a/src/main/resources/ocelot/desktop/spritesheet.txt +++ b/src/main/resources/ocelot/desktop/spritesheet.txt @@ -77,17 +77,18 @@ nodes/Computer 339 180 16 16 nodes/ComputerActivityOverlay 356 180 16 16 nodes/ComputerErrorOverlay 373 180 16 16 nodes/ComputerOnOverlay 390 180 16 16 -nodes/Screen 407 180 16 16 -nodes/ScreenOnOverlay 424 180 16 16 +nodes/NewNode 407 180 16 16 +nodes/Screen 424 180 16 16 +nodes/ScreenOnOverlay 441 180 16 16 screen/BorderB 310 197 2 8 screen/BorderT 307 197 2 10 -screen/CornerBL 459 180 8 8 -screen/CornerBR 468 180 8 8 -screen/CornerTL 441 180 8 10 -screen/CornerTR 450 180 8 10 +screen/CornerBL 476 180 8 8 +screen/CornerBR 485 180 8 8 +screen/CornerTL 458 180 8 10 +screen/CornerTR 467 180 8 10 window/BorderDark 333 197 1 4 window/BorderLight 335 197 1 4 -window/CloseButton 477 180 7 6 +window/CloseButton 494 180 7 6 window/CornerBL 313 197 4 4 window/CornerBR 318 197 4 4 window/CornerTL 323 197 4 4 diff --git a/src/main/scala/ocelot/desktop/geometry/Rect2D.scala b/src/main/scala/ocelot/desktop/geometry/Rect2D.scala index be68482..9339b67 100644 --- a/src/main/scala/ocelot/desktop/geometry/Rect2D.scala +++ b/src/main/scala/ocelot/desktop/geometry/Rect2D.scala @@ -7,6 +7,8 @@ object Rect2D { case class Rect2D(x: Float, y: Float, w: Float, h: Float) { def contains(p: Vector2D): Boolean = p.x >= x && p.y >= y && p.x <= x + w && p.y <= y + h + def contains(r: Rect2D): Boolean = r.x >= x && r.y >= y && r.x + r.w <= x + w && r.y + r.h <= y + h + def origin: Vector2D = Vector2D(x, y) def min: Vector2D = origin diff --git a/src/main/scala/ocelot/desktop/ui/widget/ScrollView.scala b/src/main/scala/ocelot/desktop/ui/widget/ScrollView.scala index 3b82a90..7681be1 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/ScrollView.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/ScrollView.scala @@ -3,8 +3,8 @@ package ocelot.desktop.ui.widget import ocelot.desktop.color.RGBAColorNorm import ocelot.desktop.geometry.{Rect2D, Size2D, Vector2D} import ocelot.desktop.graphics.Graphics -import ocelot.desktop.ui.{KeyEvents, UiHandler} import ocelot.desktop.ui.event.{MouseEvent, ScrollEvent} +import ocelot.desktop.ui.{KeyEvents, UiHandler} import ocelot.desktop.util.Logging class ScrollView(val inner: Widget) extends Widget with Logging { @@ -114,13 +114,13 @@ class ScrollView(val inner: Widget) extends Widget with Logging { private def drawVThumb(g: Graphics): Unit = { val b = vThumbBounds g.rect(position.x + size.width - 11, position.y, 10, size.height, RGBAColorNorm(0.9f, 0.9f, 0.9f, vAnim * 0.15f)) - g.rect(b.x + 3, b.y, b.w - 6, b.h, RGBAColorNorm(0.6f, 0.15f, 0.35f, vAnim * 0.5f + 0.4f)) + g.rect(b.x + 3, b.y, b.w - 6, b.h, RGBAColorNorm(0.8f, 0.25f, 0.45f, vAnim * 0.5f + 0.4f)) } private def drawHThumb(g: Graphics): Unit = { val b = hThumbBounds g.rect(position.x, position.y + size.height - 11, size.width - 12, 10, RGBAColorNorm(0.9f, 0.9f, 0.9f, hAnim * 0.15f)) - g.rect(b.x, b.y + 3, b.w, b.h - 6, RGBAColorNorm(0.6f, 0.15f, 0.35f, hAnim * 0.5f + 0.4f)) + g.rect(b.x, b.y + 3, b.w, b.h - 6, RGBAColorNorm(0.8f, 0.25f, 0.45f, hAnim * 0.5f + 0.4f)) } private def maxXOffset: Float = inner.size.width - size.width diff --git a/src/main/scala/ocelot/desktop/ui/window/NodeSelector.scala b/src/main/scala/ocelot/desktop/ui/window/NodeSelector.scala index 980d567..cf96277 100644 --- a/src/main/scala/ocelot/desktop/ui/window/NodeSelector.scala +++ b/src/main/scala/ocelot/desktop/ui/window/NodeSelector.scala @@ -1,5 +1,6 @@ package ocelot.desktop.ui.window +import ocelot.desktop.color.RGBAColorNorm import ocelot.desktop.geometry.{Padding2D, Rect2D} import ocelot.desktop.graphics.Graphics import ocelot.desktop.ui.UiHandler @@ -7,7 +8,7 @@ import ocelot.desktop.ui.event.CloseWindowEvent import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.widget.{PaddingBox, ScrollView, Widget} import ocelot.desktop.ui.workspace.{NodeRegistry, NodeTypeWidget} -import ocelot.desktop.util.animation.UnitAnimation +import ocelot.desktop.util.animation.{ColorAnimation, UnitAnimation} import ocelot.desktop.util.{DrawUtils, Logging, Orientation} class NodeSelector extends Window with Logging { @@ -52,10 +53,14 @@ class NodeSelector extends Window with Logging { private var heightAnimation: UnitAnimation = _ private var animationTime: Float = 0f + private var FinalRingColor: RGBAColorNorm = RGBAColorNorm(0.3f, 0.5f, 0.4f) + val colorAnimation: ColorAnimation = new ColorAnimation(FinalRingColor.copy(a = 0f), speed = 3f) + def isShown: Boolean = _isShown override def update(): Unit = { if (isShown) { + colorAnimation.update() heightAnimation.update() if (isClosing) { @@ -81,7 +86,9 @@ class NodeSelector extends Window with Logging { override def draw(g: Graphics): Unit = { if (!isShown) return - DrawUtils.windowWithShadow(g, position.x, position.y, size.width, size.height, 0.5f, 0.3f) + + g.rect(position.x, position.y, size.width, size.height, RGBAColorNorm(0, 0, 0, colorAnimation.getHSVA.a * 0.4f)) + DrawUtils.ring(g, position.x, position.y, size.width, size.height, thickness = 1, color = colorAnimation.color) super.draw(g) } @@ -113,6 +120,8 @@ class NodeSelector extends Window with Logging { override def show(): Unit = { if (isClosing) return; + colorAnimation.goto(FinalRingColor.copy(a = 1f)) + _isOpen = true _isFocused = true _isShown = true @@ -125,6 +134,8 @@ class NodeSelector extends Window with Logging { override def hide(): Unit = { if (isClosing) return; + colorAnimation.goto(FinalRingColor.copy(a = 0f)) + heightAnimation = UnitAnimation.easeInQuad(0.25f) heightAnimation.time = 1 heightAnimation.goDown() diff --git a/src/main/scala/ocelot/desktop/ui/workspace/NodeRegistry.scala b/src/main/scala/ocelot/desktop/ui/workspace/NodeRegistry.scala index 62fe004..558866f 100644 --- a/src/main/scala/ocelot/desktop/ui/workspace/NodeRegistry.scala +++ b/src/main/scala/ocelot/desktop/ui/workspace/NodeRegistry.scala @@ -9,7 +9,15 @@ object NodeRegistry { types += t; } - for (i <- 0 to 100) { - register(NodeType("Screen" + i, "nodes/Screen", () => new ScreenNode)) + for (i <- 0 to 79) { + register(NodeType("Screen" + i, "nodes/Screen", i % 4, () => new ScreenNode)) + } + + for (i <- 0 to 3) { + register(NodeType("Screen" + i, "nodes/Screen", i % 4, () => new ScreenNode)) + } + + for (i <- 0 to 3) { + register(NodeType("Computer" + i, "nodes/Computer", i % 4, () => new ScreenNode)) } } diff --git a/src/main/scala/ocelot/desktop/ui/workspace/NodeType.scala b/src/main/scala/ocelot/desktop/ui/workspace/NodeType.scala index 425da3a..eeaa2ae 100644 --- a/src/main/scala/ocelot/desktop/ui/workspace/NodeType.scala +++ b/src/main/scala/ocelot/desktop/ui/workspace/NodeType.scala @@ -1,5 +1,5 @@ package ocelot.desktop.ui.workspace -case class NodeType(name: String, icon: String, factory: () => Node) extends Ordered[NodeType] { +case class NodeType(name: String, icon: String, tier: Int, factory: () => Node) extends Ordered[NodeType] { override def compare(that: NodeType): Int = this.name.compare(that.name) } \ No newline at end of file diff --git a/src/main/scala/ocelot/desktop/ui/workspace/NodeTypeWidget.scala b/src/main/scala/ocelot/desktop/ui/workspace/NodeTypeWidget.scala index dc2b1c2..332bcb9 100644 --- a/src/main/scala/ocelot/desktop/ui/workspace/NodeTypeWidget.scala +++ b/src/main/scala/ocelot/desktop/ui/workspace/NodeTypeWidget.scala @@ -3,6 +3,7 @@ package ocelot.desktop.ui.workspace import ocelot.desktop.geometry.Size2D import ocelot.desktop.graphics.Graphics import ocelot.desktop.ui.widget.Widget +import ocelot.desktop.util.TierColor class NodeTypeWidget(nodeType: NodeType) extends Widget { override def minimumSize: Size2D = Size2D(68, 68) @@ -12,6 +13,6 @@ class NodeTypeWidget(nodeType: NodeType) extends Widget { size = maximumSize override def draw(g: Graphics): Unit = { - g.sprite(nodeType.icon, position.x + 2, position.y + 2, size.width - 4, size.height - 4) + g.sprite(nodeType.icon, position.x + 2, position.y + 2, size.width - 4, size.height - 4, TierColor.get(nodeType.tier)) } } diff --git a/src/main/scala/ocelot/desktop/ui/workspace/WorkspaceView.scala b/src/main/scala/ocelot/desktop/ui/workspace/WorkspaceView.scala index d9e6eed..cabf6ae 100644 --- a/src/main/scala/ocelot/desktop/ui/workspace/WorkspaceView.scala +++ b/src/main/scala/ocelot/desktop/ui/workspace/WorkspaceView.scala @@ -1,7 +1,7 @@ package ocelot.desktop.ui.workspace import ocelot.desktop.OcelotDesktop -import ocelot.desktop.color.RGBAColor +import ocelot.desktop.color.{Color, RGBAColor} import ocelot.desktop.geometry.{Rect2D, Size2D, Vector2D} import ocelot.desktop.graphics.Graphics import ocelot.desktop.ui.event._ @@ -19,8 +19,9 @@ class WorkspaceView extends Widget with DragHandler with ClickHandler { private var nodeGrabPoint = Vector2D(0, 0) private var cameraOffset = Vector2D(0, 0) - private val nodeSelector: NodeSelector = new NodeSelector - private val windowPool: WindowPool = new WindowPool + private var newNodePos = Vector2D(0, 0) + private val nodeSelector = new NodeSelector + private val windowPool = new WindowPool children +:= windowPool override def minimumSize: Size2D = Size2D(200, 200) @@ -67,12 +68,31 @@ class WorkspaceView extends Widget with DragHandler with ClickHandler { if (nodeSelector.isShown) { nodeSelector.hide() } else { - windowPool.handleEvent(OpenWindowEvent(nodeSelector)) + openSelector(pos) } - } } + private def openSelector(p: Vector2D): Unit = { + val pos = p - Vector2D(32, 32) + windowPool.handleEvent(OpenWindowEvent(nodeSelector)) + newNodePos = pos - cameraOffset + + val size = Size2D(nodeSelector.maximumSize.width, 250) + + val offsets = Array( + Vector2D(-size.width / 2 + 40, 100), + Vector2D(-size.width - 100, -size.height / 2 + 40), + Vector2D(100, -size.height / 2 + 40), + Vector2D(-size.width / 2 + 40, -size.height - 100), + ) + + for (offset <- offsets) { + nodeSelector.position = (p + offset).max(Vector2D(20, 20)).min(Vector2D(width - size.width - 20, height - size.height - 20)) + if (!Rect2D(pos.x, pos.y, 64, 64).collides(Rect2D(nodeSelector.position, size))) return + } + } + private def checkCollision(node: Node, obstacle: Node): Unit = { val a = node.bounds val b = obstacle.bounds @@ -83,7 +103,9 @@ class WorkspaceView extends Widget with DragHandler with ClickHandler { node.position -= penetrationVector } - private def drawConnection(g: Graphics, a: Rect2D, b: Rect2D, thickness: Float = 4): Unit = { + private def drawConnection(g: Graphics, a: Rect2D, b: Rect2D, thickness: Float = 4, col: Color = RGBAColor(150, 150, 150)): Unit = { + if (a.collides(b)) return + val dist = a.distanceTo(b) / 2f val addition = if (dist <= 58.885f) @@ -96,16 +118,20 @@ class WorkspaceView extends Widget with DragHandler with ClickHandler { val aRect = a.inflate(addition.toFloat) val bRect = b.inflate(addition.toFloat) - val pairs: Array[(Vector2D, Vector2D)] = - for (a <- aRect.centerPoints; b <- bRect.centerPoints) - yield (a, b) + val aCPInf = aRect.centerPoints + val bCPInf = bRect.centerPoints + val aCP = a.centerPoints + val bCP = b.centerPoints - val pair = pairs.minBy(pair => (pair._1 - pair._2).length.toInt) - val (start, end) = pair - val col = RGBAColor(150, 150, 150) - g.line(start, end, thickness, col) - g.line(start, a.center, thickness, col) - g.line(end, b.center, thickness, col) + val pairs = + for (a <- 0 to 3; b <- 0 to 3) + yield (aCP(a), bCP(b), aCPInf(a), bCPInf(b)) + + val pair = pairs.minBy(pair => (pair._3 - pair._4).length.toInt) + val (aStart, bStart, aEnd, bEnd) = pair + g.line(aEnd, bEnd, thickness, col) + g.line(aStart, aEnd, thickness, col) + g.line(bStart, bEnd, thickness, col) } override def draw(g: Graphics): Unit = { @@ -129,9 +155,19 @@ class WorkspaceView extends Widget with DragHandler with ClickHandler { g.save() g.translate(cameraOffset.x + position.x, cameraOffset.y + position.y) drawConnection(g, nodes(0).bounds, nodes(1).bounds) + nodes.foreach(_.draw(g)) + + val col = nodeSelector.colorAnimation.color + if (nodeSelector.isShown) { + g.sprite("nodes/NewNode", newNodePos.x, newNodePos.y, 64, 64, col) + } + g.restore() + if (nodeSelector.isShown) + drawConnection(g, Rect2D(newNodePos.x + cameraOffset.x, newNodePos.y + cameraOffset.y, 64, 64), nodeSelector.bounds, col = col) + drawChildren(g) } diff --git a/src/main/scala/ocelot/desktop/util/DrawUtils.scala b/src/main/scala/ocelot/desktop/util/DrawUtils.scala index da9e07c..ee61385 100644 --- a/src/main/scala/ocelot/desktop/util/DrawUtils.scala +++ b/src/main/scala/ocelot/desktop/util/DrawUtils.scala @@ -33,6 +33,13 @@ object DrawUtils { DrawUtils.windowBorder(g, x, y, w, h, RGBAColorNorm(1, 1, 1, backgroundAlpha)) } + def ring(g: Graphics, x: Float, y: Float, w: Float, h: Float, thickness: Float = 4, color: Color = RGBAColor(255, 255, 255)): Unit = { + g.rect(x, y, thickness, h, color) + g.rect(x + w - thickness, y, thickness, h, color) + g.rect(x + thickness, y, w - thickness * 2f, thickness, color) + g.rect(x + thickness, y + h - thickness, w - thickness * 2f, thickness, color) + } + def windowBorder(g: Graphics, x: Float, y: Float, w: Float, h: Float, color: Color = RGBAColor(255, 255, 255)): Unit = { g.sprite("window/CornerTL", x, y, 8, 8, color)