mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-04 22:58:29 +08:00
Added dev mode and added more manual tweaks for the render geometry.
This commit is contained in:
parent
29192e5684
commit
b856a22851
@ -50,7 +50,8 @@ private fun <Model : NinjaModel, Obj : NinjaObject<Model, Obj>, Context> parseNi
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: cache model and object offsets so we don't reparse the same data.
|
||||
// We don't need to cache references to other objects or models because in practice the graph is
|
||||
// a tree, i.e. no two objects point to the same object or model.
|
||||
private fun <Model : NinjaModel, Obj : NinjaObject<Model, Obj>, Context> parseSiblingObjects(
|
||||
cursor: Cursor,
|
||||
parseModel: (cursor: Cursor, context: Context) -> Model,
|
||||
|
@ -74,7 +74,7 @@ private val AREAS by lazy {
|
||||
|
||||
@Suppress("UNUSED_CHANGED_VALUE")
|
||||
val ep4 = listOf(
|
||||
createArea(0, "Pioneer II (Ep. IV)", order++, 1),
|
||||
createArea(0, "Pioneer II", order++, 1),
|
||||
createArea(1, "Crater Route 1", order++, 1),
|
||||
createArea(2, "Crater Route 2", order++, 1),
|
||||
createArea(3, "Crater Route 3", order++, 1),
|
||||
|
@ -241,8 +241,8 @@ class UiStore(private val applicationUrl: ApplicationUrl) : Store() {
|
||||
val bindingParts = mutableListOf<String>()
|
||||
|
||||
if (e.ctrlKey) bindingParts.add("Ctrl")
|
||||
if (e.shiftKey) bindingParts.add("Shift")
|
||||
if (e.altKey) bindingParts.add("Alt")
|
||||
if (e.shiftKey) bindingParts.add("Shift")
|
||||
bindingParts.add(e.key.toUpperCase())
|
||||
|
||||
val binding = bindingParts.joinToString("-")
|
||||
|
@ -614,6 +614,7 @@ external class MeshBasicMaterial(
|
||||
|
||||
external interface MeshLambertMaterialParameters : MaterialParameters {
|
||||
var color: Color
|
||||
var map: Texture?
|
||||
var skinning: Boolean
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,6 @@ class AreaAssetLoader(private val assetLoader: AssetLoader) : DisposableContaine
|
||||
): Pair<Object3D, List<SectionModel>> {
|
||||
val fix = MANUAL_FIXES[Pair(episode, areaVariant.area.id)]
|
||||
val sections = mutableMapOf<Int, SectionModel>()
|
||||
console.log(renderGeometry)
|
||||
|
||||
val group =
|
||||
renderGeometryToGroup(renderGeometry, textures) { renderSection, areaObj, mesh ->
|
||||
@ -370,7 +369,33 @@ class AreaAssetLoader(private val assetLoader: AssetLoader) : DisposableContaine
|
||||
// Pioneer 2
|
||||
Pair(Episode.I, 0) to Fix(
|
||||
renderOnTopTextures = jsSetOf(
|
||||
70, 71, 72, 126, 127, 155, 156, 198, 230, 231, 232, 233, 234,
|
||||
20,
|
||||
40,
|
||||
41,
|
||||
67,
|
||||
70,
|
||||
71,
|
||||
72,
|
||||
93,
|
||||
94,
|
||||
96,
|
||||
105,
|
||||
120,
|
||||
121,
|
||||
122,
|
||||
155,
|
||||
156,
|
||||
170,
|
||||
198,
|
||||
218,
|
||||
220,
|
||||
221,
|
||||
230,
|
||||
231,
|
||||
232,
|
||||
233,
|
||||
234,
|
||||
243,
|
||||
),
|
||||
hiddenObjects = jsSetOf(
|
||||
"s_m_0_6a_d_iu5sg6",
|
||||
@ -404,14 +429,39 @@ class AreaAssetLoader(private val assetLoader: AssetLoader) : DisposableContaine
|
||||
"s_m_0_4_1_is53va",
|
||||
"s_m_0_3l_6_igzvga",
|
||||
"s_n_0_en_3_iiawrz",
|
||||
"a_k_0_1k_3_ihdi9s",
|
||||
),
|
||||
),
|
||||
// Forest 1
|
||||
Pair(Episode.I, 1) to Fix(
|
||||
renderOnTopTextures = jsSetOf(12, 41),
|
||||
renderOnTopTextures = jsSetOf(12, 24, 41),
|
||||
// Hiding trees and their shadows, doesn't seem to improve things.
|
||||
// hiddenObjects = jsSetOf(
|
||||
// // Trees
|
||||
// "s_n_0_2i_2_im1teq",
|
||||
// "s_n_0_2i_2_im1tep",
|
||||
// // Baked-in shadows.
|
||||
// "s_n_0_2n_1_irv6ha",
|
||||
// "s_n_0_2g_1_iqvdru",
|
||||
// "s_n_0_2p_1_irv6h6",
|
||||
// "s_n_0_47_1_iqve55",
|
||||
// "s_n_0_3p_1_ip2uvk",
|
||||
// "s_n_0_1r_1_iqve64",
|
||||
// "s_n_0_1f_1_irv6h0",
|
||||
// "s_n_0_1o_1_iqvdnv",
|
||||
// "s_n_0_28_1_iqvdw5",
|
||||
// "s_n_0_2b_1_iqvdrj",
|
||||
// "s_n_0_22_1_ip2w4r",
|
||||
// "s_n_0_3i_1_iqvdxp",
|
||||
// "s_n_0_33_1_iqve4e",
|
||||
// "s_n_0_2i_1_ip2v47",
|
||||
// "s_n_0_3a_1_ip2ugm",
|
||||
// "s_n_0_39_1_irv672",
|
||||
// ),
|
||||
),
|
||||
// Cave 1
|
||||
Pair(Episode.I, 3) to Fix(
|
||||
renderOnTopTextures = jsSetOf(89),
|
||||
hiddenObjects = jsSetOf(
|
||||
"s_n_0_8_1_iqrqjj",
|
||||
"s_i_0_b5_1_is7ajh",
|
||||
@ -437,6 +487,14 @@ class AreaAssetLoader(private val assetLoader: AssetLoader) : DisposableContaine
|
||||
"s_n_0_3i_1_iurb4o",
|
||||
"s_n_0_22_1_ii9035",
|
||||
"s_n_0_2i_3_iiqupy",
|
||||
"s_n_0_s_3_im3sg2",
|
||||
"s_n_0_o_2_im3v5x",
|
||||
"s_n_0_52_2_ilqxdf",
|
||||
"s_n_0_1g_3_im5sui",
|
||||
"s_n_0_15_2_im5sum",
|
||||
"s_n_0_6l_1_im1ktx",
|
||||
"s_n_0_3v_1_ikzchf",
|
||||
"s_n_0_2i_3_ilfw56",
|
||||
),
|
||||
),
|
||||
// Cave 2
|
||||
@ -530,10 +588,69 @@ class AreaAssetLoader(private val assetLoader: AssetLoader) : DisposableContaine
|
||||
// Jungle Area East
|
||||
Pair(Episode.II, 6) to Fix(
|
||||
renderOnTopTextures = jsSetOf(0, 1, 2, 18, 21, 24),
|
||||
hiddenObjects = jsSetOf(
|
||||
"a_m_0_1i_1_isf1hw",
|
||||
"a_m_0_1i_1_isfvf0",
|
||||
"a_m_0_1i_1_ise7ew",
|
||||
"a_m_0_1i_1_ishhj6",
|
||||
"a_m_0_1i_1_isiw4p",
|
||||
"a_m_0_1i_1_ishyp4",
|
||||
"a_m_0_1i_1_isewhg",
|
||||
"a_m_0_1i_1_isemhl",
|
||||
"a_m_0_1i_1_isiuce",
|
||||
"a_m_0_1i_1_isfvey",
|
||||
"a_m_0_1i_1_isgolp",
|
||||
"a_m_0_1i_1_iseg19",
|
||||
"a_m_0_1i_1_isdzut",
|
||||
"a_m_0_1i_1_isf0vs",
|
||||
"a_m_0_1i_1_ishrwm",
|
||||
"a_m_0_1i_1_isivaf",
|
||||
"a_m_0_1i_1_isf0vs",
|
||||
"a_m_0_1i_1_isfqe9",
|
||||
),
|
||||
),
|
||||
// Subterranean Desert 1
|
||||
Pair(Episode.IV, 6) to Fix(
|
||||
renderOnTopTextures = jsSetOf(48, 50, 58, 66, 80, 81, 92, 93, 94, 99, 100, 103),
|
||||
hiddenObjects = jsSetOf(
|
||||
"s_v_f_16u_b_j2s5tx",
|
||||
"s_v_d_84_f_j046sf",
|
||||
"s_v_1v_205_2n_jb17vl",
|
||||
"s_n_0_1s_1_iwnfqt",
|
||||
"s_n_0_g1_6_iovjxw",
|
||||
"s_v_d_z6_k_j1viu6",
|
||||
"s_n_0_do_4_ipdh8p",
|
||||
"s_v_c_7y_c_iu7yzc",
|
||||
"s_v_8_4a_8_ixe9km",
|
||||
"s_v_4_15_4_in60hf",
|
||||
"s_n_0_6_1_ihtf3l",
|
||||
"s_n_0_6_1_ikxbmr",
|
||||
"s_v_9_3e_9_itbo7o",
|
||||
"s_v_t_19k_r_iv3zbt",
|
||||
"s_v_a_2s_a_ix4iob",
|
||||
"s_v_b_37_b_iu5dp9",
|
||||
"s_v_6_5t_7_iqx2nn",
|
||||
"s_v_8_145_l_j0crhw",
|
||||
"s_n_0_6_1_ikk5cn",
|
||||
"s_v_5_15r_d_j2n06s",
|
||||
"s_v_p_8n_p_j1enrp",
|
||||
"s_v_b_p3_d_iu4vwf",
|
||||
"s_v_c_3z_c_ithfqt",
|
||||
"s_v_2_3g_2_itis48",
|
||||
"s_v_17_h3_13_j7o59x",
|
||||
"s_n_0_2t_1_iw2868",
|
||||
"s_v_5_k1_8_ir35lp",
|
||||
"s_v_h_7k_y_j5h3h2",
|
||||
"s_v_8_4d_8_irrw8y",
|
||||
"s_v_o_1qg_h_iyilpg", // Removes roof and walls but also some rocks in the middle.
|
||||
"s_v_10_14y_11_j0vhyd",
|
||||
),
|
||||
),
|
||||
).also {
|
||||
// VR Spaceship Beta = VR Spaceship Alpha
|
||||
it[Pair(Episode.II, 4)] = it[Pair(Episode.II, 3)]!!
|
||||
// Ep. IV Pioneer II = Ep. I Pioneer II
|
||||
it[Pair(Episode.IV, 0)] = it[Pair(Episode.I, 0)]!!
|
||||
}
|
||||
|
||||
private val raycaster = Raycaster()
|
||||
|
@ -1,6 +1,7 @@
|
||||
package world.phantasmal.web.questEditor.rendering.input.state
|
||||
|
||||
import world.phantasmal.web.core.minus
|
||||
import world.phantasmal.web.externals.three.Mesh
|
||||
import world.phantasmal.web.externals.three.Vector2
|
||||
import world.phantasmal.web.externals.three.Vector3
|
||||
import world.phantasmal.web.questEditor.models.QuestEntityModel
|
||||
@ -85,6 +86,7 @@ class IdleState(
|
||||
pickEntity(event.pointerDevicePosition) == null
|
||||
) {
|
||||
ctx.setSelectedEntity(null)
|
||||
pickAndHighlightMesh()
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,6 +177,19 @@ class IdleState(
|
||||
return Pick(entity, grabOffset, dragAdjust)
|
||||
}
|
||||
|
||||
private fun pickAndHighlightMesh() {
|
||||
if (ctx.devMode.value) {
|
||||
val intersection = ctx.intersectObject(
|
||||
pointerDevicePosition,
|
||||
ctx.renderContext.renderGeometry,
|
||||
) { it.`object`.visible }
|
||||
|
||||
ctx.setHighlightedMesh(intersection?.`object` as Mesh?)
|
||||
} else {
|
||||
ctx.setHighlightedMesh(null)
|
||||
}
|
||||
}
|
||||
|
||||
private class Pick(
|
||||
val entity: QuestEntityModel<*, *>,
|
||||
|
||||
|
@ -1,10 +1,15 @@
|
||||
package world.phantasmal.web.questEditor.rendering.input.state
|
||||
|
||||
import mu.KotlinLogging
|
||||
import world.phantasmal.core.asJsArray
|
||||
import world.phantasmal.lib.fileFormats.ninja.XjObject
|
||||
import world.phantasmal.observable.value.Val
|
||||
import world.phantasmal.web.core.dot
|
||||
import world.phantasmal.web.core.minusAssign
|
||||
import world.phantasmal.web.core.plusAssign
|
||||
import world.phantasmal.web.core.rendering.OrbitalCameraInputManager
|
||||
import world.phantasmal.web.core.rendering.conversion.AreaObjectUserData
|
||||
import world.phantasmal.web.core.rendering.conversion.fingerPrint
|
||||
import world.phantasmal.web.externals.three.*
|
||||
import world.phantasmal.web.questEditor.actions.CreateEntityAction
|
||||
import world.phantasmal.web.questEditor.actions.DeleteEntityAction
|
||||
@ -17,11 +22,19 @@ import world.phantasmal.web.questEditor.stores.QuestEditorStore
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.atan2
|
||||
|
||||
private val logger = KotlinLogging.logger {}
|
||||
|
||||
class StateContext(
|
||||
private val questEditorStore: QuestEditorStore,
|
||||
val renderContext: QuestRenderContext,
|
||||
val cameraInputManager: OrbitalCameraInputManager,
|
||||
) {
|
||||
/**
|
||||
* Highlighted mesh with its original colors.
|
||||
*/
|
||||
private var highlightedMesh: Pair<Mesh, List<Color>>? = null
|
||||
|
||||
val devMode: Val<Boolean> = questEditorStore.devMode
|
||||
val quest: Val<QuestModel?> = questEditorStore.currentQuest
|
||||
val area: Val<AreaModel?> = questEditorStore.currentArea
|
||||
val wave: Val<WaveModel?> = questEditorStore.selectedEvent.flatMapNull { it?.wave }
|
||||
@ -153,8 +166,8 @@ class StateContext(
|
||||
|
||||
// Calculate the angle between the two vectors and rotate the entity around its y-axis
|
||||
// by that angle.
|
||||
val cos = axisToGrab.dot(axisToPointer)
|
||||
val sin = planeNormal.dot(axisToGrab.cross(axisToPointer))
|
||||
val cos = axisToGrab dot axisToPointer
|
||||
val sin = planeNormal dot axisToGrab.cross(axisToPointer)
|
||||
val angle = atan2(sin, cos)
|
||||
|
||||
entity.setWorldRotation(
|
||||
@ -240,6 +253,51 @@ class StateContext(
|
||||
return raycasterIntersections.find(predicate)
|
||||
}
|
||||
|
||||
fun setHighlightedMesh(mesh: Mesh?) {
|
||||
highlightedMesh?.let { (prevMesh, prevColors) ->
|
||||
prevMesh.material.unsafeCast<Array<MeshBasicMaterial>>().forEachIndexed { i, mat ->
|
||||
mat.color.set(prevColors[i])
|
||||
}
|
||||
}
|
||||
|
||||
highlightedMesh = null
|
||||
|
||||
if (mesh != null) {
|
||||
logger.info {
|
||||
val userData = mesh.userData.unsafeCast<AreaObjectUserData>()
|
||||
|
||||
val areaObj = userData.areaObject
|
||||
val textureIds = mutableSetOf<Int>()
|
||||
|
||||
fun getAllTextureIds(xjObject: XjObject) {
|
||||
xjObject.model?.meshes?.forEach { it.material.textureId?.let(textureIds::add) }
|
||||
xjObject.children.forEach(::getAllTextureIds)
|
||||
}
|
||||
|
||||
getAllTextureIds(areaObj.xjObject)
|
||||
|
||||
buildString {
|
||||
append("Section ")
|
||||
append(userData.sectionId)
|
||||
append(" (finger print: ")
|
||||
append(areaObj.fingerPrint())
|
||||
append(", texture IDs: ")
|
||||
textureIds.joinTo(this)
|
||||
append(')')
|
||||
}
|
||||
}
|
||||
|
||||
val origColors = mutableListOf<Color>()
|
||||
|
||||
mesh.material.unsafeCast<Array<MeshBasicMaterial>>().forEach {
|
||||
origColors.add(it.color.clone())
|
||||
it.color.set(0xB0FF00)
|
||||
}
|
||||
|
||||
highlightedMesh = Pair(mesh, origColors)
|
||||
}
|
||||
}
|
||||
|
||||
private fun intersectPlane(
|
||||
origin: Vector2,
|
||||
plane: Plane,
|
||||
|
@ -22,6 +22,7 @@ class QuestEditorStore(
|
||||
private val areaStore: AreaStore,
|
||||
private val undoManager: UndoManager,
|
||||
) : Store() {
|
||||
private val _devMode = mutableVal(false)
|
||||
private val _currentQuest = mutableVal<QuestModel?>(null)
|
||||
private val _currentArea = mutableVal<AreaModel?>(null)
|
||||
private val _selectedEvent = mutableVal<QuestEventModel?>(null)
|
||||
@ -30,6 +31,8 @@ class QuestEditorStore(
|
||||
private val mainUndo = UndoStack(undoManager)
|
||||
private val _showCollisionGeometry = mutableVal(true)
|
||||
|
||||
val devMode: Val<Boolean> = _devMode
|
||||
|
||||
val runner = QuestRunner()
|
||||
val currentQuest: Val<QuestModel?> = _currentQuest
|
||||
val currentArea: Val<AreaModel?> = _currentArea
|
||||
@ -55,6 +58,14 @@ class QuestEditorStore(
|
||||
val showCollisionGeometry: Val<Boolean> = _showCollisionGeometry
|
||||
|
||||
init {
|
||||
addDisposables(
|
||||
uiStore.onGlobalKeyDown(PwToolType.QuestEditor, "Ctrl-Alt-Shift-D") {
|
||||
_devMode.value = !_devMode.value
|
||||
|
||||
logger.info { "Dev mode ${if (devMode.value) "on" else "off"}." }
|
||||
},
|
||||
)
|
||||
|
||||
observe(uiStore.currentTool) { tool ->
|
||||
if (tool == PwToolType.QuestEditor) {
|
||||
makeMainUndoCurrent()
|
||||
|
Loading…
Reference in New Issue
Block a user