mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 01:16:46 -04:00
outsource javafx text component rendering
This commit is contained in:
parent
89e4254ddd
commit
e236585ef1
@ -90,13 +90,14 @@ object Minosoft {
|
||||
val taskWorker = TaskWorker(errorHandler = { _, error -> error.printStackTrace(); error.crash() }, forcePool = true)
|
||||
|
||||
MinosoftBoot.register(taskWorker)
|
||||
|
||||
taskWorker += WorkerTask(identifier = BootTasks.LANGUAGE_FILES, dependencies = arrayOf(BootTasks.PROFILES), executor = this::loadLanguageFiles)
|
||||
|
||||
if (!RunConfiguration.DISABLE_EROS) {
|
||||
javafx(taskWorker)
|
||||
}
|
||||
if (RunConfiguration.DISABLE_EROS && !RunConfiguration.DISABLE_RENDERING) {
|
||||
// eros is disabled, but rendering not, force initialize the desktop, otherwise eros will do so
|
||||
// eros is disabled, but rendering not, force initialize the desktop, because eros won't
|
||||
DefaultThreadPool += { SystemUtil.api = DesktopAPI() }
|
||||
}
|
||||
|
||||
@ -160,9 +161,8 @@ object Minosoft {
|
||||
}
|
||||
|
||||
private fun checkMacOS() {
|
||||
if (RunConfiguration.X_START_ON_FIRST_THREAD_SET && (!RunConfiguration.DISABLE_RENDERING || !RunConfiguration.DISABLE_EROS)) {
|
||||
Log.log(LogMessageType.GENERAL, LogLevels.WARN) { "You are using macOS. To use rendering you must not set the jvm argument §9-XstartOnFirstThread§r. Please remove it!" }
|
||||
ShutdownManager.shutdown(reason = AbstractShutdownReason.CRASH)
|
||||
}
|
||||
if (!RunConfiguration.X_START_ON_FIRST_THREAD_SET || !(!RunConfiguration.DISABLE_RENDERING || !RunConfiguration.DISABLE_EROS)) return
|
||||
Log.log(LogMessageType.GENERAL, LogLevels.WARN) { "You are using macOS. To use rendering you must not set the jvm argument §9-XstartOnFirstThread§r. Please remove it!" }
|
||||
ShutdownManager.shutdown(reason = AbstractShutdownReason.CRASH)
|
||||
}
|
||||
}
|
||||
|
@ -29,10 +29,8 @@ import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.KUtil.format
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.get
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.scene.Node
|
||||
|
||||
class BaseComponent : ChatComponent {
|
||||
class BaseComponent : ChatComponent, Iterable<ChatComponent> {
|
||||
val parts: MutableList<ChatComponent> = mutableListOf()
|
||||
|
||||
constructor(parts: MutableList<ChatComponent>) {
|
||||
@ -165,13 +163,6 @@ class BaseComponent : ChatComponent {
|
||||
return stringBuilder.toString()
|
||||
}
|
||||
|
||||
override fun getJavaFXText(nodes: ObservableList<Node>): ObservableList<Node> {
|
||||
for (part in parts) {
|
||||
part.getJavaFXText(nodes)
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
override fun obfuscate(): BaseComponent {
|
||||
for (part in parts) part.obfuscate(); return this
|
||||
}
|
||||
@ -284,4 +275,8 @@ class BaseComponent : ChatComponent {
|
||||
|
||||
return parts.toTypedArray()
|
||||
}
|
||||
|
||||
override fun iterator(): Iterator<ChatComponent> {
|
||||
return parts.iterator()
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,6 @@ import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil.text
|
||||
import de.bixilon.minosoft.util.json.Jackson
|
||||
import javafx.collections.FXCollections
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.scene.Node
|
||||
import javafx.scene.text.TextFlow
|
||||
|
||||
/**
|
||||
@ -48,17 +45,6 @@ interface ChatComponent {
|
||||
|
||||
fun getJson(): Any
|
||||
|
||||
/**
|
||||
* @return Returns a list of Nodes, drawable in JavaFX (TextFlow)
|
||||
*/
|
||||
fun getJavaFXText(nodes: ObservableList<Node>): ObservableList<Node>
|
||||
|
||||
/**
|
||||
* @return Returns a list of Nodes, drawable in JavaFX (TextFlow)
|
||||
*/
|
||||
val javaFXText: ObservableList<Node>
|
||||
get() = getJavaFXText(FXCollections.observableArrayList())
|
||||
|
||||
val textFlow: TextFlow
|
||||
get() {
|
||||
val textFlow = TextFlow()
|
||||
|
@ -14,8 +14,7 @@
|
||||
package de.bixilon.minosoft.data.text
|
||||
|
||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.scene.Node
|
||||
|
||||
object EmptyComponent : ChatComponent {
|
||||
override val ansi: String get() = ""
|
||||
override val legacy: String get() = ""
|
||||
@ -23,8 +22,6 @@ object EmptyComponent : ChatComponent {
|
||||
|
||||
override fun getJson(): Any = emptyList<Any>()
|
||||
|
||||
override fun getJavaFXText(nodes: ObservableList<Node>): ObservableList<Node> = nodes
|
||||
|
||||
override fun setFallbackColor(color: RGBColor) = this
|
||||
|
||||
override fun getTextAt(pointer: Int): TextComponent = throw IllegalArgumentException()
|
||||
|
@ -14,7 +14,6 @@ package de.bixilon.minosoft.data.text
|
||||
|
||||
import de.bixilon.kutil.enums.BitEnumSet
|
||||
import de.bixilon.kutil.json.MutableJsonObject
|
||||
import de.bixilon.minosoft.config.profile.profiles.eros.ErosProfileManager
|
||||
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
||||
import de.bixilon.minosoft.data.text.events.click.ClickEvent
|
||||
import de.bixilon.minosoft.data.text.events.hover.HoverEvent
|
||||
@ -23,15 +22,6 @@ import de.bixilon.minosoft.data.text.formatting.TextStyle
|
||||
import de.bixilon.minosoft.data.text.formatting.color.ChatColors
|
||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import javafx.animation.Animation
|
||||
import javafx.animation.KeyFrame
|
||||
import javafx.animation.Timeline
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.scene.Node
|
||||
import javafx.scene.paint.Color
|
||||
import javafx.scene.text.Text
|
||||
import javafx.util.Duration
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
|
||||
open class TextComponent(
|
||||
@ -118,63 +108,6 @@ open class TextComponent(
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
override fun getJavaFXText(nodes: ObservableList<Node>): ObservableList<Node> {
|
||||
val text = Text(this.message)
|
||||
val color = this.color
|
||||
if (color == null) {
|
||||
text.styleClass += "text-default-color"
|
||||
} else {
|
||||
if (ErosProfileManager.selected.text.colored) {
|
||||
text.fill = Color.rgb(color.red, color.green, color.blue)
|
||||
}
|
||||
}
|
||||
if (FormattingCodes.OBFUSCATED in formatting) {
|
||||
// ToDo: This is just slow
|
||||
val obfuscatedTimeline = if (ErosProfileManager.selected.text.obfuscated) {
|
||||
val index = AtomicInteger()
|
||||
Timeline(
|
||||
KeyFrame(Duration.millis(50.0), {
|
||||
val chars = text.text.toCharArray()
|
||||
for (i in chars.indices) {
|
||||
chars[i] = ProtocolDefinition.OBFUSCATED_CHARS[index.getAndIncrement() % ProtocolDefinition.OBFUSCATED_CHARS.size]
|
||||
}
|
||||
text.text = String(chars)
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
Timeline(
|
||||
KeyFrame(Duration.millis(500.0), {
|
||||
text.isVisible = false
|
||||
}),
|
||||
KeyFrame(Duration.millis(1000.0), {
|
||||
text.isVisible = true
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
obfuscatedTimeline.cycleCount = Animation.INDEFINITE
|
||||
obfuscatedTimeline.play()
|
||||
text.styleClass.add("obfuscated")
|
||||
}
|
||||
if (FormattingCodes.BOLD in formatting) {
|
||||
text.style += "-fx-font-weight: bold;"
|
||||
}
|
||||
if (FormattingCodes.STRIKETHROUGH in formatting) {
|
||||
text.style += "-fx-strikethrough: true;"
|
||||
}
|
||||
if (FormattingCodes.UNDERLINED in formatting) {
|
||||
text.style += "-fx-underline: true;"
|
||||
}
|
||||
if (FormattingCodes.ITALIC in formatting) {
|
||||
text.style += "-fx-font-style: italic;"
|
||||
}
|
||||
nodes.add(text)
|
||||
|
||||
clickEvent?.applyJavaFX(text)
|
||||
hoverEvent?.applyJavaFX(text)
|
||||
return nodes
|
||||
}
|
||||
|
||||
override fun getJson(): Any {
|
||||
if (message.isEmpty()) {
|
||||
return emptyMap<String, Any>()
|
||||
|
@ -28,6 +28,7 @@ import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
||||
import de.bixilon.minosoft.gui.eros.controller.EmbeddedJavaFXController
|
||||
import de.bixilon.minosoft.gui.eros.controller.JavaFXController
|
||||
import de.bixilon.minosoft.gui.eros.controller.JavaFXWindowController
|
||||
import de.bixilon.minosoft.gui.eros.util.text.JavaFXTextRenderer
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
import de.bixilon.minosoft.util.crash.freeze.FreezeDumpUtil
|
||||
import de.bixilon.minosoft.util.delegate.JavaFXDelegate.observeFX
|
||||
@ -148,7 +149,7 @@ object JavaFXUtil {
|
||||
var TextFlow.text: Any?
|
||||
get() = TODO("Can not get the text of a TextFlow (yet)")
|
||||
set(value) {
|
||||
this.children.setAll(IntegratedLanguage.LANGUAGE.translate(value).javaFXText)
|
||||
this.children.setAll(JavaFXTextRenderer.render(IntegratedLanguage.LANGUAGE.translate(value)))
|
||||
}
|
||||
|
||||
var TextField.placeholder: Any?
|
||||
|
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2023 Moritz Zwerger
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.eros.util.text
|
||||
|
||||
import de.bixilon.minosoft.config.profile.profiles.eros.ErosProfileManager
|
||||
import de.bixilon.minosoft.data.text.BaseComponent
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.data.text.EmptyComponent
|
||||
import de.bixilon.minosoft.data.text.TextComponent
|
||||
import de.bixilon.minosoft.data.text.formatting.FormattingCodes
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.logging.Log
|
||||
import de.bixilon.minosoft.util.logging.LogLevels
|
||||
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||
import javafx.animation.Animation
|
||||
import javafx.animation.KeyFrame
|
||||
import javafx.animation.Timeline
|
||||
import javafx.scene.Node
|
||||
import javafx.scene.paint.Color
|
||||
import javafx.scene.text.Text
|
||||
import javafx.util.Duration
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
interface JavaFXTextRenderer<C> {
|
||||
|
||||
fun render(nodes: MutableList<Node>, text: C)
|
||||
|
||||
|
||||
object BaseComponentRenderer : JavaFXTextRenderer<BaseComponent> {
|
||||
override fun render(nodes: MutableList<Node>, text: BaseComponent) {
|
||||
for (part in text.parts) {
|
||||
render(nodes, part)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TextComponentRenderer : JavaFXTextRenderer<TextComponent> {
|
||||
override fun render(nodes: MutableList<Node>, text: TextComponent) {
|
||||
val node = Text(text.message)
|
||||
val color = text.color
|
||||
if (color == null) {
|
||||
node.styleClass += "text-default-color"
|
||||
} else {
|
||||
if (ErosProfileManager.selected.text.colored) {
|
||||
node.fill = Color.rgb(color.red, color.green, color.blue)
|
||||
}
|
||||
}
|
||||
if (FormattingCodes.OBFUSCATED in text.formatting) {
|
||||
// ToDo: This is just slow
|
||||
val obfuscatedTimeline = if (ErosProfileManager.selected.text.obfuscated) {
|
||||
val index = AtomicInteger()
|
||||
Timeline(
|
||||
KeyFrame(Duration.millis(50.0), {
|
||||
val chars = node.text.toCharArray()
|
||||
for (i in chars.indices) {
|
||||
chars[i] = ProtocolDefinition.OBFUSCATED_CHARS[index.getAndIncrement() % ProtocolDefinition.OBFUSCATED_CHARS.size]
|
||||
}
|
||||
node.text = String(chars)
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
Timeline(
|
||||
KeyFrame(Duration.millis(500.0), {
|
||||
node.isVisible = false
|
||||
}),
|
||||
KeyFrame(Duration.millis(1000.0), {
|
||||
node.isVisible = true
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
obfuscatedTimeline.cycleCount = Animation.INDEFINITE
|
||||
obfuscatedTimeline.play()
|
||||
node.styleClass.add("obfuscated")
|
||||
}
|
||||
if (FormattingCodes.BOLD in text.formatting) {
|
||||
node.style += "-fx-font-weight: bold;"
|
||||
}
|
||||
if (FormattingCodes.STRIKETHROUGH in text.formatting) {
|
||||
node.style += "-fx-strikethrough: true;"
|
||||
}
|
||||
if (FormattingCodes.UNDERLINED in text.formatting) {
|
||||
node.style += "-fx-underline: true;"
|
||||
}
|
||||
if (FormattingCodes.ITALIC in text.formatting) {
|
||||
node.style += "-fx-font-style: italic;"
|
||||
}
|
||||
nodes.add(node)
|
||||
|
||||
text.clickEvent?.applyJavaFX(node)
|
||||
text.hoverEvent?.applyJavaFX(node)
|
||||
}
|
||||
}
|
||||
|
||||
companion object : JavaFXTextRenderer<ChatComponent> {
|
||||
|
||||
fun render(text: ChatComponent): MutableList<Node> {
|
||||
val nodes: MutableList<Node> = mutableListOf()
|
||||
render(nodes, text)
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
override fun render(nodes: MutableList<Node>, text: ChatComponent) = when (text) {
|
||||
is EmptyComponent -> Unit
|
||||
is BaseComponent -> BaseComponentRenderer.render(nodes, text)
|
||||
is TextComponent -> TextComponentRenderer.render(nodes, text)
|
||||
else -> Log.log(LogMessageType.OTHER, LogLevels.WARN) { "Can not render $text" }
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user