diff --git a/sprites/icons/DragLMB.png b/sprites/icons/DragLMB.png new file mode 100644 index 0000000..e6e8bc7 Binary files /dev/null and b/sprites/icons/DragLMB.png differ diff --git a/sprites/icons/DragRMB.png b/sprites/icons/DragRMB.png new file mode 100644 index 0000000..edc2358 Binary files /dev/null and b/sprites/icons/DragRMB.png differ diff --git a/sprites/icons/LMB.png b/sprites/icons/LMB.png new file mode 100644 index 0000000..72810fa Binary files /dev/null and b/sprites/icons/LMB.png differ diff --git a/sprites/icons/RMB.png b/sprites/icons/RMB.png new file mode 100644 index 0000000..c4c0980 Binary files /dev/null and b/sprites/icons/RMB.png differ diff --git a/src/main/resources/ocelot/desktop/colorscheme.txt b/src/main/resources/ocelot/desktop/colorscheme.txt index 6ba79c3..77b9bab 100644 --- a/src/main/resources/ocelot/desktop/colorscheme.txt +++ b/src/main/resources/ocelot/desktop/colorscheme.txt @@ -31,4 +31,9 @@ ContextMenuSeparator = #444444 ComputerAddress = #333333 -ScreenOff = #000000 \ No newline at end of file +ScreenOff = #000000 + +StatusBar = #181818 +StatusBarBorder = #222222 +StatusBarForeground = #777777 +StatusBarIcon = #bbbbbb \ No newline at end of file diff --git a/src/main/resources/ocelot/desktop/spritesheet.png b/src/main/resources/ocelot/desktop/spritesheet.png index b4c796f..ca6ea6a 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 ead16c2..769f74c 100644 --- a/src/main/resources/ocelot/desktop/spritesheet.txt +++ b/src/main/resources/ocelot/desktop/spritesheet.txt @@ -1,98 +1,102 @@ BackgroundPattern 0 0 304 304 ComputerMotherboard 305 0 79 70 -Empty 337 277 1 1 +Empty 417 0 1 1 EmptySlot 441 96 18 18 -ShadowBorder 305 277 1 24 +ShadowBorder 385 0 1 24 ShadowCorner 424 71 24 24 buttons/PowerOff 460 96 18 18 buttons/PowerOn 479 96 18 18 -icons/CPU 424 129 16 16 -icons/Card 441 129 16 16 -icons/ComponentBus 458 129 16 16 -icons/EEPROM 475 129 16 16 -icons/Floppy 492 129 16 16 -icons/HDD 424 146 16 16 -icons/Memory 441 146 16 16 -icons/NA 458 146 16 16 -icons/RackMountable 475 146 16 16 -icons/Tier0 492 146 16 16 -icons/Tier1 449 71 16 16 -icons/Tier2 466 71 16 16 +icons/CPU 424 144 16 16 +icons/Card 441 144 16 16 +icons/ComponentBus 458 144 16 16 +icons/DragLMB 424 129 21 14 +icons/DragRMB 446 129 21 14 +icons/EEPROM 475 144 16 16 +icons/Floppy 492 144 16 16 +icons/HDD 449 71 16 16 +icons/LMB 373 268 11 14 +icons/Memory 466 71 16 16 +icons/NA 483 71 16 16 +icons/RMB 385 268 11 14 +icons/RackMountable 356 168 16 16 +icons/Tier0 373 168 16 16 +icons/Tier1 390 168 16 16 +icons/Tier2 407 168 16 16 items/APU0 356 71 16 96 items/APU1 373 71 16 96 items/APU2 390 71 16 96 -items/CPU0 483 71 16 16 -items/CPU1 356 168 16 16 -items/CPU2 373 168 16 16 -items/CardBase 390 168 16 16 -items/CircuitBoard 407 168 16 16 -items/ComponentBus0 424 168 16 16 -items/ComponentBus1 441 168 16 16 -items/ComponentBus2 458 168 16 16 -items/ComponentBus3 475 168 16 16 +items/CPU0 424 168 16 16 +items/CPU1 441 168 16 16 +items/CPU2 458 168 16 16 +items/CardBase 475 168 16 16 +items/CircuitBoard 492 168 16 16 +items/ComponentBus0 305 200 16 16 +items/ComponentBus1 322 200 16 16 +items/ComponentBus2 339 200 16 16 +items/ComponentBus3 356 200 16 16 items/DataCard0 305 71 16 128 items/DataCard1 322 71 16 128 items/DataCard2 339 71 16 128 -items/DebugCard 492 168 16 16 -items/DiskDriveMountable 305 200 16 16 -items/EEPROM 322 200 16 16 -items/FloppyDisk_dyeBlack 339 200 16 16 -items/FloppyDisk_dyeBlue 356 200 16 16 -items/FloppyDisk_dyeBrown 373 200 16 16 -items/FloppyDisk_dyeCyan 390 200 16 16 -items/FloppyDisk_dyeGray 407 200 16 16 -items/FloppyDisk_dyeGreen 424 200 16 16 -items/FloppyDisk_dyeLightBlue 441 200 16 16 -items/FloppyDisk_dyeLightGray 458 200 16 16 -items/FloppyDisk_dyeLime 475 200 16 16 -items/FloppyDisk_dyeMagenta 492 200 16 16 -items/FloppyDisk_dyeOrange 305 217 16 16 -items/FloppyDisk_dyePink 322 217 16 16 -items/FloppyDisk_dyePurple 339 217 16 16 -items/FloppyDisk_dyeRed 356 217 16 16 -items/FloppyDisk_dyeWhite 373 217 16 16 -items/FloppyDisk_dyeYellow 390 217 16 16 -items/GraphicsCard0 407 217 16 16 -items/GraphicsCard1 424 217 16 16 -items/GraphicsCard2 441 217 16 16 -items/HardDiskDrive0 458 217 16 16 -items/HardDiskDrive1 475 217 16 16 -items/HardDiskDrive2 492 217 16 16 +items/DebugCard 373 200 16 16 +items/DiskDriveMountable 390 200 16 16 +items/EEPROM 407 200 16 16 +items/FloppyDisk_dyeBlack 424 200 16 16 +items/FloppyDisk_dyeBlue 441 200 16 16 +items/FloppyDisk_dyeBrown 458 200 16 16 +items/FloppyDisk_dyeCyan 475 200 16 16 +items/FloppyDisk_dyeGray 492 200 16 16 +items/FloppyDisk_dyeGreen 305 217 16 16 +items/FloppyDisk_dyeLightBlue 322 217 16 16 +items/FloppyDisk_dyeLightGray 339 217 16 16 +items/FloppyDisk_dyeLime 356 217 16 16 +items/FloppyDisk_dyeMagenta 373 217 16 16 +items/FloppyDisk_dyeOrange 390 217 16 16 +items/FloppyDisk_dyePink 407 217 16 16 +items/FloppyDisk_dyePurple 424 217 16 16 +items/FloppyDisk_dyeRed 441 217 16 16 +items/FloppyDisk_dyeWhite 458 217 16 16 +items/FloppyDisk_dyeYellow 475 217 16 16 +items/GraphicsCard0 492 217 16 16 +items/GraphicsCard1 305 234 16 16 +items/GraphicsCard2 322 234 16 16 +items/HardDiskDrive0 339 234 16 16 +items/HardDiskDrive1 356 234 16 16 +items/HardDiskDrive2 373 234 16 16 items/InternetCard 424 96 16 32 items/LinkedCard 407 71 16 96 -items/Memory0 305 234 16 16 -items/Memory1 322 234 16 16 -items/Memory2 339 234 16 16 -items/Memory3 356 234 16 16 -items/Memory4 373 234 16 16 -items/Memory5 390 234 16 16 -items/NetworkCard 407 234 16 16 -items/RedstoneCard0 424 234 16 16 -items/RedstoneCard1 441 234 16 16 -items/Server0 458 234 16 16 -items/Server1 475 234 16 16 -items/Server2 492 234 16 16 -items/Server3 305 251 16 16 -items/WirelessNetworkCard0 322 251 16 16 -items/WirelessNetworkCard1 339 251 16 16 -nodes/Computer 356 251 16 16 -nodes/ComputerActivityOverlay 373 251 16 16 -nodes/ComputerErrorOverlay 390 251 16 16 -nodes/ComputerOnOverlay 407 251 16 16 -nodes/NewNode 424 251 16 16 -nodes/Relay 441 251 16 16 -nodes/Screen 458 251 16 16 -nodes/ScreenOnOverlay 475 251 16 16 -screen/BorderB 310 277 2 8 -screen/BorderT 307 277 2 10 -screen/CornerBL 305 268 8 8 -screen/CornerBR 314 268 8 8 -screen/CornerTL 492 251 8 10 -screen/CornerTR 501 251 8 10 -window/BorderDark 333 277 1 4 -window/BorderLight 335 277 1 4 -window/CloseButton 323 268 7 6 -window/CornerBL 313 277 4 4 -window/CornerBR 318 277 4 4 -window/CornerTL 323 277 4 4 -window/CornerTR 328 277 4 4 +items/Memory0 390 234 16 16 +items/Memory1 407 234 16 16 +items/Memory2 424 234 16 16 +items/Memory3 441 234 16 16 +items/Memory4 458 234 16 16 +items/Memory5 475 234 16 16 +items/NetworkCard 492 234 16 16 +items/RedstoneCard0 305 251 16 16 +items/RedstoneCard1 322 251 16 16 +items/Server0 339 251 16 16 +items/Server1 356 251 16 16 +items/Server2 373 251 16 16 +items/Server3 390 251 16 16 +items/WirelessNetworkCard0 407 251 16 16 +items/WirelessNetworkCard1 424 251 16 16 +nodes/Computer 441 251 16 16 +nodes/ComputerActivityOverlay 458 251 16 16 +nodes/ComputerErrorOverlay 475 251 16 16 +nodes/ComputerOnOverlay 492 251 16 16 +nodes/NewNode 305 268 16 16 +nodes/Relay 322 268 16 16 +nodes/Screen 339 268 16 16 +nodes/ScreenOnOverlay 356 268 16 16 +screen/BorderB 390 0 2 8 +screen/BorderT 387 0 2 10 +screen/CornerBL 415 268 8 8 +screen/CornerBR 424 268 8 8 +screen/CornerTL 397 268 8 10 +screen/CornerTR 406 268 8 10 +window/BorderDark 413 0 1 4 +window/BorderLight 415 0 1 4 +window/CloseButton 433 268 7 6 +window/CornerBL 393 0 4 4 +window/CornerBR 398 0 4 4 +window/CornerTL 403 0 4 4 +window/CornerTR 408 0 4 4 diff --git a/src/main/scala/ocelot/desktop/node/Node.scala b/src/main/scala/ocelot/desktop/node/Node.scala index 2a6ccaa..3984f37 100644 --- a/src/main/scala/ocelot/desktop/node/Node.scala +++ b/src/main/scala/ocelot/desktop/node/Node.scala @@ -41,7 +41,7 @@ trait Node extends Widget with DragHandler with ClickHandler with HoverHandler { case ClickEvent(MouseEvent.Button.Right, _) => val menu = new ContextMenu setupContextMenu(menu) - workspaceView.rootWidget.contextMenus.open(menu) + root.get.contextMenus.open(menu) case DragEvent(DragEvent.State.Start, MouseEvent.Button.Left, pos) => startMoving(pos) @@ -88,6 +88,16 @@ trait Node extends Widget with DragHandler with ClickHandler with HoverHandler { })) } + override def update(): Unit = { + super.update() + if (isHovered || isMoving) { + root.get.statusBar.addMouseEntry("icons/LMB", "Open") + root.get.statusBar.addMouseEntry("icons/RMB", "Menu") + root.get.statusBar.addMouseEntry("icons/DragLMB", "Move node") + root.get.statusBar.addMouseEntry("icons/DragRMB", "Connect/Disconnect") + } + } + def environment: Environment def icon: String = "icons/NA" diff --git a/src/main/scala/ocelot/desktop/node/NodeTypeWidget.scala b/src/main/scala/ocelot/desktop/node/NodeTypeWidget.scala index 5419a5b..57b1048 100644 --- a/src/main/scala/ocelot/desktop/node/NodeTypeWidget.scala +++ b/src/main/scala/ocelot/desktop/node/NodeTypeWidget.scala @@ -2,12 +2,12 @@ package ocelot.desktop.node import ocelot.desktop.geometry.Size2D import ocelot.desktop.graphics.Graphics -import ocelot.desktop.ui.event.handlers.ClickHandler +import ocelot.desktop.ui.event.handlers.{ClickHandler, HoverHandler} import ocelot.desktop.ui.event.{ClickEvent, MouseEvent} import ocelot.desktop.ui.widget.Widget import ocelot.desktop.util.TierColor -class NodeTypeWidget(val nodeType: NodeType) extends Widget with ClickHandler { +class NodeTypeWidget(val nodeType: NodeType) extends Widget with ClickHandler with HoverHandler { override def minimumSize: Size2D = Size2D(68, 68) override def maximumSize: Size2D = minimumSize @@ -24,4 +24,11 @@ class NodeTypeWidget(val nodeType: NodeType) extends Widget with ClickHandler { override def draw(g: Graphics): Unit = { g.sprite(nodeType.icon, position.x + 2, position.y + 2, size.width - 4, size.height - 4, TierColor.get(nodeType.tier)) } + + override def update(): Unit = { + super.update() + if (isHovered) { + root.get.statusBar.addMouseEntry("icons/LMB", "Add node") + } + } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/RootWidget.scala b/src/main/scala/ocelot/desktop/ui/widget/RootWidget.scala index 5989b96..587385e 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/RootWidget.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/RootWidget.scala @@ -5,19 +5,31 @@ import ocelot.desktop.graphics.Graphics import ocelot.desktop.ui.UiHandler import ocelot.desktop.ui.UiHandler.graphics import ocelot.desktop.ui.event.KeyEvent -import ocelot.desktop.ui.layout.CopyLayout +import ocelot.desktop.ui.layout.{CopyLayout, LinearLayout} import ocelot.desktop.ui.widget.contextmenu.ContextMenus -import ocelot.desktop.util.DrawUtils +import ocelot.desktop.ui.widget.statusbar.StatusBar +import ocelot.desktop.util.{DrawUtils, Orientation} import org.lwjgl.input.Keyboard class RootWidget extends Widget { - override protected val layout = new CopyLayout(this) + override protected val layout = new LinearLayout(this, orientation = Orientation.Vertical) + root = Some(this) - val workspaceView: WorkspaceView = new WorkspaceView - val contextMenus: ContextMenus = new ContextMenus + val workspaceView = new WorkspaceView + workspaceView.root = root + workspaceView.createDefaultWorkspace() + + val contextMenus = new ContextMenus + val statusBar = new StatusBar + + children :+= new Widget { + override protected val layout = new CopyLayout(this) + children :+= workspaceView + children :+= contextMenus + } + + children :+= statusBar - children :+= workspaceView - children :+= contextMenus private var isDebugViewVisible = false diff --git a/src/main/scala/ocelot/desktop/ui/widget/Widget.scala b/src/main/scala/ocelot/desktop/ui/widget/Widget.scala index 4aeb7f0..d8b77e7 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/Widget.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/Widget.scala @@ -13,6 +13,7 @@ class Widget { protected var _children: Array[Widget] = Array[Widget]() protected var _parent: Option[Widget] = None + protected var _root: Option[RootWidget] = None protected var _position: Vector2D = Vector2D(0, 0) protected var _size: Size2D = Size2D(0, 0) @@ -35,8 +36,10 @@ class Widget { final def children_=(value: Array[Widget]): Unit = { _children = value - for (child <- _children) + for (child <- _children) { child._parent = Some(this) + child.root = _root + } recalculateBounds() size = _size @@ -46,6 +49,13 @@ class Widget { final def parent: Option[Widget] = _parent + final def root_=(v: Option[RootWidget]): Unit = { + _root = v + children.foreach(_.root = v) + } + + final def root: Option[RootWidget] = _root + def minimumSize: Size2D = layout.minimumSize def maximumSize: Size2D = layout.maximumSize.max(minimumSize) diff --git a/src/main/scala/ocelot/desktop/ui/widget/WorkspaceView.scala b/src/main/scala/ocelot/desktop/ui/widget/WorkspaceView.scala index 27485f1..6ee3c5c 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/WorkspaceView.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/WorkspaceView.scala @@ -38,14 +38,11 @@ class WorkspaceView extends Widget with DragHandler with ClickHandler with Hover override def hierarchy: Array[Widget] = nodes.toArray } - createDefaultWorkspace() - - def rootWidget: RootWidget = parent.get.asInstanceOf[RootWidget] - def addNode(node: Node, pos: Vector2D = newNodePos): Unit = { node.position = pos + cameraOffset resolveCollision(node) node.workspaceView = this + node.root = _root nodes += node } @@ -390,5 +387,13 @@ class WorkspaceView extends Widget with DragHandler with ClickHandler with Hover override def update(): Unit = { super.update() nodes.foreach(_.update()) + + if (isHovered && newConnection.isEmpty) { + if (nodeSelector.isShown) + root.get.statusBar.addMouseEntry("icons/LMB", "Close selector") + else + root.get.statusBar.addMouseEntry("icons/LMB", "Add node") + root.get.statusBar.addMouseEntry("icons/DragLMB", "Move camera") + } } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/statusbar/MouseEntry.scala b/src/main/scala/ocelot/desktop/ui/widget/statusbar/MouseEntry.scala new file mode 100644 index 0000000..2d6495a --- /dev/null +++ b/src/main/scala/ocelot/desktop/ui/widget/statusbar/MouseEntry.scala @@ -0,0 +1,21 @@ +package ocelot.desktop.ui.widget.statusbar + +import ocelot.desktop.ColorScheme +import ocelot.desktop.color.Color +import ocelot.desktop.geometry.Size2D +import ocelot.desktop.graphics.Graphics +import ocelot.desktop.ui.widget.Widget +import ocelot.desktop.util.Spritesheet + +class MouseEntry(icon: String, text: String) extends Widget { + private val iconSize = Spritesheet.spriteSize(icon) + override def minimumSize: Size2D = Size2D(iconSize.width + 24 + text.length * 8, 16) + override def maximumSize: Size2D = minimumSize + + override def draw(g: Graphics): Unit = { + g.sprite(icon, position + Size2D(8, height / 2 - iconSize.height / 2), ColorScheme("StatusBarIcon")) + g.background = Color.Transparent + g.foreground = ColorScheme("StatusBarForeground") + g.text(position.x + iconSize.width + 16, position.y, text) + } +} diff --git a/src/main/scala/ocelot/desktop/ui/widget/statusbar/StatusBar.scala b/src/main/scala/ocelot/desktop/ui/widget/statusbar/StatusBar.scala new file mode 100644 index 0000000..8c61a42 --- /dev/null +++ b/src/main/scala/ocelot/desktop/ui/widget/statusbar/StatusBar.scala @@ -0,0 +1,25 @@ +package ocelot.desktop.ui.widget.statusbar + +import ocelot.desktop.ColorScheme +import ocelot.desktop.geometry.Size2D +import ocelot.desktop.graphics.Graphics +import ocelot.desktop.ui.layout.{AlignItems, LinearLayout} +import ocelot.desktop.ui.widget.Widget + +class StatusBar extends Widget { + override protected val layout = new LinearLayout(this, alignItems = AlignItems.Center) + override def minimumSize: Size2D = Size2D(100, 18) + override def maximumSize: Size2D = Size2D(Float.PositiveInfinity, 18) + override def receiveMouseEvents = true + + def addMouseEntry(icon: String, text: String): Unit = { + children :+= new MouseEntry(icon, text) + } + + override def draw(g: Graphics): Unit = { + g.rect(bounds, ColorScheme("StatusBar")) + g.line(position, position + Size2D(width, 0), 1, ColorScheme("StatusBarBorder")) + drawChildren(g) + children = Array() + } +}