Compare commits
4 commits
next
...
renderer-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c139c9365d | ||
|
|
eff87f42e5 | ||
|
|
c151e414d9 | ||
|
|
96a6b790db |
11 changed files with 225 additions and 1 deletions
|
|
@ -8,6 +8,7 @@ import { ItemsRenderer } from 'mc-assets/dist/itemsRenderer'
|
||||||
import { WorldBlockProvider } from 'mc-assets/dist/worldBlockProvider'
|
import { WorldBlockProvider } from 'mc-assets/dist/worldBlockProvider'
|
||||||
import { generateSpiralMatrix } from 'flying-squid/dist/utils'
|
import { generateSpiralMatrix } from 'flying-squid/dist/utils'
|
||||||
import { subscribeKey } from 'valtio/utils'
|
import { subscribeKey } from 'valtio/utils'
|
||||||
|
import { proxy } from 'valtio'
|
||||||
import { dynamicMcDataFiles } from '../../buildMesherConfig.mjs'
|
import { dynamicMcDataFiles } from '../../buildMesherConfig.mjs'
|
||||||
import { toMajorVersion } from '../../../src/utils'
|
import { toMajorVersion } from '../../../src/utils'
|
||||||
import { ResourcesManager } from '../../../src/resourcesManager'
|
import { ResourcesManager } from '../../../src/resourcesManager'
|
||||||
|
|
@ -49,6 +50,7 @@ export const defaultWorldRendererConfig = {
|
||||||
fetchPlayerSkins: true,
|
fetchPlayerSkins: true,
|
||||||
highlightBlockColor: 'blue',
|
highlightBlockColor: 'blue',
|
||||||
foreground: true,
|
foreground: true,
|
||||||
|
enableDebugOverlay: false,
|
||||||
_experimentalSmoothChunkLoading: true,
|
_experimentalSmoothChunkLoading: true,
|
||||||
_renderByChunks: false
|
_renderByChunks: false
|
||||||
}
|
}
|
||||||
|
|
@ -60,6 +62,17 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
|
||||||
worldReadyPromise = this.worldReadyResolvers.promise
|
worldReadyPromise = this.worldReadyResolvers.promise
|
||||||
timeOfTheDay = 0
|
timeOfTheDay = 0
|
||||||
worldSizeParams = { minY: 0, worldHeight: 256 }
|
worldSizeParams = { minY: 0, worldHeight: 256 }
|
||||||
|
reactiveDebugParams = proxy({
|
||||||
|
stopRendering: false,
|
||||||
|
chunksRenderAboveOverride: undefined as number | undefined,
|
||||||
|
chunksRenderAboveEnabled: false,
|
||||||
|
chunksRenderBelowOverride: undefined as number | undefined,
|
||||||
|
chunksRenderBelowEnabled: false,
|
||||||
|
chunksRenderDistanceOverride: undefined as number | undefined,
|
||||||
|
chunksRenderDistanceEnabled: false,
|
||||||
|
disableEntities: false,
|
||||||
|
// disableParticles: false
|
||||||
|
})
|
||||||
|
|
||||||
active = false
|
active = false
|
||||||
|
|
||||||
|
|
@ -315,6 +328,11 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
|
||||||
subscribeKey(this.worldRendererConfig, key, callback)
|
subscribeKey(this.worldRendererConfig, key, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onReactiveDebugUpdated<T extends keyof typeof this.reactiveDebugParams>(key: T, callback: (value: typeof this.reactiveDebugParams[T]) => void) {
|
||||||
|
callback(this.reactiveDebugParams[key])
|
||||||
|
subscribeKey(this.reactiveDebugParams, key, callback)
|
||||||
|
}
|
||||||
|
|
||||||
watchReactivePlayerState () {
|
watchReactivePlayerState () {
|
||||||
this.onReactiveValueUpdated('backgroundColor', (value) => {
|
this.onReactiveValueUpdated('backgroundColor', (value) => {
|
||||||
this.changeBackgroundColor(value)
|
this.changeBackgroundColor(value)
|
||||||
|
|
|
||||||
|
|
@ -455,7 +455,39 @@ export class WorldRendererThree extends WorldRendererCommon {
|
||||||
this.cameraShake.setBaseRotation(pitch, yaw)
|
this.cameraShake.setBaseRotation(pitch, yaw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugChunksVisibilityOverride () {
|
||||||
|
const { chunksRenderAboveOverride, chunksRenderBelowOverride, chunksRenderDistanceOverride, chunksRenderAboveEnabled, chunksRenderBelowEnabled, chunksRenderDistanceEnabled } = this.reactiveDebugParams
|
||||||
|
|
||||||
|
const baseY = this.cameraSectionPos.y * 16
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.displayOptions.inWorldRenderingConfig.enableDebugOverlay &&
|
||||||
|
chunksRenderAboveOverride !== undefined ||
|
||||||
|
chunksRenderBelowOverride !== undefined ||
|
||||||
|
chunksRenderDistanceOverride !== undefined
|
||||||
|
) {
|
||||||
|
for (const [key, object] of Object.entries(this.sectionObjects)) {
|
||||||
|
const [x, y, z] = key.split(',').map(Number)
|
||||||
|
const isVisible =
|
||||||
|
// eslint-disable-next-line no-constant-binary-expression, sonarjs/no-redundant-boolean
|
||||||
|
(chunksRenderAboveEnabled && chunksRenderAboveOverride !== undefined) ? y <= (baseY + chunksRenderAboveOverride) : true &&
|
||||||
|
// eslint-disable-next-line @stylistic/indent-binary-ops, no-constant-binary-expression, sonarjs/no-redundant-boolean
|
||||||
|
(chunksRenderBelowEnabled && chunksRenderBelowOverride !== undefined) ? y >= (baseY - chunksRenderBelowOverride) : true &&
|
||||||
|
// eslint-disable-next-line @stylistic/indent-binary-ops
|
||||||
|
(chunksRenderDistanceEnabled && chunksRenderDistanceOverride !== undefined) ? Math.abs(y - baseY) <= chunksRenderDistanceOverride : true
|
||||||
|
|
||||||
|
object.visible = isVisible
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const object of Object.values(this.sectionObjects)) {
|
||||||
|
object.visible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render (sizeChanged = false) {
|
render (sizeChanged = false) {
|
||||||
|
if (this.reactiveDebugParams.stopRendering) return
|
||||||
|
this.debugChunksVisibilityOverride()
|
||||||
const start = performance.now()
|
const start = performance.now()
|
||||||
this.lastRendered = performance.now()
|
this.lastRendered = performance.now()
|
||||||
this.cursorBlock.render()
|
this.cursorBlock.render()
|
||||||
|
|
@ -468,7 +500,9 @@ export class WorldRendererThree extends WorldRendererCommon {
|
||||||
this.camera.updateProjectionMatrix()
|
this.camera.updateProjectionMatrix()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.entities.render()
|
if (!this.reactiveDebugParams.disableEntities) {
|
||||||
|
this.entities.render()
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
|
// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
|
||||||
const cam = this.cameraGroupVr instanceof THREE.Group ? this.cameraGroupVr.children.find(child => child instanceof THREE.PerspectiveCamera) as THREE.PerspectiveCamera : this.camera
|
const cam = this.cameraGroupVr instanceof THREE.Group ? this.cameraGroupVr.children.find(child => child instanceof THREE.PerspectiveCamera) as THREE.PerspectiveCamera : this.camera
|
||||||
|
|
|
||||||
|
|
@ -678,6 +678,12 @@ export const f3Keybinds: Array<{
|
||||||
},
|
},
|
||||||
mobileTitle: 'Show Chunks Debug',
|
mobileTitle: 'Show Chunks Debug',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
action () {
|
||||||
|
showModal({ reactType: 'renderer-debug' })
|
||||||
|
},
|
||||||
|
mobileTitle: 'Renderer Debug Menu',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'KeyY',
|
key: 'KeyY',
|
||||||
async action () {
|
async action () {
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,9 @@ export const guiOptionsScheme: {
|
||||||
'none'
|
'none'
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
rendererPerfDebugOverlay: {
|
||||||
|
text: 'Performance Debug',
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
custom () {
|
custom () {
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@ const defaultOptions = {
|
||||||
vrSupport: true, // doesn't directly affect the VR mode, should only disable the button which is annoying to android users
|
vrSupport: true, // doesn't directly affect the VR mode, should only disable the button which is annoying to android users
|
||||||
vrPageGameRendering: false,
|
vrPageGameRendering: false,
|
||||||
renderDebug: 'basic' as 'none' | 'advanced' | 'basic',
|
renderDebug: 'basic' as 'none' | 'advanced' | 'basic',
|
||||||
|
rendererPerfDebugOverlay: false,
|
||||||
|
|
||||||
// advanced bot options
|
// advanced bot options
|
||||||
autoRespawn: false,
|
autoRespawn: false,
|
||||||
|
|
|
||||||
115
src/react/RendererDebugMenu.tsx
Normal file
115
src/react/RendererDebugMenu.tsx
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
import { WorldRendererCommon } from 'renderer/viewer/lib/worldrendererCommon'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { useSnapshot } from 'valtio'
|
||||||
|
import { options } from '../optionsStorage'
|
||||||
|
import Screen from './Screen'
|
||||||
|
import Button from './Button'
|
||||||
|
import Slider from './Slider'
|
||||||
|
import styles from './rendererDebugMenu.module.css'
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const worldRenderer = window.world as WorldRendererCommon
|
||||||
|
const { reactiveDebugParams } = worldRenderer
|
||||||
|
const { chunksRenderAboveEnabled, chunksRenderBelowEnabled, chunksRenderDistanceEnabled, chunksRenderAboveOverride, chunksRenderBelowOverride, chunksRenderDistanceOverride, stopRendering, disableEntities } = useSnapshot(reactiveDebugParams)
|
||||||
|
|
||||||
|
const { rendererPerfDebugOverlay } = useSnapshot(options)
|
||||||
|
|
||||||
|
// Helper to round values to nearest step
|
||||||
|
const roundToStep = (value: number, step: number) => Math.round(value / step) * step
|
||||||
|
|
||||||
|
if (!rendererPerfDebugOverlay) return null
|
||||||
|
|
||||||
|
return <div className={styles.container}>
|
||||||
|
<div className={styles.column}>
|
||||||
|
<h3>Rendering Controls</h3>
|
||||||
|
<Button
|
||||||
|
label={stopRendering ? 'Start Rendering' : 'Stop Rendering'}
|
||||||
|
onClick={() => { reactiveDebugParams.stopRendering = !reactiveDebugParams.stopRendering }}
|
||||||
|
overlayColor={stopRendering ? 'red' : undefined}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
label={disableEntities ? 'Enable Entities' : 'Disable Entities'}
|
||||||
|
onClick={() => { reactiveDebugParams.disableEntities = !reactiveDebugParams.disableEntities }}
|
||||||
|
overlayColor={disableEntities ? 'red' : undefined}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.column}>
|
||||||
|
<h3>Chunks Render Settings</h3>
|
||||||
|
<div className={styles.sliderGroup}>
|
||||||
|
<Button
|
||||||
|
label={chunksRenderAboveEnabled ? 'Disable Above Override' : 'Enable Above Override'}
|
||||||
|
onClick={() => {
|
||||||
|
const newState = !chunksRenderAboveEnabled
|
||||||
|
reactiveDebugParams.chunksRenderAboveEnabled = newState
|
||||||
|
if (newState) { reactiveDebugParams.chunksRenderAboveOverride = 0 } else { reactiveDebugParams.chunksRenderAboveOverride = undefined }
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Slider
|
||||||
|
label="Chunks Above"
|
||||||
|
min={0}
|
||||||
|
max={256}
|
||||||
|
value={chunksRenderAboveOverride ?? 0}
|
||||||
|
style={{ width: '100%', }}
|
||||||
|
updateValue={(value) => {
|
||||||
|
const roundedValue = roundToStep(value, 16)
|
||||||
|
reactiveDebugParams.chunksRenderAboveOverride = roundedValue
|
||||||
|
}}
|
||||||
|
disabledReason={chunksRenderAboveEnabled ? undefined : 'Override not enabled'}
|
||||||
|
unit=""
|
||||||
|
valueDisplay={roundToStep(reactiveDebugParams.chunksRenderAboveOverride ?? 0, 16)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.sliderGroup}>
|
||||||
|
<Button
|
||||||
|
label={chunksRenderBelowEnabled ? 'Disable Below Override' : 'Enable Below Override'}
|
||||||
|
onClick={() => {
|
||||||
|
const newState = !chunksRenderBelowEnabled
|
||||||
|
reactiveDebugParams.chunksRenderBelowEnabled = newState
|
||||||
|
if (newState) { reactiveDebugParams.chunksRenderBelowOverride = 0 } else { reactiveDebugParams.chunksRenderBelowOverride = undefined }
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Slider
|
||||||
|
label="Chunks Below"
|
||||||
|
min={0}
|
||||||
|
max={256}
|
||||||
|
style={{ width: '100%', }}
|
||||||
|
value={chunksRenderBelowOverride ?? 0}
|
||||||
|
updateValue={(value) => {
|
||||||
|
const roundedValue = roundToStep(value, 16)
|
||||||
|
reactiveDebugParams.chunksRenderBelowOverride = roundedValue
|
||||||
|
}}
|
||||||
|
disabledReason={chunksRenderBelowEnabled ? undefined : 'Override not enabled'}
|
||||||
|
unit=""
|
||||||
|
valueDisplay={roundToStep(reactiveDebugParams.chunksRenderBelowOverride ?? 0, 16)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div className={styles.sliderGroup}>
|
||||||
|
<Button
|
||||||
|
label={chunksRenderDistanceEnabled ? 'Disable Distance Override' : 'Enable Distance Override'}
|
||||||
|
onClick={() => {
|
||||||
|
const newState = !chunksRenderDistanceEnabled
|
||||||
|
reactiveDebugParams.chunksRenderDistanceEnabled = newState
|
||||||
|
if (newState) { reactiveDebugParams.chunksRenderDistanceOverride = 8 } else { reactiveDebugParams.chunksRenderDistanceOverride = undefined }
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Slider
|
||||||
|
label="Render Distance"
|
||||||
|
min={1}
|
||||||
|
max={32}
|
||||||
|
style={{ width: '100%', }}
|
||||||
|
value={chunksRenderDistanceOverride ?? 8}
|
||||||
|
updateValue={(value) => {
|
||||||
|
const roundedValue = Math.round(value)
|
||||||
|
reactiveDebugParams.chunksRenderDistanceOverride = roundedValue
|
||||||
|
}}
|
||||||
|
disabledReason={chunksRenderDistanceEnabled ? undefined : 'Override not enabled'}
|
||||||
|
unit=""
|
||||||
|
valueDisplay={Math.round(reactiveDebugParams.chunksRenderDistanceOverride ?? 8)}
|
||||||
|
/>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
min-height: calc(20px * var(--scale));
|
min-height: calc(20px * var(--scale));
|
||||||
|
max-height: calc(20px * var(--scale));
|
||||||
font-family: minecraft, mojangles, monospace;
|
font-family: minecraft, mojangles, monospace;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
|
||||||
34
src/react/rendererDebugMenu.module.css
Normal file
34
src/react/rendererDebugMenu.module.css
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 10px;
|
||||||
|
height: 100%;
|
||||||
|
padding-top: env(safe-area-inset-top, 10px);
|
||||||
|
padding-left: env(safe-area-inset-left, 10px);
|
||||||
|
padding-right: env(safe-area-inset-right, 10px);
|
||||||
|
padding-bottom: env(safe-area-inset-bottom, 10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column h3 {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
color: white;
|
||||||
|
text-shadow: 2px 2px 0 rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sliderGroup {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
9
src/react/rendererDebugMenu.module.css.d.ts
vendored
Normal file
9
src/react/rendererDebugMenu.module.css.d.ts
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
// This file is automatically generated.
|
||||||
|
// Please do not change this file!
|
||||||
|
interface CssExports {
|
||||||
|
column: string;
|
||||||
|
container: string;
|
||||||
|
sliderGroup: string;
|
||||||
|
}
|
||||||
|
declare const cssExports: CssExports;
|
||||||
|
export default cssExports;
|
||||||
|
|
@ -61,6 +61,7 @@ import ControDebug from './react/ControDebug'
|
||||||
import ChunksDebug from './react/ChunksDebug'
|
import ChunksDebug from './react/ChunksDebug'
|
||||||
import ChunksDebugScreen from './react/ChunksDebugScreen'
|
import ChunksDebugScreen from './react/ChunksDebugScreen'
|
||||||
import DebugResponseTimeIndicator from './react/debugs/DebugResponseTimeIndicator'
|
import DebugResponseTimeIndicator from './react/debugs/DebugResponseTimeIndicator'
|
||||||
|
import RendererDebugMenu from './react/RendererDebugMenu'
|
||||||
import CreditsAboutModal from './react/CreditsAboutModal'
|
import CreditsAboutModal from './react/CreditsAboutModal'
|
||||||
import GlobalOverlayHints from './react/GlobalOverlayHints'
|
import GlobalOverlayHints from './react/GlobalOverlayHints'
|
||||||
|
|
||||||
|
|
@ -167,6 +168,7 @@ const InGameUi = () => {
|
||||||
{!disabledUiParts.includes('bossbars') && displayBossBars && <BossBarOverlayProvider />}
|
{!disabledUiParts.includes('bossbars') && displayBossBars && <BossBarOverlayProvider />}
|
||||||
<VoiceMicrophone />
|
<VoiceMicrophone />
|
||||||
<ChunksDebugScreen />
|
<ChunksDebugScreen />
|
||||||
|
<RendererDebugMenu />
|
||||||
</PerComponentErrorBoundary>
|
</PerComponentErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ export const watchOptionsAfterViewerInit = () => {
|
||||||
watchValue(options, o => {
|
watchValue(options, o => {
|
||||||
appViewer.inWorldRenderingConfig.vrSupport = o.vrSupport
|
appViewer.inWorldRenderingConfig.vrSupport = o.vrSupport
|
||||||
appViewer.inWorldRenderingConfig.vrPageGameRendering = o.vrPageGameRendering
|
appViewer.inWorldRenderingConfig.vrPageGameRendering = o.vrPageGameRendering
|
||||||
|
appViewer.inWorldRenderingConfig.enableDebugOverlay = o.rendererPerfDebugOverlay
|
||||||
})
|
})
|
||||||
|
|
||||||
watchValue(options, (o, isChanged) => {
|
watchValue(options, (o, isChanged) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue