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 # check this on https://modmuss50.me/fabric.html
fabric_version=0.114.0+1.21.4 fabric_version=0.114.0+1.21.4
kotlin.version=2.1.0 kotlin.version=2.3.0
compose.version=1.6.10 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 { class DebugTimer {
var time = System.currentTimeMillis() var time = System.currentTimeMillis()
fun log(string: String) {
fun log(message: String) {
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
println("$string: ${now - time} ms") ComposeUiMod.logger.info("{}: {} ms", message, now - time)
time = now time = now
} }
} }

View File

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

View File

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