diff --git a/sprites/window/BorderDark.png b/sprites/window/BorderDark.png new file mode 100644 index 0000000..a4e8fd6 Binary files /dev/null and b/sprites/window/BorderDark.png differ diff --git a/sprites/window/BorderH.png b/sprites/window/BorderLight.png similarity index 100% rename from sprites/window/BorderH.png rename to sprites/window/BorderLight.png diff --git a/sprites/window/BorderV.png b/sprites/window/BorderV.png deleted file mode 100644 index 41e66c9..0000000 Binary files a/sprites/window/BorderV.png and /dev/null differ diff --git a/src/main/resources/ocelot/desktop/spritesheet.png b/src/main/resources/ocelot/desktop/spritesheet.png index e7803a0..371be5b 100644 Binary files a/src/main/resources/ocelot/desktop/spritesheet.png and b/src/main/resources/ocelot/desktop/spritesheet.png differ diff --git a/src/main/resources/ocelot/desktop/spritesheet.txt b/src/main/resources/ocelot/desktop/spritesheet.txt index 90a304f..ea04a11 100644 --- a/src/main/resources/ocelot/desktop/spritesheet.txt +++ b/src/main/resources/ocelot/desktop/spritesheet.txt @@ -1,5 +1,5 @@ BackgroundPattern 0 0 304 304 -Empty 340 197 1 1 +Empty 337 197 1 1 ShadowBorder 305 197 1 24 ShadowCorner 424 0 24 24 buttons/PowerOff 441 25 18 18 @@ -85,8 +85,8 @@ screen/CornerBL 459 180 8 8 screen/CornerBR 468 180 8 8 screen/CornerTL 441 180 8 10 screen/CornerTR 450 180 8 10 -window/BorderH 333 197 1 4 -window/BorderV 335 197 4 1 +window/BorderDark 333 197 1 4 +window/BorderLight 335 197 1 4 window/CloseButton 477 180 7 6 window/CornerBL 313 197 4 4 window/CornerBR 318 197 4 4 diff --git a/src/main/scala/ocelot/desktop/ui/window/BasicWindow.scala b/src/main/scala/ocelot/desktop/ui/window/BasicWindow.scala index f8e2079..a402380 100644 --- a/src/main/scala/ocelot/desktop/ui/window/BasicWindow.scala +++ b/src/main/scala/ocelot/desktop/ui/window/BasicWindow.scala @@ -26,9 +26,9 @@ trait BasicWindow extends Window { state.goto(0.2f) } - protected def backgroundAlpha: Float = state.value.min(0.5f) * 2 + protected def backgroundAlpha: Float = state.value - protected def shadowAlpha: Float = (state.value - 0.5f).max(0) + protected def shadowAlpha: Float = state.value * 0.5f override def update(): Unit = { super.update() diff --git a/src/main/scala/ocelot/desktop/ui/window/ComputerWindow.scala b/src/main/scala/ocelot/desktop/ui/window/ComputerWindow.scala index d0253d9..42ac0c9 100644 --- a/src/main/scala/ocelot/desktop/ui/window/ComputerWindow.scala +++ b/src/main/scala/ocelot/desktop/ui/window/ComputerWindow.scala @@ -15,7 +15,7 @@ class ComputerWindow extends BasicWindow { val y = position.y val w = size.width val h = size.height - DrawUtils.shadow(g, x - 22, y - 22, w + 44, h + 52, shadowAlpha) - DrawUtils.screenBorder(g, x, y, w, h, RGBAColorNorm(1, 1, 1, backgroundAlpha)) +// DrawUtils.shadow(g, x - 22, y - 22, w + 44, h + 52, shadowAlpha) + DrawUtils.windowBorder(g, x, y, w, h, RGBAColorNorm(1, 1, 1, backgroundAlpha)) } } \ No newline at end of file diff --git a/src/main/scala/ocelot/desktop/ui/window/Window.scala b/src/main/scala/ocelot/desktop/ui/window/Window.scala index c09d286..8f1b246 100644 --- a/src/main/scala/ocelot/desktop/ui/window/Window.scala +++ b/src/main/scala/ocelot/desktop/ui/window/Window.scala @@ -4,7 +4,7 @@ import ocelot.desktop.geometry.Rect2D import ocelot.desktop.ui.widget.Widget trait Window extends Widget { - def dragRegions: Iterator[Rect2D] = Iterator() + def dragRegions: Iterator[Rect2D] = Iterator(Rect2D(position, size)) def onOpened(): Unit = {} diff --git a/src/main/scala/ocelot/desktop/ui/window/WindowPool.scala b/src/main/scala/ocelot/desktop/ui/window/WindowPool.scala index 744095f..3ac7177 100644 --- a/src/main/scala/ocelot/desktop/ui/window/WindowPool.scala +++ b/src/main/scala/ocelot/desktop/ui/window/WindowPool.scala @@ -18,51 +18,74 @@ class WindowPool extends Widget with DragHandler { window.size = window.minimumSize window.position = (size / 2 - window.size / 2).toVector.round window.show() - window.focus() - windows.lastOption.foreach(_.unfocus()) - children :+= window + children +:= window + changeFocus(0) } case CloseWindowEvent(window) => val idx = windows.indexOf(window) children = children.patch(idx, Nil, 1) + changeFocus(windows.length - 1) case MouseEvent(MouseEvent.State.Press, _) => val mousePos = UiHandler.mousePosition - findWindowUnderCursor(mousePos).foreach(pair => { - val (window, idx) = pair -// if (!window.isFocused) { - window.focus() - windows.lastOption.foreach(_.unfocus()) - children = children.patch(idx, Nil, 1) :+ window -// } - }) + findWindowUnderCursor(mousePos).foreach(changeFocus) - case DragEvent(DragEvent.State.Start, MouseEvent.Button.Left, mousePos) => - movingWindow = findWindowUnderCursor(mousePos) - .map(_._1) - .filter(_.dragRegions.forall(_.contains(mousePos))) - - grabPoint = movingWindow.map(mousePos - _.position).getOrElse(grabPoint) - if (movingWindow.isDefined) UiHandler.cursor = Cursor.Hand - - case DragEvent(DragEvent.State.Drag, MouseEvent.Button.Left, mousePos) => - movingWindow.foreach(_.position = mousePos - grabPoint) - if (movingWindow.isDefined) UiHandler.cursor = Cursor.Hand - - case DragEvent(DragEvent.State.Stop, MouseEvent.Button.Left, _) => - movingWindow = None + case DragEvent(DragEvent.State.Start, MouseEvent.Button.Left, mousePos) => startDragging(mousePos) + case DragEvent(DragEvent.State.Drag, MouseEvent.Button.Left, mousePos) => continueDragging(mousePos) + case DragEvent(DragEvent.State.Stop, MouseEvent.Button.Left, _) => endDragging() case _ => } private def windows: Array[Window] = children.map(_.asInstanceOf[Window]) - private def findWindowUnderCursor(pos: Vector2D): Option[(Window, Int)] = + private def findWindowUnderCursor(pos: Vector2D): Option[Int] = windows .reverseIterator .zip((children.length - 1 to 0 by -1).iterator) .find(_._1.bounds.contains(pos)) + .map(_._2) + + private def changeFocus(idx: Int): Unit = { + if (idx < 0 || idx >= children.length) return + + val window = windows(idx) + windows.lastOption.foreach(_.unfocus()) + window.focus() + children = children.patch(idx, Nil, 1) :+ window + } + + private def startDragging(mousePos: Vector2D): Unit = { + val idx = findWindowUnderCursor(mousePos) match { + case Some(value) => value + case None => return + } + + println(idx) + + val window = windows(idx) + if (window.dragRegions.exists(_.contains(mousePos))) { + movingWindow = Some(window) + grabPoint = mousePos - window.position + changeFocus(idx) + } + } + + private def continueDragging(mousePos: Vector2D): Unit = { + val window = movingWindow match { + case Some(value) => value + case None => return + } + + window.position = mousePos - grabPoint + UiHandler.cursor = Cursor.Hand + } + + private def endDragging(): Unit = { + movingWindow = None + } + override def handleEvent(event: Event): Unit = { eventHandlers(event) diff --git a/src/main/scala/ocelot/desktop/ui/workspace/WorkspaceView.scala b/src/main/scala/ocelot/desktop/ui/workspace/WorkspaceView.scala index 9c22f0e..1c65146 100644 --- a/src/main/scala/ocelot/desktop/ui/workspace/WorkspaceView.scala +++ b/src/main/scala/ocelot/desktop/ui/workspace/WorkspaceView.scala @@ -65,8 +65,7 @@ class WorkspaceView extends Widget with DragHandler with ClickHandler { windowPool.handleEvent(OpenWindowEvent(window)) case None => - println(nodeSelector) - windowPool.handleEvent(OpenWindowEvent(nodeSelector)) +// windowPool.handleEvent(OpenWindowEvent(nodeSelector)) } } diff --git a/src/main/scala/ocelot/desktop/util/DrawUtils.scala b/src/main/scala/ocelot/desktop/util/DrawUtils.scala index 70169d5..e6725e0 100644 --- a/src/main/scala/ocelot/desktop/util/DrawUtils.scala +++ b/src/main/scala/ocelot/desktop/util/DrawUtils.scala @@ -29,10 +29,24 @@ object DrawUtils { def windowBorder(g: Graphics, x: Float, y: Float, w: Float, h: Float, color: Color = RGBAColor(255, 255, 255)): Unit = { - g.sprite("window/CornerTL", x - 16, y - 20, 16, 20, color) - g.sprite("window/CornerTR", x + w, y - 20, 16, 20, color) - g.sprite("window/CornerBL", x - 16, y + h, 16, 16, color) - g.sprite("window/CornerBR", x + w, y + h, 16, 16, color) + g.sprite("window/CornerTL", x, y, 8, 8, color) + g.sprite("window/CornerTR", x + w - 8, y, 8, 8, color) + g.sprite("window/CornerBL", x, y + h - 8, 8, 8, color) + g.sprite("window/CornerBR", x + w - 8, y + h - 8, 8, 8, color) + + g.sprite("window/BorderLight", x + 8, y, w - 16, 8, color) + g.sprite("window/BorderDark", x + 8, y + h - 8, w - 16, 8, color) + + g.save() + g.translate(x, y + 8) + g.rotate(270.toRadians) + g.sprite("window/BorderLight", 0, 0, -h + 16, 8, color) + g.sprite("window/BorderDark", 0, w - 8, -h + 16, 8, color) + g.restore() + + g.sprite = "Empty" + g.foreground = RGBAColor(198, 198, 198, color.toRGBA.a) + g.rect(x + 8, y + 8, w - 16, h - 16) } def shadow(g: Graphics, x: Float, y: Float, w: Float, h: Float, a: Float = 0.8f): Unit = { @@ -64,7 +78,7 @@ object DrawUtils { g.save() g.translate(x + w / 2f, y + h / 2f) g.rotate(angle) - g.sprite("ShadowCorner", -w / 2f, -h / 2f, w, h, col) + g.sprite(sprite, -w / 2f, -h / 2f, w, h, col) g.restore() } diff --git a/src/main/scala/ocelot/desktop/util/animation/ValueAnimation.scala b/src/main/scala/ocelot/desktop/util/animation/ValueAnimation.scala index 2e84393..2712c30 100644 --- a/src/main/scala/ocelot/desktop/util/animation/ValueAnimation.scala +++ b/src/main/scala/ocelot/desktop/util/animation/ValueAnimation.scala @@ -3,51 +3,60 @@ package ocelot.desktop.util.animation import ocelot.desktop.ui.UiHandler import ocelot.desktop.util.animation.easing.{Easing, EasingFunction} -class ValueAnimation(init: Float = 0f, speed: Float = 2f) { - // broken - - private var _value: Float = init - private var target = 0f - private var timeToTarget = 0f - private var totalDistance = 0f +class ValueAnimation(init: Float = 0f, speed: Float = 7f) { + private var _value = init + private var start = init + private var end = init + private var time = 0f private var reached = false - private var _easing = Easing.linear - private var nextEasing = easing + private var _easing: EasingFunction = Easing.easeInOutQuad + private var nextEasing = _easing def easing: EasingFunction = _easing def easing_=(value: EasingFunction): Unit = { nextEasing = value + updateEasing() } def value: Float = _value def jump(to: Float): Unit = { _value = to - timeToTarget = 0 - target = to - reached = true + start = to + end = to + updateReached() } def goto(to: Float): Unit = { - target = to - totalDistance = (_value - target).abs - timeToTarget = totalDistance / speed - reached = (_value - target).abs < 0.00001 + start = _value + end = to + time = 0 + updateReached() } def update(): Unit = { -// if (reached) return + if (reached) return - val dt = UiHandler.dt - timeToTarget = (timeToTarget - dt / speed).max(0) + val dist = (end - start).abs + val dt = (UiHandler.dt * speed) / dist + time = (time + dt).min(1).max(0) - if (_value > target) - _value = target + easing(timeToTarget) * totalDistance + _value = if (start > end) + start - time * dist else - _value = target - easing(timeToTarget) * totalDistance + start + time * dist - reached = (_value - target).abs < 0.00001 + updateReached() + if (reached) _easing = nextEasing + } + + private def updateReached(): Unit = { + reached = (_value - end).abs < 0.001 + } + + private def updateEasing(): Unit = { + updateReached() if (reached) _easing = nextEasing } }