mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-15 02:12:42 -04:00
Allow printing 3D prints that can be walked through (non-colliding), as well as shapes with no texture (texture="") appearing transparent, closes #1238.
Also improved face culling on 3D prints when rendering, improving render performance in certain scenarios.
This commit is contained in:
parent
64d3f93177
commit
1d933fd9f5
@ -972,6 +972,11 @@ opencomputers {
|
||||
# don't care about that and prefer them to be not totally shadowless,
|
||||
# enable this.
|
||||
printsHaveOpacity: false
|
||||
|
||||
# By what (linear) factor the cost of a print increases if one or both of
|
||||
# its states are non-collidable (i.e. entities can move through them).
|
||||
# This only influences the chamelium cost.
|
||||
noclipMultiplier: 2
|
||||
}
|
||||
|
||||
hologram {
|
||||
|
@ -144,6 +144,7 @@ hdd3 {
|
||||
["oc:materialCircuitBoardPrinted", "oc:materialDisk", craftingPiston]
|
||||
["oc:circuitChip3", "oc:materialDisk", diamond]]
|
||||
}
|
||||
|
||||
dataCard {
|
||||
input: [[nuggetIron, "oc:materialALU", "oc:circuitChip2"]
|
||||
["", "oc:materialCard", ""]]
|
||||
|
@ -328,6 +328,7 @@ class Settings(val config: Config) {
|
||||
val printMaterialValue = config.getInt("printer.materialValue") max 0
|
||||
val printInkValue = config.getInt("printer.inkValue") max 0
|
||||
val printsHaveOpacity = config.getBoolean("printer.printsHaveOpacity")
|
||||
val noclipMultiplier = config.getDouble("printer.noclipMultiplier") max 0
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
// integration
|
||||
|
@ -1,5 +1,6 @@
|
||||
package li.cil.oc.client.renderer.block
|
||||
|
||||
import com.google.common.base.Strings
|
||||
import li.cil.oc.Constants
|
||||
import li.cil.oc.api.Items
|
||||
import li.cil.oc.common.block
|
||||
@ -17,12 +18,13 @@ object Print {
|
||||
|
||||
def render(data: PrintData, state: Boolean, facing: ForgeDirection, x: Int, y: Int, z: Int, block: Block, renderer: RenderBlocks): Unit = {
|
||||
val shapes = if (state) data.stateOn else data.stateOff
|
||||
printBlock.isSingleShape = shapes.size == 1
|
||||
if (shapes.isEmpty) {
|
||||
printBlock.textureOverride = Option(resolveTexture("missingno"))
|
||||
renderer.setRenderBounds(0, 0, 0, 1, 1, 1)
|
||||
renderer.renderStandardBlock(block, x, y, z)
|
||||
}
|
||||
else for (shape <- shapes) {
|
||||
else for (shape <- shapes if !Strings.isNullOrEmpty(shape.texture)) {
|
||||
val bounds = shape.bounds.rotateTowards(facing)
|
||||
printBlock.colorMultiplierOverride = shape.tint
|
||||
printBlock.textureOverride = Option(resolveTexture(shape.texture))
|
||||
@ -33,6 +35,7 @@ object Print {
|
||||
}
|
||||
printBlock.colorMultiplierOverride = None
|
||||
printBlock.textureOverride = None
|
||||
printBlock.isSingleShape = false
|
||||
}
|
||||
|
||||
def resolveTexture(name: String): IIcon = {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package li.cil.oc.client.renderer.item
|
||||
|
||||
import com.google.common.base.Strings
|
||||
import li.cil.oc.Constants
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api
|
||||
@ -150,6 +151,11 @@ object ItemRenderer extends IItemRenderer {
|
||||
val bounds = shape.bounds
|
||||
val texture = Print.resolveTexture(shape.texture)
|
||||
|
||||
if (Strings.isNullOrEmpty(shape.texture)) {
|
||||
RenderState.makeItBlend()
|
||||
GL11.glColor4f(1, 1, 1, 0.25f)
|
||||
}
|
||||
|
||||
shape.tint.foreach(color => {
|
||||
val r = (color >> 16).toByte
|
||||
val g = (color >> 8).toByte
|
||||
|
@ -3,6 +3,7 @@ package li.cil.oc.common.block
|
||||
import java.util
|
||||
import java.util.Random
|
||||
|
||||
import com.google.common.base.Strings
|
||||
import cpw.mods.fml.relauncher.Side
|
||||
import cpw.mods.fml.relauncher.SideOnly
|
||||
import li.cil.oc.Localization
|
||||
@ -40,6 +41,8 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends
|
||||
var colorMultiplierOverride: Option[Int] = None
|
||||
// Also used in model rendering, can't use renderer's override logic because that'll disable tinting.
|
||||
var textureOverride: Option[IIcon] = None
|
||||
// Again, used in model rendering, used to know whether we can potentially skip rendering sides.
|
||||
var isSingleShape = false
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def getIcon(world: IBlockAccess, x: Int, y: Int, z: Int, globalSide: ForgeDirection, localSide: ForgeDirection): IIcon =
|
||||
@ -80,7 +83,19 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends
|
||||
case _ => super.getLightOpacity(world, x, y, z)
|
||||
}
|
||||
|
||||
override def shouldSideBeRendered(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = true
|
||||
override def shouldSideBeRendered(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = !isSingleShape || (world.getTileEntity(x, y, z) match {
|
||||
case print: tileentity.Print if isSideSolid(world, x, y, z, side.getOpposite) =>
|
||||
side match {
|
||||
case ForgeDirection.DOWN => minY > 0
|
||||
case ForgeDirection.UP => maxY < 1
|
||||
case ForgeDirection.NORTH => minZ > 0
|
||||
case ForgeDirection.SOUTH => maxZ < 1
|
||||
case ForgeDirection.WEST => minX > 0
|
||||
case ForgeDirection.EAST => maxX < 1
|
||||
case _ => true
|
||||
}
|
||||
case _ => super.shouldSideBeRendered(world, x, y, z, side)
|
||||
})
|
||||
|
||||
override def isBlockSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = isSideSolid(world, x, y, z, side)
|
||||
|
||||
@ -88,7 +103,7 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends
|
||||
world.getTileEntity(x, y, z) match {
|
||||
case print: tileentity.Print =>
|
||||
val shapes = if (print.state) print.data.stateOn else print.data.stateOff
|
||||
for (shape <- shapes) {
|
||||
for (shape <- shapes if !Strings.isNullOrEmpty(shape.texture)) {
|
||||
val bounds = shape.bounds.rotateTowards(print.facing)
|
||||
val fullX = bounds.minX == 0 && bounds.maxX == 1
|
||||
val fullY = bounds.minY == 0 && bounds.maxY == 1
|
||||
@ -118,6 +133,8 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends
|
||||
override def addCollisionBoxesToList(world: World, x: Int, y: Int, z: Int, mask: AxisAlignedBB, list: util.List[_], entity: Entity): Unit = {
|
||||
world.getTileEntity(x, y, z) match {
|
||||
case print: tileentity.Print =>
|
||||
if (if (print.state) print.data.noclipOn else print.data.noclipOff) return
|
||||
|
||||
def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
|
||||
val shapes = if (print.state) print.data.stateOn else print.data.stateOff
|
||||
for (shape <- shapes) {
|
||||
|
@ -30,6 +30,8 @@ class PrintData extends ItemData(Constants.BlockName.Print) {
|
||||
val stateOn = mutable.Set.empty[PrintData.Shape]
|
||||
var isBeaconBase = false
|
||||
var lightLevel = 0
|
||||
var noclipOff = false
|
||||
var noclipOn = false
|
||||
|
||||
def hasActiveState = stateOn.nonEmpty
|
||||
|
||||
@ -68,6 +70,8 @@ class PrintData extends ItemData(Constants.BlockName.Print) {
|
||||
stateOn ++= nbt.getTagList("stateOn", NBT.TAG_COMPOUND).map(PrintData.nbtToShape)
|
||||
isBeaconBase = nbt.getBoolean("isBeaconBase")
|
||||
lightLevel = (nbt.getByte("lightLevel") & 0xFF) max 0 min 15
|
||||
noclipOff = nbt.getBoolean("noclipOff")
|
||||
noclipOn = nbt.getBoolean("noclipOn")
|
||||
|
||||
opacityDirty = true
|
||||
}
|
||||
@ -82,6 +86,8 @@ class PrintData extends ItemData(Constants.BlockName.Print) {
|
||||
nbt.setNewTagList("stateOn", stateOn.map(PrintData.shapeToNBT))
|
||||
nbt.setBoolean("isBeaconBase", isBeaconBase)
|
||||
nbt.setByte("lightLevel", lightLevel.toByte)
|
||||
nbt.setBoolean("noclipOff", noclipOff)
|
||||
nbt.setBoolean("noclipOn", noclipOn)
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,6 +125,7 @@ object PrintData {
|
||||
def computeCosts(data: PrintData) = {
|
||||
val totalVolume = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.volume)
|
||||
val totalSurface = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.surface)
|
||||
val multiplier = if (data.noclipOff || data.noclipOn) Settings.get.noclipMultiplier else 1
|
||||
|
||||
if (totalVolume > 0) {
|
||||
val baseMaterialRequired = (totalVolume / 2) max 1
|
||||
@ -127,7 +134,7 @@ object PrintData {
|
||||
else baseMaterialRequired
|
||||
val inkRequired = (totalSurface / 6) max 1
|
||||
|
||||
Option((materialRequired, inkRequired))
|
||||
Option((materialRequired * multiplier, inkRequired))
|
||||
}
|
||||
else None
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def canPrint = data.stateOff.size > 0 && data.stateOff.size <= Settings.get.maxPrintComplexity && data.stateOn.size <= Settings.get.maxPrintComplexity
|
||||
def canPrint = data.stateOff.nonEmpty && data.stateOff.size <= Settings.get.maxPrintComplexity && data.stateOn.size <= Settings.get.maxPrintComplexity
|
||||
|
||||
def isPrinting = output.isDefined
|
||||
|
||||
@ -136,6 +136,19 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
|
||||
result(data.isButtonMode)
|
||||
}
|
||||
|
||||
@Callback(doc = """function(collideOff:boolean, collideOn:boolean) -- Get whether the printed block should be collidable or not.""")
|
||||
def setCollidable(context: Context, args: Arguments): Array[Object] = {
|
||||
val (collideOff, collideOn) = (args.checkBoolean(0), args.checkBoolean(1))
|
||||
data.noclipOff = !collideOff
|
||||
data.noclipOn = !collideOn
|
||||
null
|
||||
}
|
||||
|
||||
@Callback(doc = """function():boolean, boolean -- Get whether the printed block should be collidable or not.""")
|
||||
def isCollidable(context: Context, args: Arguments): Array[Object] = {
|
||||
result(!data.noclipOff, !data.noclipOn)
|
||||
}
|
||||
|
||||
@Callback(doc = """function(minX:number, minY:number, minZ:number, maxX:number, maxY:number, maxZ:number, texture:string[, state:boolean=false][,tint:number]) -- Adds a shape to the printers configuration, optionally specifying whether it is for the off or on state.""")
|
||||
def addShape(context: Context, args: Arguments): Array[Object] = {
|
||||
if (data.stateOff.size > Settings.get.maxPrintComplexity || data.stateOn.size > Settings.get.maxPrintComplexity) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user