Add iron note block

This commit is contained in:
LeshaInc 2023-03-19 17:43:06 +03:00
parent d04ecf156d
commit bcb617815d
No known key found for this signature in database
GPG Key ID: 7F51850974C1C795
11 changed files with 75 additions and 55 deletions

@ -1 +1 @@
Subproject commit 62e45f6c5dd19ddfbdbc0d4239529b91a011059b
Subproject commit 5d6dee430d6cd04f466d876f10f109b3a3d1057b

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -1,5 +1,5 @@
BackgroundPattern 0 0 304 304
BarSegment 476 105 16 4
BarSegment 493 105 16 4
ComputerMotherboard 305 0 79 70
Empty 9 316 1 1
EmptySlot 441 147 18 18
@ -8,7 +8,7 @@ KnobCenter 436 0 50 50
KnobLimits 305 71 50 50
ShadowBorder 0 305 1 24
ShadowCorner 424 122 24 24
TabArrow 441 105 8 14
TabArrow 458 105 8 14
buttons/BottomDrawerClose 460 147 18 18
buttons/BottomDrawerOpen 479 147 18 18
buttons/PowerOff 424 180 18 18
@ -102,11 +102,12 @@ nodes/ComputerOnOverlay 441 88 16 16
nodes/DiskDrive 458 88 16 16
nodes/DiskDriveActivity 475 88 16 16
nodes/DiskDriveFloppy 492 88 16 16
nodes/NewNode 356 105 16 16
nodes/NoteBlock 373 105 16 16
nodes/Relay 390 105 16 16
nodes/Screen 407 105 16 16
nodes/ScreenOnOverlay 424 105 16 16
nodes/IronNoteBlock 356 105 16 16
nodes/NewNode 373 105 16 16
nodes/NoteBlock 390 105 16 16
nodes/Relay 407 105 16 16
nodes/Screen 424 105 16 16
nodes/ScreenOnOverlay 441 105 16 16
panel/BorderB 8 305 4 4
panel/BorderL 63 305 4 2
panel/BorderR 13 305 4 4
@ -116,13 +117,13 @@ panel/CornerBR 28 305 4 4
panel/CornerTL 33 305 4 4
panel/CornerTR 38 305 4 4
panel/Fill 6 316 2 2
particles/Note 468 105 7 10
particles/Note 485 105 7 10
screen/BorderB 5 305 2 8
screen/BorderT 2 305 2 10
screen/CornerBL 365 236 8 8
screen/CornerBR 374 236 8 8
screen/CornerTL 450 105 8 10
screen/CornerTR 459 105 8 10
screen/CornerTL 467 105 8 10
screen/CornerTR 476 105 8 10
window/BorderDark 2 316 1 4
window/BorderLight 4 316 1 4
window/CloseButton 383 236 7 6

View File

@ -3,7 +3,7 @@ package ocelot.desktop
import buildinfo.BuildInfo
import li.flor.nativejfilechooser.NativeJFileChooser
import ocelot.desktop.audio._
import ocelot.desktop.node.nodes.NoteBlockNode
import ocelot.desktop.node.nodes.{IronNoteBlockNode, NoteBlockNode}
import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.swing.SplashScreen
import ocelot.desktop.ui.widget._
@ -384,10 +384,14 @@ object OcelotDesktop extends Logging {
}
EventBus.subscribe[NoteBlockTriggerEvent] { event =>
SoundSource.fromBuffer(SoundBuffers.NoteBlock(event.instrument), SoundCategory.Beep, pitch = NoteBlockNode.pitches(event.pitch)).play()
UiHandler.root.workspaceView.nodes.find(_.entity.node.address == event.address).get
.asInstanceOf[NoteBlockNode]
.addParticle(event.pitch)
SoundSource.fromBuffer(SoundBuffers.NoteBlock(event.instrument), SoundCategory.Beep,
pitch = NoteBlockNode.Pitches(event.pitch), volume = event.volume.toFloat.min(1f).max(0f)).play()
val node = UiHandler.root.workspaceView.nodes.find(_.entity.node.address == event.address).get
node match {
case nb: NoteBlockNode => nb.addParticle(event.pitch)
case nb: IronNoteBlockNode => nb.addParticle(event.pitch)
case _ =>
}
}
val soundFloppyAccess = SoundBuffers.MachineFloppyAccess.map(buffer => SoundSource.fromBuffer(buffer, SoundCategory.Environment))

View File

@ -78,7 +78,7 @@ object Audio extends Logging {
AL10.alSourcef(sourceId, AL10.AL_PITCH, source.pitch)
AL10.alSource3f(sourceId, AL10.AL_POSITION, 0f, 0f, 0f)
AL10.alSourcei(sourceId, AL10.AL_LOOPING, if (source.looping) AL10.AL_TRUE else AL10.AL_FALSE)
AL10.alSourcef(sourceId, AL10.AL_GAIN, SoundCategory.getSettingsValue(source.soundCategory) * Settings.get.volumeMaster)
AL10.alSourcef(sourceId, AL10.AL_GAIN, source.volume * SoundCategory.getSettingsValue(source.soundCategory) * Settings.get.volumeMaster)
AL10.alSourcePlay(sourceId)
val state = SourceState(sourceId, associatedBufferId = if (isAssociated) bufferId else -1, SoundSource.Status.Playing)
@ -105,7 +105,7 @@ object Audio extends Logging {
if (isDisabled) return
sources.filterInPlace { case (source, state) =>
AL10.alSourcef(state.sourceId, AL10.AL_GAIN, SoundCategory.getSettingsValue(source.soundCategory) * Settings.get.volumeMaster)
AL10.alSourcef(state.sourceId, AL10.AL_GAIN, source.volume * SoundCategory.getSettingsValue(source.soundCategory) * Settings.get.volumeMaster)
AL10.alGetSourcei(state.sourceId, AL10.AL_SOURCE_STATE) match {
case AL10.AL_PLAYING =>
state.status = SoundSource.Status.Playing

View File

@ -5,7 +5,8 @@ import java.time.Duration
class SoundSource(val kind: SoundSource.Kind,
val soundCategory: SoundCategory.Value,
val looping: Boolean,
val pitch: Float) {
val pitch: Float,
val volume: Float) {
def duration: Duration = {
val seconds = kind match {
@ -55,13 +56,13 @@ object SoundSource {
case class KindSoundSamples(samples: SoundSamples) extends Kind
def fromBuffer(buffer: SoundBuffer, soundCategory: SoundCategory.Value,
looping: Boolean = false, pitch: Float = 1f): SoundSource = {
new SoundSource(SoundSource.KindSoundBuffer(buffer), soundCategory, looping, pitch)
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,
looping: Boolean = false, pitch: Float = 1f): SoundSource = {
new SoundSource(SoundSource.KindSoundSamples(samples), soundCategory, looping, pitch)
looping: Boolean = false, pitch: Float = 1f, volume: Float = 1f): SoundSource = {
new SoundSource(SoundSource.KindSoundSamples(samples), soundCategory, looping, pitch, volume)
}
object Status extends Enumeration {

View File

@ -1,7 +1,7 @@
package ocelot.desktop.node
import ocelot.desktop.node.nodes._
import totoro.ocelot.brain.entity.{Cable, Case, FloppyDiskDrive, NoteBlock, Relay, Screen}
import totoro.ocelot.brain.entity.{Cable, Case, FloppyDiskDrive, IronNoteBlock, NoteBlock, Relay, Screen}
import scala.collection.mutable
@ -39,4 +39,8 @@ object NodeRegistry {
register(NodeType("NoteBlock", "nodes/NoteBlock", -1, () => {
new NoteBlockNode(new NoteBlock)
}))
register(NodeType("IronNoteBlock", "nodes/IronNoteBlock", -1, () => {
new IronNoteBlockNode(new IronNoteBlock)
}))
}

View File

@ -0,0 +1,7 @@
package ocelot.desktop.node.nodes
import totoro.ocelot.brain.entity.IronNoteBlock
class IronNoteBlockNode(val ironNoteBlock: IronNoteBlock) extends NoteBlockNodeBase(ironNoteBlock) {
override def icon: String = "nodes/IronNoteBlock"
}

View File

@ -1,25 +1,16 @@
package ocelot.desktop.node.nodes
import ocelot.desktop.geometry.{Size2D, Vector2D}
import ocelot.desktop.graphics.Graphics
import ocelot.desktop.node.Node
import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuSubmenu}
import ocelot.desktop.{ColorScheme, OcelotDesktop}
import totoro.ocelot.brain.entity.NoteBlock
import totoro.ocelot.brain.entity.traits.Environment
import totoro.ocelot.brain.nbt.NBTTagCompound
import scala.collection.mutable
class NoteBlockNode(val noteBlock: NoteBlock) extends Node(noteBlock) {
class NoteBlockNode(val noteBlock: NoteBlock) extends NoteBlockNodeBase(noteBlock) {
override def icon: String = "nodes/NoteBlock"
override def setupContextMenu(menu: ContextMenu): Unit = {
menu.addEntry(new ContextMenuSubmenu("Instrument") {
{
val maxLen = NoteBlockNode.instruments.map(_._2.length).max
for ((instrument, name) <- NoteBlockNode.instruments) {
val maxLen = NoteBlockNode.Instruments.map(_._2.length).max
for ((instrument, name) <- NoteBlockNode.Instruments) {
val dot = if (noteBlock.instrument == instrument) '•' else ' '
addEntry(new ContextMenuEntry(name.padTo(maxLen, ' ') + dot, () => noteBlock.instrument = instrument))
}
@ -29,31 +20,14 @@ class NoteBlockNode(val noteBlock: NoteBlock) extends Node(noteBlock) {
menu.addSeparator()
super.setupContextMenu(menu)
}
private val particles = mutable.ArrayBuffer[(Float, Int)]()
def addParticle(pitch: Int): Unit = {
synchronized {
particles += ((0f, pitch))
}
}
override def drawParticles(g: Graphics): Unit = synchronized {
for ((time, pitch) <- particles.reverseIterator) {
val col = ColorScheme("Note" + pitch).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)
}
particles.mapInPlace { case (t, p) => (t + 1.2f * UiHandler.dt, p) }
particles.filterInPlace(_._1 <= 1f)
}
}
object NoteBlockNode {
val pitches = List(
val Pitches: Seq[Float] = List(
0.500000f, 0.529732f, 0.561231f, 0.594604f, 0.629961f, 0.667420f, 0.707107f, 0.749154f, 0.793701f, 0.840896f, 0.890899f, 0.943874f,
1.059463f, 1.122462f, 1.189207f, 1.259921f, 1.334840f, 1.414214f, 1.498307f, 1.587401f, 1.681793f, 1.781797f, 1.887749f, 2.000000f)
val instruments = List(
private val Instruments = List(
("bass", "Bass (Wood)"),
("snare", "Snare Drum (Sand)"),
("hat", "Hi-hat (Glass)"),

View File

@ -0,0 +1,29 @@
package ocelot.desktop.node.nodes
import ocelot.desktop.ColorScheme
import ocelot.desktop.geometry.{Size2D, Vector2D}
import ocelot.desktop.graphics.Graphics
import ocelot.desktop.node.Node
import ocelot.desktop.ui.UiHandler
import totoro.ocelot.brain.entity.traits.{Entity, Environment}
import scala.collection.mutable
abstract class NoteBlockNodeBase(entity: Entity with Environment) extends Node(entity) {
private val particles = mutable.ArrayBuffer[(Float, Int)]()
def addParticle(pitch: Int): Unit = {
synchronized {
particles += ((0f, pitch))
}
}
override def drawParticles(g: Graphics): Unit = synchronized {
for ((time, pitch) <- particles.reverseIterator) {
val col = ColorScheme("Note" + pitch).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)
}
particles.mapInPlace { case (t, p) => (t + 1.2f * UiHandler.dt, p) }
particles.filterInPlace(_._1 <= 1f)
}
}