diff --git a/src/main/java/org/wysko/midis2jam2/midi/MidiFile.java b/src/main/java/org/wysko/midis2jam2/midi/MidiFile.java index f0834896..a47eef66 100644 --- a/src/main/java/org/wysko/midis2jam2/midi/MidiFile.java +++ b/src/main/java/org/wysko/midis2jam2/midi/MidiFile.java @@ -53,6 +53,8 @@ public MidiFile() { public double length; + public String name; + /** * Reads a MIDI file and parses pertinent information. * @@ -134,6 +136,7 @@ public static MidiFile readMidiFile(File midiFile) throws IOException, InvalidMi } } file.length = file.eventInSeconds(max); + file.name = midiFile.getName(); return file; } diff --git a/src/main/kotlin/org/wysko/midis2jam2/DesktopMidis2jam2.kt b/src/main/kotlin/org/wysko/midis2jam2/DesktopMidis2jam2.kt index 23d3840d..b1acb2d0 100644 --- a/src/main/kotlin/org/wysko/midis2jam2/DesktopMidis2jam2.kt +++ b/src/main/kotlin/org/wysko/midis2jam2/DesktopMidis2jam2.kt @@ -151,6 +151,7 @@ class DesktopMidis2jam2( standController.tick() lyricController.tick(timeSinceStart) autocamController.tick(timeSinceStart, tpf) + hudController.tick(timeSinceStart, fade.value) preventCameraFromLeaving(app.camera) /* This is a hack to prevent the first few frames from updating the timeSinceStart variable. */ diff --git a/src/main/kotlin/org/wysko/midis2jam2/Midis2jam2.kt b/src/main/kotlin/org/wysko/midis2jam2/Midis2jam2.kt index 1b720db0..89f335f1 100644 --- a/src/main/kotlin/org/wysko/midis2jam2/Midis2jam2.kt +++ b/src/main/kotlin/org/wysko/midis2jam2/Midis2jam2.kt @@ -207,6 +207,7 @@ abstract class Midis2jam2( currentCamera = Camera.CAMERA_1A debugTextController = DebugTextController(this) + hudController = HudController(this) super.initialize(stateManager, app) } @@ -284,6 +285,9 @@ abstract class Midis2jam2( /** The autocam controller. */ lateinit var autocamController: AutoCamController + /** The HUD controller. */ + lateinit var hudController: HudController + /** * When the MIDI sequence ends, the [timeSinceStart] is recorded to this variable to know when to close the * app (three seconds after the end). diff --git a/src/main/kotlin/org/wysko/midis2jam2/world/HudController.kt b/src/main/kotlin/org/wysko/midis2jam2/world/HudController.kt new file mode 100644 index 00000000..37eee5d9 --- /dev/null +++ b/src/main/kotlin/org/wysko/midis2jam2/world/HudController.kt @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2022 Jacob Wysko + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +package org.wysko.midis2jam2.world + +import com.jme3.font.BitmapText +import com.jme3.math.ColorRGBA +import com.jme3.math.Vector3f +import com.jme3.scene.Node +import org.wysko.midis2jam2.Midis2jam2 + +private const val VERTICAL_FILLBAR_SCALE = 0.7f +private const val FILLBAR_LOCATION_OFFSET = 3f +private const val FILLBAR_WIDTH = 16 +private const val FILLBAR_BOX_WIDTH = 512 +private const val MAXIMUM_FILLBAR_SCALE = (FILLBAR_BOX_WIDTH - (FILLBAR_LOCATION_OFFSET * 2)) / FILLBAR_WIDTH + +/** + * Displays the fillbar and file name on-screen. + * + * @param context context to the main class + */ +class HudController(val context: Midis2jam2) { + + /** + * The node that contains the fillbar and text. + */ + private val node: Node = Node().also { + context.app.guiNode.attachChild(it) + it.move(10f, 10f, 0f) + } + + /** + * The name text. + */ + private val text = BitmapText(context.assetManager.loadFont("Interface/Fonts/Default.fnt")).apply { + node.attachChild(this) + text = context.file.name + this.move(0f, 40f, 0f) + color = ColorRGBA(1f, 1f, 1f, 1f) + } + + /** + * The red fillbar. + */ + private val fillbar = context.assetManager.loadSprite("SongFillbar.bmp").also { + node.attachChild(it) + it.move(FILLBAR_LOCATION_OFFSET, FILLBAR_LOCATION_OFFSET, 1f) + + } + + init { + context.assetManager.loadSprite("SongFillbarBox.bmp").also { + node.attachChild(it) + } + } + + /** + * Updates animation. + */ + fun tick(timeSinceStart: Double, fadeValue: Float) { + fillbar.localScale = Vector3f( + (MAXIMUM_FILLBAR_SCALE * (timeSinceStart / context.file.length)).toFloat(), + VERTICAL_FILLBAR_SCALE, + 1f + ) + node.children.forEach { + when (it) { + is Sprite -> { + it.opacity = fadeValue + } + is BitmapText -> { + it.color = ColorRGBA(1f, 1f, 1f, fadeValue) + } + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/wysko/midis2jam2/world/Jme3AssetLoading.kt b/src/main/kotlin/org/wysko/midis2jam2/world/Jme3AssetLoading.kt index 009b699d..b3d2dc5d 100644 --- a/src/main/kotlin/org/wysko/midis2jam2/world/Jme3AssetLoading.kt +++ b/src/main/kotlin/org/wysko/midis2jam2/world/Jme3AssetLoading.kt @@ -24,6 +24,7 @@ import com.jme3.scene.Spatial import org.wysko.midis2jam2.util.MaterialType import org.wysko.midis2jam2.util.MaterialType.UNSHADED + /** The constant LIGHTING_MAT. */ const val LIGHTING_MAT: String = "Common/MatDefs/Light/Lighting.j3md" @@ -66,5 +67,8 @@ fun AssetManager.unshadedMaterial(texture: String): Material = Material(this, UN setTexture(COLOR_MAP, this@unshadedMaterial.loadTexture(texture.assetPrefix())) } +fun AssetManager.loadSprite(texture: String): Sprite = Sprite(this, texture.assetPrefix()) + + /** Prepends a string with "Assets/" if it isn't already. */ fun String.assetPrefix(): String = if (this.startsWith("Assets/")) this else "Assets/$this" diff --git a/src/main/kotlin/org/wysko/midis2jam2/world/PictureWithFade.kt b/src/main/kotlin/org/wysko/midis2jam2/world/PictureWithFade.kt new file mode 100644 index 00000000..aef9624a --- /dev/null +++ b/src/main/kotlin/org/wysko/midis2jam2/world/PictureWithFade.kt @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 Jacob Wysko + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +package org.wysko.midis2jam2.world + +import com.jme3.asset.AssetManager +import com.jme3.material.Material +import com.jme3.material.RenderState +import com.jme3.math.ColorRGBA +import com.jme3.scene.Node +import com.jme3.texture.Texture2D +import com.jme3.ui.Picture + +/** + * A type of [Picture] that allows for an easy to modify opacity setting. It is also wrapped within a [Node] so it is + * scalable. + */ +class Sprite(assetManager: AssetManager, texture: String) : Node() { + + private val picture: Picture = Picture(texture).apply { + (assetManager.loadTexture(texture) as Texture2D).also { + setTexture(assetManager, it, true) + setWidth(it.image.width.toFloat()) + setHeight(it.image.height.toFloat()) + } + material = this.material.clone().apply { + additionalRenderState.blendMode = RenderState.BlendMode.Alpha + } + }.also { + this.attachChild(it) + } + + /** + * The opacity of this sprite. + */ + var opacity: Float = 1f + set(value) { + this.picture.material.setColor("Color", ColorRGBA(1f, 1f, 1f, value)) + field = value + } + +} \ No newline at end of file