mirror of
https://gitlab.com/cc-ru/ocelot/ocelot-desktop.git
synced 2025-12-20 02:59:19 +01:00
201 lines
5.9 KiB
Scala
201 lines
5.9 KiB
Scala
package ocelot.desktop.node.nodes
|
|
|
|
import ocelot.desktop.geometry.{Rect2D, Size2D, Vector2D}
|
|
import ocelot.desktop.graphics.{Graphics, IconSource}
|
|
import ocelot.desktop.inventory.Item
|
|
import ocelot.desktop.inventory.item.{DiskDriveMountableItem, RackMountableItem, ServerItem}
|
|
import ocelot.desktop.node.Node.{HighlightThickness, NoHighlightSize, Size, TexelCount}
|
|
import ocelot.desktop.node.{ComputerAwareNode, NodePort}
|
|
import ocelot.desktop.ui.event.ClickEvent
|
|
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
|
import ocelot.desktop.ui.widget.window.Window
|
|
import ocelot.desktop.util.DrawUtils
|
|
import ocelot.desktop.windows.RackWindow
|
|
import totoro.ocelot.brain.entity.Rack
|
|
import totoro.ocelot.brain.entity.traits.{ComponentInventory, Environment, Inventory, RackMountable}
|
|
import totoro.ocelot.brain.network
|
|
import totoro.ocelot.brain.util.Direction
|
|
|
|
class RackNode(val rack: Rack)
|
|
extends ComputerAwareNode(rack)
|
|
{
|
|
override val icon: String = "nodes/rack/Empty"
|
|
|
|
override def exposeAddress = false
|
|
|
|
override def ports: Array[NodePort] = Array(
|
|
NodePort(Some(Direction.Bottom)),
|
|
NodePort(Some(Direction.Top)),
|
|
NodePort(Some(Direction.Back)),
|
|
NodePort(Some(Direction.Right)),
|
|
NodePort(Some(Direction.Left))
|
|
)
|
|
|
|
override def getNodeByPort(port: NodePort): network.Node = rack.sidedNode(port.direction.get)
|
|
|
|
override def shouldReceiveEventsFor(address: String): Boolean =
|
|
super.shouldReceiveEventsFor(address) ||
|
|
rack.inventory.entities.exists {
|
|
case mountable: RackMountable if mountable.node.address == address => true
|
|
case mountable: RackMountable with ComponentInventory => mountable.inventory.entities.exists {
|
|
case environment: Environment => environment.node.address == address
|
|
}
|
|
case _ => false
|
|
}
|
|
|
|
override def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = {
|
|
RackNode.addContextMenuEntriesOfMountable(menu, getMountableByClick(event))
|
|
|
|
super.setupContextMenu(menu, event)
|
|
}
|
|
|
|
override def draw(g: Graphics): Unit = {
|
|
super.draw(g)
|
|
|
|
val x = position.x + HighlightThickness
|
|
val y = position.y + HighlightThickness
|
|
var prefix: String = null
|
|
|
|
for (i <- 0 until 4) {
|
|
Slot(i).get match {
|
|
case Some(serverItem: ServerItem) =>
|
|
prefix = s"nodes/rack/server/$i/"
|
|
|
|
// Background
|
|
g.sprite(
|
|
s"${prefix}Default",
|
|
x,
|
|
y,
|
|
NoHighlightSize,
|
|
NoHighlightSize
|
|
)
|
|
|
|
// Activity overlay
|
|
DrawUtils.drawComputerNodeActivity(
|
|
g,
|
|
x,
|
|
y,
|
|
serverItem.server.machine,
|
|
prefix
|
|
)
|
|
case Some(diskDriveMountableItem: DiskDriveMountableItem) =>
|
|
prefix = s"nodes/rack/drive/$i/"
|
|
|
|
// Background
|
|
g.sprite(
|
|
s"${prefix}Default",
|
|
x,
|
|
y,
|
|
NoHighlightSize,
|
|
NoHighlightSize
|
|
)
|
|
|
|
diskDriveMountableItem.drawActivityAndFloppy(
|
|
g,
|
|
Rect2D(
|
|
x,
|
|
y,
|
|
NoHighlightSize,
|
|
NoHighlightSize
|
|
),
|
|
prefix
|
|
)
|
|
case _ =>
|
|
}
|
|
}
|
|
}
|
|
|
|
override def dispose(): Unit = {
|
|
for (i <- 0 until 4) {
|
|
Slot(i).get match {
|
|
case Some(serverItem: ServerItem) => serverItem.onRemoved()
|
|
case _=>
|
|
}
|
|
}
|
|
|
|
super.dispose()
|
|
}
|
|
|
|
// -------------------------------- Inventory --------------------------------
|
|
|
|
override type I = Item with RackMountableItem
|
|
override def brainInventory: Inventory = rack.inventory.owner
|
|
|
|
// -------------------------------- Window --------------------------------
|
|
|
|
private lazy val currentWindow = new RackWindow(this)
|
|
|
|
override def window: Option[Window] = Some(currentWindow)
|
|
|
|
// ---------------------------- ShiftClickNode ----------------------------
|
|
|
|
private def getMountableByClick(event: ClickEvent): Option[RackMountableItem] = {
|
|
val horizontalMargin = HighlightThickness + (1 / TexelCount) * Size
|
|
val verticalMargin = HighlightThickness + (2 / TexelCount) * Size
|
|
|
|
val localPosition = Vector2D(
|
|
event.mousePos.x - position.x - horizontalMargin,
|
|
event.mousePos.y - position.y - verticalMargin
|
|
)
|
|
|
|
val m = Size2D(
|
|
this.width - horizontalMargin * 2,
|
|
this.height - verticalMargin * 2
|
|
)
|
|
|
|
// Checking if click was inside mountables area
|
|
if (localPosition.x < 0 || localPosition.y < 0 || localPosition.x > m.width || localPosition.y > m.height)
|
|
return None
|
|
|
|
val mountableIndex = (localPosition.y / m.height * 4).toInt
|
|
|
|
Slot(mountableIndex).get.collect {
|
|
case item: RackMountableItem => item
|
|
}
|
|
}
|
|
|
|
override protected def onShiftClick(event: ClickEvent): Unit = {
|
|
getMountableByClick(event) match {
|
|
case Some(serverItem: ServerItem) =>
|
|
serverItem.toggleIsTurnedOn()
|
|
|
|
case Some(diskDriveMountableItem: DiskDriveMountableItem) =>
|
|
if (diskDriveMountableItem.isFloppyItemPresent)
|
|
diskDriveMountableItem.eject()
|
|
|
|
case _ =>
|
|
}
|
|
}
|
|
|
|
override protected def hoveredShiftStatusBarText: String = "Turn server on/off"
|
|
}
|
|
|
|
object RackNode {
|
|
def addContextMenuEntriesOfMountable(menu: ContextMenu, item: Option[RackMountableItem]): Unit = {
|
|
item match {
|
|
case Some(serverItem: ServerItem) =>
|
|
menu.addEntry(ContextMenuEntry("Set up", IconSource.Window) {
|
|
serverItem.window.get.open()
|
|
})
|
|
|
|
if (serverItem.isInRack) {
|
|
menu.addSeparator()
|
|
|
|
serverItem.addPowerContextMenuEntries(menu)
|
|
}
|
|
|
|
serverItem.addTierContextMenuEntries(menu)
|
|
|
|
menu.addSeparator()
|
|
|
|
case Some(diskDriveMountableItem: DiskDriveMountableItem) =>
|
|
if (diskDriveMountableItem.isFloppyItemPresent) {
|
|
diskDriveMountableItem.addDiskDriveMenuEntries(menu)
|
|
|
|
menu.addSeparator()
|
|
}
|
|
|
|
case _ =>
|
|
}
|
|
}
|
|
} |