Show FM/AM routing

This commit is contained in:
LeshaInc 2023-04-04 15:36:24 +03:00
parent f58214b1e4
commit 8961a368a6
No known key found for this signature in database
GPG Key ID: 7F51850974C1C795
8 changed files with 198 additions and 54 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 B

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 531 B

After

Width:  |  Height:  |  Size: 530 B

View File

@ -123,7 +123,15 @@ PlotFill = #ccfdcc25
PlotLine = #ccfdcc PlotLine = #ccfdcc
PlotText = #333333 PlotText = #333333
WaveOff = #33663340 SoundCardWaveOff = #33663340
WaveActive = #339933 SoundCardWaveActive = #339933
WireOff = #929292 SoundCardWireOff = #929292
SoundCardWire0 = #237f23
SoundCardWire1 = #237f77
SoundCardWire2 = #23567f
SoundCardWire3 = #69237f
SoundCardWire4 = #7f2331
SoundCardWire5 = #7f5123
SoundCardWire6 = #7f7723
SoundCardWire7 = #000000

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -1,7 +1,7 @@
BackgroundPattern 0 0 304 304 BackgroundPattern 0 0 304 304
BarSegment 29 355 16 4 BarSegment 29 355 16 4
ComputerMotherboard 305 0 79 70 ComputerMotherboard 305 0 79 70
Empty 12 405 1 1 Empty 12 414 1 1
EmptySlot 458 147 18 18 EmptySlot 458 147 18 18
Knob 385 0 50 50 Knob 385 0 50 50
KnobCenter 436 0 50 50 KnobCenter 436 0 50 50
@ -43,6 +43,8 @@ icons/WaveSawtooth 86 305 24 10
icons/WaveSine 111 305 24 10 icons/WaveSine 111 305 24 10
icons/WaveSquare 136 305 24 10 icons/WaveSquare 136 305 24 10
icons/WaveTriangle 161 305 24 10 icons/WaveTriangle 161 305 24 10
icons/WireArrowLeft 2 394 4 8
icons/WireArrowRight 7 394 4 8
items/APU0 373 122 16 96 items/APU0 373 122 16 96
items/APU1 390 122 16 96 items/APU1 390 122 16 96
items/APU2 407 122 16 96 items/APU2 407 122 16 96
@ -101,17 +103,17 @@ items/Server3 424 105 16 16
items/SoundCard 356 122 16 128 items/SoundCard 356 122 16 128
items/WirelessNetworkCard0 441 105 16 16 items/WirelessNetworkCard0 441 105 16 16
items/WirelessNetworkCard1 458 105 16 16 items/WirelessNetworkCard1 458 105 16 16
light-panel/BookmarkLeft 391 219 20 14 light-panel/BookmarkLeft 17 305 18 14
light-panel/BookmarkRight 17 305 18 14 light-panel/BookmarkRight 391 219 20 14
light-panel/BorderB 8 394 4 4 light-panel/BorderB 8 403 4 4
light-panel/BorderL 98 394 4 2 light-panel/BorderL 98 403 4 2
light-panel/BorderR 13 394 4 4 light-panel/BorderR 13 403 4 4
light-panel/BorderT 18 394 4 4 light-panel/BorderT 18 403 4 4
light-panel/CornerBL 23 394 4 4 light-panel/CornerBL 23 403 4 4
light-panel/CornerBR 28 394 4 4 light-panel/CornerBR 28 403 4 4
light-panel/CornerTL 33 394 4 4 light-panel/CornerTL 33 403 4 4
light-panel/CornerTR 38 394 4 4 light-panel/CornerTR 38 403 4 4
light-panel/Fill 6 405 2 2 light-panel/Fill 6 414 2 2
light-panel/Vent 0 355 2 38 light-panel/Vent 0 355 2 38
nodes/Cable 3 366 8 8 nodes/Cable 3 366 8 8
nodes/Computer 475 105 16 16 nodes/Computer 475 105 16 16
@ -127,26 +129,26 @@ nodes/NoteBlock 453 51 16 16
nodes/Relay 470 51 16 16 nodes/Relay 470 51 16 16
nodes/Screen 487 51 16 16 nodes/Screen 487 51 16 16
nodes/ScreenOnOverlay 0 305 16 16 nodes/ScreenOnOverlay 0 305 16 16
panel/BorderB 43 394 4 4 panel/BorderB 43 403 4 4
panel/BorderL 103 394 4 2 panel/BorderL 103 403 4 2
panel/BorderR 48 394 4 4 panel/BorderR 48 403 4 4
panel/BorderT 53 394 4 4 panel/BorderT 53 403 4 4
panel/CornerBL 58 394 4 4 panel/CornerBL 58 403 4 4
panel/CornerBR 63 394 4 4 panel/CornerBR 63 403 4 4
panel/CornerTL 68 394 4 4 panel/CornerTL 68 403 4 4
panel/CornerTR 73 394 4 4 panel/CornerTR 73 403 4 4
panel/Fill 9 405 2 2 panel/Fill 9 414 2 2
particles/Note 21 355 7 10 particles/Note 21 355 7 10
screen/BorderB 5 394 2 8 screen/BorderB 5 403 2 8
screen/BorderT 2 394 2 10 screen/BorderT 2 403 2 10
screen/CornerBL 12 366 8 8 screen/CornerBL 12 366 8 8
screen/CornerBR 21 366 8 8 screen/CornerBR 21 366 8 8
screen/CornerTL 3 355 8 10 screen/CornerTL 3 355 8 10
screen/CornerTR 12 355 8 10 screen/CornerTR 12 355 8 10
window/BorderDark 2 405 1 4 window/BorderDark 2 414 1 4
window/BorderLight 4 405 1 4 window/BorderLight 4 414 1 4
window/CloseButton 30 366 7 6 window/CloseButton 30 366 7 6
window/CornerBL 78 394 4 4 window/CornerBL 78 403 4 4
window/CornerBR 83 394 4 4 window/CornerBR 83 403 4 4
window/CornerTL 88 394 4 4 window/CornerTL 88 403 4 4
window/CornerTR 93 394 4 4 window/CornerTR 93 403 4 4

View File

@ -2,7 +2,7 @@ package ocelot.desktop.ui.widget.card
import ocelot.desktop.ColorScheme import ocelot.desktop.ColorScheme
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.geometry.{Padding2D, Rect2D, Size2D} import ocelot.desktop.geometry.{Padding2D, Rect2D, Size2D, Vector2D}
import ocelot.desktop.graphics.Graphics import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.layout.{Layout, LinearLayout} import ocelot.desktop.ui.layout.{Layout, LinearLayout}
import ocelot.desktop.ui.widget.card.SoundCardWindow._ import ocelot.desktop.ui.widget.card.SoundCardWindow._
@ -31,6 +31,12 @@ class SoundCardWindow(card: SoundCard) extends BasicWindow {
new Channel(proc, osc) new Channel(proc, osc)
} }
private val patchbays: Array[Patchbay] = (0 until numChannels / 2)
.map(i => new Patchbay(2 * i, 2 * i + 1, isFirst = i == 0, isLast = i == numChannels / 2 - 1))
.toArray
private val existingConnectors = new mutable.ArrayBuffer[Connector]()
private var eventSub: Option[EventBus.Subscription] = None private var eventSub: Option[EventBus.Subscription] = None
children :+= new PaddingBox(new Widget { children :+= new PaddingBox(new Widget {
@ -44,20 +50,13 @@ class SoundCardWindow(card: SoundCard) extends BasicWindow {
children :+= new PaddingBox(masterOscilloscope, Padding2D(left = 4, right = 4)) children :+= new PaddingBox(masterOscilloscope, Padding2D(left = 4, right = 4))
for (i <- process.channels.indices by 2) { for (i <- 0 until numChannels / 2) {
children :+= new Widget { children :+= new Widget {
children :+= channelWidgets(i) children :+= channelWidgets(2 * i)
children :+= new Patchbay(i, i + 1, isFirst = i == 0, isLast = i == numChannels - 2) children :+= patchbays(i)
children :+= channelWidgets(i + 1) children :+= channelWidgets(2 * i + 1)
} }
} }
if (numChannels % 2 == 1) {
val i = numChannels - 1
children :+= channelWidgets(i)
children :+= new Patchbay(i, -1, isFirst = false, isLast = true)
children :+= new Widget
}
}, Padding2D.equal(8)) }, Padding2D.equal(8))
private def numChannels: Int = process.channels.length private def numChannels: Int = process.channels.length
@ -84,9 +83,118 @@ class SoundCardWindow(card: SoundCard) extends BasicWindow {
beginDraw(g) beginDraw(g)
DrawUtils.windowWithShadow(g, position.x, position.y, size.width, size.height, 1f, 0.5f) DrawUtils.windowWithShadow(g, position.x, position.y, size.width, size.height, 1f, 0.5f)
drawChildren(g) drawChildren(g)
drawConnectors(g)
endDraw(g) endDraw(g)
} }
private def drawConnectors(g: Graphics): Unit = {
val initColor = ColorScheme("Label")
for (i <- 0 until numChannels) {
setColCh(i, initColor)
setColAm(i, initColor)
setColFm(i, initColor)
}
existingConnectors.clear()
var colorIdx = 0
var color = ColorScheme("SoundCardWire0")
val px = patchbays(0).posLeftCh.x
for (i <- 0 until numChannels) {
var hadAny = false
for (j <- 0 until numChannels) {
if (i != j) {
val dstCh = process.channels(j)
if (dstCh.amplitudeMod.exists(_.modulatorIndex == i)) {
setColAm(j, color)
drawConnector(g, px, posCh(i), posAm(j), colorIdx)
hadAny = true
}
if (dstCh.frequencyMod.exists(_.modulatorIndex == i)) {
setColFm(j, color)
drawConnector(g, px, posCh(i), posFm(j), colorIdx)
hadAny = true
}
}
}
if (hadAny) {
setColCh(i, color)
colorIdx += 1
color = ColorScheme(s"SoundCardWire${colorIdx % 8}")
}
}
}
private def drawConnector(g: Graphics, px: Float, a: Vector2D, b: Vector2D, colorIdx: Int): Unit = {
var from = a.y
var to = b.y
if (from > to) {
from = b.y
to = a.y
}
var column = 0
val existing = existingConnectors.find(con => con.colorIdx == colorIdx)
if (existing.isDefined) {
column = existing.get.column
} else {
var done = false
while (column >= 0 && column < 6 && !done) {
val conflict = existingConnectors.exists(con => {
con.column == column && con.from <= to && con.to >= from
})
if (conflict) {
column += 1
} else {
done = true
}
}
}
val mx = px + column * 4 + 9
val col = ColorScheme(s"SoundCardWire${colorIdx % 8}")
g.line(a, Vector2D(mx, a.y), 2, col)
g.line(Vector2D(mx, from - 1), Vector2D(mx, to + 1), 2, col)
g.line(b, Vector2D(mx, b.y), 2, col)
if (b.x > px) {
g.sprite("icons/WireArrowRight", b.x - 4, b.y - 4, col)
} else {
g.sprite("icons/WireArrowLeft", b.x, b.y - 4, col)
}
existingConnectors += Connector(column, colorIdx, from, to)
}
private def posCh(i: Int): Vector2D = {
if (i % 2 == 0) patchbays(i / 2).posLeftCh else patchbays(i / 2).posRightCh
}
private def posAm(i: Int): Vector2D = {
if (i % 2 == 0) patchbays(i / 2).posLeftAm else patchbays(i / 2).posRightAm
}
private def posFm(i: Int): Vector2D = {
if (i % 2 == 0) patchbays(i / 2).posLeftFm else patchbays(i / 2).posRightFm
}
private def setColCh(i: Int, col: Color): Unit = {
if (i % 2 == 0) patchbays(i / 2).colLeftCh = col else patchbays(i / 2).colRightCh = col
}
private def setColAm(i: Int, col: Color): Unit = {
if (i % 2 == 0) patchbays(i / 2).colLeftAm = col else patchbays(i / 2).colRightAm = col
}
private def setColFm(i: Int, col: Color): Unit = {
if (i % 2 == 0) patchbays(i / 2).colLeftFm = col else patchbays(i / 2).colRightFm = col
}
override def update(): Unit = { override def update(): Unit = {
super.update() super.update()
@ -183,7 +291,7 @@ object SoundCardWindow {
case ADSREnvelope.Phase.Release => releaseStart + elapsedMs case ADSREnvelope.Phase.Release => releaseStart + elapsedMs
} }
var col = ColorScheme("WaveActive").withAlpha(0.6f) var col = ColorScheme("SoundCardWaveActive").withAlpha(0.6f)
for (sx <- 0 until bounds.w.toInt) { for (sx <- 0 until bounds.w.toInt) {
val t = (sx / bounds.w) * envDuration val t = (sx / bounds.w) * envDuration
if (t >= elapsedTime) col = col.withAlpha(0.2f) if (t >= elapsedTime) col = col.withAlpha(0.2f)
@ -202,7 +310,7 @@ object SoundCardWindow {
val ay = bounds.y + bounds.h val ay = bounds.y + bounds.h
val by = bounds.y val by = bounds.y
val cy = bounds.y + (1 - env.sustain) * bounds.h val cy = bounds.y + (1 - env.sustain) * bounds.h
col = ColorScheme("WaveActive") col = ColorScheme("SoundCardWaveActive")
var ax = bounds.x var ax = bounds.x
var bx = bounds.x + env.attack * unit var bx = bounds.x + env.attack * unit
@ -233,7 +341,7 @@ object SoundCardWindow {
override def draw(g: Graphics): Unit = { override def draw(g: Graphics): Unit = {
for (((icon, clazz), i) <- waves.zipWithIndex) { for (((icon, clazz), i) <- waves.zipWithIndex) {
val active = clazz.isInstance(channel.generator) val active = clazz.isInstance(channel.generator)
val color = if (active) ColorScheme("WaveActive") else ColorScheme("WaveOff") val color = if (active) ColorScheme("SoundCardWaveActive") else ColorScheme("SoundCardWaveOff")
g.sprite(icon, position.x + 24 * i + 2, position.y + 4, color) g.sprite(icon, position.x + 24 * i + 2, position.y + 4, color)
} }
@ -276,9 +384,28 @@ object SoundCardWindow {
} }
private class Patchbay(leftIdx: Int, rightIdx: Int, isFirst: Boolean, isLast: Boolean) extends Widget { private class Patchbay(leftIdx: Int, rightIdx: Int, isFirst: Boolean, isLast: Boolean) extends Widget {
override def minimumSize: Size2D = Size2D(68, 100) var colLeftCh: Color = ColorScheme("Label")
var colLeftAm: Color = ColorScheme("Label")
var colLeftFm: Color = ColorScheme("Label")
var colRightCh: Color = ColorScheme("Label")
var colRightAm: Color = ColorScheme("Label")
var colRightFm: Color = ColorScheme("Label")
override def maximumSize: Size2D = Size2D(68, Float.PositiveInfinity) override def minimumSize: Size2D = Size2D(74, 100)
override def maximumSize: Size2D = Size2D(74, Float.PositiveInfinity)
def posLeftCh: Vector2D = Vector2D(position.x + 18, position.y + 22)
def posLeftAm: Vector2D = Vector2D(position.x + 18, position.y + 38)
def posLeftFm: Vector2D = Vector2D(position.x + 18, position.y + 54)
def posRightCh: Vector2D = Vector2D(position.x + width - 20, position.y + 22)
def posRightAm: Vector2D = Vector2D(position.x + width - 20, position.y + 38)
def posRightFm: Vector2D = Vector2D(position.x + width - 20, position.y + 54)
override def draw(g: Graphics): Unit = { override def draw(g: Graphics): Unit = {
val x = position.x val x = position.x
@ -309,33 +436,40 @@ object SoundCardWindow {
} }
for (i <- 0 until 6) { for (i <- 0 until 6) {
g.rect(x + 23 + i * 4, y - 2, 2, h + 4, ColorScheme("WireOff")) g.rect(x + 26 + i * 4, y - 2, 2, h + 4, ColorScheme("SoundCardWireOff"))
} }
y -= sy y -= sy
h += sh h += sh
g.sprite("light-panel/BookmarkLeft", x, y + 16, 20, 14) g.sprite("light-panel/BookmarkLeft", x, y + 16, 18, 14)
g.sprite("light-panel/BookmarkLeft", x, y + 32, 20, 14) g.sprite("light-panel/BookmarkLeft", x, y + 32, 18, 14)
g.sprite("light-panel/BookmarkLeft", x, y + 48, 20, 14) g.sprite("light-panel/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 + 16, 20, 14)
g.sprite("light-panel/BookmarkRight", x + w - 20, y + 32, 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("light-panel/BookmarkRight", x + w - 20, y + 48, 20, 14)
g.setSmallFont() g.setSmallFont()
g.foreground = ColorScheme("Label")
g.background = Color.Transparent g.background = Color.Transparent
g.foreground = colLeftCh
g.text(x, y + 18, s"C${leftIdx + 1}") g.text(x, y + 18, s"C${leftIdx + 1}")
g.foreground = colLeftAm
g.text(x, y + 34, "AM") g.text(x, y + 34, "AM")
g.foreground = colLeftFm
g.text(x, y + 50, "FM") g.text(x, y + 50, "FM")
g.foreground = colRightCh
g.text(x + w - 18, y + 18, s"C${rightIdx + 1}") g.text(x + w - 18, y + 18, s"C${rightIdx + 1}")
g.foreground = colRightAm
g.text(x + w - 18, y + 34, "AM") g.text(x + w - 18, y + 34, "AM")
g.foreground = colRightFm
g.text(x + w - 18, y + 50, "FM") g.text(x + w - 18, y + 50, "FM")
g.setNormalFont() g.setNormalFont()
} }
} }
private case class Connector(column: Int, colorIdx: Int, from: Float, to: Float)
} }