Have the SoundSource object store factories rather than sources

Closes #182.
This commit is contained in:
Fingercomp 2025-09-17 22:32:14 +03:00
parent 2aba4a7969
commit 3b82541da6
No known key found for this signature in database
GPG Key ID: BBC71CEE45D86E37
24 changed files with 115 additions and 97 deletions

@ -1 +1 @@
Subproject commit 16b022033a861af41be3c126aa8824a7e3d12396 Subproject commit da5dd8877035f4994b77047658561d316319b54b

View File

@ -30,10 +30,6 @@ object Audio extends Logging {
def isDisabled: Boolean = _disabled def isDisabled: Boolean = _disabled
def numSources: Int = synchronized {
sources.size
}
def newStream( def newStream(
soundCategory: SoundCategory.Value, soundCategory: SoundCategory.Value,
pitch: Float = 1f, pitch: Float = 1f,
@ -81,7 +77,7 @@ object Audio extends Logging {
} }
} }
source = SoundSource.fromStream(stream, soundCategory, looping = false, pitch, volume) source = SoundSource.fromStream(stream, soundCategory, looping = false, pitch, volume).build()
(stream, source) (stream, source)
} }
@ -118,7 +114,7 @@ object Audio extends Logging {
tx.onFailure { AL10W.alDeleteSources(sourceId) } tx.onFailure { AL10W.alDeleteSources(sourceId) }
source.kind match { source.kind match {
case SoundSource.KindSoundBuffer(buffer) => case SoundSource.Kind.Buffer(buffer) =>
buffer.bufferId match { buffer.bufferId match {
case Some(bufferId) => case Some(bufferId) =>
AL10W.alSourcei(sourceId, AL10.AL_BUFFER, bufferId) AL10W.alSourcei(sourceId, AL10.AL_BUFFER, bufferId)
@ -128,14 +124,14 @@ object Audio extends Logging {
tx.abort() tx.abort()
} }
case SoundSource.KindSoundSamples(samples) => case SoundSource.Kind.Samples(samples) =>
Transaction.run { innerTx => Transaction.run { innerTx =>
val bufferId = samples.genBuffer().getOrElse { tx.abort() } val bufferId = samples.genBuffer().getOrElse { tx.abort() }
innerTx.onFailure { AL10W.alDeleteBuffers(bufferId) } innerTx.onFailure { AL10W.alDeleteBuffers(bufferId) }
AL10W.alSourceQueueBuffers(sourceId, bufferId) AL10W.alSourceQueueBuffers(sourceId, bufferId)
} }
case SoundSource.KindStream(_) => case SoundSource.Kind.Stream(_) =>
} }
AL10W.alSourcef(sourceId, AL10.AL_PITCH, source.pitch) AL10W.alSourcef(sourceId, AL10.AL_PITCH, source.pitch)

View File

@ -3,7 +3,7 @@ package ocelot.desktop.audio
import java.nio.ByteBuffer import java.nio.ByteBuffer
object BeepGenerator { object BeepGenerator {
def newBeep(pattern: String, frequency: Short, duration: Short): SoundSource = { def newBeep(pattern: String, frequency: Short, duration: Short): SoundSource.Factory = {
val sampleCounts = pattern.toCharArray val sampleCounts = pattern.toCharArray
.map(ch => if (ch == '.') duration else 2 * duration) .map(ch => if (ch == '.') duration else 2 * duration)
.map(_ * Audio.sampleRate / 1000) .map(_ * Audio.sampleRate / 1000)

View File

@ -1,6 +0,0 @@
package ocelot.desktop.audio
trait ClickSoundSource {
def press: SoundSource
def release: SoundSource
}

View File

@ -0,0 +1,6 @@
package ocelot.desktop.audio
trait ClickSoundSourceFactory {
def press: SoundSource.Factory
def release: SoundSource.Factory
}

View File

@ -14,10 +14,10 @@ class SoundSource(
var position: Vector3D = Vector3D(0, 0, 0), var position: Vector3D = Vector3D(0, 0, 0),
) { ) {
def duration: Option[Duration] = kind match { def duration: Option[Duration] = kind match {
case SoundSource.KindSoundBuffer(buffer) => case SoundSource.Kind.Buffer(buffer) =>
Some(Duration(buffer.numSamples.toFloat / buffer.sampleRate, TimeUnit.SECONDS)) Some(Duration(buffer.numSamples.toFloat / buffer.sampleRate, TimeUnit.SECONDS))
case SoundSource.KindSoundSamples(SoundSamples(buffer, rate, format)) => case SoundSource.Kind.Samples(SoundSamples(buffer, rate, format)) =>
val bps = format match { val bps = format match {
case SoundSamples.Format.Stereo16 => 2 case SoundSamples.Format.Stereo16 => 2
case SoundSamples.Format.Mono8 => 1 case SoundSamples.Format.Mono8 => 1
@ -26,7 +26,7 @@ class SoundSource(
Some(Duration(buffer.limit().toFloat / (rate * bps), TimeUnit.SECONDS)) Some(Duration(buffer.limit().toFloat / (rate * bps), TimeUnit.SECONDS))
case SoundSource.KindStream(_) => case SoundSource.Kind.Stream(_) =>
None None
} }
@ -62,26 +62,52 @@ class SoundSource(
object SoundSource { object SoundSource {
sealed trait Kind sealed trait Kind
case class KindSoundBuffer(buffer: SoundBuffer) extends Kind object Kind {
case class Buffer(buffer: SoundBuffer) extends Kind
case class KindSoundSamples(samples: SoundSamples) extends Kind case class Samples(samples: SoundSamples) extends Kind
case class Stream(stream: SoundStream) extends Kind
case class KindStream(stream: SoundStream) extends Kind
def fromBuffer(buffer: SoundBuffer, soundCategory: SoundCategory.Value,
looping: Boolean = false, pitch: Float = 1f, volume: Float = 1f): SoundSource = {
new SoundSource(SoundSource.KindSoundBuffer(buffer), soundCategory, looping, pitch, volume)
} }
def fromSamples(samples: SoundSamples, soundCategory: SoundCategory.Value, class Factory(
looping: Boolean = false, pitch: Float = 1f, volume: Float = 1f): SoundSource = { val kind: Kind,
new SoundSource(SoundSource.KindSoundSamples(samples), soundCategory, looping, pitch, volume) val soundCategory: SoundCategory.Value,
val looping: Boolean,
val pitch: Float,
val volume: Float,
) {
def build(): SoundSource = new SoundSource(kind, soundCategory, looping, pitch, volume)
def play(): SoundSource = {
val source = build()
source.play()
source
}
} }
def fromStream(stream: SoundStream, soundCategory: SoundCategory.Value, def fromBuffer(
looping: Boolean = false, pitch: Float = 1f, volume: Float = 1f): SoundSource = { buffer: SoundBuffer,
new SoundSource(SoundSource.KindStream(stream), soundCategory, looping, pitch, volume) soundCategory: SoundCategory.Value,
} looping: Boolean = false,
pitch: Float = 1f,
volume: Float = 1f,
): Factory = new Factory(SoundSource.Kind.Buffer(buffer), soundCategory, looping, pitch, volume)
def fromSamples(
samples: SoundSamples,
soundCategory: SoundCategory.Value,
looping: Boolean = false,
pitch: Float = 1f,
volume: Float = 1f,
): Factory = new Factory(SoundSource.Kind.Samples(samples), soundCategory, looping, pitch, volume)
def fromStream(
stream: SoundStream,
soundCategory: SoundCategory.Value,
looping: Boolean = false,
pitch: Float = 1f,
volume: Float = 1f,
): Factory = new Factory(SoundSource.Kind.Stream(stream), soundCategory, looping, pitch, volume)
object Status extends Enumeration { object Status extends Enumeration {
val Playing, Paused, Stopped = Value val Playing, Paused, Stopped = Value
@ -89,44 +115,40 @@ object SoundSource {
// ---------------------------------------------------------------- // ----------------------------------------------------------------
object InterfaceClick extends ClickSoundSource { object InterfaceClick extends ClickSoundSourceFactory {
override lazy val press: SoundSource = override lazy val press: Factory = SoundSource.fromBuffer(SoundBuffers.InterfaceClickPress, SoundCategory.Interface)
SoundSource.fromBuffer(SoundBuffers.InterfaceClickPress, SoundCategory.Interface)
override lazy val release: SoundSource = override lazy val release: Factory =
SoundSource.fromBuffer(SoundBuffers.InterfaceClickRelease, SoundCategory.Interface) SoundSource.fromBuffer(SoundBuffers.InterfaceClickRelease, SoundCategory.Interface)
} }
object InterfaceClickLow extends ClickSoundSource { object InterfaceClickLow extends ClickSoundSourceFactory {
override lazy val press: SoundSource = override lazy val press: Factory =
SoundSource.fromBuffer(SoundBuffers.InterfaceClickPress, SoundCategory.Interface, pitch = 0.8f) SoundSource.fromBuffer(SoundBuffers.InterfaceClickPress, SoundCategory.Interface, pitch = 0.8f)
override lazy val release: SoundSource = override lazy val release: Factory =
SoundSource.fromBuffer(SoundBuffers.InterfaceClickRelease, SoundCategory.Interface, pitch = 0.8f) SoundSource.fromBuffer(SoundBuffers.InterfaceClickRelease, SoundCategory.Interface, pitch = 0.8f)
} }
object InterfaceTick extends ClickSoundSource { object InterfaceTick extends ClickSoundSourceFactory {
override lazy val press: SoundSource = override lazy val press: Factory = SoundSource.fromBuffer(SoundBuffers.InterfaceTickPress, SoundCategory.Interface)
SoundSource.fromBuffer(SoundBuffers.InterfaceTickPress, SoundCategory.Interface)
override lazy val release: SoundSource = override lazy val release: Factory =
SoundSource.fromBuffer(SoundBuffers.InterfaceTickRelease, SoundCategory.Interface) SoundSource.fromBuffer(SoundBuffers.InterfaceTickRelease, SoundCategory.Interface)
} }
lazy val InterfaceShutter: SoundSource = lazy val InterfaceShutter: Factory = SoundSource.fromBuffer(SoundBuffers.InterfaceShutter, SoundCategory.Interface)
SoundSource.fromBuffer(SoundBuffers.InterfaceShutter, SoundCategory.Interface)
object MinecraftClick extends ClickSoundSource { object MinecraftClick extends ClickSoundSourceFactory {
override lazy val press: SoundSource = override lazy val press: Factory = SoundSource.fromBuffer(SoundBuffers.MinecraftClickPress, SoundCategory.Interface)
SoundSource.fromBuffer(SoundBuffers.MinecraftClickPress, SoundCategory.Interface)
override lazy val release: SoundSource = override lazy val release: Factory =
SoundSource.fromBuffer(SoundBuffers.MinecraftClickRelease, SoundCategory.Interface) SoundSource.fromBuffer(SoundBuffers.MinecraftClickRelease, SoundCategory.Interface)
} }
lazy val MachineFloppyInsert: SoundSource = lazy val MachineFloppyInsert: Factory =
SoundSource.fromBuffer(SoundBuffers.MachineFloppyInsert, SoundCategory.Environment) SoundSource.fromBuffer(SoundBuffers.MachineFloppyInsert, SoundCategory.Environment)
lazy val MachineFloppyEject: SoundSource = lazy val MachineFloppyEject: Factory =
SoundSource.fromBuffer(SoundBuffers.MachineFloppyEject, SoundCategory.Environment) SoundSource.fromBuffer(SoundBuffers.MachineFloppyEject, SoundCategory.Environment)
} }

View File

@ -5,7 +5,7 @@ import ocelot.desktop.color.Color
import ocelot.desktop.util.NumberUtils.ExtendedFloat import ocelot.desktop.util.NumberUtils.ExtendedFloat
import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.inventory.item.SelfDestructingCardItem import ocelot.desktop.inventory.item.SelfDestructingCardItem
import ocelot.desktop.node.BoomCardFxHandler.{ExpandIntensity, ExpandPeriod, FlickerAlpha, FlickerDuty, GlowAlpha, MaxSize, MinSize} import ocelot.desktop.node.BoomCardFxHandler._
import ocelot.desktop.ui.UiHandler import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.event.BrainEvent import ocelot.desktop.ui.event.BrainEvent
import ocelot.desktop.{ColorScheme, OcelotDesktop} import ocelot.desktop.{ColorScheme, OcelotDesktop}
@ -15,11 +15,11 @@ trait BoomCardFxHandler extends Node with PositionalSoundSourcesNode with SmokeP
private var boomPhase: Float = -1 private var boomPhase: Float = -1
private lazy val explosionSound = { private lazy val explosionSound = {
SoundSource.fromBuffer(SoundBuffers.MinecraftExplosion, SoundCategory.Environment) SoundSource.fromBuffer(SoundBuffers.MinecraftExplosion, SoundCategory.Environment).build()
} }
private lazy val countdownBeepSound = { private lazy val countdownBeepSound = {
SoundSource.fromBuffer(SoundBuffers.SelfDestructingCardCountdownBeep, SoundCategory.Environment) SoundSource.fromBuffer(SoundBuffers.SelfDestructingCardCountdownBeep, SoundCategory.Environment).build()
} }
override def soundSources: Seq[SoundSource] = super.soundSources ++ Seq( override def soundSources: Seq[SoundSource] = super.soundSources ++ Seq(

View File

@ -26,7 +26,7 @@ class TapeDriveNode(val tapeDrive: TapeDrive)
SoundBuffers.MachineTapeRewind, SoundBuffers.MachineTapeRewind,
SoundCategory.Records, SoundCategory.Records,
looping = true, looping = true,
) ).build()
private lazy val streams: (SoundStream, SoundSource) = Audio.newStream(SoundCategory.Records) private lazy val streams: (SoundStream, SoundSource) = Audio.newStream(SoundCategory.Records)
private def stream: SoundStream = streams._1 private def stream: SoundStream = streams._1

View File

@ -1,7 +1,7 @@
package ocelot.desktop.ui.widget package ocelot.desktop.ui.widget
import ocelot.desktop.ColorScheme import ocelot.desktop.ColorScheme
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.geometry.Size2D import ocelot.desktop.geometry.Size2D
import ocelot.desktop.graphics.Graphics import ocelot.desktop.graphics.Graphics
@ -66,5 +66,5 @@ class Button(tooltip: Option[Tooltip] = None) extends Widget with MouseHandler w
g.text(position.x + ((width - textWidth) / 2).round, position.y + 4, text) g.text(position.x + ((width - textWidth) / 2).round, position.y + 4, text)
} }
protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClick protected def clickSoundSource: ClickSoundSourceFactory = SoundSource.InterfaceClick
} }

View File

@ -1,7 +1,7 @@
package ocelot.desktop.ui.widget package ocelot.desktop.ui.widget
import ocelot.desktop.OcelotDesktop import ocelot.desktop.OcelotDesktop
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.geometry.Padding2D import ocelot.desktop.geometry.Padding2D
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.ChangeSimulationSpeedDialog.validateIntervalUs import ocelot.desktop.ui.widget.ChangeSimulationSpeedDialog.validateIntervalUs
@ -89,7 +89,7 @@ class ChangeSimulationSpeedDialog extends ModalDialog {
children :+= new PaddingBox( children :+= new PaddingBox(
new Button { new Button {
override def text: String = "Cancel" override def text: String = "Cancel"
override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow override protected def clickSoundSource: ClickSoundSourceFactory = SoundSource.InterfaceClickLow
override def onClick(): Unit = close() override def onClick(): Unit = close()
}, },
Padding2D(right = 8), Padding2D(right = 8),

View File

@ -1,6 +1,6 @@
package ocelot.desktop.ui.widget package ocelot.desktop.ui.widget
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.geometry.Padding2D import ocelot.desktop.geometry.Padding2D
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.modal.ModalDialog import ocelot.desktop.ui.widget.modal.ModalDialog
@ -24,7 +24,7 @@ class CloseConfirmationDialog extends ModalDialog {
children :+= new PaddingBox( children :+= new PaddingBox(
new Button { new Button {
override def text: String = "Cancel" override def text: String = "Cancel"
override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow override protected def clickSoundSource: ClickSoundSourceFactory = SoundSource.InterfaceClickLow
override def onClick(): Unit = close() override def onClick(): Unit = close()
}, },
Padding2D(left = 8), Padding2D(left = 8),

View File

@ -1,7 +1,7 @@
package ocelot.desktop.ui.widget package ocelot.desktop.ui.widget
import ocelot.desktop.ColorScheme import ocelot.desktop.ColorScheme
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.geometry.Size2D import ocelot.desktop.geometry.Size2D
import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.graphics.{Graphics, IconSource}
@ -196,7 +196,7 @@ class IconButton(
iconMixAnimation.update() iconMixAnimation.update()
} }
protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClick protected def clickSoundSource: ClickSoundSourceFactory = SoundSource.InterfaceClick
} }
object IconButton { object IconButton {

View File

@ -1,6 +1,6 @@
package ocelot.desktop.ui.widget package ocelot.desktop.ui.widget
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.geometry.Padding2D import ocelot.desktop.geometry.Padding2D
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.modal.ModalDialog import ocelot.desktop.ui.widget.modal.ModalDialog
@ -43,7 +43,7 @@ class InputDialog(
children :+= new Filler children :+= new Filler
children :+= new Button { children :+= new Button {
override def text: String = "Cancel" override def text: String = "Cancel"
override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow override protected def clickSoundSource: ClickSoundSourceFactory = SoundSource.InterfaceClickLow
override def onClick(): Unit = close() override def onClick(): Unit = close()
} }
children :+= new PaddingBox( children :+= new PaddingBox(

View File

@ -1,7 +1,7 @@
package ocelot.desktop.ui.widget package ocelot.desktop.ui.widget
import ocelot.desktop.ColorScheme import ocelot.desktop.ColorScheme
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.geometry.{Padding2D, Size2D} import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.Graphics import ocelot.desktop.graphics.Graphics
@ -51,5 +51,5 @@ class MenuBarButton(label: String, handler: () => Unit = () => {}) extends Widge
drawChildren(g) drawChildren(g)
} }
protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClick protected def clickSoundSource: ClickSoundSourceFactory = SoundSource.InterfaceClick
} }

View File

@ -1,6 +1,6 @@
package ocelot.desktop.ui.widget package ocelot.desktop.ui.widget
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.geometry.Padding2D import ocelot.desktop.geometry.Padding2D
import ocelot.desktop.node.nodes.ScreenNode import ocelot.desktop.node.nodes.ScreenNode
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.LinearLayout
@ -77,7 +77,7 @@ class ScreenAspectRatioDialog(screenNode: ScreenNode) extends ModalDialog {
children :+= new PaddingBox( children :+= new PaddingBox(
new Button { new Button {
override def text: String = "Cancel" override def text: String = "Cancel"
override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow override protected def clickSoundSource: ClickSoundSourceFactory = SoundSource.InterfaceClickLow
override def onClick(): Unit = close() override def onClick(): Unit = close()
}, },
Padding2D(right = 8), Padding2D(right = 8),

View File

@ -1,7 +1,7 @@
package ocelot.desktop.ui.widget package ocelot.desktop.ui.widget
import ocelot.desktop.ColorScheme import ocelot.desktop.ColorScheme
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.util.NumberUtils.ExtendedFloat import ocelot.desktop.util.NumberUtils.ExtendedFloat
import ocelot.desktop.geometry.Size2D import ocelot.desktop.geometry.Size2D
@ -106,5 +106,5 @@ class Slider(var value: Float, val text: String, val snapPoints: Int = 0)
g.text(position.x + ((width - textWidth) / 2).round, position.y + 4, formatText) g.text(position.x + ((width - textWidth) / 2).round, position.y + 4, formatText)
} }
protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceTick protected def clickSoundSource: ClickSoundSourceFactory = SoundSource.InterfaceTick
} }

View File

@ -1,7 +1,7 @@
package ocelot.desktop.ui.widget package ocelot.desktop.ui.widget
import ocelot.desktop.ColorScheme import ocelot.desktop.ColorScheme
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.geometry.{Padding2D, Size2D} import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.ui.UiHandler import ocelot.desktop.ui.UiHandler
@ -66,7 +66,7 @@ class TunnelDialog(
children :+= new Filler children :+= new Filler
children :+= new Button { children :+= new Button {
override def text: String = "Cancel" override def text: String = "Cancel"
override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow override protected def clickSoundSource: ClickSoundSourceFactory = SoundSource.InterfaceClickLow
override def onClick(): Unit = close() override def onClick(): Unit = close()
} }
children :+= new PaddingBox( children :+= new PaddingBox(

View File

@ -1,7 +1,7 @@
package ocelot.desktop.ui.widget.contextmenu package ocelot.desktop.ui.widget.contextmenu
import ocelot.desktop.ColorScheme import ocelot.desktop.ColorScheme
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.geometry.{Padding2D, Size2D} import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.graphics.{Graphics, IconSource}
@ -16,8 +16,8 @@ class ContextMenuEntry(
label: String, label: String,
icon: Option[ContextMenuIcon] = None, icon: Option[ContextMenuIcon] = None,
onClick: () => Unit = () => {}, onClick: () => Unit = () => {},
sound: ClickSoundSource = SoundSource.InterfaceClick, sound: ClickSoundSourceFactory = SoundSource.InterfaceClick,
soundDisabled: ClickSoundSource = SoundSource.InterfaceClickLow, soundDisabled: ClickSoundSourceFactory = SoundSource.InterfaceClickLow,
) extends Widget with MouseHandler with HoverHandler { ) extends Widget with MouseHandler with HoverHandler {
private[contextmenu] val alpha = new ValueAnimation(0f, 10f) private[contextmenu] val alpha = new ValueAnimation(0f, 10f)
@ -132,7 +132,7 @@ class ContextMenuEntry(
g.restore() g.restore()
} }
protected def clickSoundSource: ClickSoundSource = protected def clickSoundSource: ClickSoundSourceFactory =
if (isEnabled) sound else soundDisabled if (isEnabled) sound else soundDisabled
} }
@ -172,7 +172,7 @@ object ContextMenuEntry {
def apply( def apply(
label: String, label: String,
icon: IconSource, icon: IconSource,
sound: ClickSoundSource, sound: ClickSoundSourceFactory,
)(onClick: => Unit): ContextMenuEntry = { )(onClick: => Unit): ContextMenuEntry = {
new ContextMenuEntry( new ContextMenuEntry(
label, label,

View File

@ -1,7 +1,7 @@
package ocelot.desktop.ui.widget.settings package ocelot.desktop.ui.widget.settings
import ocelot.desktop.{ColorScheme, Settings} import ocelot.desktop.{ColorScheme, Settings}
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.geometry.{Padding2D, Size2D} import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.Graphics import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.LinearLayout
@ -39,7 +39,7 @@ class SettingsDialog extends ModalDialog {
children :+= new Button { children :+= new Button {
override def text: String = "Cancel" override def text: String = "Cancel"
override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow override protected def clickSoundSource: ClickSoundSourceFactory = SoundSource.InterfaceClickLow
override def onClick(): Unit = { override def onClick(): Unit = {
resetSettings() resetSettings()
close() close()

View File

@ -1,7 +1,7 @@
package ocelot.desktop.ui.widget.verticalmenu package ocelot.desktop.ui.widget.verticalmenu
import ocelot.desktop.ColorScheme import ocelot.desktop.ColorScheme
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.geometry.{Padding2D, Size2D} import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.graphics.{Graphics, IconSource}
@ -68,5 +68,5 @@ class VerticalMenuButton(icon: IconSource, label: String, handler: VerticalMenuB
drawChildren(g) drawChildren(g)
} }
protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClick protected def clickSoundSource: ClickSoundSourceFactory = SoundSource.InterfaceClick
} }

View File

@ -7,7 +7,7 @@ trait AudibleComputerAware extends ComputerAware {
SoundBuffers.MachineComputerRunning, SoundBuffers.MachineComputerRunning,
SoundCategory.Environment, SoundCategory.Environment,
looping = true, looping = true,
) ).build()
def updateRunningSound(): Unit = { def updateRunningSound(): Unit = {
if (!computer.machine.isRunning && soundComputerRunning.playing) { if (!computer.machine.isRunning && soundComputerRunning.playing) {

View File

@ -1,6 +1,6 @@
package ocelot.desktop.windows package ocelot.desktop.windows
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.geometry.{Padding2D, Size2D} import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.inventory.item.ServerItem import ocelot.desktop.inventory.item.ServerItem
@ -219,7 +219,7 @@ class ComputerWindow(computerAware: ComputerAware) extends BasicWindow {
override def onReleased(): Unit = computerAware.turnOff() override def onReleased(): Unit = computerAware.turnOff()
override protected def clickSoundSource: ClickSoundSource = SoundSource.MinecraftClick override protected def clickSoundSource: ClickSoundSourceFactory = SoundSource.MinecraftClick
} }
}, },
Padding2D( Padding2D(

View File

@ -1,7 +1,7 @@
package ocelot.desktop.windows package ocelot.desktop.windows
import ocelot.desktop.ColorScheme import ocelot.desktop.ColorScheme
import ocelot.desktop.audio.{ClickSoundSource, SoundSource} import ocelot.desktop.audio.{ClickSoundSourceFactory, SoundSource}
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.geometry.{Padding2D, Rect2D, Size2D} import ocelot.desktop.geometry.{Padding2D, Rect2D, Size2D}
import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.graphics.{Graphics, IconSource}
@ -256,7 +256,7 @@ class RackWindow(rackNode: RackNode) extends PanelWindow {
g.text(x, y, text) g.text(x, y, text)
} }
override protected def clickSoundSource: ClickSoundSource = SoundSource.MinecraftClick override protected def clickSoundSource: ClickSoundSourceFactory = SoundSource.MinecraftClick
}, },
Padding2D(left = -15, top = 45), Padding2D(left = -15, top = 45),
) )

View File

@ -1,6 +1,6 @@
package ocelot.desktop.windows package ocelot.desktop.windows
import ocelot.desktop.audio.{Audio, ClickSoundSource, SoundBuffers, SoundCategory, SoundSource} import ocelot.desktop.audio.{Audio, ClickSoundSourceFactory, SoundBuffers, SoundCategory, SoundSource}
import ocelot.desktop.color.{Color, RGBAColorNorm} import ocelot.desktop.color.{Color, RGBAColorNorm}
import ocelot.desktop.geometry.{Padding2D, Size2D} import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.graphics.{Graphics, IconSource}
@ -143,7 +143,7 @@ class TapeDriveWindow(val tapeDriveNode: TapeDriveNode) extends PanelWindow {
} }
} }
override protected def clickSoundSource: ClickSoundSource = TapeButtonSound override protected def clickSoundSource: ClickSoundSourceFactory = TapeButtonSound
} }
} }
@ -158,17 +158,17 @@ class TapeDriveWindow(val tapeDriveNode: TapeDriveNode) extends PanelWindow {
} }
object TapeDriveWindow { object TapeDriveWindow {
private object TapeButtonSound extends ClickSoundSource { private object TapeButtonSound extends ClickSoundSourceFactory {
override lazy val press: SoundSource = override lazy val press: SoundSource.Factory =
SoundSource.fromBuffer(SoundBuffers.MachineTapeButtonPress, SoundCategory.Environment) SoundSource.fromBuffer(SoundBuffers.MachineTapeButtonPress, SoundCategory.Environment)
override lazy val release: SoundSource = override lazy val release: SoundSource.Factory =
SoundSource.fromBuffer(SoundBuffers.MachineTapeButtonRelease, SoundCategory.Environment) SoundSource.fromBuffer(SoundBuffers.MachineTapeButtonRelease, SoundCategory.Environment)
} }
private lazy val TapeInsert: SoundSource = private lazy val TapeInsert: SoundSource.Factory =
SoundSource.fromBuffer(SoundBuffers.MachineTapeInsert, SoundCategory.Environment) SoundSource.fromBuffer(SoundBuffers.MachineTapeInsert, SoundCategory.Environment)
private lazy val TapeEject: SoundSource = private lazy val TapeEject: SoundSource.Factory =
SoundSource.fromBuffer(SoundBuffers.MachineTapeEject, SoundCategory.Environment) SoundSource.fromBuffer(SoundBuffers.MachineTapeEject, SoundCategory.Environment)
} }