Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/label mapping #14

Merged
merged 5 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id("org.openjfx.javafxplugin") version "0.0.13"
id("org.openjfx.javafxplugin") version "0.1.0"
kotlin("jvm") version "1.9.10"
kotlin("plugin.serialization") version "1.9.10"
application
Expand Down Expand Up @@ -56,16 +56,16 @@ val javaFXOptions = the<org.openjfx.gradle.JavaFXOptions>()

dependencies {
implementation(project("qodat-api"))
implementation("org.jsoup:jsoup:1.15.4")
implementation("org.jsoup:jsoup:1.17.2")
implementation("us.ihmc:ihmc-javafx-toolkit:17-0.21.2")
implementation("org.jcodec:jcodec:0.2.5")
implementation("org.jcodec:jcodec-javase:0.2.5")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-javafx:1.6.4")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-javafx:1.8.0")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.5.0")
implementation("org.orbisgis:poly2tri-core:0.1.2")
implementation("com.displee:rs-cache-library:6.9")
implementation("com.displee:rs-cache-library:7.1.3")
implementation("org.joml:joml-primitives:1.10.0")
implementation("org.joml:joml:1.10.5")
implementation("no.tornado:tornadofx:1.7.20")
Expand Down
6 changes: 6 additions & 0 deletions src/main/kotlin/stan/qodat/Properties.kt
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ object Properties {
val osrsCachePath = SimpleObjectProperty(rootPath.get().resolve("caches/OS/rev203"))
val qodatCachePath = SimpleObjectProperty(rootPath.get().resolve("caches/qodat"))
val legacyCachePath = SimpleObjectProperty(rootPath.get().resolve("caches/667"))
val labelMappingPath = SimpleObjectProperty(rootPath.get().resolve("labels.json"))

val downloadsPath = SimpleObjectProperty(rootPath.get().resolve("downloads"))

Expand Down Expand Up @@ -139,6 +140,8 @@ object Properties {
val copyModelsFromNpc = SimpleBooleanProperty(true)
val copyAnimationsFromNpc = SimpleBooleanProperty(true)

val showIdAfterLabel = SimpleBooleanProperty(true)

fun bind(sessionManager: PropertiesManager) {

sessionManager.bind("anti-aliasing", antialiasing) {
Expand Down Expand Up @@ -204,12 +207,15 @@ object Properties {
sessionManager.bindPath("osrs-cache-path", osrsCachePath)
sessionManager.bindPath("qodat-cache-path", qodatCachePath)
sessionManager.bindPath("legacy-cache-path", legacyCachePath)
sessionManager.bindPath("label-mapping-path", labelMappingPath)
sessionManager.bindPath("main-data-path", projectFilesPath)
sessionManager.bindPath("exports-path", defaultExportsPath)

sessionManager.bindPath("last-wavefront-single-export-path", lastWaveFrontSingleExportPath)
sessionManager.bindPath("last-wavefront-sequence-export-path", lastWaveFrontSequenceExportPath)
sessionManager.bindPath("last-gif-export-path", lastGIFExportPath)
sessionManager.bindPath("last-sprite-export-path", lastSpriteExportPath)

sessionManager.bindBoolean("show-id-after-label", showIdAfterLabel)
}
}
76 changes: 70 additions & 6 deletions src/main/kotlin/stan/qodat/scene/control/LabeledHBox.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import javafx.beans.property.SimpleStringProperty
import javafx.geometry.Pos
import javafx.scene.control.Label
import javafx.scene.layout.HBox
import javafx.scene.paint.Color
import javafx.scene.text.Font
import javafx.scene.text.FontWeight
import stan.qodat.Properties
import stan.qodat.util.LabelMapping
import tornadofx.*
import kotlin.error

/**
* Represents a [HBox] containing a [Label] bound to the text property.
Expand All @@ -12,15 +19,72 @@ import javafx.scene.layout.HBox
* @since 31/01/2021
*/
class LabeledHBox(
textProperty: SimpleStringProperty,
private val originalValueProperty: SimpleStringProperty,
spacing: Double = 10.0,
alignment: Pos = Pos.CENTER_LEFT
alignment: Pos = Pos.CENTER_LEFT,
private val labelPrefix: String? = null
) : HBox(spacing) {

val label = Label()
private val actualTextProperty = stringProperty(mappingOrOriginal())

val editableValueProperty = stringProperty(mappingOrNull()?:"").apply {
onChange {
if (it != null) {
LabelMapping[key()] = it
actualTextProperty.value = it.ifBlank { originalValueProperty.value }
}
}
}

private fun mappingOrOriginal() =
mappingOrNull()?: originalValueProperty.value
private fun mappingOrNull() =
labelPrefix?.let { LabelMapping[key()] }
private fun key() =
"${labelPrefix ?: error("Label prefix is required for editable labeled hbox!")}.${originalValueProperty.value}"

val editableProperty = booleanProperty(false)

init {
this.alignment = alignment
label.textProperty().bind(textProperty)
children.add(label)
editableProperty.onChange { updateChildren() }
focusedProperty().onChange { if (!it) editableProperty.set(false) }
updateChildren()
}

private fun LabeledHBox.updateChildren() {
children.clear()
if (editableProperty.get()) {
textfield(editableValueProperty) {
focusedProperty().onChange {
if (!it)
editableProperty.set(false)
}
setOnKeyPressed {
if (it.code.name == "ENTER")
editableProperty.set(false)
}
}
} else {
if (actualTextProperty.value.isNullOrBlank()) {
actualTextProperty.value = originalValueProperty.value
}
text(actualTextProperty) {
font = Font.font("Menlo", FontWeight.BOLD, 13.0)
fill = Color(214 / 255.0, 214 / 255.0, 214 / 255.0, 1.0)
if (labelPrefix != null) {
onDoubleClick {
editableProperty.set(true)
}
}
}
if (actualTextProperty.value != originalValueProperty.value && Properties.showIdAfterLabel.value) {
text(originalValueProperty) {
font = Font.font("Menlo", FontWeight.EXTRA_LIGHT, 13.0)
fill = Color.web("#A4B8C8")
}
}
}
}
}
}

22 changes: 17 additions & 5 deletions src/main/kotlin/stan/qodat/scene/runescape/animation/Animation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import stan.qodat.scene.transform.Transformable
import stan.qodat.scene.transform.Transformer
import stan.qodat.task.BackgroundTasks
import stan.qodat.util.Searchable
import tornadofx.contextmenu
import tornadofx.item
import tornadofx.stringBinding

/**
* Represents a [Transformer] for [Model] objects.
Expand All @@ -35,7 +38,7 @@ import stan.qodat.util.Searchable
* @since 28/01/2021
*/
class Animation(
label: String,
private val label: String,
private val definition: AnimationDefinition? = null,
private val cache: Cache? = null
) : Transformer<AnimationFrame>, Searchable, ViewNodeProvider, Encoder {
Expand All @@ -49,6 +52,7 @@ class Animation(
val treeItemProperty = SimpleObjectProperty<AnimationTreeItem>()
val exportFrameArchiveId = SimpleIntegerProperty()
val labelProperty = SimpleStringProperty(label)
val nameProperty = SimpleStringProperty(label)
val idProperty = SimpleIntegerProperty()
val loopOffsetProperty = SimpleIntegerProperty(definition?.loopOffset ?: -1)
val leftHandItemProperty = SimpleIntegerProperty(definition?.leftHandItem ?: -1)
Expand Down Expand Up @@ -114,12 +118,20 @@ class Animation(
}
}

override fun getName() = labelProperty.get()
override fun getName() = nameProperty.get()

override fun getViewNode(): Node {
if (!this::viewBox.isInitialized) {
viewBox = LabeledHBox(labelProperty).apply {
label.contextMenu = ContextMenu().apply {
viewBox = LabeledHBox(labelProperty, labelPrefix = "animation").apply {
nameProperty.bind(editableValueProperty.stringBinding(labelProperty) {
"${editableValueProperty.get()} (${labelProperty.get()})"
})
contextmenu {
item("Rename") {
setOnAction {
editableProperty.set(true)
}
}
menu("export") {
menuItem("GIF") {
BackgroundTasks.submit(
Expand Down Expand Up @@ -163,4 +175,4 @@ class Animation(
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ import stan.qodat.scene.transform.Transformable
abstract class AnimatedEntity<D : AnimatedEntityDefinition>(
cache: Cache,
definition: D,
private val animationProvider: D.() -> Array<Animation>
) : Entity<D>(cache, definition), Transformable, GroupableTransformable {
private val animationProvider: D.() -> Array<Animation>,
labelPrefix: String? = null,
) : Entity<D>(cache, definition, labelPrefix), Transformable, GroupableTransformable {

private lateinit var animations: Array<Animation>
// private lateinit var skeletons: Map<Int, AnimationSkeleton>
Expand Down Expand Up @@ -58,4 +59,4 @@ abstract class AnimatedEntity<D : AnimatedEntityDefinition>(
for (model in getModels())
model.animate(frame)
}
}
}
5 changes: 3 additions & 2 deletions src/main/kotlin/stan/qodat/scene/runescape/entity/Entity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ import stan.qodat.util.getMaterial
*/
abstract class Entity<D : EntityDefinition>(
protected val cache: Cache,
val definition: D
val definition: D,
val labelPrefix: String? = null
) : Exportable, SceneNodeProvider, ViewNodeProvider, TreeItemProvider {

private var modelGroup: Group? = null
Expand Down Expand Up @@ -142,7 +143,7 @@ abstract class Entity<D : EntityDefinition>(
override fun getViewNode(): Node {
if (!this::viewBox.isInitialized) {
val optionalInt = definition.getOptionalId()
val box = LabeledHBox(labelProperty)
val box = LabeledHBox(labelProperty, labelPrefix = labelPrefix)
viewBox = if (optionalInt.isPresent)
HBox().apply {
val id = optionalInt.asInt.toString()
Expand Down
6 changes: 3 additions & 3 deletions src/main/kotlin/stan/qodat/scene/runescape/entity/Item.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package stan.qodat.scene.runescape.entity

import stan.qodat.Properties
import qodat.cache.Cache
import qodat.cache.Encoder
import qodat.cache.definition.ItemDefinition
import stan.qodat.Properties

/**
* TODO: add documentation
Expand All @@ -12,7 +12,7 @@ import qodat.cache.definition.ItemDefinition
* @since 28/01/2021
*/
class Item(cache: Cache, definition: ItemDefinition)
: Entity<ItemDefinition>(cache, definition), Encoder {
: Entity<ItemDefinition>(cache, definition, "item"), Encoder {

override fun property() = Properties.selectedItemName
}
}
6 changes: 3 additions & 3 deletions src/main/kotlin/stan/qodat/scene/runescape/entity/NPC.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package stan.qodat.scene.runescape.entity

import stan.qodat.Properties
import qodat.cache.Cache
import qodat.cache.EncodeResult
import qodat.cache.Encoder
import qodat.cache.definition.NPCDefinition
import stan.qodat.Properties
import stan.qodat.cache.impl.oldschool.OldschoolCacheRuneLite
import stan.qodat.scene.runescape.animation.Animation
import java.io.UnsupportedEncodingException
Expand All @@ -19,7 +19,7 @@ class NPC(
cache: Cache = OldschoolCacheRuneLite,
definition: NPCDefinition,
animationProvider: NPCDefinition.() -> Array<Animation>
) : AnimatedEntity<NPCDefinition>(cache, definition, animationProvider), Encoder {
) : AnimatedEntity<NPCDefinition>(cache, definition, animationProvider, "npc"), Encoder {

override fun encode(format: Cache) : EncodeResult {
throw UnsupportedEncodingException()
Expand All @@ -28,4 +28,4 @@ class NPC(
override fun toString(): String = getName()

override fun property() = Properties.selectedNpcName
}
}
6 changes: 3 additions & 3 deletions src/main/kotlin/stan/qodat/scene/runescape/entity/Object.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package stan.qodat.scene.runescape.entity

import stan.qodat.Properties
import qodat.cache.Cache
import qodat.cache.EncodeResult
import qodat.cache.Encoder
import qodat.cache.definition.ObjectDefinition
import stan.qodat.Properties
import stan.qodat.cache.impl.oldschool.OldschoolCacheRuneLite
import stan.qodat.scene.runescape.animation.Animation
import java.io.UnsupportedEncodingException
Expand All @@ -19,11 +19,11 @@ class Object(
cache: Cache = OldschoolCacheRuneLite,
definition: ObjectDefinition,
animationProvider: ObjectDefinition.() -> Array<Animation>
) : AnimatedEntity<ObjectDefinition>(cache, definition, animationProvider), Encoder {
) : AnimatedEntity<ObjectDefinition>(cache, definition, animationProvider, "loc"), Encoder {

override fun encode(format: Cache) : EncodeResult {
throw UnsupportedEncodingException()
}

override fun property() = Properties.selectedObjectName
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ class SpotAnimation(
cache: Cache = OldschoolCacheRuneLite,
definition: SpotAnimationDefinition,
animationProvider: SpotAnimationDefinition.() -> Array<Animation>
) : AnimatedEntity<SpotAnimationDefinition>(cache, definition, animationProvider), Encoder {
) : AnimatedEntity<SpotAnimationDefinition>(cache, definition, animationProvider, labelPrefix = "spot_anim"), Encoder {

override fun toString(): String = getName()

override fun property() = Properties.selectedSpotAnimName
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/stan/qodat/scene/runescape/model/Model.kt
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ class Model(label: String,

override fun getViewNode(): Node {
if (!this::viewBox.isInitialized) {
viewBox = LabeledHBox(labelProperty)
viewBox = LabeledHBox(labelProperty, labelPrefix = "model")
}
return viewBox
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class InterfaceGroup(val cache: Cache, private val groupId: Int, val definitions
val nameProperty = SimpleStringProperty(idProperty.get().toString())

private val viewBox: HBox by lazy {
LabeledHBox(nameProperty)
LabeledHBox(nameProperty, labelPrefix = "widget")
}

private val sceneGroup: Group by lazy {
Expand All @@ -48,4 +48,4 @@ class InterfaceGroup(val cache: Cache, private val groupId: Int, val definitions

override fun treeItemExpandedProperty(): BooleanProperty =
Properties.treeItemInterfaceExpanded
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/stan/qodat/scene/runescape/ui/Sprite.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Sprite(val definition: SpriteDefinition) : SceneNodeProvider, ViewNodeProv
}

val viewNode: HBox by lazy {
LabeledHBox(nameProperty) .apply {
LabeledHBox(nameProperty, labelPrefix = "sprite").apply {
contextmenu {
styleClass += "wave-front-format-export-menu"
for (exportFormat in SpriteExportFormat.all)
Expand Down
Loading
Loading