import { TevStage , IndTexStage , TexGen , ColorChannelControl , GXMaterial , LightChannelControl , AlphaTest , RopInfo , SwapTable } from "./gx_material" ; import * as GX from "./gx_enum" ; import { autoOptimizeMaterial } from "./gx_render" ; function copyColorChannelControl ( colorChannel ) { return { lightingEnabled : colorChannel . lightingEnabled , matColorSource : colorChannel . matColorSource , ambColorSource : colorChannel . ambColorSource , litMask : colorChannel . litMask , diffuseFunction : colorChannel . diffuseFunction , attenuationFunction : colorChannel . attenuationFunction , } ; } function copyLightChannelControl ( lightChannel ) { return { alphaChannel : copyColorChannelControl ( lightChannel . alphaChannel ) , colorChannel : copyColorChannelControl ( lightChannel . colorChannel ) , } ; } function copyTexGen ( texGen ) { return { type : texGen . type , source : texGen . source , matrix : texGen . matrix , normalize : texGen . normalize , postMatrix : texGen . postMatrix , } ; } function copyTevStage ( tevStage ) { return { colorInA : tevStage . colorInA , colorInB : tevStage . colorInB , colorInC : tevStage . colorInC , colorInD : tevStage . colorInD , colorOp : tevStage . colorOp , colorBias : tevStage . colorBias , colorScale : tevStage . colorScale , colorClamp : tevStage . colorClamp , colorRegId : tevStage . colorRegId , alphaInA : tevStage . alphaInA , alphaInB : tevStage . alphaInB , alphaInC : tevStage . alphaInC , alphaInD : tevStage . alphaInD , alphaOp : tevStage . alphaOp , alphaBias : tevStage . alphaBias , alphaScale : tevStage . alphaScale , alphaClamp : tevStage . alphaClamp , alphaRegId : tevStage . alphaRegId , texCoordId : tevStage . texCoordId , texMap : tevStage . texMap , channelId : tevStage . channelId , konstColorSel : tevStage . konstColorSel , konstAlphaSel : tevStage . konstAlphaSel , indTexStage : tevStage . indTexStage , indTexFormat : tevStage . indTexFormat , indTexBiasSel : tevStage . indTexBiasSel , indTexAlphaSel : tevStage . indTexAlphaSel , indTexMatrix : tevStage . indTexMatrix , indTexWrapS : tevStage . indTexWrapS , indTexWrapT : tevStage . indTexWrapT , indTexAddPrev : tevStage . indTexAddPrev , indTexUseOrigLOD : tevStage . indTexUseOrigLOD , texSwapTable : tevStage . texSwapTable , rasSwapTable : tevStage . rasSwapTable , } ; } function copyIndTexStage ( indStage ) { return { texture : indStage . texture , texCoordId : indStage . texCoordId , scaleS : indStage . scaleS , scaleT : indStage . scaleT , } ; } function copyRopInfo ( ropInfo ) { return { fogType : ropInfo . fogType , fogAdjEnabled : ropInfo . fogAdjEnabled , blendMode : ropInfo . blendMode , blendSrcFactor : ropInfo . blendSrcFactor , blendDstFactor : ropInfo . blendDstFactor , blendLogicOp : ropInfo . blendLogicOp , depthTest : ropInfo . depthTest , depthFunc : ropInfo . depthFunc , depthWrite : ropInfo . depthWrite , dstAlpha : ropInfo . dstAlpha , colorUpdate : ropInfo . colorUpdate , alphaUpdate : ropInfo . alphaUpdate , } ; } function copyAlphaTest ( alphaTest ) { return { compareA : alphaTest . compareA , referenceA : alphaTest . referenceA , op : alphaTest . op , compareB : alphaTest . compareB , referenceB : alphaTest . referenceB , } ; } export class GXMaterialBuilder { private cullMode : GX . CullMode ; private lightChannels : LightChannelControl [ ] = [ ] ; private texGens : TexGen [ ] = [ ] ; private tevStages : TevStage [ ] = [ ] ; private indTexStages : IndTexStage [ ] = [ ] ; private alphaTest : AlphaTest ; private ropInfo : RopInfo ; private usePnMtxIdx ? : boolean ; constructor ( private name = null ) { this . reset ( ) ; } public reset ( ) { this . cullMode = GX . CullMode . NONE ; this . lightChannels . length = 0 ; this . texGens . length = 0 ; this . tevStages . length = 0 ; this . indTexStages . length = 0 ; this . alphaTest = { } as AlphaTest ; this . setAlphaCompare ( GX . CompareType . ALWAYS , 0 , GX . AlphaOp . AND , GX . CompareType . ALWAYS , 0 ) ; this . ropInfo = { } as RopInfo ; this . setFog ( GX . FogType . NONE , false ) ; this . setBlendMode ( GX . BlendMode . NONE , GX . BlendFactor . SRCALPHA , GX . BlendFactor . INVSRCALPHA , GX . LogicOp . CLEAR ) ; this . setZMode ( true , GX . CompareType . LEQUAL , true ) ; this . setColorUpdate ( true ) ; this . setAlphaUpdate ( false ) ; this . usePnMtxIdx = undefined ; } public setCullMode ( cullMode ) { this . cullMode = cullMode ; } private ensureTexCoordGen ( idx ) { if ( this . texGens [ idx ] === undefined ) { this . texGens [ idx ] = { } as TexGen ; } return this . texGens [ idx ] ; } public setTexCoordGen ( idx , type , source , matrix , normalize = false , postMatrix = GX . PostTexGenMatrix . PTIDENTITY ) { const texGen = this . ensureTexCoordGen ( idx ) ; texGen . type = type ; texGen . source = source ; texGen . matrix = matrix ; texGen . normalize = normalize ; texGen . postMatrix = postMatrix ; } private ensureLightChannel ( idx ) { if ( this . lightChannels [ idx ] === undefined ) { this . lightChannels [ idx ] = { colorChannel : { } as ColorChannelControl , alphaChannel : { } as ColorChannelControl , } ; this . setChanCtrlInternal ( this . lightChannels [ idx ] . colorChannel , false , GX . ColorSrc . REG , GX . ColorSrc . REG , 0 , GX . DiffuseFunction . NONE , GX . AttenuationFunction . NONE ) ; this . setChanCtrlInternal ( this . lightChannels [ idx ] . alphaChannel , false , GX . ColorSrc . REG , GX . ColorSrc . REG , 0 , GX . DiffuseFunction . NONE , GX . AttenuationFunction . NONE ) ; } return this . lightChannels [ idx ] ; } private setChanCtrlInternal ( chanCtrl , enable , ambSrc , matSrc , lightMask , diffFn , attnFn ) { chanCtrl . lightingEnabled = enable ; chanCtrl . ambColorSource = ambSrc ; chanCtrl . matColorSource = matSrc ; chanCtrl . litMask = lightMask ; chanCtrl . diffuseFunction = diffFn ; chanCtrl . attenuationFunction = attnFn ; } public setChanCtrl ( idx , enable , ambSrc , matSrc , lightMask , diffFn , attnFn ) { const lightChannel = this . ensureLightChannel ( idx & 0x01 ) ; const set = ( idx >>> 1 ) + 1 ; if ( ! ! ( set & 0x01 ) ) this . setChanCtrlInternal ( lightChannel . colorChannel , enable , ambSrc , matSrc , lightMask , diffFn , attnFn ) ; if ( ! ! ( set & 0x02 ) ) this . setChanCtrlInternal ( lightChannel . alphaChannel , enable , ambSrc , matSrc , lightMask , diffFn , attnFn ) ; } private ensureTevStage ( idx ) { if ( this . tevStages [ idx ] === undefined ) { this . tevStages [ idx ] = { } as TevStage ; if ( idx <= 7 ) this . setTevOrder ( idx , GX . TexCoordID . TEXCOORD0 + idx , GX . TexMapID . TEXMAP0 + idx , GX . RasColorChannelID . COLOR0A0 ) ; else this . setTevOrder ( idx , GX . TexCoordID . TEXCOORD_NULL , GX . TexMapID . TEXMAP_NULL , GX . RasColorChannelID . COLOR0A0 ) ; this . setTevColorOp ( idx , GX . TevOp . ADD , GX . TevBias . ZERO , GX . TevScale . SCALE_1 , true , GX . Register . PREV ) , this . setTevAlphaOp ( idx , GX . TevOp . ADD , GX . TevBias . ZERO , GX . TevScale . SCALE_1 , true , GX . Register . PREV ) , this . setTevColorIn ( idx , GX . CC . ZERO , GX . CC . ZERO , GX . CC . ZERO , GX . CC . TEXC ) , this . setTevAlphaIn ( idx , GX . CA . ZERO , GX . CA . ZERO , GX . CA . ZERO , GX . CA . TEXA ) , this . setTevKColorSel ( idx , GX . KonstColorSel . KCSEL_2_8 ) ; this . setTevKAlphaSel ( idx , GX . KonstAlphaSel . KASEL_1 ) ; this . setTevDirect ( idx ) ; } return this . tevStages [ idx ] ; } public setTevOrder ( idx , texCoordID , texMap , channelId ) { const tevStage = this . ensureTevStage ( idx ) ; tevStage . texCoordId = texCoordID ; tevStage . texMap = texMap ; tevStage . channelId = channelId ; } public setTevColorOp ( idx , colorOp , colorBias , colorScale , colorClamp , colorRegId ) { const tevStage = this . ensureTevStage ( idx ) ; tevStage . colorOp = colorOp ; tevStage . colorBias = colorBias ; tevStage . colorScale = colorScale ; tevStage . colorClamp = colorClamp ; tevStage . colorRegId = colorRegId ; } public setTevAlphaOp ( idx , alphaOp , alphaBias , alphaScale , alphaClamp , alphaRegId ) { const tevStage = this . ensureTevStage ( idx ) ; tevStage . alphaOp = alphaOp ; tevStage . alphaBias = alphaBias ; tevStage . alphaScale = alphaScale ; tevStage . alphaClamp = alphaClamp ; tevStage . alphaRegId = alphaRegId ; } public setTevColorIn ( idx , colorInA , colorInB , colorInC , colorInD ) { const tevStage = this . ensureTevStage ( idx ) ; tevStage . colorInA = colorInA ; tevStage . colorInB = colorInB ; tevStage . colorInC = colorInC ; tevStage . colorInD = colorInD ; } public setTevAlphaIn ( idx , alphaInA , alphaInB , alphaInC , alphaInD ) { const tevStage = this . ensureTevStage ( idx ) ; tevStage . alphaInA = alphaInA ; tevStage . alphaInB = alphaInB ; tevStage . alphaInC = alphaInC ; tevStage . alphaInD = alphaInD ; } public setTevKColorSel ( idx , sel ) { const tevStage = this . ensureTevStage ( idx ) ; tevStage . konstColorSel = sel ; } public setTevKAlphaSel ( idx , sel ) { const tevStage = this . ensureTevStage ( idx ) ; tevStage . konstAlphaSel = sel ; } public setTevSwapMode ( idx , rasSwapTable , texSwapTable ) { const tevStage = this . ensureTevStage ( idx ) ; tevStage . rasSwapTable = rasSwapTable ; tevStage . texSwapTable = texSwapTable ; } public setTevIndirect ( tevStageIdx , indTexStage , format , biasSel , matrixSel , wrapS , wrapT , addPrev , utcLod , alphaSel ) { const tevStage = this . ensureTevStage ( tevStageIdx ) ; tevStage . indTexStage = indTexStage ; tevStage . indTexFormat = format ; tevStage . indTexBiasSel = biasSel ; tevStage . indTexAlphaSel = alphaSel ; tevStage . indTexMatrix = matrixSel ; tevStage . indTexWrapS = wrapS ; tevStage . indTexWrapT = wrapT ; tevStage . indTexAddPrev = addPrev ; tevStage . indTexUseOrigLOD = utcLod ; } public setTevIndWarp ( tevStageIdx , indTexStage , signedOffsets , replaceMode , matrixSel ) { const biasSel = signedOffsets ? GX . IndTexBiasSel . ST : GX . IndTexBiasSel . NONE ; const wrap = replaceMode ? GX . IndTexWrap . _0 : GX . IndTexWrap . OFF ; this . setTevIndirect ( tevStageIdx , indTexStage , GX . IndTexFormat . _8 , biasSel , matrixSel , wrap , wrap , false , false , GX . IndTexAlphaSel . OFF ) ; } public setTevDirect ( tevStageIdx ) { this . setTevIndirect ( tevStageIdx , GX . IndTexStageID . STAGE0 , GX . IndTexFormat . _8 , GX . IndTexBiasSel . NONE , GX . IndTexMtxID . OFF , GX . IndTexWrap . OFF , GX . IndTexWrap . OFF , false , false , GX . IndTexAlphaSel . OFF ) ; } private ensureIndTexStage ( idx ) { if ( this . indTexStages [ idx ] === undefined ) { this . indTexStages [ idx ] = { } as IndTexStage ; this . setIndTexScale ( idx , GX . IndTexScale . _1 , GX . IndTexScale . _1 ) ; } return this . indTexStages [ idx ] ; } public setIndTexOrder ( idx , texcoord , texmap ) { const indStage = this . ensureIndTexStage ( idx ) ; indStage . texCoordId = texcoord ; indStage . texture = texmap ; } public setIndTexScale ( idx , scaleS , scaleT ) { const indStage = this . ensureIndTexStage ( idx ) ; indStage . scaleS = scaleS ; indStage . scaleT = scaleT ; } public setAlphaCompare ( compareA , referenceA , op , compareB , referenceB ) { this . alphaTest . compareA = compareA ; this . alphaTest . referenceA = referenceA / 0xFF ; this . alphaTest . op = op ; this . alphaTest . compareB = compareB ; this . alphaTest . referenceB = referenceB / 0xFF ; } public setFog ( fogType , fogAdjEnabled ) { this . ropInfo . fogType = fogType ; this . ropInfo . fogAdjEnabled = fogAdjEnabled ; } public setBlendMode ( blendMode , srcFactor , dstFactor , logicOp = GX . LogicOp . CLEAR ) { this . ropInfo . blendMode = blendMode ; this . ropInfo . blendSrcFactor = srcFactor ; this . ropInfo . blendDstFactor = dstFactor ; this . ropInfo . blendLogicOp = logicOp ; } public setZMode ( depthTest , depthFunc , depthWrite ) { this . ropInfo . depthTest = depthTest ; this . ropInfo . depthFunc = depthFunc ; this . ropInfo . depthWrite = depthWrite ; } public setDstAlpha ( v ? ) { this . ropInfo . dstAlpha = v ; } public setColorUpdate ( v ) { this . ropInfo . colorUpdate = v ; } public setAlphaUpdate ( v ) { this . ropInfo . alphaUpdate = v ; } public setUsePnMtxIdx ( v ) { this . usePnMtxIdx = v ; } public finish ( name = null ) { if ( name === null ) name = this . name ; if ( name === null ) name = '' ; const material = { name : name , cullMode : this . cullMode , lightChannels : this . lightChannels . map ( copyLightChannelControl ) , texGens : this . texGens . map ( copyTexGen ) , tevStages : this . tevStages . map ( copyTevStage ) , indTexStages : this . indTexStages . map ( copyIndTexStage ) , alphaTest : copyAlphaTest ( this . alphaTest ) , ropInfo : copyRopInfo ( this . ropInfo ) , usePnMtxIdx : this . usePnMtxIdx , } ; autoOptimizeMaterial ( material ) ; return material ; } }