feat: 更新compose框架和kotlin版本

This commit is contained in:
2026-02-08 04:24:38 +08:00
parent cd0e21abc8
commit 33ae82a39c
8 changed files with 180 additions and 36 deletions

View File

@@ -14,5 +14,5 @@ archives_base_name=compose-ui-mod
# check this on https://modmuss50.me/fabric.html
fabric_version=0.114.0+1.21.4
kotlin.version=2.1.0
compose.version=1.6.10
kotlin.version=2.3.0
compose.version=1.10.0

View File

@@ -1,26 +0,0 @@
package net.airgame.compose.ui.client
import net.airgame.compose.ui.client.screen.ComposeScreen
import net.fabricmc.api.ClientModInitializer
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper
import net.minecraft.client.option.KeyBinding
import net.minecraft.client.util.InputUtil
class ComposeUIMod : ClientModInitializer {
private val bind = KeyBinding("测试", InputUtil.GLFW_KEY_G, "测试")
override fun onInitializeClient() {
KeyBindingHelper.registerKeyBinding(bind)
ClientTickEvents.END_CLIENT_TICK.register(ClientTickEvents.EndTick { client ->
while (bind.wasPressed()) {
val screen = ComposeScreen {
CenterUI {
TestUI()
}
}
client.setScreen(screen)
}
})
}
}

View File

@@ -0,0 +1,44 @@
package net.airgame.compose.ui.client
import net.airgame.compose.ui.client.screen.ComposeScreen
import net.airgame.compose.ui.client.screen.ComposeScreenV2
import net.fabricmc.api.ClientModInitializer
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper
import net.minecraft.client.option.KeyBinding
import net.minecraft.client.util.InputUtil
import org.slf4j.Logger
import org.slf4j.LoggerFactory
class ComposeUiMod : ClientModInitializer {
companion object {
val logger: Logger = LoggerFactory.getLogger("ComposeUiMod")
}
private val keyV1 = KeyBinding("测试V1", InputUtil.GLFW_KEY_G, "测试")
private val keyV2 = KeyBinding("测试V2", InputUtil.GLFW_KEY_J, "测试")
override fun onInitializeClient() {
KeyBindingHelper.registerKeyBinding(keyV1)
ClientTickEvents.END_CLIENT_TICK.register(ClientTickEvents.EndTick { client ->
if (keyV1.wasPressed()) {
val screen = ComposeScreen {
CenterUI {
TestUI()
}
}
client.setScreen(screen)
return@EndTick
}
if (keyV2.wasPressed()) {
val screen = ComposeScreenV2 {
CenterUI {
TestUI()
}
}
client.setScreen(screen)
return@EndTick
}
})
}
}

View File

@@ -2,9 +2,10 @@ package net.airgame.compose.ui.client
class DebugTimer {
var time = System.currentTimeMillis()
fun log(string: String) {
fun log(message: String) {
val now = System.currentTimeMillis()
println("$string: ${now - time} ms")
ComposeUiMod.logger.info("{}: {} ms", message, now - time)
time = now
}
}

View File

@@ -7,8 +7,8 @@ import androidx.compose.ui.graphics.Canvas
import androidx.compose.ui.graphics.asComposeCanvas
import androidx.compose.ui.input.pointer.PointerButton
import androidx.compose.ui.input.pointer.PointerEventType
import androidx.compose.ui.scene.CanvasLayersComposeScene
import androidx.compose.ui.scene.ComposeScene
import androidx.compose.ui.scene.MultiLayerComposeScene
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntSize
import com.mojang.blaze3d.platform.TextureUtil
@@ -74,7 +74,7 @@ class ComposeScreen(
private val mcGuiScale = MinecraftClient.getInstance().options.guiScale.value.toFloat()
private val fontScaleValue = 1f
private val scene: ComposeScene = MultiLayerComposeScene(
private val scene: ComposeScene = CanvasLayersComposeScene(
density = if (mcGuiScale <= 0) {
Density(1f, fontScaleValue)
} else {
@@ -209,7 +209,6 @@ class ComposeScreen(
): Boolean {
val x = MinecraftClient.getInstance().mouse.x.toFloat()
val y = MinecraftClient.getInstance().mouse.y.toFloat()
println("mouseScrolled: $x $y $horizontalAmount $verticalAmount")
mainScope.launch {
scene.sendPointerEvent(
PointerEventType.Scroll,

View File

@@ -0,0 +1,126 @@
package net.airgame.compose.ui.client.screen
import androidx.compose.runtime.Composable
import androidx.compose.ui.InternalComposeUiApi
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.pointer.PointerButton
import androidx.compose.ui.input.pointer.PointerEventType
import net.airgame.compose.ui.client.ComposeUiMod
import net.airgame.compose.ui.client.render.ComposeRender
import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.DrawContext
import net.minecraft.client.gui.screen.Screen
import net.minecraft.text.Text
@OptIn(InternalComposeUiApi::class)
class ComposeScreenV2(
val composeContent: @Composable (ComposeScreenV2) -> Unit
) : Screen(Text.literal("FrameRenderComposeScreen")) {
private val composeRender = ComposeRender()
private val windowWidth: Int get() = MinecraftClient.getInstance().window.width
private val windowHeight: Int get() = MinecraftClient.getInstance().window.height
private val guiScale: Float
get() {
val scale = MinecraftClient.getInstance().options.guiScale.value.toFloat()
if (scale <= 0) return 1f
return scale / 2
}
private val fontScale: Float get() = 1f
override fun init() {
composeRender.init(windowWidth, windowHeight, guiScale, fontScale) {
composeContent(this)
}
ComposeUiMod.logger.info(
"init: width={} height={} guiScale={} fontScale={}",
windowWidth, windowHeight, guiScale, fontScale
)
}
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
super.render(context, mouseX, mouseY, delta)
context.draw {
val vertexConsumer = it.getBuffer(composeRender.output)
val matrix4f = context.matrices.peek().positionMatrix
vertexConsumer.vertex(matrix4f, 0f, 0f, 0f).texture(0f, 0f)
vertexConsumer.vertex(matrix4f, 0f, height.toFloat(), 0f).texture(0f, 1f)
vertexConsumer.vertex(matrix4f, width.toFloat(), height.toFloat(), 0f).texture(1f, 1f)
vertexConsumer.vertex(matrix4f, width.toFloat(), 0f, 0f).texture(1f, 0f)
}
}
override fun resize(client: MinecraftClient, width: Int, height: Int) {
this.width = width
this.height = height
composeRender.resize(windowWidth, windowHeight, guiScale, fontScale)
ComposeUiMod.logger.info(
"resize: width={} height={} guiScale={} fontScale={}",
windowWidth, windowHeight, guiScale, fontScale
)
}
private fun getMouseButton(button: Int) = when (button) {
0 -> PointerButton.Primary
1 -> PointerButton.Secondary
2 -> PointerButton.Tertiary
3 -> PointerButton.Back
4 -> PointerButton.Forward
else -> PointerButton.Primary
}
private fun getMousePosition() = Offset(
MinecraftClient.getInstance().mouse.x.toFloat(),
MinecraftClient.getInstance().mouse.y.toFloat()
)
override fun mouseMoved(mouseX: Double, mouseY: Double) {
composeRender.post {
it.sendPointerEvent(
PointerEventType.Move,
position = getMousePosition()
)
}
}
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
composeRender.post {
it.sendPointerEvent(
PointerEventType.Press,
button = getMouseButton(button),
position = getMousePosition()
)
}
return true
}
override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
composeRender.post {
it.sendPointerEvent(
PointerEventType.Release,
button = getMouseButton(button),
position = getMousePosition()
)
}
return true
}
override fun mouseScrolled(
mouseX: Double, mouseY: Double, horizontalAmount: Double, verticalAmount: Double
): Boolean {
composeRender.post {
it.sendPointerEvent(
PointerEventType.Scroll,
button = PointerButton.Tertiary,
position = getMousePosition(),
scrollDelta = Offset(horizontalAmount.toFloat(), -verticalAmount.toFloat())
)
}
return true
}
override fun close() {
MinecraftClient.getInstance().setScreen(null)
composeRender.destroy()
}
}

View File

@@ -2,7 +2,7 @@ package net.airgame.compose.ui
import net.fabricmc.api.ModInitializer
class ComposeUI : ModInitializer {
class ComposeUi : ModInitializer {
override fun onInitialize() {
}

View File

@@ -11,10 +11,10 @@
"environment": "client",
"entrypoints": {
"client": [
"net.airgame.compose.ui.client.ComposeUIMod"
"net.airgame.compose.ui.client.ComposeUiMod"
],
"main": [
"net.airgame.compose.ui.ComposeUI"
"net.airgame.compose.ui.ComposeUi"
]
},
"mixins": [