mirror of
https://gitlab.com/cc-ru/ocelot/ocelot-desktop.git
synced 2025-12-20 02:59:19 +01:00
291 lines
9.2 KiB
Scala
291 lines
9.2 KiB
Scala
package ocelot.desktop.windows
|
|
|
|
import ocelot.desktop.OcelotDesktop
|
|
import ocelot.desktop.color.{Color, IntColor}
|
|
import ocelot.desktop.util.NumberUtils.ExtendedFloat
|
|
import ocelot.desktop.geometry._
|
|
import ocelot.desktop.graphics.IconSource
|
|
import ocelot.desktop.graphics.mesh.{Mesh3D, MeshBuilder3D}
|
|
import ocelot.desktop.graphics.scene.{Scene3D, SceneMesh3D}
|
|
import ocelot.desktop.node.nodes.HologramProjectorNode
|
|
import ocelot.desktop.ui.widget.window.PanelWindow
|
|
import ocelot.desktop.ui.widget.{IconButton, Viewport3DWidget, Widget}
|
|
import totoro.ocelot.brain.Settings
|
|
import totoro.ocelot.brain.entity.HologramProjector
|
|
import totoro.ocelot.brain.util.Tier
|
|
|
|
object HologramProjectorWindow {
|
|
private lazy val ProjectorMesh: Array[Mesh3D] = Array(Tier.One, Tier.Two).map(tier => {
|
|
val builder = new MeshBuilder3D
|
|
builder.scale = 1.0f / 16.0f
|
|
builder.spriteUVScale = 1.0f / 16.0f
|
|
|
|
val spriteTop = s"blocks/HologramProjector${tier.num}Top"
|
|
val spriteBottom = "blocks/Generic"
|
|
val spriteSide = "blocks/HologramProjectorSide"
|
|
|
|
builder.cuboid(
|
|
Vector3D(4, 0, 4),
|
|
Vector3D(12, 3, 12),
|
|
left = None,
|
|
right = None,
|
|
front = None,
|
|
back = None,
|
|
top = Some((spriteTop, Rect2D(4, 4, 8, 8))),
|
|
bottom = Some((spriteBottom, Rect2D(4, 4, 8, 8))),
|
|
)
|
|
|
|
builder.cuboid(
|
|
Vector3D(0, 0, 0),
|
|
Vector3D(2, 7, 16),
|
|
top = Some((spriteTop, Rect2D(0, 0, 2, 16))),
|
|
bottom = Some((spriteBottom, Rect2D(0, 0, 2, 16))),
|
|
front = Some((spriteSide, Rect2D(2, 9, -2, 7))),
|
|
back = Some((spriteSide, Rect2D(0, 9, 2, 7))),
|
|
left = Some((spriteSide, Rect2D(0, 9, 16, 7))),
|
|
right = Some((spriteSide, Rect2D(0, 9, 16, 7))),
|
|
)
|
|
|
|
builder.cuboid(
|
|
Vector3D(14, 0, 0),
|
|
Vector3D(16, 7, 16),
|
|
top = Some((spriteTop, Rect2D(14, 0, 2, 16))),
|
|
bottom = Some((spriteBottom, Rect2D(14, 0, 2, 16))),
|
|
front = Some((spriteSide, Rect2D(0, 9, 2, 7))),
|
|
back = Some((spriteSide, Rect2D(2, 9, -2, 7))),
|
|
left = Some((spriteSide, Rect2D(0, 9, 16, 7))),
|
|
right = Some((spriteSide, Rect2D(0, 9, 16, 7))),
|
|
)
|
|
|
|
builder.cuboid(
|
|
Vector3D(2, 0, 0),
|
|
Vector3D(14, 7, 2),
|
|
left = None,
|
|
right = None,
|
|
top = Some((spriteTop, Rect2D(2, 0, 12, 2))),
|
|
bottom = Some((spriteBottom, Rect2D(2, 2, 12, -2))),
|
|
front = Some((spriteSide, Rect2D(2, 9, 12, 7))),
|
|
back = Some((spriteSide, Rect2D(2, 9, 12, 7))),
|
|
)
|
|
|
|
builder.cuboid(
|
|
Vector3D(2, 0, 14),
|
|
Vector3D(14, 7, 16),
|
|
left = None,
|
|
right = None,
|
|
top = Some((spriteTop, Rect2D(2, 14, 12, 2))),
|
|
bottom = Some((spriteBottom, Rect2D(2, 16, 12, -2))),
|
|
front = Some((spriteSide, Rect2D(2, 9, 12, 7))),
|
|
back = Some((spriteSide, Rect2D(2, 9, 12, 7))),
|
|
)
|
|
|
|
builder.cuboid(
|
|
Vector3D(2, 0, 2),
|
|
Vector3D(4, 5, 14),
|
|
front = None,
|
|
back = None,
|
|
left = None,
|
|
top = Some((spriteTop, Rect2D(2, 2, 2, 12))),
|
|
bottom = Some((spriteBottom, Rect2D(2, 2, 2, 12))),
|
|
right = Some((spriteSide, Rect2D(2, 16, 12, -5))),
|
|
)
|
|
|
|
builder.cuboid(
|
|
Vector3D(12, 0, 2),
|
|
Vector3D(14, 5, 14),
|
|
front = None,
|
|
back = None,
|
|
right = None,
|
|
top = Some((spriteTop, Rect2D(12, 2, 2, 12))),
|
|
bottom = Some((spriteBottom, Rect2D(12, 2, 2, 12))),
|
|
left = Some((spriteSide, Rect2D(2, 16, 12, -5))),
|
|
)
|
|
|
|
builder.cuboid(
|
|
Vector3D(4, 0, 2),
|
|
Vector3D(12, 5, 4),
|
|
left = None,
|
|
right = None,
|
|
front = None,
|
|
top = Some((spriteTop, Rect2D(4, 2, 8, 2))),
|
|
bottom = Some((spriteBottom, Rect2D(4, 2, 8, 2))),
|
|
back = Some((spriteSide, Rect2D(4, 16, 8, -5))),
|
|
)
|
|
|
|
builder.cuboid(
|
|
Vector3D(4, 0, 12),
|
|
Vector3D(12, 5, 14),
|
|
left = None,
|
|
right = None,
|
|
back = None,
|
|
top = Some((spriteTop, Rect2D(4, 12, 8, 2))),
|
|
bottom = Some((spriteBottom, Rect2D(4, 12, 8, 2))),
|
|
front = Some((spriteSide, Rect2D(4, 16, 8, -5))),
|
|
)
|
|
|
|
builder.build()
|
|
})
|
|
}
|
|
|
|
class HologramProjectorWindow(val hologramProjectorNode: HologramProjectorNode) extends PanelWindow {
|
|
private def hologram: HologramProjector = hologramProjectorNode.hologramProjector
|
|
|
|
private var mesh: Option[Mesh3D] = None
|
|
|
|
private val viewport = new Viewport3DWidget {
|
|
private var gridVisible = true
|
|
|
|
override protected def setupToolbar(toolbar: Widget): Unit = {
|
|
super.setupToolbar(toolbar)
|
|
|
|
toolbar.children :+= new IconButton(
|
|
IconSource.Icons.GridOff,
|
|
IconSource.Icons.Grid,
|
|
pressedColor = Color.White.withAlpha(0.5f),
|
|
releasedColor = Color.White.withAlpha(0.2f),
|
|
mode = IconButton.Mode.Switch,
|
|
darkenActiveColorFactor = 0.5f,
|
|
model = IconButton.ReadOnlyModel(gridVisible),
|
|
) {
|
|
override def onPressed(): Unit = gridVisible = true
|
|
|
|
override def onReleased(): Unit = gridVisible = false
|
|
}
|
|
}
|
|
|
|
override protected def createScene(): Scene3D = {
|
|
val scene = new Scene3D
|
|
scene.camera = camera
|
|
|
|
scene.lightSource.basis = Basis3D.rotate(Vector3D.AxisZ, 30f.toRadians) *
|
|
Basis3D.rotate(Vector3D.AxisX, 30f.toRadians)
|
|
|
|
if (gridVisible) {
|
|
val grid = new SceneMesh3D(Mesh3D.Grid)
|
|
grid.lightingFactor = 0
|
|
grid.textureFactor = 0
|
|
scene.meshes += grid
|
|
}
|
|
|
|
val projectorMesh = new SceneMesh3D(HologramProjectorWindow.ProjectorMesh(hologram.tier.id))
|
|
scene.meshes += projectorMesh
|
|
|
|
mesh.foreach(mesh => {
|
|
val workspace = hologram.workspace
|
|
|
|
val subTick =
|
|
(System.nanoTime() - workspace.getLastTickNanoTime).toFloat / 1e9f / OcelotDesktop.tpsCounter.dt.max(1e-9f)
|
|
val time = workspace.getIngameTime + subTick.clamped(0, 1)
|
|
|
|
var transform = Transform3D.translate(0.5f, 0.5f, 0.5f) *
|
|
Transform3D.rotate(
|
|
Vector3D(hologram.rotationX, hologram.rotationY, hologram.rotationZ),
|
|
hologram.rotationAngle.toRadians,
|
|
) *
|
|
Transform3D.rotate(
|
|
Vector3D(hologram.rotationSpeedX, hologram.rotationSpeedY, hologram.rotationSpeedZ),
|
|
(hologram.rotationSpeed * (time % (360 * 20 - 1)) / 20f).toRadians,
|
|
) *
|
|
Transform3D.scale(1.001f) *
|
|
Transform3D.translate(
|
|
(hologram.translationX * hologram.width / 16f - 1.5f) * hologram.scale,
|
|
hologram.translationY * hologram.height / 16f * hologram.scale,
|
|
(hologram.translationZ * hologram.width / 16f - 1.5f) * hologram.scale,
|
|
)
|
|
|
|
val hologramFlickerFrequency = Settings.get.hologramFlickerFrequency
|
|
val random = workspace.rand
|
|
|
|
if (hologramFlickerFrequency > 0 && workspace.rand.nextDouble() < hologramFlickerFrequency) {
|
|
transform *= Transform3D.scale(Vector3D(
|
|
1 + random.nextGaussian() * 0.01,
|
|
1 + random.nextGaussian() * 0.001,
|
|
1 + random.nextGaussian() * 0.01,
|
|
))
|
|
transform *= Transform3D.translate(Vector3D(
|
|
random.nextGaussian() * 0.01,
|
|
random.nextGaussian() * 0.01,
|
|
random.nextGaussian() * 0.01,
|
|
))
|
|
}
|
|
|
|
transform *= Transform3D.scale(Vector3D(hologram.scale / 16f, hologram.scale / 16f, hologram.scale / 16f))
|
|
|
|
val hologramMesh = new SceneMesh3D(mesh)
|
|
hologramMesh.isOpaque = false
|
|
hologramMesh.transform = transform
|
|
hologramMesh.color = Color.White.withAlpha(0.75f)
|
|
scene.meshes += hologramMesh
|
|
})
|
|
|
|
scene
|
|
}
|
|
}
|
|
|
|
setInner(viewport)
|
|
|
|
override protected def title: String = "Hologram Projector " + hologramProjectorNode.label.getOrElse("")
|
|
|
|
override protected def titleMaxLength: Int = 69
|
|
|
|
override def update(): Unit = {
|
|
super.update()
|
|
|
|
if (hologram.isDirty) {
|
|
updateMesh()
|
|
hologram.isDirty = false
|
|
}
|
|
}
|
|
|
|
private def updateMesh(): Unit = {
|
|
val builder = new MeshBuilder3D
|
|
|
|
def getValue(x: Int, y: Int, z: Int): Int = {
|
|
if (x >= 0 && y >= 0 && z >= 0 && x < hologram.width && z < hologram.width && y < hologram.height)
|
|
hologram.getColor(x, y, z)
|
|
else
|
|
0
|
|
}
|
|
|
|
def isEmpty(x: Int, y: Int, z: Int): Boolean = getValue(x, y, z) == 0
|
|
|
|
def getColor(x: Int, y: Int, z: Int): Color = IntColor(hologram.colors(getValue(x, y, z) - 1))
|
|
|
|
var hologramIsEmpty = true
|
|
|
|
for (x <- 0 until hologram.width) {
|
|
for (z <- 0 until hologram.width) {
|
|
for (y <- 0 until hologram.height) {
|
|
if (!isEmpty(x, y, z)) {
|
|
hologramIsEmpty = false
|
|
val color = getColor(x, y, z)
|
|
val face = Some(("blocks/HologramEffect", Rect2D.Unit))
|
|
|
|
builder.cuboid(
|
|
Vector3D(x, y, z),
|
|
Vector3D(x + 1, y + 1, z + 1),
|
|
color = color,
|
|
left = face.filter(_ => isEmpty(x - 1, y, z)),
|
|
right = face.filter(_ => isEmpty(x + 1, y, z)),
|
|
top = face.filter(_ => isEmpty(x, y + 1, z)),
|
|
bottom = face.filter(_ => isEmpty(x, y - 1, z)),
|
|
front = face.filter(_ => isEmpty(x, y, z - 1)),
|
|
back = face.filter(_ => isEmpty(x, y, z + 1)),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!hologramIsEmpty) {
|
|
mesh = Some(builder.build())
|
|
} else {
|
|
mesh = None
|
|
}
|
|
}
|
|
|
|
override def dispose(): Unit = {
|
|
viewport.dispose()
|
|
}
|
|
}
|