diff --git a/.scalafmt.conf b/.scalafmt.conf index d997455..04111a4 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -2,7 +2,6 @@ version = 3.9.9 runner.dialect = scala213 preset = default maxColumn = 120 -indent.defnSite = 2 align = { preset = none @@ -27,4 +26,10 @@ docstrings = { oneline = unfold wrap = keep forceBlankLineBefore = false -} \ No newline at end of file +} + +indent { + defnSite = 2 + extendSite = 2 + withSiteRelativeToExtends = 2 +} diff --git a/src/main/scala/ocelot/desktop/graphics/Graphics.scala b/src/main/scala/ocelot/desktop/graphics/Graphics.scala index 390bb43..cab960c 100644 --- a/src/main/scala/ocelot/desktop/graphics/Graphics.scala +++ b/src/main/scala/ocelot/desktop/graphics/Graphics.scala @@ -2,7 +2,6 @@ package ocelot.desktop.graphics import ocelot.desktop.color.{Color, RGBAColorNorm} import ocelot.desktop.geometry.{Rect2D, Size2D, Transform2D, Vector2D} -import ocelot.desktop.graphics.IconSource.Animation import ocelot.desktop.graphics.Texture.MinFilteringMode import ocelot.desktop.graphics.mesh.{Mesh2D, MeshInstance2D, MeshVertex2D} import ocelot.desktop.graphics.render.InstanceRenderer @@ -280,105 +279,87 @@ class Graphics(private var width: Int, private var height: Int, private var scal // I hate scala. Overloaded methods with default arguments are not allowed def sprite(icon: IconSource, bounds: Rect2D): Unit = { - sprite(icon.path, bounds.x, bounds.y, bounds.w, bounds.h, Color.White, icon.animation) + sprite(icon, bounds.x, bounds.y, bounds.w, bounds.h, Color.White) } def sprite(icon: IconSource, bounds: Rect2D, color: Color): Unit = { - sprite(icon.path, bounds.x, bounds.y, bounds.w, bounds.h, color, icon.animation) + sprite(icon, bounds.x, bounds.y, bounds.w, bounds.h, color) } def sprite(icon: IconSource, pos: Vector2D, size: Size2D): Unit = { - sprite(icon.path, pos.x, pos.y, size.width, size.height, Color.White, icon.animation) + sprite(icon, pos.x, pos.y, size.width, size.height, Color.White) + } + + def sprite(icon: IconSource, pos: Vector2D, color: Color): Unit = { + sprite(icon, pos.x, pos.y, color) } def sprite(icon: IconSource, pos: Vector2D, size: Size2D, color: Color): Unit = { - sprite(icon.path, pos.x, pos.y, size.width, size.height, color, icon.animation) + sprite(icon, pos.x, pos.y, size.width, size.height, color) } def sprite(icon: IconSource, x: Float, y: Float): Unit = { - sprite(icon.path, x, y, icon.animation) + sprite(icon, x, y, Color.White) } def sprite(icon: IconSource, x: Float, y: Float, width: Float, height: Float): Unit = { - sprite(icon.path, x, y, width, height, animation = icon.animation) + sprite(icon, x, y, width, height, Color.White) } - def sprite(icon: IconSource, x: Float, y: Float, width: Float, height: Float, color: Color): Unit = { - sprite(icon.path, x, y, width, height, color, icon.animation) + def sprite(icon: IconSource, x: Float, y: Float, color: Color): Unit = { + val size = Spritesheet.spriteSize(icon.path) + sprite(icon, x, y, size.width, size.height, color) } - def sprite(name: String, bounds: Rect2D): Unit = { - sprite(name, bounds.origin, bounds.size, Color.White) - } - - def sprite(name: String, x: Float, y: Float, color: Color): Unit = { - sprite(name, Vector2D(x, y), Spritesheet.spriteSize(name), color) - } - - def sprite(name: String, pos: Vector2D, color: Color): Unit = { - sprite(name, pos, Spritesheet.spriteSize(name), color) - } - - def sprite(name: String, pos: Vector2D, size: Size2D, color: Color): Unit = { - sprite(name, pos.x, pos.y, size.width, size.height, color) - } - - def sprite(name: String, pos: Vector2D, size: Size2D): Unit = { - sprite(name, pos.x, pos.y, size.width, size.height) - } - - def sprite(name: String, x: Float, y: Float): Unit = { - sprite(name, x, y, Color.White, None) - } - - def sprite(name: String, x: Float, y: Float, animation: Option[Animation]): Unit = { - sprite(name, x, y, Color.White, animation) - } - - def sprite(name: String, x: Float, y: Float, color: Color, animation: Option[Animation]): Unit = { - val size = Spritesheet.spriteSize(name) - sprite(name, x, y, size.width, size.height, color, animation) - } - - def sprite(name: String, x: Float, y: Float, width: Float, height: Float, - color: Color = Color.White, - animation: Option[Animation] = None): Unit = { - sprite = name + def sprite( + icon: IconSource, + x: Float, + y: Float, + width: Float, + height: Float, + color: Color, + ): Unit = { + sprite = icon.path foreground = color - val spriteRect = animation match { - case Some(animation) => - val duration = animation.frames.map(_._2).sum - var timeOffset = 0f - var curFrame = 0 + val spriteRect = icon.animation.map { animation => + val duration = animation.frames.map(_._2).sum + var timeOffset = 0f + var curFrame = 0 - breakable { - for ((idx, dur) <- animation.frames) { - timeOffset += dur - curFrame = idx - if (timeOffset >= time % duration) break - } + breakable { + for ((idx, dur) <- animation.frames) { + timeOffset += dur + curFrame = idx + if (timeOffset >= time % duration) break } + } - val size = animation.frameSize match { - case Some(size) => Size2D(this.spriteRect.w, this.spriteRect.w * size.height / size.width) - case None => Size2D(this.spriteRect.w, this.spriteRect.w) - } - Some(this.spriteRect.copy(y = this.spriteRect.y + curFrame * size.height, h = size.height)) + val size = animation.frameSize match { + case Some(size) => Size2D(this.spriteRect.w, this.spriteRect.w * size.height / size.width) + case None => Size2D(this.spriteRect.w, this.spriteRect.w) + } - case None => None + this.spriteRect.copy(y = this.spriteRect.y + curFrame * size.height, h = size.height) } _rect(x, y, width, height, fixUV = true, spriteRect) } - def sprite(name: String, x: Float, y: Float, width: Float, height: Float, - color: Color, - spriteRect: Rect2D): Unit = { + def sprite( + name: String, + x: Float, + y: Float, + width: Float, + height: Float, + color: Color, + spriteRect: Option[Rect2D], + fixUV: Boolean = true, + ): Unit = { sprite = name foreground = color - _rect(x, y, width, height, fixUV = true, Some(spriteRect)) + _rect(x, y, width, height, fixUV, spriteRect) } def rect(r: Rect2D, color: Color): Unit = { @@ -386,7 +367,7 @@ class Graphics(private var width: Int, private var height: Int, private var scal } def rect(x: Float, y: Float, width: Float, height: Float, color: Color = RGBAColorNorm(1f, 1f, 1f)): Unit = { - sprite("Empty", x, y, width, height, color) + sprite(IconSource.Empty, x, y, width, height, color) } private def checkFont(): Unit = { diff --git a/src/main/scala/ocelot/desktop/graphics/IconSource.scala b/src/main/scala/ocelot/desktop/graphics/IconSource.scala index cc254de..10d3d56 100644 --- a/src/main/scala/ocelot/desktop/graphics/IconSource.scala +++ b/src/main/scala/ocelot/desktop/graphics/IconSource.scala @@ -3,86 +3,148 @@ package ocelot.desktop.graphics import ocelot.desktop.geometry.Size2D import ocelot.desktop.ui.widget.modal.notification.NotificationType.NotificationType import totoro.ocelot.brain.entity.tape.Tape.{Kind => TapeKind} -import totoro.ocelot.brain.util.Direction.{Direction, Down, Up, North, South, West, East} +import totoro.ocelot.brain.util.Direction.{Direction, Down, East, North, South, Up, West} import totoro.ocelot.brain.util.DyeColor import totoro.ocelot.brain.util.ExtendedTier.ExtendedTier import totoro.ocelot.brain.util.Tier.Tier -case class IconSource( - path: String, - animation: Option[IconSource.Animation] = None, -) +case class IconSource(path: String, animation: Option[IconSource.Animation] = None) object IconSource { - object Items { - protected val prefix: String = "items" + case class Animation(frames: Array[(Int, Float)], frameSize: Option[Size2D]) + object Animation { + def apply(frames: (Int, Float)*) = new Animation(frames.toArray, None) + def apply(size: Size2D)(frames: (Int, Float)*) = new Animation(frames.toArray, Some(size)) + def apply(size: Option[Size2D] = None)(frames: Array[(Int, Float)]) = new Animation(frames, size) + } + + class IconScope(directory: String)(implicit parent: Option[IconScope]) { + // this makes nested `IconScope` declarations use `this` as their parent scope. + implicit def scope: Option[IconScope] = Some(this) + + private def prefix: String = parent match { + case Some(parent) => s"${parent.prefix}/$directory" + case None => directory + } + + protected def get(name: String): IconSource = { + get(name, None) + } + + protected def get(name: String, animation: Animation): IconSource = { + get(name, Some(animation)) + } + + protected def get(name: String, animation: Option[Animation]): IconSource = { + IconSource(s"$prefix/$name", animation) + } + } + + private implicit val scope: Option[IconScope] = None + + val Empty: IconSource = IconSource("Empty") + val EmptySlot: IconSource = IconSource("EmptySlot") + val ShadowCorner: IconSource = IconSource("ShadowCorner") + val ShadowBorder: IconSource = IconSource("ShadowBorder") + val TabArrow: IconSource = IconSource("TabArrow") + val BarSegment: IconSource = IconSource("BarSegment") + val BackgroundPattern: IconSource = IconSource("BackgroundPattern") + val Logo: IconSource = IconSource("Logo") + + val Knob: IconSource = IconSource("Knob") + val KnobLimits: IconSource = IconSource("KnobLimits") + val KnobCenter: IconSource = IconSource("KnobCenter") + + val Loading: IconSource = IconSource( + "Loading", + Some( + Animation(Size2D(48, 32))( + (0, 0.7f), + (1, 0.7f), + (2, 0.7f), + (3, 0.7f), + (4, 0.7f), + (5, 0.7f), + (6, 0.7f), + (7, 0.7f), + (8, 0.7f), + (9, 0.7f), + (10, 0.7f), + (11, 0.7f), + (12, 0.7f), + (13, 0.7f), + ) + ), + ) + + object Items extends IconScope("items") { val Cpu: Tier => IconSource = { tier => - IconSource(s"$prefix/CPU${tier.id}") + get(s"CPU${tier.id}") } val Apu: Tier => IconSource = { tier => - IconSource(s"$prefix/APU${tier.id}", animation = Some(Animations.Apu)) + get(s"APU${tier.id}", Animations.Apu) } val GraphicsCard: Tier => IconSource = { tier => - IconSource(s"$prefix/GraphicsCard${tier.id}") + get(s"GraphicsCard${tier.id}") } - val NetworkCard: IconSource = IconSource(s"$prefix/NetworkCard") + val NetworkCard: IconSource = get("NetworkCard") val WirelessNetworkCard: Tier => IconSource = { tier => - IconSource(s"$prefix/WirelessNetworkCard${tier.id}") + get(s"WirelessNetworkCard${tier.id}") } - val LinkedCard: IconSource = IconSource(s"$prefix/LinkedCard", animation = Some(Animations.LinkedCard)) + val LinkedCard: IconSource = get("LinkedCard", Animations.LinkedCard) - val InternetCard: IconSource = IconSource(s"$prefix/InternetCard", animation = Some(Animations.InternetCard)) + val InternetCard: IconSource = get("InternetCard", Animations.InternetCard) val RedstoneCard: Tier => IconSource = { tier => - IconSource(s"$prefix/RedstoneCard${tier.id}") + get(s"RedstoneCard${tier.id}") } val DataCard: Tier => IconSource = { tier => - IconSource(s"$prefix/DataCard${tier.id}", animation = Some(Animations.DataCard)) + get(s"DataCard${tier.id}", Animations.DataCard) } - val SoundCard: IconSource = IconSource(s"$prefix/SoundCard", animation = Some(Animations.DataCard)) + val SoundCard: IconSource = get("SoundCard", Animations.DataCard) val SelfDestructingCard: IconSource = - IconSource(s"$prefix/SelfDestructingCard", animation = Some(Animations.SelfDestructingCard)) + get("SelfDestructingCard", Animations.SelfDestructingCard) - val OcelotCard: IconSource = IconSource(s"$prefix/OcelotCard", animation = Some(Animations.OcelotCard)) + val OcelotCard: IconSource = get("OcelotCard", Animations.OcelotCard) val HardDiskDrive: Tier => IconSource = { tier => - IconSource(s"$prefix/HardDiskDrive${tier.id}") + get(s"HardDiskDrive${tier.id}") } - val Eeprom: IconSource = IconSource(s"$prefix/EEPROM") + val Eeprom: IconSource = get("EEPROM") val FloppyDisk: DyeColor => IconSource = { color => - IconSource(s"$prefix/FloppyDisk_${color.name}") + get(s"FloppyDisk_${color.name}") } val Memory: ExtendedTier => IconSource = { tier => - IconSource(s"$prefix/Memory${tier.id}") + get(s"Memory${tier.id}") } val Server: Tier => IconSource = { tier => - IconSource(s"$prefix/Server${tier.id}") + get(s"Server${tier.id}") } val ComponentBus: Tier => IconSource = { tier => - IconSource(s"$prefix/ComponentBus${tier.id}") + get(s"ComponentBus${tier.id}") } val Tape: TapeKind => IconSource = { case TapeKind.Golder => Tape(TapeKind.Gold) case TapeKind.NetherStarrer => Tape(TapeKind.NetherStar) - case kind => IconSource(s"$prefix/Tape$kind") + case kind => get(s"Tape$kind") } - val DiskDriveMountable: IconSource = IconSource(s"$prefix/DiskDriveMountable") + val DiskDriveMountable: IconSource = get("DiskDriveMountable") // noinspection ScalaWeakerAccess object Animations { @@ -104,342 +166,368 @@ object IconSource { } } - case class Animation(frames: Array[(Int, Float)], frameSize: Option[Size2D]) - - object Animation { - def apply(frames: (Int, Float)*) = new Animation(frames.toArray, None) - def apply(size: Size2D, frames: (Int, Float)*) = new Animation(frames.toArray, Some(size)) - def apply(size: Option[Size2D] = None, frames: Array[(Int, Float)]) = new Animation(frames, size) - } - - // ----------------------- Ocelot interface icons ----------------------- - - val Loading: IconSource = IconSource( - "Loading", - animation = Some(Animation( - Size2D(48, 32), - (0, 0.7f), - (1, 0.7f), - (2, 0.7f), - (3, 0.7f), - (4, 0.7f), - (5, 0.7f), - (6, 0.7f), - (7, 0.7f), - (8, 0.7f), - (9, 0.7f), - (10, 0.7f), - (11, 0.7f), - (12, 0.7f), - (13, 0.7f), - )), - ) - - object Icons { - protected val prefix: String = "icons" - - val Card: IconSource = IconSource(s"$prefix/Card") - val Cpu: IconSource = IconSource(s"$prefix/CPU") - val Hdd: IconSource = IconSource(s"$prefix/HDD") - val Eeprom: IconSource = IconSource(s"$prefix/EEPROM") - val Floppy: IconSource = IconSource(s"$prefix/Floppy") - val Memory: IconSource = IconSource(s"$prefix/Memory") - val Server: IconSource = IconSource(s"$prefix/Server") - val ComponentBus: IconSource = IconSource(s"$prefix/ComponentBus") + object Icons extends IconScope("icons") { + val Card: IconSource = get("Card") + val Cpu: IconSource = get("CPU") + val Hdd: IconSource = get("HDD") + val Eeprom: IconSource = get("EEPROM") + val Floppy: IconSource = get("Floppy") + val Memory: IconSource = get("Memory") + val Server: IconSource = get("Server") + val ComponentBus: IconSource = get("ComponentBus") val Tier: Tier => IconSource = { tier => - IconSource(s"$prefix/Tier${tier.id}") + get(s"Tier${tier.id}") } - val SideNone: IconSource = IconSource(s"$prefix/SideNone") - val SideAny: IconSource = IconSource(s"$prefix/SideAny") - val SideUndefined: IconSource = IconSource(s"$prefix/SideUndefined") + val SideNone: IconSource = get("SideNone") + val SideAny: IconSource = get("SideAny") + val SideUndefined: IconSource = get("SideUndefined") val Side: Direction => IconSource = { - case Down => IconSource(s"$prefix/SideDown") - case Up => IconSource(s"$prefix/SideUp") - case North => IconSource(s"$prefix/SideNorth") - case South => IconSource(s"$prefix/SideSouth") - case West => IconSource(s"$prefix/SideWest") - case East => IconSource(s"$prefix/SideEast") + case Down => get("SideDown") + case Up => get("SideUp") + case North => get("SideNorth") + case South => get("SideSouth") + case West => get("SideWest") + case East => get("SideEast") case _ => SideUndefined } val Notification: NotificationType => IconSource = { notificationType => - IconSource(s"$prefix/Notification$notificationType") + get(s"Notification$notificationType") } - val SettingsKeymap: IconSource = IconSource(s"$prefix/SettingsKeymap") - val SettingsSystem: IconSource = IconSource(s"$prefix/SettingsSystem") - val SettingsSound: IconSource = IconSource(s"$prefix/SettingsSound") - val SettingsUI: IconSource = IconSource(s"$prefix/SettingsUI") - val Delete: IconSource = IconSource(s"$prefix/Delete") - val Label: IconSource = IconSource(s"$prefix/Label") - val Copy: IconSource = IconSource(s"$prefix/Copy") - val AspectRatio: IconSource = IconSource(s"$prefix/AspectRatio") - val Eject: IconSource = IconSource(s"$prefix/Eject") - val Restart: IconSource = IconSource(s"$prefix/Restart") - val Edit: IconSource = IconSource(s"$prefix/Edit") - val Folder: IconSource = IconSource(s"$prefix/Folder") - val FolderSlash: IconSource = IconSource(s"$prefix/FolderSlash") - val Code: IconSource = IconSource(s"$prefix/Code") - val File: IconSource = IconSource(s"$prefix/File") - val Link: IconSource = IconSource(s"$prefix/Link") - val LinkSlash: IconSource = IconSource(s"$prefix/LinkSlash") - val Power: IconSource = IconSource(s"$prefix/Power") - val Save: IconSource = IconSource(s"$prefix/Save") - val SaveAs: IconSource = IconSource(s"$prefix/SaveAs") - val Plus: IconSource = IconSource(s"$prefix/Plus") - val Cross: IconSource = IconSource(s"$prefix/Cross") - val Microchip: IconSource = IconSource(s"$prefix/Microchip") - val Antenna: IconSource = IconSource(s"$prefix/Antenna") - val Window: IconSource = IconSource(s"$prefix/Window") - val Tiers: IconSource = IconSource(s"$prefix/Tiers") - val LinesHorizontal: IconSource = IconSource(s"$prefix/LinesHorizontal") - val ArrowRight: IconSource = IconSource(s"$prefix/ArrowRight") - val Book: IconSource = IconSource(s"$prefix/Book") - val Help: IconSource = IconSource(s"$prefix/Help") - val Ocelot: IconSource = IconSource(s"$prefix/Ocelot") - val Guitar: IconSource = IconSource(s"$prefix/Guitar") - val Keyboard: IconSource = IconSource(s"$prefix/Keyboard") - val KeyboardOff: IconSource = IconSource(s"$prefix/KeyboardOff") - val ButtonRandomize: IconSource = IconSource(s"$prefix/ButtonRandomize") - val ButtonClipboard: IconSource = IconSource(s"$prefix/ButtonClipboard") - val ButtonCheck: IconSource = IconSource(s"$prefix/ButtonCheck") - val Home: IconSource = IconSource(s"$prefix/Home") - val Pin: IconSource = IconSource(s"$prefix/Pin") - val Unpin: IconSource = IconSource(s"$prefix/Unpin") - val Close: IconSource = IconSource(s"$prefix/Close") - val Grid: IconSource = IconSource(s"$prefix/Grid") - val GridOff: IconSource = IconSource(s"$prefix/GridOff") + val NA: IconSource = get("NA") + val SettingsKeymap: IconSource = get("SettingsKeymap") + val SettingsSystem: IconSource = get("SettingsSystem") + val SettingsSound: IconSource = get("SettingsSound") + val SettingsUI: IconSource = get("SettingsUI") + val Delete: IconSource = get("Delete") + val Label: IconSource = get("Label") + val Copy: IconSource = get("Copy") + val AspectRatio: IconSource = get("AspectRatio") + val Eject: IconSource = get("Eject") + val Restart: IconSource = get("Restart") + val Edit: IconSource = get("Edit") + val Folder: IconSource = get("Folder") + val FolderSlash: IconSource = get("FolderSlash") + val Code: IconSource = get("Code") + val File: IconSource = get("File") + val Link: IconSource = get("Link") + val LinkSlash: IconSource = get("LinkSlash") + val Power: IconSource = get("Power") + val Save: IconSource = get("Save") + val SaveAs: IconSource = get("SaveAs") + val Plus: IconSource = get("Plus") + val Cross: IconSource = get("Cross") + val Microchip: IconSource = get("Microchip") + val Antenna: IconSource = get("Antenna") + val Window: IconSource = get("Window") + val Tiers: IconSource = get("Tiers") + val LinesHorizontal: IconSource = get("LinesHorizontal") + val ArrowRight: IconSource = get("ArrowRight") + val Book: IconSource = get("Book") + val Help: IconSource = get("Help") + val Ocelot: IconSource = get("Ocelot") + val Guitar: IconSource = get("Guitar") + val Keyboard: IconSource = get("Keyboard") + val KeyboardOff: IconSource = get("KeyboardOff") + val ButtonRandomize: IconSource = get("ButtonRandomize") + val ButtonClipboard: IconSource = get("ButtonClipboard") + val ButtonCheck: IconSource = get("ButtonCheck") + val Home: IconSource = get("Home") + val Pin: IconSource = get("Pin") + val Unpin: IconSource = get("Unpin") + val Close: IconSource = get("Close") + val Grid: IconSource = get("Grid") + val GridOff: IconSource = get("GridOff") + val LMB: IconSource = get("LMB") + val RMB: IconSource = get("RMB") + val DragLMB: IconSource = get("DragLMB") + val DragRMB: IconSource = get("DragRMB") + + val WireArrowLeft: IconSource = get("WireArrowLeft") + val WireArrowRight: IconSource = get("WireArrowRight") + + val WaveSine: IconSource = get("WaveSine") + val WaveTriangle: IconSource = get("WaveTriangle") + val WaveSawtooth: IconSource = get("WaveSawtooth") + val WaveSquare: IconSource = get("WaveSquare") + val WaveNoise: IconSource = get("WaveNoise") + val WaveLFSR: IconSource = get("WaveLFSR") } - // ----------------------- Node icons ----------------------- + object Nodes extends IconScope("nodes") { + val NewNode: IconSource = get("NewNode") - val NA: IconSource = IconSource("icons/NA") - - object Nodes { - val NewNode: IconSource = IconSource("nodes/NewNode") - - val Cable: IconSource = IconSource("nodes/Cable") - val Camera: IconSource = IconSource("nodes/Camera") - val Chest: IconSource = IconSource("nodes/Chest") + val Cable: IconSource = get("Cable") + val Camera: IconSource = get("Camera") + val Chest: IconSource = get("Chest") val HologramProjector: Tier => IconSource = { tier => - IconSource(s"nodes/HologramProjector${tier.id}") + get(s"HologramProjector${tier.id}") } - val IronNoteBlock: IconSource = IconSource("nodes/IronNoteBlock") - val NoteBlock: IconSource = IconSource("nodes/NoteBlock") - val OpenFMRadio: IconSource = IconSource("nodes/OpenFMRadio") - val Relay: IconSource = IconSource("nodes/Relay") - val TapeDrive: IconSource = IconSource("nodes/TapeDrive") + val IronNoteBlock: IconSource = get("IronNoteBlock") + val NoteBlock: IconSource = get("NoteBlock") + val OpenFMRadio: IconSource = get("OpenFMRadio") + val Relay: IconSource = get("Relay") + val TapeDrive: IconSource = get("TapeDrive") - object Computer extends PowerIconSource with DiskActivityIconSource { - override protected def prefix: String = "nodes/computer" + val Lamp: IconSource = get("Lamp") + val LampFrame: IconSource = get("LampFrame") + val LampGlow: IconSource = get("LampGlow") - val Default: IconSource = IconSource(s"$prefix/Default") + object Computer extends IconScope("computer") with PowerIconSource with DiskActivityIconSource { + val Default: IconSource = get("Default") } - object DiskDrive extends DiskActivityIconSource with FloppyDriveIconSource { - override protected def prefix: String = "nodes/disk-drive" - - val Default: IconSource = IconSource(s"$prefix/Default") + object DiskDrive extends IconScope("disk-drive") with DiskActivityIconSource with FloppyDriveIconSource { + val Default: IconSource = get("Default") } - object Lamp extends IconSource("nodes/Lamp") { - val Frame: IconSource = IconSource("nodes/LampFrame") - val Glow: IconSource = IconSource("nodes/LampGlow") + object Microcontroller extends IconScope("microcontroller") with PowerIconSource { + val Default: IconSource = get("Default") } - object Microcontroller extends PowerIconSource { - override protected def prefix: String = "nodes/microcontroller" - - val Default: IconSource = IconSource(s"$prefix/Default") - } - - object OcelotBlock { - val Default: IconSource = IconSource( - "nodes/ocelot-block/Default", - animation = Some(Animation(Size2D(16, 16), (0, 30f), (1, 5f), (2, 2f), (0, 20f), (3, 3f), (4, 2f))), + object OcelotBlock extends IconScope("ocelot-block") { + val Default: IconSource = get( + "Default", + Some(Animation(Size2D(16, 16))((0, 30f), (1, 5f), (2, 2f), (0, 20f), (3, 3f), (4, 2f))), ) - val Rx: IconSource = IconSource("nodes/ocelot-block/Rx") - val Tx: IconSource = IconSource("nodes/ocelot-block/Tx") + val Rx: IconSource = get("Rx") + val Tx: IconSource = get("Tx") } - object Rack { - protected val prefix: String = "nodes/rack" - - val Empty: IconSource = IconSource(s"$prefix/Empty") - val Default: IconSource = IconSource(s"$prefix/Default") + object Rack extends IconScope("rack") { + val Empty: IconSource = get("Empty") + val Default: IconSource = get("Default") val Server: Array[Server] = Array.tabulate(4)(new Server(_)) val Drive: Array[Drive] = Array.tabulate(4)(new Drive(_)) - class Server(val slot: Int) extends PowerIconSource with DiskActivityIconSource with NetworkActivityIconSource { - override protected def prefix: String = s"${Rack.prefix}/server/$slot" + class Server(val slot: Int) + extends IconScope(s"server/$slot") + with PowerIconSource + with DiskActivityIconSource + with NetworkActivityIconSource { - val Default: IconSource = IconSource(s"$prefix/Default") + val Default: IconSource = get("Default") } - class Drive(val slot: Int) extends DiskActivityIconSource with FloppyDriveIconSource { - override protected def prefix: String = s"${Rack.prefix}/drive/$slot" + class Drive(val slot: Int) + extends IconScope(s"drive/$slot") + with DiskActivityIconSource + with FloppyDriveIconSource { - val Default: IconSource = IconSource(s"$prefix/Default") + val Default: IconSource = get("Default") } } - object Raid { - protected val prefix: String = "nodes/raid" - - val Default: IconSource = IconSource(s"$prefix/Default") + object Raid extends IconScope("raid") { + val Default: IconSource = get("Default") val Drive: Array[Drive] = Array.tabulate(3)(new Drive(_)) - class Drive(val slot: Int) extends DiskActivityIconSource { - override protected def prefix: String = s"${Raid.prefix}/$slot" - - val Error: IconSource = IconSource(s"$prefix/Error") + class Drive(val slot: Int) extends IconScope(slot.toString) with DiskActivityIconSource { + val Error: IconSource = get("Error") } } - object Screen { - protected val prefix: String = "nodes/screen" + object Screen extends IconScope("screen") { + val Standalone: IconSource = get("Standalone") + val PowerOnOverlay: IconSource = get("PowerOnOverlay") - val Standalone: IconSource = IconSource(s"$prefix/Standalone") - val PowerOnOverlay: IconSource = IconSource(s"$prefix/PowerOnOverlay") + val ColumnTop: IconSource = get("ColumnTop") + val ColumnMiddle: IconSource = get("ColumnMiddle") + val ColumnBottom: IconSource = get("ColumnBottom") - val ColumnTop: IconSource = IconSource(s"$prefix/ColumnTop") - val ColumnMiddle: IconSource = IconSource(s"$prefix/ColumnMiddle") - val ColumnBottom: IconSource = IconSource(s"$prefix/ColumnBottom") + val RowLeft: IconSource = get("RowLeft") + val RowMiddle: IconSource = get("RowMiddle") + val RowRight: IconSource = get("RowRight") - val RowLeft: IconSource = IconSource(s"$prefix/RowLeft") - val RowMiddle: IconSource = IconSource(s"$prefix/RowMiddle") - val RowRight: IconSource = IconSource(s"$prefix/RowRight") + val TopLeft: IconSource = get("TopLeft") + val TopMiddle: IconSource = get("TopMiddle") + val TopRight: IconSource = get("TopRight") - val TopLeft: IconSource = IconSource(s"$prefix/TopLeft") - val TopMiddle: IconSource = IconSource(s"$prefix/TopMiddle") - val TopRight: IconSource = IconSource(s"$prefix/TopRight") + val MiddleLeft: IconSource = get("MiddleLeft") + val Middle: IconSource = get("Middle") + val MiddleRight: IconSource = get("MiddleRight") - val MiddleLeft: IconSource = IconSource(s"$prefix/MiddleLeft") - val Middle: IconSource = IconSource(s"$prefix/Middle") - val MiddleRight: IconSource = IconSource(s"$prefix/MiddleRight") - - val BottomLeft: IconSource = IconSource(s"$prefix/BottomLeft") - val BottomMiddle: IconSource = IconSource(s"$prefix/BottomMiddle") - val BottomRight: IconSource = IconSource(s"$prefix/BottomRight") + val BottomLeft: IconSource = get("BottomLeft") + val BottomMiddle: IconSource = get("BottomMiddle") + val BottomRight: IconSource = get("BottomRight") } - object Holidays { - protected val prefix: String = "nodes/holidays" - - val Christmas: IconSource = IconSource(s"$prefix/Christmas") - val Valentines: IconSource = IconSource(s"$prefix/Valentines") - val Halloween: IconSource = IconSource(s"$prefix/Halloween") + object Holidays extends IconScope("holidays") { + val Christmas: IconSource = get("Christmas") + val Valentines: IconSource = get("Valentines") + val Halloween: IconSource = get("Halloween") } } - trait PowerIconSource { - protected def prefix: String - - val On: IconSource = IconSource(s"$prefix/On") - val Error: IconSource = IconSource(s"$prefix/Error") + trait PowerIconSource extends IconScope { + val On: IconSource = get("On") + val Error: IconSource = get("Error") } - trait DiskActivityIconSource { - protected def prefix: String - - val DiskActivity: IconSource = IconSource(s"$prefix/DiskActivity") + trait DiskActivityIconSource extends IconScope { + val DiskActivity: IconSource = get("DiskActivity") } - trait NetworkActivityIconSource { - protected def prefix: String - - val NetworkActivity: IconSource = IconSource(s"$prefix/NetworkActivity") + trait NetworkActivityIconSource extends IconScope { + val NetworkActivity: IconSource = get("NetworkActivity") } - trait FloppyDriveIconSource { - protected def prefix: String - - val Floppy: IconSource = IconSource(s"$prefix/Floppy") + trait FloppyDriveIconSource extends IconScope { + val Floppy: IconSource = get("Floppy") } - object Screen { - protected val prefix: String = "screen" + object Screen extends IconScope("screen") { + val InnerCornerTL: IconSource = get("InnerCornerTL") + val InnerCornerTR: IconSource = get("InnerCornerTR") + val InnerCornerBL: IconSource = get("InnerCornerBL") + val InnerCornerBR: IconSource = get("InnerCornerBR") - val InnerCornerTL: IconSource = IconSource(s"$prefix/InnerCornerTL") - val InnerCornerTR: IconSource = IconSource(s"$prefix/InnerCornerTR") - val InnerCornerBL: IconSource = IconSource(s"$prefix/InnerCornerBL") - val InnerCornerBR: IconSource = IconSource(s"$prefix/InnerCornerBR") + val OuterCornerTL: IconSource = get("OuterCornerTL") + val OuterCornerTR: IconSource = get("OuterCornerTR") + val OuterCornerBL: IconSource = get("OuterCornerBL") + val OuterCornerBR: IconSource = get("OuterCornerBR") - val OuterCornerTL: IconSource = IconSource(s"$prefix/OuterCornerTL") - val OuterCornerTR: IconSource = IconSource(s"$prefix/OuterCornerTR") - val OuterCornerBL: IconSource = IconSource(s"$prefix/OuterCornerBL") - val OuterCornerBR: IconSource = IconSource(s"$prefix/OuterCornerBR") + val InnerBorderT: IconSource = get("InnerBorderT") + val OuterBorderT: IconSource = get("OuterBorderT") - val InnerBorderT: IconSource = IconSource(s"$prefix/InnerBorderT") - val OuterBorderT: IconSource = IconSource(s"$prefix/OuterBorderT") - - val InnerBorderB: IconSource = IconSource(s"$prefix/InnerBorderB") + val InnerBorderB: IconSource = get("InnerBorderB") } - // ----------------------- Particles ----------------------- - - object Particles { - protected val prefix: String = "particles" - - val Smoke: IconSource = IconSource(s"$prefix/Smoke") + object Particles extends IconScope("particles") { + val Note: IconSource = get("Note") + val Smoke: IconSource = get("Smoke") } - // ----------------------- Buttons ----------------------- + object Buttons extends IconScope("buttons") { + val BottomDrawerOpen: IconSource = get("BottomDrawerOpen") + val BottomDrawerClose: IconSource = get("BottomDrawerClose") - object Buttons { - protected val prefix: String = "buttons" - - val BottomDrawerOpen: IconSource = IconSource(s"$prefix/BottomDrawerOpen") - val BottomDrawerClose: IconSource = IconSource(s"$prefix/BottomDrawerClose") - - val PowerOff: IconSource = IconSource(s"$prefix/PowerOff") - val PowerOn: IconSource = IconSource(s"$prefix/PowerOn") + val PowerOff: IconSource = get("PowerOff") + val PowerOn: IconSource = get("PowerOn") val OpenFMRadioVolumeOff: Boolean => IconSource = { isUp => - IconSource(s"$prefix/OpenFMRadioVolume${if (isUp) "Up" else "Down"}Off") + get(s"OpenFMRadioVolume${if (isUp) "Up" else "Down"}Off") } val OpenFMRadioVolumeOn: Boolean => IconSource = { isUp => - IconSource(s"$prefix/OpenFMRadioVolume${if (isUp) "Up" else "Down"}On") + get(s"OpenFMRadioVolume${if (isUp) "Up" else "Down"}On") } - val OpenFMRadioRedstoneOff: IconSource = IconSource(s"$prefix/OpenFMRadioRedstoneOff") - val OpenFMRadioRedstoneOn: IconSource = IconSource(s"$prefix/OpenFMRadioRedstoneOn") + val OpenFMRadioRedstoneOff: IconSource = get("OpenFMRadioRedstoneOff") + val OpenFMRadioRedstoneOn: IconSource = get("OpenFMRadioRedstoneOn") - val OpenFMRadioCloseOff: IconSource = IconSource(s"$prefix/OpenFMRadioCloseOff") - val OpenFMRadioCloseOn: IconSource = IconSource(s"$prefix/OpenFMRadioCloseOn") + val OpenFMRadioCloseOff: IconSource = get("OpenFMRadioCloseOff") + val OpenFMRadioCloseOn: IconSource = get("OpenFMRadioCloseOn") - val OpenFMRadioStartOff: IconSource = IconSource(s"$prefix/OpenFMRadioStartOff") - val OpenFMRadioStopOn: IconSource = IconSource(s"$prefix/OpenFMRadioStopOn") + val OpenFMRadioStartOff: IconSource = get("OpenFMRadioStartOff") + val OpenFMRadioStopOn: IconSource = get("OpenFMRadioStopOn") - val RackRelayOff: IconSource = IconSource(s"$prefix/RackRelayOff") - val RackRelayOn: IconSource = IconSource(s"$prefix/RackRelayOn") + val RackRelayOff: IconSource = get("RackRelayOff") + val RackRelayOn: IconSource = get("RackRelayOn") } - // ----------------------- Window icons ----------------------- + object Window extends IconScope("window") { + val CornerTL: IconSource = get("CornerTL") + val CornerTR: IconSource = get("CornerTR") + val CornerBL: IconSource = get("CornerBL") + val CornerBR: IconSource = get("CornerBR") - object Window { - protected val prefix: String = "window" - - object Tape { - protected val prefix: String = s"${Window.prefix}/tape" + val BorderLight: IconSource = get("BorderLight") + val BorderDark: IconSource = get("BorderDark") + object Tape extends IconScope("tape") { abstract class TapeButtonIconSource private[Tape] (sprite: String) { - val Released: IconSource = IconSource(s"$prefix/$sprite") - val Pressed: IconSource = IconSource(s"$prefix/${sprite}Pressed") + val Released: IconSource = get(sprite) + val Pressed: IconSource = get(s"${sprite}Pressed") } object Back extends TapeButtonIconSource("Back") object Play extends TapeButtonIconSource("Play") object Stop extends TapeButtonIconSource("Stop") object Forward extends TapeButtonIconSource("Forward") + + val Screen: IconSource = get("Screen") } + + object Case extends IconScope("case") { + val Motherboard: IconSource = get("Motherboard") + } + + object Rack extends IconScope("rack") { + val Motherboard: IconSource = get("Motherboard") + val Lines: IconSource = get("Lines") + + trait DirectionIconSource { + protected def iconPrefix: String + + val DirectionIcon: Direction => IconSource = { direction => + get(s"$iconPrefix${direction.side.capitalize}") + } + } + + trait ConnectorIconSource { + protected def iconPrefix: String + + val Connector: IconSource = get(s"${iconPrefix}Connector") + } + + object Side extends DirectionIconSource with ConnectorIconSource { + override protected def iconPrefix: String = "Side" + } + + object Network extends DirectionIconSource with ConnectorIconSource { + override protected def iconPrefix: String = "Network" + } + + object Node extends DirectionIconSource { + override protected def iconPrefix: String = "Node" + } + } + + object Raid extends IconScope("raid") { + val Slots: IconSource = get("Slots") + } + + val OpenFMRadio: IconSource = get("OpenFMRadio") + } + + object Panel extends IconScope("panel") { + val CornerTL: IconSource = get("CornerTL") + val CornerTR: IconSource = get("CornerTR") + val CornerBL: IconSource = get("CornerBL") + val CornerBR: IconSource = get("CornerBR") + + val BorderT: IconSource = get("BorderT") + val BorderB: IconSource = get("BorderB") + val BorderL: IconSource = get("BorderL") + val BorderR: IconSource = get("BorderR") + + val Fill: IconSource = get("Fill") + } + + object LightPanel extends IconScope("light-panel") { + val CornerTL: IconSource = get("CornerTL") + val CornerTR: IconSource = get("CornerTR") + val CornerBL: IconSource = get("CornerBL") + val CornerBR: IconSource = get("CornerBR") + + val BorderT: IconSource = get("BorderT") + val BorderB: IconSource = get("BorderB") + val BorderL: IconSource = get("BorderL") + val BorderR: IconSource = get("BorderR") + + val Fill: IconSource = get("Fill") + val Vent: IconSource = get("Vent") + + val BookmarkLeft: IconSource = get("BookmarkLeft") + val BookmarkRight: IconSource = get("BookmarkRight") } } diff --git a/src/main/scala/ocelot/desktop/node/BoomCardFxHandler.scala b/src/main/scala/ocelot/desktop/node/BoomCardFxHandler.scala index 9a5cf0c..4e110ee 100644 --- a/src/main/scala/ocelot/desktop/node/BoomCardFxHandler.scala +++ b/src/main/scala/ocelot/desktop/node/BoomCardFxHandler.scala @@ -82,7 +82,7 @@ trait BoomCardFxHandler extends Node with PositionalSoundSourcesNode with SmokeP } g.sprite( - IconSource.Nodes.Lamp.Glow, + IconSource.Nodes.LampGlow, position - size * glowSize, size * (1 + 2 * glowSize), ColorScheme("BoomCardGlowStart").lerp(ColorScheme("BoomCardGlowEnd"), boomPhase).withAlpha(alpha), diff --git a/src/main/scala/ocelot/desktop/node/Node.scala b/src/main/scala/ocelot/desktop/node/Node.scala index 36e19b0..1734cce 100644 --- a/src/main/scala/ocelot/desktop/node/Node.scala +++ b/src/main/scala/ocelot/desktop/node/Node.scala @@ -104,11 +104,11 @@ abstract class Node extends Widget with MouseHandler with HoverHandler with Pers super.update() if (isHovered || isMoving) { - root.get.statusBar.addMouseEntry("icons/RMB", "Menu") - root.get.statusBar.addMouseEntry("icons/DragLMB", "Move node") + root.get.statusBar.addMouseEntry(IconSource.Icons.RMB, "Menu") + root.get.statusBar.addMouseEntry(IconSource.Icons.DragLMB, "Move node") if (ports.nonEmpty) { - root.get.statusBar.addMouseEntry("icons/DragRMB", "Connect/Disconnect") + root.get.statusBar.addMouseEntry(IconSource.Icons.DragRMB, "Connect/Disconnect") } } } @@ -119,7 +119,7 @@ abstract class Node extends Widget with MouseHandler with HoverHandler with Pers super.dispose() } - def iconSource: IconSource = IconSource.NA + def icon: IconSource = IconSource.Icons.NA def iconColor: Color = RGBAColor(255, 255, 255) @@ -263,13 +263,12 @@ abstract class Node extends Widget with MouseHandler with HoverHandler with Pers drawHighlight(g) g.sprite( - iconSource.path, + icon, position.x + HighlightThickness, position.y + HighlightThickness, size.width - HighlightThickness * 2, size.height - HighlightThickness * 2, iconColor, - iconSource.animation, ) } diff --git a/src/main/scala/ocelot/desktop/node/NodeTypeWidget.scala b/src/main/scala/ocelot/desktop/node/NodeTypeWidget.scala index 641a675..0f5e9e3 100644 --- a/src/main/scala/ocelot/desktop/node/NodeTypeWidget.scala +++ b/src/main/scala/ocelot/desktop/node/NodeTypeWidget.scala @@ -2,7 +2,7 @@ package ocelot.desktop.node import ocelot.desktop.color.Color import ocelot.desktop.geometry.Size2D -import ocelot.desktop.graphics.Graphics +import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.node.Node.Size import ocelot.desktop.ui.event.handlers.{HoverHandler, MouseHandler} import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent} @@ -39,20 +39,19 @@ class NodeTypeWidget(val nodeType: NodeType) extends Widget with MouseHandler wi val size = Spritesheet.spriteSize(nodeType.icon) * 4 g.sprite( - nodeType.icon.path, + nodeType.icon, position.x + Size / 2 - size.width / 2, position.y + Size / 2 - size.height / 2, size.width, size.height, nodeType.tier.map(TierColor.get).getOrElse(Color.White), - nodeType.icon.animation, ) } override def update(): Unit = { super.update() if (isHovered) { - root.get.statusBar.addMouseEntry("icons/LMB", "Add node") + root.get.statusBar.addMouseEntry(IconSource.Icons.LMB, "Add node") } } } diff --git a/src/main/scala/ocelot/desktop/node/ShiftClickNode.scala b/src/main/scala/ocelot/desktop/node/ShiftClickNode.scala index 3293c64..d39e02d 100644 --- a/src/main/scala/ocelot/desktop/node/ShiftClickNode.scala +++ b/src/main/scala/ocelot/desktop/node/ShiftClickNode.scala @@ -1,5 +1,6 @@ package ocelot.desktop.node +import ocelot.desktop.graphics.IconSource import ocelot.desktop.ui.event.sources.KeyEvents import ocelot.desktop.ui.event.{ClickEvent, MouseEvent} @@ -22,6 +23,6 @@ trait ShiftClickNode extends Node { super.update() if (isHovered || isMoving) - root.get.statusBar.addKeyMouseEntry("icons/LMB", "SHIFT", hoveredShiftStatusBarText) + root.get.statusBar.addKeyMouseEntry(IconSource.Icons.LMB, "SHIFT", hoveredShiftStatusBarText) } } diff --git a/src/main/scala/ocelot/desktop/node/SmokeParticleNode.scala b/src/main/scala/ocelot/desktop/node/SmokeParticleNode.scala index bcb70a5..f92ee42 100644 --- a/src/main/scala/ocelot/desktop/node/SmokeParticleNode.scala +++ b/src/main/scala/ocelot/desktop/node/SmokeParticleNode.scala @@ -43,10 +43,10 @@ trait SmokeParticleNode extends Node { SmokeParticleSize.width, SmokeParticleSize.height, color, - spriteRect.copy( + Some(spriteRect.copy( y = spriteRect.y + animationFrame * spriteRect.w, h = spriteRect.w, - ), + )), ) } } diff --git a/src/main/scala/ocelot/desktop/node/WindowedNode.scala b/src/main/scala/ocelot/desktop/node/WindowedNode.scala index a09e05c..caa80a3 100644 --- a/src/main/scala/ocelot/desktop/node/WindowedNode.scala +++ b/src/main/scala/ocelot/desktop/node/WindowedNode.scala @@ -1,9 +1,9 @@ package ocelot.desktop.node +import ocelot.desktop.graphics.IconSource import ocelot.desktop.ui.event.sources.KeyEvents import ocelot.desktop.ui.event.{ClickEvent, MouseEvent} import ocelot.desktop.ui.widget.window.{Window, Windowed} -import org.lwjgl.input.Keyboard trait WindowedNode[T <: Window] extends Node with Windowed[T] { override def dispose(): Unit = { @@ -14,7 +14,7 @@ trait WindowedNode[T <: Window] extends Node with Windowed[T] { override def update(): Unit = { if (isHovered || isMoving) - root.get.statusBar.addMouseEntry("icons/LMB", if (windowCreated && window.isOpen) "Close" else "Open") + root.get.statusBar.addMouseEntry(IconSource.Icons.LMB, if (windowCreated && window.isOpen) "Close" else "Open") super.update() } diff --git a/src/main/scala/ocelot/desktop/node/nodes/CableNode.scala b/src/main/scala/ocelot/desktop/node/nodes/CableNode.scala index 4f59e24..f3c8e34 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/CableNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/CableNode.scala @@ -6,7 +6,7 @@ import ocelot.desktop.node.EntityNode import totoro.ocelot.brain.entity.Cable class CableNode(val cable: Cable) extends EntityNode(cable) { - override def iconSource: IconSource = IconSource.Nodes.Cable + override def icon: IconSource = IconSource.Nodes.Cable override def rotatable: Boolean = false diff --git a/src/main/scala/ocelot/desktop/node/nodes/CameraNode.scala b/src/main/scala/ocelot/desktop/node/nodes/CameraNode.scala index a4d95f3..8ef7562 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/CameraNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/CameraNode.scala @@ -6,7 +6,7 @@ import ocelot.desktop.node.{EntityNode, LabeledEntityNode, WindowedNode} import ocelot.desktop.windows.CameraWindow class CameraNode(val camera: Camera) extends EntityNode(camera) with LabeledEntityNode with WindowedNode[CameraWindow] { - override def iconSource: IconSource = IconSource.Nodes.Camera + override def icon: IconSource = IconSource.Nodes.Camera override def rotatable: Boolean = true diff --git a/src/main/scala/ocelot/desktop/node/nodes/ChestNode.scala b/src/main/scala/ocelot/desktop/node/nodes/ChestNode.scala index 59e5e33..6ccaba3 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/ChestNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/ChestNode.scala @@ -10,7 +10,7 @@ import ocelot.desktop.windows.ChestWindow class ChestNode extends LabeledNode with WindowedNode[ChestWindow] with PersistedInventory { override type I = Item with PersistableItem - override def iconSource: IconSource = IconSource.Nodes.Chest + override def icon: IconSource = IconSource.Nodes.Chest override def rotatable: Boolean = false diff --git a/src/main/scala/ocelot/desktop/node/nodes/ColorfulLampNode.scala b/src/main/scala/ocelot/desktop/node/nodes/ColorfulLampNode.scala index 73afe77..a4182bb 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/ColorfulLampNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/ColorfulLampNode.scala @@ -24,12 +24,12 @@ class ColorfulLampNode(val lamp: ColorfulLamp) extends EntityNode(lamp) with Lab ) g.rect(position.x + 2, position.y + 2, size.width - 4, size.height - 4, lastColor) - g.sprite(IconSource.Nodes.Lamp.Frame, position.x + 2, position.y + 2, size.width - 4, size.height - 4) + g.sprite(IconSource.Nodes.LampFrame, position.x + 2, position.y + 2, size.width - 4, size.height - 4) } override def drawLight(g: Graphics): Unit = { super.drawLight(g) - g.sprite(IconSource.Nodes.Lamp.Glow, position - size / 2, size * 2, lastColor) + g.sprite(IconSource.Nodes.LampGlow, position - size / 2, size * 2, lastColor) } eventHandlers += { diff --git a/src/main/scala/ocelot/desktop/node/nodes/ComputerNode.scala b/src/main/scala/ocelot/desktop/node/nodes/ComputerNode.scala index 3ee9500..b6b64ed 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/ComputerNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/ComputerNode.scala @@ -20,7 +20,7 @@ class ComputerNode(val computerCase: Case) with AudibleComputerAware with WindowedNode[ComputerWindow] { - override val iconSource: IconSource = IconSource.Nodes.Computer.Default + override val icon: IconSource = IconSource.Nodes.Computer.Default override def iconColor: Color = TierColor.get(computerCase.tier) override def rotatable: Boolean = true diff --git a/src/main/scala/ocelot/desktop/node/nodes/DiskDriveNode.scala b/src/main/scala/ocelot/desktop/node/nodes/DiskDriveNode.scala index 2025a41..2f629cf 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/DiskDriveNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/DiskDriveNode.scala @@ -21,7 +21,7 @@ class DiskDriveNode(entity: FloppyDiskDrive) with ShiftClickNode with WindowedNode[DiskDriveWindow] { - override def iconSource: IconSource = IconSource.Nodes.DiskDrive.Default + override def icon: IconSource = IconSource.Nodes.DiskDrive.Default override def rotatable: Boolean = true diff --git a/src/main/scala/ocelot/desktop/node/nodes/HologramProjectorNode.scala b/src/main/scala/ocelot/desktop/node/nodes/HologramProjectorNode.scala index 23b7d36..9a61ff7 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/HologramProjectorNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/HologramProjectorNode.scala @@ -8,7 +8,7 @@ import totoro.ocelot.brain.entity.HologramProjector class HologramProjectorNode(val hologramProjector: HologramProjector) extends EntityNode(hologramProjector) with LabeledEntityNode with WindowedNode[HologramProjectorWindow] { - override def iconSource: IconSource = IconSource.Nodes.HologramProjector(hologramProjector.tier) + override def icon: IconSource = IconSource.Nodes.HologramProjector(hologramProjector.tier) override def rotatable: Boolean = false diff --git a/src/main/scala/ocelot/desktop/node/nodes/IronNoteBlockNode.scala b/src/main/scala/ocelot/desktop/node/nodes/IronNoteBlockNode.scala index 13f7f91..2d4999e 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/IronNoteBlockNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/IronNoteBlockNode.scala @@ -9,7 +9,7 @@ import totoro.ocelot.brain.event.{EventBus, NoteBlockTriggerEvent} import scala.util.Random class IronNoteBlockNode(val ironNoteBlock: IronNoteBlock) extends NoteBlockNodeBase(ironNoteBlock) { - override def iconSource: IconSource = IconSource.Nodes.IronNoteBlock + override def icon: IconSource = IconSource.Nodes.IronNoteBlock override def rotatable: Boolean = false diff --git a/src/main/scala/ocelot/desktop/node/nodes/MicrocontrollerNode.scala b/src/main/scala/ocelot/desktop/node/nodes/MicrocontrollerNode.scala index 5dc62f9..b12368a 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/MicrocontrollerNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/MicrocontrollerNode.scala @@ -21,7 +21,7 @@ class MicrocontrollerNode(val microcontroller: Microcontroller) with DefaultSlotItemsFillable with WindowedNode[ComputerWindow] { - override val iconSource: IconSource = IconSource.Nodes.Microcontroller.Default + override val icon: IconSource = IconSource.Nodes.Microcontroller.Default override def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = { addPowerContextMenuEntries(menu) diff --git a/src/main/scala/ocelot/desktop/node/nodes/NoteBlockNode.scala b/src/main/scala/ocelot/desktop/node/nodes/NoteBlockNode.scala index 5f9d676..aef4aa6 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/NoteBlockNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/NoteBlockNode.scala @@ -7,7 +7,7 @@ import totoro.ocelot.brain.entity.NoteBlock import totoro.ocelot.brain.event.{EventBus, NoteBlockTriggerEvent} class NoteBlockNode(val noteBlock: NoteBlock) extends NoteBlockNodeBase(noteBlock) { - override def iconSource: IconSource = IconSource.Nodes.NoteBlock + override def icon: IconSource = IconSource.Nodes.NoteBlock override def rotatable: Boolean = false diff --git a/src/main/scala/ocelot/desktop/node/nodes/NoteBlockNodeBase.scala b/src/main/scala/ocelot/desktop/node/nodes/NoteBlockNodeBase.scala index 84e7b91..e59c748 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/NoteBlockNodeBase.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/NoteBlockNodeBase.scala @@ -3,7 +3,7 @@ package ocelot.desktop.node.nodes import ocelot.desktop.ColorScheme import ocelot.desktop.audio.{SoundBuffers, SoundCategory, SoundSource} import ocelot.desktop.geometry.{Size2D, Vector2D} -import ocelot.desktop.graphics.Graphics +import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.node.{EntityNode, LabeledEntityNode} import ocelot.desktop.ui.UiHandler import ocelot.desktop.ui.event.BrainEvent @@ -27,15 +27,19 @@ abstract class NoteBlockNodeBase(entity: Entity with Environment) extends Entity override def update(): Unit = { super.update() if (isHovered || isMoving) { - root.get.statusBar.addMouseEntry("icons/LMB", "Play sample") + root.get.statusBar.addMouseEntry(IconSource.Icons.LMB, "Play sample") } } private class NoteParticle(pitch: Int) extends Particle(speed = 1.2f) { override def draw(g: Graphics): Unit = { val col = ColorScheme("Note" + pitch.min(24).max(0)).withAlpha(1 - (2 * time - 1).min(1).max(0)) - g.sprite("particles/Note", position + Vector2D(pitch / 24f * 40f + 5, height / 2 - 10 - 100 * time), - Size2D(14, 20), col) + g.sprite( + IconSource.Particles.Note, + position + Vector2D(pitch / 24f * 40f + 5, height / 2 - 10 - 100 * time), + Size2D(14, 20), + col, + ) } } } diff --git a/src/main/scala/ocelot/desktop/node/nodes/OcelotBlockNode.scala b/src/main/scala/ocelot/desktop/node/nodes/OcelotBlockNode.scala index 5d9fdf9..3d07fb0 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/OcelotBlockNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/OcelotBlockNode.scala @@ -22,7 +22,7 @@ class OcelotBlockNode(val ocelot: OcelotBlock) override def name: String = "Ocelot Block" - override def iconSource: IconSource = IconSource.Nodes.OcelotBlock.Default + override def icon: IconSource = IconSource.Nodes.OcelotBlock.Default override def rotatable: Boolean = false @@ -68,13 +68,12 @@ class OcelotBlockNode(val ocelot: OcelotBlock) if (alpha > 0) { g.sprite( - icon.path, + icon, position.x + HighlightThickness, position.y + HighlightThickness, size.width - HighlightThickness * 2, size.height - HighlightThickness * 2, RGBAColorNorm(1f, 1f, 1f, alpha), - icon.animation, ) } } diff --git a/src/main/scala/ocelot/desktop/node/nodes/OpenFMRadioNode.scala b/src/main/scala/ocelot/desktop/node/nodes/OpenFMRadioNode.scala index f4f3960..53b031b 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/OpenFMRadioNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/OpenFMRadioNode.scala @@ -9,7 +9,7 @@ import ocelot.desktop.windows.OpenFMRadioWindow class OpenFMRadioNode(val openFMRadio: OpenFMRadio) extends EntityNode(openFMRadio) with LabeledEntityNode with WindowedNode[OpenFMRadioWindow] { - override def iconSource: IconSource = IconSource.Nodes.OpenFMRadio + override def icon: IconSource = IconSource.Nodes.OpenFMRadio override def rotatable: Boolean = true diff --git a/src/main/scala/ocelot/desktop/node/nodes/RackNode.scala b/src/main/scala/ocelot/desktop/node/nodes/RackNode.scala index 19b8722..b332f3e 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/RackNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/RackNode.scala @@ -18,7 +18,7 @@ import totoro.ocelot.brain.network import totoro.ocelot.brain.util.Direction class RackNode(val rack: Rack) extends ComputerAwareNode(rack) with WindowedNode[RackWindow] { - override val iconSource: IconSource = IconSource.Nodes.Rack.Empty + override val icon: IconSource = IconSource.Nodes.Rack.Empty override def exposeAddress = false override def ports: Array[NodePort] = Array( diff --git a/src/main/scala/ocelot/desktop/node/nodes/RaidNode.scala b/src/main/scala/ocelot/desktop/node/nodes/RaidNode.scala index 97a82b6..23c56f1 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/RaidNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/RaidNode.scala @@ -27,7 +27,7 @@ class RaidNode(val raid: Raid) with WindowedNode[RaidWindow] { var diskSlots: Array[HddSlotWidget] = Array.tabulate(3)(index => new HddSlotWidget(Slot(index), Tier.Three)) - override val iconSource: IconSource = IconSource.Nodes.Raid.Default + override val icon: IconSource = IconSource.Nodes.Raid.Default override def rotatable: Boolean = true diff --git a/src/main/scala/ocelot/desktop/node/nodes/RelayNode.scala b/src/main/scala/ocelot/desktop/node/nodes/RelayNode.scala index b4440a2..36ecf84 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/RelayNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/RelayNode.scala @@ -11,7 +11,7 @@ import totoro.ocelot.brain.util.Direction class RelayNode(val relay: Relay) extends EntityNode(relay) with SyncedInventory with LabeledNode with WindowedNode[RelayWindow] { - override val iconSource: IconSource = IconSource.Nodes.Relay + override val icon: IconSource = IconSource.Nodes.Relay override def ports: Array[NodePort] = Array( NodePort(Some(Direction.North)), diff --git a/src/main/scala/ocelot/desktop/node/nodes/ScreenNode.scala b/src/main/scala/ocelot/desktop/node/nodes/ScreenNode.scala index b4f2065..9bfb6c1 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/ScreenNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/ScreenNode.scala @@ -91,7 +91,7 @@ class ScreenNode(val screen: Screen) } } - override def iconSource: IconSource = IconSource.Nodes.Screen.Standalone + override def icon: IconSource = IconSource.Nodes.Screen.Standalone override def iconColor: Color = TierColor.get(screen.tier) diff --git a/src/main/scala/ocelot/desktop/node/nodes/TapeDriveNode.scala b/src/main/scala/ocelot/desktop/node/nodes/TapeDriveNode.scala index 92cac49..3cdce38 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/TapeDriveNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/TapeDriveNode.scala @@ -18,7 +18,7 @@ class TapeDriveNode(val tapeDrive: TapeDrive) with PositionalSoundSourcesNode with WindowedNode[TapeDriveWindow] { - override def iconSource: IconSource = IconSource.Nodes.TapeDrive + override def icon: IconSource = IconSource.Nodes.TapeDrive override def rotatable: Boolean = true diff --git a/src/main/scala/ocelot/desktop/ui/widget/Histogram.scala b/src/main/scala/ocelot/desktop/ui/widget/Histogram.scala index be259a4..ce21bb0 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/Histogram.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/Histogram.scala @@ -2,7 +2,7 @@ package ocelot.desktop.ui.widget import ocelot.desktop.ColorScheme import ocelot.desktop.color.Color -import ocelot.desktop.graphics.Graphics +import ocelot.desktop.graphics.{Graphics, IconSource} import scala.collection.mutable.ArrayBuffer @@ -13,8 +13,8 @@ class Histogram extends Widget { private def drawBars(g: Graphics): Unit = { def drawBarSegment(i: Int, color: Color): Unit = { - g.sprite("BarSegment", position.x, position.y + i * 6, 16, 4, color) - g.sprite("BarSegment", position.x + 18, position.y + i * 6, 16, 4, color) + g.sprite(IconSource.BarSegment, position.x, position.y + i * 6, 16, 4, color) + g.sprite(IconSource.BarSegment, position.x + 18, position.y + i * 6, 16, 4, color) } val ratio = history.last diff --git a/src/main/scala/ocelot/desktop/ui/widget/Icon.scala b/src/main/scala/ocelot/desktop/ui/widget/Icon.scala index f796545..71532b8 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/Icon.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/Icon.scala @@ -17,16 +17,13 @@ class Icon(icon: IconSource, size: Size2D = null, private val color: Color = Col def iconColor: Color = color def iconSize: Size2D = { - if (size != null) size - else if (icon.animation.isDefined && icon.animation.get.frameSize.isDefined) - icon.animation.get.frameSize.get - else Spritesheet.spriteSize(icon.path) + Option(size).getOrElse(Spritesheet.spriteSize(icon)) } override def minimumSize: Size2D = iconSize override def maximumSize: Size2D = minimumSize override def draw(g: Graphics): Unit = { - g.sprite(icon.path, bounds.x, bounds.y, bounds.w, bounds.h, iconColor, icon.animation) + g.sprite(icon, bounds, iconColor) } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/Knob.scala b/src/main/scala/ocelot/desktop/ui/widget/Knob.scala index 74e9b48..e76c117 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/Knob.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/Knob.scala @@ -2,7 +2,7 @@ package ocelot.desktop.ui.widget import ocelot.desktop.color.{Color, IntColor} import ocelot.desktop.geometry.{Size2D, Vector2D} -import ocelot.desktop.graphics.Graphics +import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.ui.UiHandler import ocelot.desktop.ui.event.MouseEvent import totoro.ocelot.brain.util.DyeColor @@ -47,14 +47,14 @@ abstract class Knob(dyeColor: DyeColor = DyeColor.Red) extends Widget { } override def draw(g: Graphics): Unit = { - g.sprite("KnobLimits", position.x, position.y, 25, 25) + g.sprite(IconSource.KnobLimits, position.x, position.y, 25, 25) g.save() g.translate(position.x + 12.5f, position.y + 12.5f) g.rotate(input.toFloat / 15f * 4.71239f - 0.785398f) - g.sprite("Knob", -12.5f, -12.5f, 25, 25, color) + g.sprite(IconSource.Knob, -12.5f, -12.5f, 25, 25, color) g.restore() - g.sprite("KnobCenter", position.x, position.y, 25, 25) + g.sprite(IconSource.KnobCenter, position.x, position.y, 25, 25) val centerColor = color.toRGBANorm.copy(a = output / 15f) - g.sprite("KnobCenter", position.x - 1, position.y - 1, 27, 27, centerColor) + g.sprite(IconSource.KnobCenter, position.x - 1, position.y - 1, 27, 27, centerColor) } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/Viewport3DWidget.scala b/src/main/scala/ocelot/desktop/ui/widget/Viewport3DWidget.scala index 0256412..9c7c586 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/Viewport3DWidget.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/Viewport3DWidget.scala @@ -150,8 +150,8 @@ abstract class Viewport3DWidget extends Widget with MouseHandler with HoverHandl scene = createScene() if (isHovered) { - root.get.statusBar.addMouseEntry("icons/LMB", "Rotate view") - root.get.statusBar.addKeyMouseEntry("icons/LMB", "Shift", "Pan view") + root.get.statusBar.addMouseEntry(IconSource.Icons.LMB, "Rotate view") + root.get.statusBar.addKeyMouseEntry(IconSource.Icons.LMB, "SHIFT", "Pan view") } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/WorkspaceView.scala b/src/main/scala/ocelot/desktop/ui/widget/WorkspaceView.scala index fb29f7a..965ca88 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/WorkspaceView.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/WorkspaceView.scala @@ -574,7 +574,7 @@ class WorkspaceView extends Widget with Persistable with MouseHandler with Hover for (x <- 0 to numRepeatsX) { for (y <- 0 to numRepeatsY) { - g.sprite("BackgroundPattern", x.toFloat * 304, y.toFloat * 304, 304, 304) + g.sprite(IconSource.BackgroundPattern, x.toFloat * 304, y.toFloat * 304, 304, 304) } } @@ -660,11 +660,11 @@ class WorkspaceView extends Widget with Persistable with MouseHandler with Hover } if (isHovered && newConnection.isEmpty) { - if (nodeSelector.isClosed) - root.get.statusBar.addMouseEntry("icons/LMB", "Add node") - else - root.get.statusBar.addMouseEntry("icons/LMB", "Close selector") - root.get.statusBar.addMouseEntry("icons/DragLMB", "Move camera") + root.get.statusBar.addMouseEntry( + IconSource.Icons.LMB, + if (nodeSelector.isClosed) "Add node" else "Close selector", + ) + root.get.statusBar.addMouseEntry(IconSource.Icons.DragLMB, "Move camera") } } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/card/SoundCardWindow.scala b/src/main/scala/ocelot/desktop/ui/widget/card/SoundCardWindow.scala index 956b2cf..6b14431 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/card/SoundCardWindow.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/card/SoundCardWindow.scala @@ -3,7 +3,7 @@ package ocelot.desktop.ui.widget.card import ocelot.desktop.ColorScheme import ocelot.desktop.color.Color import ocelot.desktop.geometry.{Padding2D, Rect2D, Size2D, Vector2D} -import ocelot.desktop.graphics.Graphics +import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.ui.layout.{Layout, LinearLayout} import ocelot.desktop.ui.widget.card.SoundCardWindow._ import ocelot.desktop.ui.widget.window.{PanelWindow, Window} @@ -167,9 +167,9 @@ class SoundCardWindow(card: SoundCard) extends PanelWindow { g.line(b, Vector2D(mx, b.y), 2, col) if (b.x > px) { - g.sprite("icons/WireArrowRight", b.x - 4, b.y - 4, col) + g.sprite(IconSource.Icons.WireArrowRight, b.x - 4, b.y - 4, col) } else { - g.sprite("icons/WireArrowLeft", b.x, b.y - 4, col) + g.sprite(IconSource.Icons.WireArrowLeft, b.x, b.y - 4, col) } existingConnectors += Connector(column, colorIdx, from, to) @@ -275,12 +275,12 @@ object SoundCardWindow { } private val waves = Array( - ("icons/WaveSine", SignalGenerator.Sine.getClass), - ("icons/WaveTriangle", SignalGenerator.Triangle.getClass), - ("icons/WaveSawtooth", SignalGenerator.Sawtooth.getClass), - ("icons/WaveSquare", SignalGenerator.Square.getClass), - ("icons/WaveNoise", classOf[SignalGenerator.Noise]), - ("icons/WaveLFSR", classOf[SignalGenerator.LFSR]), + (IconSource.Icons.WaveSine, SignalGenerator.Sine.getClass), + (IconSource.Icons.WaveTriangle, SignalGenerator.Triangle.getClass), + (IconSource.Icons.WaveSawtooth, SignalGenerator.Sawtooth.getClass), + (IconSource.Icons.WaveSquare, SignalGenerator.Square.getClass), + (IconSource.Icons.WaveNoise, classOf[SignalGenerator.Noise]), + (IconSource.Icons.WaveLFSR, classOf[SignalGenerator.LFSR]), ) private def drawEnvelope(g: Graphics, env: ADSREnvelope, bounds: Rect2D, elapsedMs: Float): Unit = { @@ -445,21 +445,21 @@ object SoundCardWindow { val sh = (if (isFirst) 10 else 0) + (if (isLast) 50 else 0) h -= sh - g.sprite("light-panel/BorderL", x, y, 4, h) - g.sprite("light-panel/BorderR", x + w - 4, y, 4, h) - g.sprite("light-panel/Fill", x + 4, y, w - 8, h) + g.sprite(IconSource.LightPanel.BorderL, x, y, 4, h) + g.sprite(IconSource.LightPanel.BorderR, x + w - 4, y, 4, h) + g.sprite(IconSource.LightPanel.Fill, x + 4, y, w - 8, h) if (isFirst) { - g.sprite("light-panel/CornerTL", x, y - 4, 4, 4) - g.sprite("light-panel/CornerTR", x + w - 4, y - 4, 4, 4) - g.sprite("light-panel/BorderT", x + 4, y - 4, w - 8, 4) + g.sprite(IconSource.LightPanel.CornerTL, x, y - 4, 4, 4) + g.sprite(IconSource.LightPanel.CornerTR, x + w - 4, y - 4, 4, 4) + g.sprite(IconSource.LightPanel.BorderT, x + 4, y - 4, w - 8, 4) } if (isLast) { - g.sprite("light-panel/CornerBL", x, y + h, 4, 4) - g.sprite("light-panel/CornerBR", x + w - 4, y + h, 4, 4) - g.sprite("light-panel/BorderB", x + 4, y + h, w - 8, 4) - g.sprite("light-panel/Vent", x, y + h + 8, w, 38) + g.sprite(IconSource.LightPanel.CornerBL, x, y + h, 4, 4) + g.sprite(IconSource.LightPanel.CornerBR, x + w - 4, y + h, 4, 4) + g.sprite(IconSource.LightPanel.BorderB, x + 4, y + h, w - 8, 4) + g.sprite(IconSource.LightPanel.Vent, x, y + h + 8, w, 38) } for (i <- 0 until 6) { @@ -469,13 +469,13 @@ object SoundCardWindow { y -= sy h += sh - g.sprite("light-panel/BookmarkLeft", x, y + 16, 18, 14) - g.sprite("light-panel/BookmarkLeft", x, y + 32, 18, 14) - g.sprite("light-panel/BookmarkLeft", x, y + 48, 18, 14) + g.sprite(IconSource.LightPanel.BookmarkLeft, x, y + 16, 18, 14) + g.sprite(IconSource.LightPanel.BookmarkLeft, x, y + 32, 18, 14) + g.sprite(IconSource.LightPanel.BookmarkLeft, x, y + 48, 18, 14) - g.sprite("light-panel/BookmarkRight", x + w - 20, y + 16, 20, 14) - g.sprite("light-panel/BookmarkRight", x + w - 20, y + 32, 20, 14) - g.sprite("light-panel/BookmarkRight", x + w - 20, y + 48, 20, 14) + g.sprite(IconSource.LightPanel.BookmarkRight, x + w - 20, y + 16, 20, 14) + g.sprite(IconSource.LightPanel.BookmarkRight, x + w - 20, y + 32, 20, 14) + g.sprite(IconSource.LightPanel.BookmarkRight, x + w - 20, y + 48, 20, 14) g.setSmallFont() g.background = Color.Transparent diff --git a/src/main/scala/ocelot/desktop/ui/widget/help/AboutDialog.scala b/src/main/scala/ocelot/desktop/ui/widget/help/AboutDialog.scala index 3b4d364..53fae51 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/help/AboutDialog.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/help/AboutDialog.scala @@ -4,7 +4,7 @@ import buildinfo.BuildInfo import ocelot.desktop.ColorScheme import ocelot.desktop.color.Color import ocelot.desktop.geometry.{Padding2D, Size2D} -import ocelot.desktop.graphics.Graphics +import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.widget.{Button, Filler, Label, PaddingBox, Widget} import ocelot.desktop.ui.widget.modal.ModalDialog @@ -25,7 +25,7 @@ class AboutDialog extends ModalDialog { override def minimumSize: Size2D = Spritesheet.spriteSize("Logo") + 40 override def draw(g: Graphics): Unit = { - g.sprite("Logo", bounds.x + 20, bounds.y + 80, ColorScheme("AboutLogo")) + g.sprite(IconSource.Logo, bounds.x + 20, bounds.y + 80, ColorScheme("AboutLogo")) drawChildren(g) } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/slot/SlotWidget.scala b/src/main/scala/ocelot/desktop/ui/widget/slot/SlotWidget.scala index 3e740a7..355f553 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/slot/SlotWidget.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/slot/SlotWidget.scala @@ -230,7 +230,7 @@ class SlotWidget[I <: Item](private val slot: Inventory#Slot)(implicit slotItemT } override final def draw(g: Graphics): Unit = { - g.sprite("EmptySlot", bounds) + g.sprite(IconSource.EmptySlot, bounds) val iconBounds = bounds.inflated(-2) diff --git a/src/main/scala/ocelot/desktop/ui/widget/statusbar/KeyMouseEntry.scala b/src/main/scala/ocelot/desktop/ui/widget/statusbar/KeyMouseEntry.scala index 02fe05c..43440b9 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/statusbar/KeyMouseEntry.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/statusbar/KeyMouseEntry.scala @@ -3,11 +3,11 @@ 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.graphics.{Graphics, IconSource} import ocelot.desktop.ui.widget.Widget import ocelot.desktop.util.{DrawUtils, Spritesheet} -class KeyMouseEntry(val icon: String, val key: String, val text: String) extends Widget { +class KeyMouseEntry(val icon: IconSource, val key: String, val text: String) extends Widget { private val iconSize = Spritesheet.spriteSize(icon) override def minimumSize: Size2D = Size2D(iconSize.width + key.length * 8 + 40 + text.length * 8, 16) diff --git a/src/main/scala/ocelot/desktop/ui/widget/statusbar/MouseEntry.scala b/src/main/scala/ocelot/desktop/ui/widget/statusbar/MouseEntry.scala index af9fd3c..c26a884 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/statusbar/MouseEntry.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/statusbar/MouseEntry.scala @@ -3,11 +3,11 @@ 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.graphics.{Graphics, IconSource} import ocelot.desktop.ui.widget.Widget import ocelot.desktop.util.Spritesheet -class MouseEntry(val icon: String, val text: String) extends Widget { +class MouseEntry(val icon: IconSource, val text: String) extends Widget { private val iconSize = Spritesheet.spriteSize(icon) override def minimumSize: Size2D = Size2D(iconSize.width + 24 + text.length * 8, 16) diff --git a/src/main/scala/ocelot/desktop/ui/widget/statusbar/StatusBar.scala b/src/main/scala/ocelot/desktop/ui/widget/statusbar/StatusBar.scala index ce05b85..a61ffb7 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/statusbar/StatusBar.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/statusbar/StatusBar.scala @@ -102,7 +102,7 @@ class StatusBar extends Widget { super.update() if (isHovered) { - root.get.statusBar.addMouseEntry("icons/RMB", "Change simulation speed") + root.get.statusBar.addMouseEntry(IconSource.Icons.RMB, "Change simulation speed") } } @@ -135,22 +135,16 @@ class StatusBar extends Widget { Padding2D(left = 8), ) - def addMouseEntry(icon: String, text: String): Unit = { - if ( - !keyMouseEntries.children.filter(_.isInstanceOf[MouseEntry]).map(_.asInstanceOf[MouseEntry]).exists( - _.icon == icon - ) - ) + def addMouseEntry(icon: IconSource, text: String): Unit = { + if (!keyMouseEntries.children.collect({ case e: MouseEntry => e.icon }).contains(icon)) { keyMouseEntries.children :+= new MouseEntry(icon, text) + } } - def addKeyMouseEntry(icon: String, key: String, text: String): Unit = { - if ( - !keyMouseEntries.children.filter(_.isInstanceOf[KeyMouseEntry]).map(_.asInstanceOf[KeyMouseEntry]).exists(v => - v.icon == icon && v.key == key - ) - ) + def addKeyMouseEntry(icon: IconSource, key: String, text: String): Unit = { + if (!keyMouseEntries.children.collect({ case e: KeyMouseEntry => e }).exists(e => e.icon == icon && e.key == key)) { keyMouseEntries.children :+= new KeyMouseEntry(icon, key, text) + } } def addKeyEntry(key: String, text: String): Unit = { diff --git a/src/main/scala/ocelot/desktop/ui/widget/verticalmenu/VerticalMenuButton.scala b/src/main/scala/ocelot/desktop/ui/widget/verticalmenu/VerticalMenuButton.scala index 36cc6ed..58ed193 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/verticalmenu/VerticalMenuButton.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/verticalmenu/VerticalMenuButton.scala @@ -64,7 +64,7 @@ class VerticalMenuButton(icon: IconSource, label: String, handler: VerticalMenuB colorAnimation.update() g.rect(bounds, colorAnimation.color) g.rect(bounds.x + bounds.w - 2f, bounds.y, 2f, bounds.h, ColorScheme("VerticalMenuBorder")) - if (selected) g.sprite("TabArrow", bounds.x + bounds.w - 8f, bounds.y + bounds.h / 2f - 7f, 8, 14) + if (selected) g.sprite(IconSource.TabArrow, bounds.x + bounds.w - 8f, bounds.y + bounds.h / 2f - 7f, 8, 14) drawChildren(g) } diff --git a/src/main/scala/ocelot/desktop/util/DrawUtils.scala b/src/main/scala/ocelot/desktop/util/DrawUtils.scala index be448fa..adfbdbb 100644 --- a/src/main/scala/ocelot/desktop/util/DrawUtils.scala +++ b/src/main/scala/ocelot/desktop/util/DrawUtils.scala @@ -92,17 +92,17 @@ object DrawUtils { } def panel(g: Graphics, x: Float, y: Float, w: Float, h: Float): Unit = { - g.sprite("panel/CornerTL", x, y, 4, 4) - g.sprite("panel/CornerTR", x + w - 4, y, 4, 4) - g.sprite("panel/CornerBL", x, y + h - 4, 4, 4) - g.sprite("panel/CornerBR", x + w - 4, y + h - 4, 4, 4) + g.sprite(IconSource.Panel.CornerTL, x, y, 4, 4) + g.sprite(IconSource.Panel.CornerTR, x + w - 4, y, 4, 4) + g.sprite(IconSource.Panel.CornerBL, x, y + h - 4, 4, 4) + g.sprite(IconSource.Panel.CornerBR, x + w - 4, y + h - 4, 4, 4) - g.sprite("panel/BorderT", x + 4, y, w - 8, 4) - g.sprite("panel/BorderB", x + 4, y + h - 4, w - 8, 4) - g.sprite("panel/BorderL", x, y + 4, 4, h - 8) - g.sprite("panel/BorderR", x + w - 4, y + 4, 4, h - 8) + g.sprite(IconSource.Panel.BorderT, x + 4, y, w - 8, 4) + g.sprite(IconSource.Panel.BorderB, x + 4, y + h - 4, w - 8, 4) + g.sprite(IconSource.Panel.BorderL, x, y + 4, 4, h - 8) + g.sprite(IconSource.Panel.BorderR, x + w - 4, y + 4, 4, h - 8) - g.sprite("panel/Fill", x + 4, y + 4, w - 8, h - 8) + g.sprite(IconSource.Panel.Fill, x + 4, y + 4, w - 8, h - 8) } def isValidPolyline(points: Array[Vector2D]): Boolean = { @@ -186,19 +186,19 @@ object DrawUtils { h: Float, color: Color = RGBAColor(255, 255, 255), ): Unit = { - 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(IconSource.Window.CornerTL, x, y, 8, 8, color) + g.sprite(IconSource.Window.CornerTR, x + w - 8, y, 8, 8, color) + g.sprite(IconSource.Window.CornerBL, x, y + h - 8, 8, 8, color) + g.sprite(IconSource.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.sprite(IconSource.Window.BorderLight, x + 8, y, w - 16, 8, color) + g.sprite(IconSource.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.sprite(IconSource.Window.BorderLight, 0, 0, -h + 16, 8, color) + g.sprite(IconSource.Window.BorderDark, 0, w - 8, -h + 16, 8, color) g.restore() g.rect(x + 8, y + 8, w - 16, h - 16, RGBAColor(198, 198, 198, color.toRGBA.a)) @@ -207,24 +207,24 @@ object DrawUtils { def shadow(g: Graphics, x: Float, y: Float, w: Float, h: Float, a: Float = 0.8f): Unit = { val col = RGBAColorNorm(1, 1, 1, a) - rotSprite(g, "ShadowCorner", x, y, 24, 24, 180.toRadians, col) - rotSprite(g, "ShadowCorner", x + w - 24, y, 24, 24, 270.toRadians, col) - rotSprite(g, "ShadowCorner", x, y + h - 24, 24, 24, 90.toRadians, col) - g.sprite("ShadowCorner", x + w - 24, y + h - 24, 24, 24, col) + rotSprite(g, IconSource.ShadowCorner, x, y, 24, 24, 180.toRadians, col) + rotSprite(g, IconSource.ShadowCorner, x + w - 24, y, 24, 24, 270.toRadians, col) + rotSprite(g, IconSource.ShadowCorner, x, y + h - 24, 24, 24, 90.toRadians, col) + g.sprite(IconSource.ShadowCorner, x + w - 24, y + h - 24, 24, 24, col) - g.sprite("ShadowBorder", x + 24, y + 24, w - 48, -24, col) - g.sprite("ShadowBorder", x + 24, y + h - 24, w - 48, 24, col) + g.sprite(IconSource.ShadowBorder, x + 24, y + 24, w - 48, -24, col) + g.sprite(IconSource.ShadowBorder, x + 24, y + h - 24, w - 48, 24, col) g.save() g.translate(x + 24, y + 24) g.rotate(90.toRadians) - g.sprite("ShadowBorder", 0, 0, h - 48, 24, col) + g.sprite(IconSource.ShadowBorder, 0, 0, h - 48, 24, col) g.restore() g.save() g.translate(x + w - 24, y + h - 24) g.rotate(270.toRadians) - g.sprite("ShadowBorder", 0, 0, h - 48, 24, col) + g.sprite(IconSource.ShadowBorder, 0, 0, h - 48, 24, col) g.restore() g.rect(x + 24, y + 24, w - 48, h - 48, RGBAColorNorm(0, 0, 0, a)) @@ -232,7 +232,7 @@ object DrawUtils { private def rotSprite( g: Graphics, - sprite: String, + icon: IconSource, x: Float, y: Float, w: Float, @@ -243,7 +243,7 @@ object DrawUtils { g.save() g.translate(x + w / 2f, y + h / 2f) g.rotate(angle) - g.sprite(sprite, -w / 2f, -h / 2f, w, h, col) + g.sprite(icon, -w / 2f, -h / 2f, w, h, col) g.restore() } diff --git a/src/main/scala/ocelot/desktop/util/Spritesheet.scala b/src/main/scala/ocelot/desktop/util/Spritesheet.scala index 4015fb3..b1cd27b 100644 --- a/src/main/scala/ocelot/desktop/util/Spritesheet.scala +++ b/src/main/scala/ocelot/desktop/util/Spritesheet.scala @@ -1,6 +1,6 @@ package ocelot.desktop.util -import ocelot.desktop.geometry.{Rect2D, Size2D, Vector2D} +import ocelot.desktop.geometry.{Rect2D, Size2D} import ocelot.desktop.graphics.{IconSource, Texture} import javax.imageio.ImageIO @@ -15,18 +15,18 @@ object Spritesheet extends Resource with Logging { def spriteSize(sprite: String): Size2D = sprites(sprite).size * resolution - def spriteSize(iconSource: IconSource): Size2D = iconSource.animation match { + def spriteSize(icon: IconSource): Size2D = icon.animation match { case Some(animation) => animation.frameSize match { case Some(size) => size case None => - val size = spriteSize(iconSource.path) + val size = spriteSize(icon.path) Size2D(size.width, size.width) } - case None => spriteSize(iconSource.path) + case None => spriteSize(icon.path) } def load(): Unit = { diff --git a/src/main/scala/ocelot/desktop/windows/ComputerWindow.scala b/src/main/scala/ocelot/desktop/windows/ComputerWindow.scala index 4602fbe..0968127 100644 --- a/src/main/scala/ocelot/desktop/windows/ComputerWindow.scala +++ b/src/main/scala/ocelot/desktop/windows/ComputerWindow.scala @@ -277,7 +277,11 @@ class ComputerWindow(computerAware: ComputerAware) extends BasicWindow { override def draw(g: Graphics): Unit = { // Background image g.sprite( - s"window/${if (isServerMachineType) "rack" else "case"}/Motherboard", + if (isServerMachineType) { + IconSource.Window.Rack.Motherboard + } else { + IconSource.Window.Case.Motherboard + }, position.x, position.y, width, diff --git a/src/main/scala/ocelot/desktop/windows/OpenFMRadioWindow.scala b/src/main/scala/ocelot/desktop/windows/OpenFMRadioWindow.scala index dbb9ad4..5976133 100644 --- a/src/main/scala/ocelot/desktop/windows/OpenFMRadioWindow.scala +++ b/src/main/scala/ocelot/desktop/windows/OpenFMRadioWindow.scala @@ -186,7 +186,7 @@ class OpenFMRadioWindow(radioNode: OpenFMRadioNode) extends BasicWindow { override def draw(g: Graphics): Unit = { beginDraw(g) // I hate this - g.sprite("window/OpenFMRadio", position.x, position.y, size.width, size.height) + g.sprite(IconSource.Window.OpenFMRadio, position.x, position.y, size.width, size.height) drawChildren(g) endDraw(g) } diff --git a/src/main/scala/ocelot/desktop/windows/RackWindow.scala b/src/main/scala/ocelot/desktop/windows/RackWindow.scala index 678592a..ef7e0a3 100644 --- a/src/main/scala/ocelot/desktop/windows/RackWindow.scala +++ b/src/main/scala/ocelot/desktop/windows/RackWindow.scala @@ -25,10 +25,6 @@ class RackWindow(rackNode: RackNode) extends PanelWindow { private val nodeButtonsGap = 12 private val nodeButtonsWidth = 10 - private def directionToSpriteName(prefix: String, direction: Direction): String = { - s"$prefix${direction.side.capitalize}" - } - private def shouldConnectionBeVisible(slotWidget: RackMountableSlotWidget, connectableIndex: Int) = { connectableIndex == 0 || ( @@ -77,23 +73,11 @@ class RackWindow(rackNode: RackNode) extends PanelWindow { override def draw(g: Graphics): Unit = { // Relay mode line if (rackNode.rack.isRelayEnabled) { - g.sprite( - s"window/rack/NetworkConnector", - position.x + 12, - position.y + 172, - 102, - 4, - ) + g.sprite(IconSource.Window.Rack.Network.Connector, position.x + 12, position.y + 172, 102, 4) } // Lines background - g.sprite( - "window/rack/Lines", - position.x + linesMarginLeft, - position.y, - size.width, - size.height, - ) + g.sprite(IconSource.Window.Rack.Lines, position.x + linesMarginLeft, position.y, size.width, size.height) super.draw(g) } @@ -120,31 +104,28 @@ class RackWindow(rackNode: RackNode) extends PanelWindow { var y = position.y var connectionHeight: Float = 0 - var prefix: String = null for (connectableIndex <- 0 until 4) { connectionHeight = if (connectableIndex == 0) lineSideHeight else lineNetworkHeight if (shouldConnectionBeVisible(mountableSlotWidget, connectableIndex)) { val connection = rackNode.rack.nodeMapping(mountableIndex)(connectableIndex) - prefix = s"window/rack/${if (connectableIndex == 0) "Side" else "Network"}" + val source = if (connectableIndex == 0) { + IconSource.Window.Rack.Side + } else { + IconSource.Window.Rack.Network + } // Connector - g.sprite( - s"${prefix}Connector", - position.x, - y, - 2, - connectionHeight, - ) + g.sprite(source.Connector, position.x, y, 2, connectionHeight) // Line - if (connection.isDefined) { + for (connection <- connection) { g.sprite( - directionToSpriteName(prefix, connection.get), + source.DirectionIcon(connection), position.x + 2, y, - connection.get match { + connection match { case Direction.Bottom => nodeButtonsGap case Direction.Top => nodeButtonsGap * 2 + nodeButtonsWidth case Direction.Back => nodeButtonsGap * 3 + nodeButtonsWidth * 2 @@ -195,21 +176,13 @@ class RackWindow(rackNode: RackNode) extends PanelWindow { rackNode.rack.connect( mountableIndex, connectableIndex - 1, - // Connection already exists, removing it - if (oldConnection.isDefined && oldConnection.get == direction) - None - // Connecting normally - else - Some(direction), + Option.unless(oldConnection.contains(direction))(direction), ) } override def draw(g: Graphics): Unit = { if (enabled) { - g.sprite( - directionToSpriteName("window/rack/Node", direction), - bounds, - ) + g.sprite(IconSource.Window.Rack.Node.DirectionIcon(direction), bounds) drawHighlight(g) } } diff --git a/src/main/scala/ocelot/desktop/windows/RaidWindow.scala b/src/main/scala/ocelot/desktop/windows/RaidWindow.scala index 02544a5..f55787d 100644 --- a/src/main/scala/ocelot/desktop/windows/RaidWindow.scala +++ b/src/main/scala/ocelot/desktop/windows/RaidWindow.scala @@ -3,7 +3,7 @@ package ocelot.desktop.windows import ocelot.desktop.ColorScheme import ocelot.desktop.color.Color import ocelot.desktop.geometry.{Padding2D, Size2D} -import ocelot.desktop.graphics.Graphics +import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.node.nodes.RaidNode import ocelot.desktop.ui.layout.{AlignItems, Layout, LinearLayout} import ocelot.desktop.ui.widget._ @@ -37,13 +37,7 @@ class RaidWindow(raidNode: RaidNode) extends PanelWindow { override def draw(g: Graphics): Unit = { // Background border - g.sprite( - "window/raid/Slots", - position.x, - position.y, - size.width, - size.height, - ) + g.sprite(IconSource.Window.Raid.Slots, position, size) super.draw(g) } diff --git a/src/main/scala/ocelot/desktop/windows/ScreenWindow.scala b/src/main/scala/ocelot/desktop/windows/ScreenWindow.scala index 22d5e91..46b9d24 100644 --- a/src/main/scala/ocelot/desktop/windows/ScreenWindow.scala +++ b/src/main/scala/ocelot/desktop/windows/ScreenWindow.scala @@ -2,7 +2,7 @@ package ocelot.desktop.windows import ocelot.desktop.color.RGBAColorNorm import ocelot.desktop.geometry.{Padding2D, Rect2D, Size2D, Vector2D} -import ocelot.desktop.graphics.Graphics +import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.node.nodes.ScreenNode import ocelot.desktop.node.nodes.ScreenNode.{FontHeight, FontWidth} import ocelot.desktop.ui.UiHandler @@ -147,8 +147,8 @@ class ScreenWindow(screenNode: ScreenNode) extends PanelWindow with Logging { super.update() if (scaleDragPoint.isDefined || scaleDragRegion.contains(UiHandler.mousePosition)) { - root.get.statusBar.addMouseEntry("icons/DragLMB", "Scale screen") - root.get.statusBar.addKeyMouseEntry("icons/DragLMB", "SHIFT", "Scale screen (magnify)") + root.get.statusBar.addMouseEntry(IconSource.Icons.DragLMB, "Scale screen") + root.get.statusBar.addKeyMouseEntry(IconSource.Icons.DragLMB, "SHIFT", "Scale screen (magnify)") } } diff --git a/src/main/scala/ocelot/desktop/windows/TapeDriveWindow.scala b/src/main/scala/ocelot/desktop/windows/TapeDriveWindow.scala index 5374919..08d097b 100644 --- a/src/main/scala/ocelot/desktop/windows/TapeDriveWindow.scala +++ b/src/main/scala/ocelot/desktop/windows/TapeDriveWindow.scala @@ -39,12 +39,12 @@ class TapeDriveWindow(val tapeDriveNode: TapeDriveNode) extends PanelWindow { override def draw(g: Graphics): Unit = { // Screen background g.sprite( - "window/tape/Screen", + IconSource.Window.Tape.Screen, bounds, ) // A barely noticeable overlay showing the playback progress - // Btw Computronix doesn't have this feature, so I won't ruin the canon and make it too annoying + // Btw Computronics doesn't have this feature, so I won't ruin the canon and make it too annoying val playedPart = tapeDriveNode.tapeDrive.position.toFloat / tapeDriveNode.tapeDrive.size.toFloat if (playedPart > 0) {