diff --git a/src/rendering/entities.ts b/src/rendering/entities.ts index 4f20d47b..f812a863 100644 --- a/src/rendering/entities.ts +++ b/src/rendering/entities.ts @@ -16,8 +16,12 @@ export const NPC_COLOR = 0xff0000; export const NPC_HOVER_COLOR = 0xff3f5f; export const NPC_SELECTED_COLOR = 0xff0054; -export function create_object_mesh(object: QuestObject, geometry: BufferGeometry): Mesh { - return create_mesh(object, geometry, [], OBJECT_COLOR, "Object"); +export function create_object_mesh( + object: QuestObject, + geometry: BufferGeometry, + textures: Texture[] +): Mesh { + return create_mesh(object, geometry, textures, OBJECT_COLOR, "Object"); } export function create_npc_mesh( diff --git a/src/stores/EntityStore.ts b/src/stores/EntityStore.ts index 905c2e47..36d9d232 100644 --- a/src/stores/EntityStore.ts +++ b/src/stores/EntityStore.ts @@ -33,6 +33,9 @@ npc_tex_cache.set(NpcType.Unknown, DEFAULT_ENTITY_TEX_PROMISE); const object_cache: Map> = new Map(); object_cache.set(ObjectType.Unknown, DEFAULT_ENTITY_PROMISE); +const object_tex_cache: Map> = new Map(); +object_tex_cache.set(ObjectType.Unknown, DEFAULT_ENTITY_TEX_PROMISE); + class EntityStore { async get_npc_geometry(npc_type: NpcType): Promise { let mesh = npc_cache.get(npc_type); @@ -90,7 +93,7 @@ class EntityStore { if (geometry) { return geometry; } else { - geometry = get_object_data(object_type) + geometry = get_object_data(object_type, AssetType.Geometry) .then(({ url, data }) => { const cursor = new ArrayBufferCursor(data, Endianness.Little); const nj_objects = url.endsWith(".nj") ? parse_nj(cursor) : parse_xj(cursor); @@ -111,6 +114,28 @@ class EntityStore { return geometry; } } + + async get_object_tex(object_type: ObjectType): Promise { + let tex = object_tex_cache.get(object_type); + + if (tex) { + return tex; + } else { + tex = get_object_data(object_type, AssetType.Texture) + .then(({ data }) => { + const cursor = new ArrayBufferCursor(data, Endianness.Little); + const xvm = parse_xvm(cursor); + return xvm_to_textures(xvm); + }) + .catch(e => { + logger.warn(`Could load texture file for ${object_type.name}.`, e); + return DEFAULT_ENTITY_TEX; + }); + + object_tex_cache.set(object_type, tex); + return tex; + } + } } export const entity_store = new EntityStore(); diff --git a/src/stores/QuestEditorStore.ts b/src/stores/QuestEditorStore.ts index 68d2b95c..c2035896 100644 --- a/src/stores/QuestEditorStore.ts +++ b/src/stores/QuestEditorStore.ts @@ -70,8 +70,9 @@ class QuestEditorStore { for (const object of quest.objects.filter(o => o.area_id === variant.area.id)) { try { const object_geom = await entity_store.get_object_geometry(object.type); + const object_tex = await entity_store.get_object_tex(object.type); this.set_section_on_visible_quest_entity(object, sections); - object.object_3d = create_object_mesh(object, object_geom); + object.object_3d = create_object_mesh(object, object_geom, object_tex); } catch (e) { logger.error(e); } diff --git a/src/stores/binary_assets.ts b/src/stores/binary_assets.ts index 837cf5fa..95118491 100644 --- a/src/stores/binary_assets.ts +++ b/src/stores/binary_assets.ts @@ -31,9 +31,10 @@ export async function get_npc_data( } export async function get_object_data( - object_type: ObjectType + object_type: ObjectType, + type: AssetType ): Promise<{ url: string; data: ArrayBuffer }> { - const url = object_type_to_url(object_type); + const url = object_type_to_url(object_type, type); const data = await get_asset(url); return { url, data }; } @@ -208,28 +209,32 @@ function npc_type_to_url(npc_type: NpcType, type: AssetType): string { } } -function object_type_to_url(object_type: ObjectType): string { - switch (object_type) { - case ObjectType.EasterEgg: - case ObjectType.ChristmasTree: - case ObjectType.ChristmasWreath: - case ObjectType.TwentyFirstCentury: - case ObjectType.Sonic: - case ObjectType.WelcomeBoard: - case ObjectType.FloatingJelifish: - case ObjectType.RuinsSeal: - case ObjectType.Dolphin: - case ObjectType.Cacti: - case ObjectType.BigBrownRock: - case ObjectType.PoisonPlant: - case ObjectType.BigBlackRocks: - case ObjectType.FallingRock: - case ObjectType.DesertFixedTypeBoxBreakableCrystals: - case ObjectType.BeeHive: - return `/objects/${object_type.pso_id}.nj`; +function object_type_to_url(object_type: ObjectType, type: AssetType): string { + if (type === AssetType.Geometry) { + switch (object_type) { + case ObjectType.EasterEgg: + case ObjectType.ChristmasTree: + case ObjectType.ChristmasWreath: + case ObjectType.TwentyFirstCentury: + case ObjectType.Sonic: + case ObjectType.WelcomeBoard: + case ObjectType.FloatingJelifish: + case ObjectType.RuinsSeal: + case ObjectType.Dolphin: + case ObjectType.Cacti: + case ObjectType.BigBrownRock: + case ObjectType.PoisonPlant: + case ObjectType.BigBlackRocks: + case ObjectType.FallingRock: + case ObjectType.DesertFixedTypeBoxBreakableCrystals: + case ObjectType.BeeHive: + return `/objects/${object_type.pso_id}.nj`; - default: - return `/objects/${object_type.pso_id}.xj`; + default: + return `/objects/${object_type.pso_id}.xj`; + } + } else { + return `/objects/${object_type.pso_id}.xvm`; } }