diff --git a/src/commonMain/kotlin/baaahs/mapper/Mapper.kt b/src/commonMain/kotlin/baaahs/mapper/Mapper.kt index 77ec37519..5dc4f3fcf 100644 --- a/src/commonMain/kotlin/baaahs/mapper/Mapper.kt +++ b/src/commonMain/kotlin/baaahs/mapper/Mapper.kt @@ -27,10 +27,14 @@ import kotlin.random.Random /** [SolidBrainShader] appears to be busted as of 2020/09. */ const val USE_SOLID_SHADERS = false +interface MapperBuilder { + fun build(): Mapper +} + abstract class Mapper( private val plugins: Plugins, private val network: Network, - sceneProvider: SceneProvider, + private val sceneProvider: SceneProvider, private val mediaDevices: MediaDevices, private val pinkyAddress: Network.Address, private val clock: Clock, @@ -64,16 +68,23 @@ abstract class Mapper( var mappingController: MappableBrain? = null init { - sceneProvider.addObserver(fireImmediately = true) { - it.openScene?.model?.let { - model = it - ui.addWireframe(it) - } + sceneProvider.addObserver(fireImmediately = false) { + setModel() } } open fun onLaunch() { - mapperScope.launch { start() } + mapperScope.launch { + setModel() + start() + } + } + + private fun setModel() { + sceneProvider.openScene?.model?.let { + model = it + ui.addWireframe(it) + } } fun start() { diff --git a/src/jsMain/kotlin/baaahs/app/ui/AppIndex.kt b/src/jsMain/kotlin/baaahs/app/ui/AppIndex.kt index 1fd41aafe..c0031bccc 100644 --- a/src/jsMain/kotlin/baaahs/app/ui/AppIndex.kt +++ b/src/jsMain/kotlin/baaahs/app/ui/AppIndex.kt @@ -14,7 +14,7 @@ import baaahs.client.WebClient import baaahs.client.document.SceneManager import baaahs.client.document.ShowManager import baaahs.gl.withCache -import baaahs.mapper.JsMapper +import baaahs.mapper.JsMapperBuilder import baaahs.mapper.sceneEditor import baaahs.show.mutable.MutableShow import baaahs.ui.* @@ -264,8 +264,8 @@ val AppIndex = xComponent("AppIndex") { props -> } else if (appState == AppState.SceneView) { sceneEditor { attrs.sceneEditorClient = props.sceneEditorClient - attrs.mapper = props.mapper attrs.sceneManager = sceneManager + attrs.mapperBuilder = props.mapperBuilder } } } @@ -310,7 +310,7 @@ external interface AppIndexProps : Props { var sceneManager: SceneManager.Facade var sceneEditorClient: SceneEditorClient.Facade - var mapper: JsMapper + var mapperBuilder: JsMapperBuilder } fun RBuilder.appIndex(handler: RHandler) = diff --git a/src/jsMain/kotlin/baaahs/client/WebClient.kt b/src/jsMain/kotlin/baaahs/client/WebClient.kt index 34f2909a1..9079e1780 100644 --- a/src/jsMain/kotlin/baaahs/client/WebClient.kt +++ b/src/jsMain/kotlin/baaahs/client/WebClient.kt @@ -14,7 +14,7 @@ import baaahs.gl.Toolchain import baaahs.io.Fs import baaahs.io.RemoteFsSerializer import baaahs.libraries.ShaderLibraries -import baaahs.mapper.JsMapper +import baaahs.mapper.JsMapperBuilder import baaahs.net.Network import baaahs.plugin.Plugins import baaahs.scene.SceneProvider @@ -32,7 +32,7 @@ class WebClient( private val sceneProvider: SceneProvider, private val storage: ClientStorage, private val sceneEditorClient: SceneEditorClient, - private val mapper: JsMapper, + private val mapperBuilder: JsMapperBuilder, remoteFsSerializer: RemoteFsSerializer, private val notifier: Notifier, private val fileDialog: FileDialog, @@ -85,7 +85,7 @@ class WebClient( this.sceneManager = this@WebClient.sceneManager.facade this.sceneEditorClient = this@WebClient.sceneEditorClient.facade - this.mapper = this@WebClient.mapper + this.mapperBuilder = this@WebClient.mapperBuilder }) } diff --git a/src/jsMain/kotlin/baaahs/di/JsModules.kt b/src/jsMain/kotlin/baaahs/di/JsModules.kt index f89ddeb3e..0c455d41e 100644 --- a/src/jsMain/kotlin/baaahs/di/JsModules.kt +++ b/src/jsMain/kotlin/baaahs/di/JsModules.kt @@ -13,7 +13,7 @@ import baaahs.gl.RootToolchain import baaahs.gl.Toolchain import baaahs.io.PubSubRemoteFsClientBackend import baaahs.io.RemoteFsSerializer -import baaahs.mapper.JsMapper +import baaahs.mapper.JsMapperBuilder import baaahs.monitor.MonitorUi import baaahs.net.Network import baaahs.plugin.ClientPlugins @@ -82,7 +82,7 @@ open class JsUiWebClientModule : WebClientModule() { scoped { Notifier(get()) } scoped { SceneEditorClient(get(), get()) } scoped { - JsMapper(get(), get(), get(), null, get(), get(), get(), get(named(Qualifier.PinkyAddress)), get(), get()) + JsMapperBuilder(get(), get(), get(), null, get(), get(), get(), get(named(Qualifier.PinkyAddress)), get(), get()) } // Dev only: diff --git a/src/jsMain/kotlin/baaahs/mapper/JsMapper.kt b/src/jsMain/kotlin/baaahs/mapper/JsMapper.kt index 85c0cb5b0..ab88055d9 100644 --- a/src/jsMain/kotlin/baaahs/mapper/JsMapper.kt +++ b/src/jsMain/kotlin/baaahs/mapper/JsMapper.kt @@ -8,12 +8,12 @@ import baaahs.geom.Vector2F import baaahs.geom.Vector3F import baaahs.geom.toThreeEuler import baaahs.imaging.* +import baaahs.mapper.JsMapper.StatusListener import baaahs.mapper.MappingSession.SurfaceData.PixelData import baaahs.model.Model import baaahs.net.Network import baaahs.plugin.Plugins import baaahs.scene.SceneProvider -import baaahs.sim.HostedWebApp import baaahs.ui.Keypress import baaahs.ui.KeypressResult import baaahs.ui.Observable @@ -28,8 +28,6 @@ import js.objects.jso import kotlinx.coroutines.* import mui.icons.material.KeyboardArrowRight import react.RBuilder -import react.ReactElement -import react.createElement import react.dom.br import three.* import three.Color @@ -78,6 +76,24 @@ class MapperStatus : Observable() { var orderedPanels: List> by notifyOnChange(emptyList()) } +class JsMapperBuilder( + private val plugins: Plugins, + private val sceneEditorClient: SceneEditorClient, + private val sceneManager: SceneManager, + private val statusListener: StatusListener? = null, + private val network: Network, + private val sceneProvider: SceneProvider, + private val mediaDevices: MediaDevices, + private val pinkyAddress: Network.Address, + private val clock: Clock, + private val clientStorage: ClientStorage, + private val mapperScope: CoroutineScope = CoroutineScope(Dispatchers.Main) +) : MapperBuilder { + override fun build(): JsMapper = JsMapper( + plugins, sceneEditorClient, sceneManager, statusListener, network, sceneProvider, mediaDevices, pinkyAddress, + clock, clientStorage, mapperScope + ) +} class JsMapper( plugins: Plugins, private val sceneEditorClient: SceneEditorClient, @@ -92,7 +108,7 @@ class JsMapper( mapperScope: CoroutineScope = CoroutineScope(Dispatchers.Main) ) : Mapper( plugins, network, sceneProvider, mediaDevices, pinkyAddress, clock, mapperScope -), HostedWebApp { +) { var mappingEnabled: Boolean = false set(value) { if (value != field) { @@ -442,14 +458,6 @@ class JsMapper( perfStatsDiv.innerText = mapperStats.summarize() } - override fun render(): ReactElement<*> { - return createElement(SceneEditorView, jso { - sceneEditorClient = this@JsMapper.sceneEditorClient.facade - mapper = this@JsMapper - sceneManager = this@JsMapper.sceneManager.facade - }) - } - override fun onLaunch() { super.onLaunch() @@ -783,7 +791,9 @@ class JsMapper( fun findVisualizer(entityName: String): PanelInfo? = entitiesByName[entityName]?.let { entityDepictions[it] } - override val ui: MapperUi = object : MapperUi { + override val ui: MapperUi by lazy { JsMapperUi() } + + inner class JsMapperUi : MapperUi { override var message: String? get() = mapperStatus.message set(value) { mapperStatus.message = value } diff --git a/src/jsMain/kotlin/baaahs/mapper/MapperAppView.kt b/src/jsMain/kotlin/baaahs/mapper/MapperAppView.kt index 5ea0918fa..0ffe3b456 100644 --- a/src/jsMain/kotlin/baaahs/mapper/MapperAppView.kt +++ b/src/jsMain/kotlin/baaahs/mapper/MapperAppView.kt @@ -32,7 +32,7 @@ val MapperAppView = xComponent("baaahs.mapper.MapperAppView" val appContext = useContext(mapperAppContext) val styles = appContext.allStyles.mapper - val ui = props.mapper + val ui = memo(props.mapperBuilder) { props.mapperBuilder.build() } observe(ui) val uiActions = memo(ui) { MemoizedJsMapper(ui) } @@ -77,18 +77,18 @@ val MapperAppView = xComponent("baaahs.mapper.MapperAppView" ui.setSizes() - val handleChangeEntity by handler(props.mapper.mappingController) { entity: Model.Entity? -> - props.mapper.mappingController?.guessedEntity = entity + val handleChangeEntity by handler(ui.mappingController) { entity: Model.Entity? -> + ui.mappingController?.guessedEntity = entity forceRender() } - val handlePixelCountChange by handler(props.mapper.mappingController) { pixelCount: String -> - props.mapper.mappingController?.expectedPixelCount = pixelCount.toIntOrNull() + val handlePixelCountChange by handler(ui.mappingController) { pixelCount: String -> + ui.mappingController?.expectedPixelCount = pixelCount.toIntOrNull() forceRender() } - val handlePixelFormatChange by handler(props.mapper.mappingController) { pixelFormat: PixelFormat? -> - props.mapper.mappingController?.pixelFormat = pixelFormat + val handlePixelFormatChange by handler(ui.mappingController) { pixelFormat: PixelFormat? -> + ui.mappingController?.pixelFormat = pixelFormat forceRender() } @@ -172,10 +172,10 @@ val MapperAppView = xComponent("baaahs.mapper.MapperAppView" } } - props.mapper.mappingController?.let { mappingController -> + ui.mappingController?.let { mappingController -> betterSelect { attrs.label = "Entity:" - attrs.values = props.mapper.entitiesByName.values.toList().map<_, Model.Entity?>{ it }.plus(null) + attrs.values = ui.entitiesByName.values.toList().map<_, Model.Entity?>{ it }.plus(null) attrs.renderValueOption = { entity -> buildElement { +(entity?.name ?: "None" ) } } attrs.value = mappingController.guessedEntity attrs.onChange = handleChangeEntity @@ -264,7 +264,7 @@ val MapperAppView = xComponent("baaahs.mapper.MapperAppView" } statusBar { - attrs.mapperStatus = props.mapper.mapperStatus + attrs.mapperStatus = ui.mapperStatus } div(+styles.perfStats) { @@ -284,7 +284,7 @@ val MapperAppView = xComponent("baaahs.mapper.MapperAppView" } twoLogNSlices { - attrs.mapper = props.mapper + attrs.mapper = ui attrs.sessionMetadata = metadata } } @@ -359,7 +359,7 @@ val MapperAppView = xComponent("baaahs.mapper.MapperAppView" } external interface MapperAppViewProps : Props { - var mapper: JsMapper + var mapperBuilder: JsMapperBuilder } fun RBuilder.mapperApp(handler: RHandler) = diff --git a/src/jsMain/kotlin/baaahs/mapper/MapperAppWrapperView.kt b/src/jsMain/kotlin/baaahs/mapper/MapperAppWrapperView.kt index bfd8433df..bb25f9d0e 100644 --- a/src/jsMain/kotlin/baaahs/mapper/MapperAppWrapperView.kt +++ b/src/jsMain/kotlin/baaahs/mapper/MapperAppWrapperView.kt @@ -29,14 +29,14 @@ private val MapperAppWrapperView = xComponent("MapperAppW attrs.value = myAppContext mapperApp { - attrs.mapper = props.mapper + attrs.mapperBuilder = props.mapperBuilder } } } external interface MapperAppWrapperProps : Props { var sceneEditorClient: SceneEditorClient.Facade - var mapper: JsMapper + var mapperBuilder: JsMapperBuilder } fun RBuilder.mapperAppWrapper(handler: RHandler) = diff --git a/src/jsMain/kotlin/baaahs/mapper/SceneEditorView.kt b/src/jsMain/kotlin/baaahs/mapper/SceneEditorView.kt index c89a36dea..1787631cb 100644 --- a/src/jsMain/kotlin/baaahs/mapper/SceneEditorView.kt +++ b/src/jsMain/kotlin/baaahs/mapper/SceneEditorView.kt @@ -80,7 +80,7 @@ val SceneEditorView = xComponent("SceneEditorView") { prop tabPanel(PageTabs.Mapping, selectedTab) { mapperAppWrapper { attrs.sceneEditorClient = props.sceneEditorClient - attrs.mapper = props.mapper + attrs.mapperBuilder = props.mapperBuilder } } } @@ -102,8 +102,8 @@ private fun RBuilder.tabPanel(tab: PageTabs, selectedTab: PageTabs, block: RBuil external interface SceneEditorViewProps : Props { var sceneEditorClient: SceneEditorClient.Facade - var mapper: JsMapper var sceneManager: SceneManager.Facade + var mapperBuilder: JsMapperBuilder } fun RBuilder.sceneEditor(handler: RHandler) =