All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.peanuuutz.fork.ui.internal.util.Preload.kt Maven / Gradle / Ivy

The newest version!
package net.peanuuutz.fork.ui.internal.util

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import kotlinx.coroutines.launch
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents
import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.widget.EmptyWidget
import net.minecraft.client.util.math.MatrixStack
import net.peanuuutz.fork.coroutine.core.ForkClientMainScope
import net.peanuuutz.fork.coroutine.core.delayTicks
import net.peanuuutz.fork.event.client.ClientReloadEvents
import net.peanuuutz.fork.render.screen.draw.Drawer
import net.peanuuutz.fork.ui.animation.animateDecay
import net.peanuuutz.fork.ui.animation.animateInt
import net.peanuuutz.fork.ui.animation.rememberUpdatedTransition
import net.peanuuutz.fork.ui.foundation.animation.AnimatedVisibility
import net.peanuuutz.fork.ui.foundation.draw.Canvas
import net.peanuuutz.fork.ui.foundation.input.rememberContentScrollState
import net.peanuuutz.fork.ui.foundation.layout.Box
import net.peanuuutz.fork.ui.foundation.layout.grid.GridCells
import net.peanuuutz.fork.ui.foundation.layout.grid.HorizontalGrid
import net.peanuuutz.fork.ui.foundation.layout.grid.VerticalGrid
import net.peanuuutz.fork.ui.foundation.layout.list.Column
import net.peanuuutz.fork.ui.foundation.layout.maxSize
import net.peanuuutz.fork.ui.foundation.layout.offset
import net.peanuuutz.fork.ui.foundation.layout.popup.NoopPopupPositioner
import net.peanuuutz.fork.ui.foundation.layout.size
import net.peanuuutz.fork.ui.foundation.text.ClickableText
import net.peanuuutz.fork.ui.foundation.text.HoverableText
import net.peanuuutz.fork.ui.foundation.text.InteractableText
import net.peanuuutz.fork.ui.preset.Background
import net.peanuuutz.fork.ui.preset.Button
import net.peanuuutz.fork.ui.preset.Checkbox
import net.peanuuutz.fork.ui.preset.Divider
import net.peanuuutz.fork.ui.preset.HorizontalScrollbar
import net.peanuuutz.fork.ui.preset.Icon
import net.peanuuutz.fork.ui.preset.IconButton
import net.peanuuutz.fork.ui.preset.Panel
import net.peanuuutz.fork.ui.preset.PanelInset
import net.peanuuutz.fork.ui.preset.Slider
import net.peanuuutz.fork.ui.preset.Switch
import net.peanuuutz.fork.ui.preset.Text
import net.peanuuutz.fork.ui.preset.TextDivider
import net.peanuuutz.fork.ui.preset.TextField
import net.peanuuutz.fork.ui.preset.TooltipArea
import net.peanuuutz.fork.ui.preset.VerticalScrollbar
import net.peanuuutz.fork.ui.preset.icons.Icons8
import net.peanuuutz.fork.ui.preset.icons.Sword
import net.peanuuutz.fork.ui.preset.theme.Theme
import net.peanuuutz.fork.ui.scene.component.ComposeComponent
import net.peanuuutz.fork.ui.scene.component.DelegatingNativeWidget
import net.peanuuutz.fork.ui.ui.context.LocalContext
import net.peanuuutz.fork.ui.ui.draw.canvas.EmptyCanvas
import net.peanuuutz.fork.ui.ui.draw.text.Paragraph
import net.peanuuutz.fork.ui.ui.modifier.Modifier
import net.peanuuutz.fork.util.fork.ForkLogger

internal object Preload :
    ComposeComponent(EmptyCanvas),
    ClientLifecycleEvents.ClientStarted,
    ClientReloadEvents.EndReloadResourcesListener
{
    private val matrices: MatrixStack = MatrixStack()

    @Composable
    override fun Content() {
        Theme {
            Box(
                modifier = Modifier.maxSize(100, 100)
            ) {
                // States

                var trigger by remember { mutableStateOf(false) }

                // Animations

                val transition = rememberUpdatedTransition(trigger)

                val int by transition.animateInt { state -> if (state) 0 else 100 }

                // Effects

                SideEffect {
                    trigger = true
                }

                LaunchedEffect(Unit) {
                    animateDecay(
                        initialValue = 0.0f,
                        initialVelocity = 100.0f
                    ) { _, _ ->
                        // ...
                    }
                }

                // Components

                val moveAway = Modifier.offset(40, 40)

                AnimatedVisibility(
                    isVisible = trigger
                ) {
                    Switch(
                        isChecked = false,
                        onValueChanged = { /* ... */ },
                        modifier = moveAway
                    )
                }

                Background {
                    Slider(
                        value = 0.0f,
                        onValueChanged = { /* ... */ },
                        range = 0.0f..1.0f,
                        modifier = moveAway
                    )
                }

                Button(
                    onClick = { /* ... */ },
                    modifier = moveAway
                ) {
                    Canvas(
                        modifier = Modifier.size(int)
                    ) {
                        // ...
                    }
                }

                Checkbox(
                    isChecked = false,
                    onValueChanged = { /* ... */ }
                )

                ClickableText(
                    paragraph = Paragraph.Empty,
                    onClick = { /* ... */ }
                )

                Column {
                    DelegatingNativeWidget(
                        factory = { EmptyWidget(0, 0) }
                    )
                }

                HorizontalGrid(
                    rows = GridCells.fixedSize(10)
                ) {
                    HoverableText(
                        paragraph = Paragraph.Empty,
                        onHover = { /* ... */ }
                    )
                }

                HorizontalScrollbar(
                    scrollState = rememberContentScrollState(),
                    modifier = moveAway
                )

                IconButton(
                    onClick = { /* ... */ },
                    modifier = moveAway
                ) {
                    Icon(
                        spec = Icons8.TextureSpec,
                        region = Icons8.Sword
                    )
                }

                InteractableText(
                    paragraph = Paragraph.Empty,
                    onHover = { /* ... */ },
                    onClick = { /* ... */ }
                )

                Panel {
                    PanelInset {
                        TextDivider(paragraph = Paragraph.Empty)
                    }
                }

                Slider(
                    value = true,
                    onValueChanged = { /* ... */ },
                    values = listOf(true, false),
                    modifier = moveAway
                )

                TextField(
                    text = "",
                    onCandidate = { false },
                    modifier = moveAway
                )

                TooltipArea(
                    tooltip = { /* ... */ },
                    context = LocalContext.current,
                    positioner = NoopPopupPositioner
                ) {
                    Text(text = "Preload")
                }

                VerticalGrid(
                    columns = GridCells.List
                ) {
                    Divider()
                }

                VerticalScrollbar(
                    scrollState = rememberContentScrollState(),
                    modifier = moveAway
                )
            }
        }
    }

    override fun onClientStarted(client: MinecraftClient) {
        ForkLogger.debug("Start UI Preload")
        // ScreenCanvas underlying renderer, which at this stage won't
        // draw anything because resources are reloading (splash screen)
        Drawer.drawText(matrices, "", 0.0f, 0.0f)
        // We dispatch some tasks in advance, so that when player first
        // enter a Compose based content, it won't lag for too long
        init()
        render(matrices, 0, 0, 0.0f)
        mouseMoved(0.1, 0.1)
    }

    override fun onEndReloadResources(client: MinecraftClient, isSuccessful: Boolean) {
        // Schedule more tasks on the next tick for layered content
        // (TooltipArea) to come in, then dispose this component
        ForkClientMainScope.launch {
            render(matrices, 0, 0, 0.0f)
            delayTicks(1L)
            render(matrices, 0, 0, 0.0f)
            delayTicks(1L)
            render(matrices, 0, 0, 0.0f)
            dispose()
            ForkLogger.debug("End UI Preload")
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy