mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-10-19 22:27:36 -04:00
Generate dynamic model lists with CMake, + refactor
* When building with CMake, dynamic model lists are now generated * Factored common code out of generate_*_list.js files to deduplicate * Better separated generated model lists from main game code `dynamic_asset_data.c` and `dynamic_animated_asset_data.c` previously #included the corresponding generated headers, and `dynamic_asset_loader.c` declared externs for the contents. This messiness was likely done so the generated code would be built automatically (the Makefile globs all C files under `src/`). Now, model list data is output to C source files which are built explicitly. This, with some refactoring, allows the previously mentioned source files and externs to be removed. This is a bit hacky in the Makefile but will be automatic under CMake by using target properties. * Reorganized some files under `tools/`
This commit is contained in:
parent
9643719a31
commit
1d0b22df61
|
@ -19,11 +19,6 @@ set(SOX "sox")
|
||||||
set(VPK "vpk")
|
set(VPK "vpk")
|
||||||
set(VTF2PNG "vtf2png")
|
set(VTF2PNG "vtf2png")
|
||||||
|
|
||||||
set(CONVERT_ASSET "${PROJECT_SOURCE_DIR}/tools/convert_asset.py")
|
|
||||||
set(EXPORT_FBX "${PROJECT_SOURCE_DIR}/tools/export_fbx.py")
|
|
||||||
set(GEN_LEVEL_LIST "${PROJECT_SOURCE_DIR}/tools/generate_level_list.js")
|
|
||||||
set(GEN_SOUND_IDS "${PROJECT_SOURCE_DIR}/tools/generate_sound_ids.js")
|
|
||||||
set(JSOX "${PROJECT_SOURCE_DIR}/tools/jsox.js")
|
|
||||||
set(SKELETOOL64 "${PROJECT_SOURCE_DIR}/skelatool64/skeletool64")
|
set(SKELETOOL64 "${PROJECT_SOURCE_DIR}/skelatool64/skeletool64")
|
||||||
|
|
||||||
# Directories
|
# Directories
|
||||||
|
|
28
Makefile
28
Makefile
|
@ -359,7 +359,9 @@ ANIM_LIST = build/assets/models/pedestal_anim.o \
|
||||||
build/assets/models/props/switch001_anim.o
|
build/assets/models/props/switch001_anim.o
|
||||||
|
|
||||||
MODEL_HEADERS = $(MODEL_LIST:%.blend=build/%.h)
|
MODEL_HEADERS = $(MODEL_LIST:%.blend=build/%.h)
|
||||||
MODEL_OBJECTS = $(MODEL_LIST:%.blend=build/%_geo.o)
|
MODEL_OBJECTS = $(MODEL_LIST:%.blend=build/%_geo.o) \
|
||||||
|
build/assets/models/dynamic_model_list.o \
|
||||||
|
build/assets/models/dynamic_animated_model_list.o
|
||||||
|
|
||||||
DYNAMIC_MODEL_HEADERS = $(DYNAMIC_MODEL_LIST:%.blend=build/%.h)
|
DYNAMIC_MODEL_HEADERS = $(DYNAMIC_MODEL_LIST:%.blend=build/%.h)
|
||||||
DYNAMIC_MODEL_OBJECTS = $(DYNAMIC_MODEL_LIST:%.blend=build/%_geo.o)
|
DYNAMIC_MODEL_OBJECTS = $(DYNAMIC_MODEL_LIST:%.blend=build/%_geo.o)
|
||||||
|
@ -415,8 +417,6 @@ build/src/scene/render_plan.o: $(MODEL_HEADERS)
|
||||||
build/src/scene/security_camera.o: build/src/audio/clips.h build/assets/models/props/security_camera.h build/assets/models/dynamic_animated_model_list.h
|
build/src/scene/security_camera.o: build/src/audio/clips.h build/assets/models/props/security_camera.h build/assets/models/dynamic_animated_model_list.h
|
||||||
build/src/scene/signage.o: $(MODEL_HEADERS)
|
build/src/scene/signage.o: $(MODEL_HEADERS)
|
||||||
build/src/scene/switch.o: build/assets/models/props/switch001.h build/assets/materials/static.h build/assets/models/dynamic_animated_model_list.h
|
build/src/scene/switch.o: build/assets/models/props/switch001.h build/assets/materials/static.h build/assets/models/dynamic_animated_model_list.h
|
||||||
build/src/util/dynamic_asset_data.o: build/assets/models/dynamic_model_list_data.h
|
|
||||||
build/src/util/dynamic_animated_asset_data.o: build/assets/models/dynamic_animated_model_list_data.h
|
|
||||||
build/src/util/dynamic_asset_loader.o: build/assets/models/dynamic_model_list.h build/assets/models/dynamic_animated_model_list.h
|
build/src/util/dynamic_asset_loader.o: build/assets/models/dynamic_model_list.h build/assets/models/dynamic_animated_model_list.h
|
||||||
build/src/menu/audio_options.o: build/src/audio/subtitles.h
|
build/src/menu/audio_options.o: build/src/audio/subtitles.h
|
||||||
build/src/menu/video_options.o: build/src/audio/subtitles.h
|
build/src/menu/video_options.o: build/src/audio/subtitles.h
|
||||||
|
@ -460,7 +460,7 @@ LUA_FILES = $(shell find tools/ -type f -name '*.lua')
|
||||||
|
|
||||||
build/%.fbx: %.blend
|
build/%.fbx: %.blend
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
$(BLENDER_3_6) $< --background --python tools/export_fbx.py -- $@
|
$(BLENDER_3_6) $< --background --python tools/models/export_fbx.py -- $@
|
||||||
|
|
||||||
build/assets/test_chambers/%.h build/assets/test_chambers/%_geo.c build/assets/test_chambers/%_anim.c: build/assets/test_chambers/%.fbx assets/test_chambers/%.yaml build/assets/materials/static.h build/src/audio/subtitles.h $(SKELATOOL64) $(TEXTURE_IMAGES) $(LUA_FILES)
|
build/assets/test_chambers/%.h build/assets/test_chambers/%_geo.c build/assets/test_chambers/%_anim.c: build/assets/test_chambers/%.fbx assets/test_chambers/%.yaml build/assets/materials/static.h build/src/audio/subtitles.h $(SKELATOOL64) $(TEXTURE_IMAGES) $(LUA_FILES)
|
||||||
$(SKELATOOL64) --script tools/level_scripts/export_level.lua --fixed-point-scale ${SCENE_SCALE} --model-scale 0.01 --name $(<:build/assets/test_chambers/%.fbx=%) -m assets/materials/static.skm.yaml -o $(<:%.fbx=%.h) $<
|
$(SKELATOOL64) --script tools/level_scripts/export_level.lua --fixed-point-scale ${SCENE_SCALE} --model-scale 0.01 --name $(<:build/assets/test_chambers/%.fbx=%) -m assets/materials/static.skm.yaml -o $(<:%.fbx=%.h) $<
|
||||||
|
@ -478,17 +478,17 @@ build/assets/materials/%_mat.o: build/assets/materials/%_mat.c
|
||||||
levels: $(TEST_CHAMBER_HEADERS)
|
levels: $(TEST_CHAMBER_HEADERS)
|
||||||
echo $(TEST_CHAMBER_HEADERS)
|
echo $(TEST_CHAMBER_HEADERS)
|
||||||
|
|
||||||
build/assets/test_chambers/level_list.h: $(TEST_CHAMBER_HEADERS) tools/generate_level_list.js
|
build/assets/test_chambers/level_list.h: $(TEST_CHAMBER_HEADERS) tools/models/generate_level_list.js tools/models/model_list_utils.js
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
node tools/generate_level_list.js $@ $(TEST_CHAMBER_HEADERS)
|
node tools/models/generate_level_list.js $@ $(TEST_CHAMBER_HEADERS)
|
||||||
|
|
||||||
build/assets/models/dynamic_model_list.h build/assets/models/dynamic_model_list_data.h: $(DYNAMIC_MODEL_HEADERS) tools/generate_dynamic_model_list.js build/assets/models/cube/cube.h
|
build/assets/models/dynamic_model_list.h build/assets/models/dynamic_model_list.c: $(DYNAMIC_MODEL_HEADERS) tools/models/generate_dynamic_model_list.js tools/models/model_list_utils.js build/assets/models/cube/cube.h
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
node tools/generate_dynamic_model_list.js build/assets/models/dynamic_model_list.h build/assets/models/dynamic_model_list_data.h $(DYNAMIC_MODEL_HEADERS)
|
node tools/models/generate_dynamic_model_list.js build/assets/models/dynamic_model_list.h $(DYNAMIC_MODEL_HEADERS)
|
||||||
|
|
||||||
build/assets/models/dynamic_animated_model_list.h build/assets/models/dynamic_animated_model_list_data.h: $(DYNAMIC_ANIMATED_MODEL_HEADERS) tools/generate_dynamic_animated_model_list.js
|
build/assets/models/dynamic_animated_model_list.h build/assets/models/dynamic_animated_model_list.c: $(DYNAMIC_ANIMATED_MODEL_HEADERS) tools/models/generate_dynamic_animated_model_list.js tools/models/model_list_utils.js
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
node tools/generate_dynamic_animated_model_list.js build/assets/models/dynamic_animated_model_list.h build/assets/models/dynamic_animated_model_list_data.h $(DYNAMIC_ANIMATED_MODEL_HEADERS)
|
node tools/models/generate_dynamic_animated_model_list.js build/assets/models/dynamic_animated_model_list.h $(DYNAMIC_ANIMATED_MODEL_HEADERS)
|
||||||
|
|
||||||
build/levels.ld: $(TEST_CHAMBER_OBJECTS) tools/generate_level_ld.js
|
build/levels.ld: $(TEST_CHAMBER_OBJECTS) tools/generate_level_ld.js
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
|
@ -536,9 +536,9 @@ build/assets/%.aifc: assets/%.sox portal_pak_dir/%.wav
|
||||||
sox $(<:assets/%.sox=portal_pak_dir/%.wav) $(shell cat $<) $(@:%.aifc=%.wav)
|
sox $(<:assets/%.sox=portal_pak_dir/%.wav) $(shell cat $<) $(@:%.aifc=%.wav)
|
||||||
$(SFZ2N64) -o $@ $(@:%.aifc=%.wav)
|
$(SFZ2N64) -o $@ $(@:%.aifc=%.wav)
|
||||||
|
|
||||||
build/assets/%.aifc: assets/%.jsox tools/jsox.js portal_pak_dir/%.wav
|
build/assets/%.aifc: assets/%.jsox tools/sound/jsox.js portal_pak_dir/%.wav
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
node tools/jsox.js $< $(<:assets/%.jsox=portal_pak_dir/%.wav) $(@:%.aifc=%.wav)
|
node tools/sound/jsox.js $< $(<:assets/%.jsox=portal_pak_dir/%.wav) $(@:%.aifc=%.wav)
|
||||||
$(SFZ2N64) -o $@ $(@:%.aifc=%.wav)
|
$(SFZ2N64) -o $@ $(@:%.aifc=%.wav)
|
||||||
|
|
||||||
build/assets/%.aifc: assets/%.msox portal_pak_dir/%.mp3
|
build/assets/%.aifc: assets/%.msox portal_pak_dir/%.mp3
|
||||||
|
@ -554,9 +554,9 @@ build/assets/sound/sounds.sounds build/assets/sound/sounds.sounds.tbl: $(SOUND_C
|
||||||
|
|
||||||
build/asm/sound_data.o: build/assets/sound/sounds.sounds build/assets/sound/sounds.sounds.tbl
|
build/asm/sound_data.o: build/assets/sound/sounds.sounds build/assets/sound/sounds.sounds.tbl
|
||||||
|
|
||||||
build/src/audio/clips.h build/src/audio/languages.h build/src/audio/languages.c: tools/generate_sound_ids.js $(SOUND_CLIPS)
|
build/src/audio/clips.h build/src/audio/languages.h build/src/audio/languages.c: tools/sound/generate_sound_ids.js $(SOUND_CLIPS)
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
node tools/generate_sound_ids.js -o $(@D) -p SOUNDS_ $(SOUND_CLIPS)
|
node tools/sound/generate_sound_ids.js -o $(@D) -p SOUNDS_ $(SOUND_CLIPS)
|
||||||
|
|
||||||
build/src/audio/clips.o: build/src/audio/clips.h
|
build/src/audio/clips.o: build/src/audio/clips.h
|
||||||
build/src/decor/decor_object_list.o: build/src/audio/clips.h
|
build/src/decor/decor_object_list.o: build/src/audio/clips.h
|
||||||
|
|
|
@ -24,6 +24,11 @@ set(MODEL_SCALE 0.01)
|
||||||
# Scaling factor for render space
|
# Scaling factor for render space
|
||||||
set(SCENE_SCALE 128)
|
set(SCENE_SCALE 128)
|
||||||
|
|
||||||
|
# Tools for asset conversion
|
||||||
|
set(CONVERT_ASSET "${PROJECT_SOURCE_DIR}/tools/convert_asset.py")
|
||||||
|
set(EXPORT_FBX "${PROJECT_SOURCE_DIR}/tools/models/export_fbx.py")
|
||||||
|
set(MODEL_LIST_UTILS "${PROJECT_SOURCE_DIR}/tools/models/model_list_utils.js")
|
||||||
|
|
||||||
add_subdirectory(materials)
|
add_subdirectory(materials)
|
||||||
add_subdirectory(models)
|
add_subdirectory(models)
|
||||||
add_subdirectory(sound)
|
add_subdirectory(sound)
|
||||||
|
|
|
@ -1,14 +1,51 @@
|
||||||
|
cmake_path(
|
||||||
|
RELATIVE_PATH CMAKE_CURRENT_SOURCE_DIR
|
||||||
|
BASE_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||||
|
OUTPUT_VARIABLE RELATIVE_CURRENT_DIR
|
||||||
|
)
|
||||||
|
|
||||||
##################
|
##################
|
||||||
## Model export ##
|
## Model export ##
|
||||||
##################
|
##################
|
||||||
|
|
||||||
# TODO: dynamic and animated models
|
# Models whose data is loaded/unloaded as needed
|
||||||
|
set(DYNAMIC_MODELS
|
||||||
set(MODELS
|
|
||||||
cube/cube
|
cube/cube
|
||||||
|
props/autoportal_frame/autoportal_frame
|
||||||
|
props/box_dropper_glass
|
||||||
|
props/cylinder_test
|
||||||
|
props/lab_chair
|
||||||
|
props/lab_desk/lab_desk01
|
||||||
|
props/lab_desk/lab_desk02
|
||||||
|
props/lab_desk/lab_desk03
|
||||||
|
props/lab_desk/lab_desk04
|
||||||
|
props/lab_monitor
|
||||||
|
props/light_rail_endcap
|
||||||
|
props/portal_cleanser
|
||||||
|
props/radio
|
||||||
|
signage/clock
|
||||||
|
signage/clock_digits
|
||||||
|
)
|
||||||
|
|
||||||
|
# Animated models whose data is loaded/unloaded as needed
|
||||||
|
set(DYNAMIC_ANIMATED_MODELS
|
||||||
|
pedestal
|
||||||
|
props/box_dropper
|
||||||
|
props/button
|
||||||
|
props/combine_ball_catcher
|
||||||
|
props/combine_ball_launcher
|
||||||
|
props/door_01
|
||||||
|
props/door_02
|
||||||
|
props/security_camera
|
||||||
|
props/switch001
|
||||||
|
)
|
||||||
|
|
||||||
|
# All models
|
||||||
|
set(MODELS
|
||||||
|
${DYNAMIC_MODELS}
|
||||||
|
${DYNAMIC_ANIMATED_MODELS}
|
||||||
fleck_ash2
|
fleck_ash2
|
||||||
grav_flare
|
grav_flare
|
||||||
pedestal
|
|
||||||
player/chell
|
player/chell
|
||||||
portal_gun/ball_trail
|
portal_gun/ball_trail
|
||||||
portal_gun/v_portalgun
|
portal_gun/v_portalgun
|
||||||
|
@ -21,32 +58,10 @@ set(MODELS
|
||||||
portal/portal_orange
|
portal/portal_orange
|
||||||
portal/portal_orange_face
|
portal/portal_orange_face
|
||||||
portal/portal_orange_filled
|
portal/portal_orange_filled
|
||||||
props/autoportal_frame/autoportal_frame
|
|
||||||
props/box_dropper
|
|
||||||
props/box_dropper_glass
|
|
||||||
props/button
|
|
||||||
props/combine_ball_catcher
|
|
||||||
props/combine_ball_launcher
|
|
||||||
props/cylinder_test
|
|
||||||
props/door_01
|
|
||||||
props/door_02
|
|
||||||
props/lab_chair
|
|
||||||
props/lab_desk/lab_desk01
|
|
||||||
props/lab_desk/lab_desk02
|
|
||||||
props/lab_desk/lab_desk03
|
|
||||||
props/lab_desk/lab_desk04
|
|
||||||
props/lab_monitor
|
|
||||||
props/light_rail_endcap
|
|
||||||
props/portal_cleanser
|
|
||||||
props/radio
|
|
||||||
props/round_elevator
|
props/round_elevator
|
||||||
props/round_elevator_collision
|
props/round_elevator_collision
|
||||||
props/round_elevator_interior
|
props/round_elevator_interior
|
||||||
props/security_camera
|
|
||||||
props/signage
|
props/signage
|
||||||
props/switch001
|
|
||||||
signage/clock
|
|
||||||
signage/clock_digits
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Most models depend on both of these. Some only depend on one or the other,
|
# Most models depend on both of these. Some only depend on one or the other,
|
||||||
|
@ -56,13 +71,10 @@ set(MODEL_DEFAULT_MATERIALS
|
||||||
${ASSETS_DIR}/materials/objects.skm.yaml
|
${ASSETS_DIR}/materials/objects.skm.yaml
|
||||||
)
|
)
|
||||||
|
|
||||||
function(_add_model_export_command MODEL_NAME OUTPUT_VARIABLE)
|
set(GEN_DYNAMIC_MODEL_LIST "${PROJECT_SOURCE_DIR}/tools/models/generate_dynamic_model_list.js")
|
||||||
cmake_path(
|
set(GEN_DYNAMIC_ANIM_MODEL_LIST "${PROJECT_SOURCE_DIR}/tools/models/generate_dynamic_animated_model_list.js")
|
||||||
RELATIVE_PATH CMAKE_CURRENT_SOURCE_DIR
|
|
||||||
BASE_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
|
||||||
OUTPUT_VARIABLE RELATIVE_CURRENT_DIR
|
|
||||||
)
|
|
||||||
|
|
||||||
|
function(_add_model_export_command MODEL_NAME OUTPUT_VARIABLE)
|
||||||
set(INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}.blend")
|
set(INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}.blend")
|
||||||
set(OUTPUT_FILE "${CMAKE_BINARY_DIR}/${RELATIVE_CURRENT_DIR}/${MODEL_NAME}.fbx")
|
set(OUTPUT_FILE "${CMAKE_BINARY_DIR}/${RELATIVE_CURRENT_DIR}/${MODEL_NAME}.fbx")
|
||||||
|
|
||||||
|
@ -121,7 +133,7 @@ function(_add_model_generate_command MODEL_NAME MODEL_FBX OUTPUT_LIST)
|
||||||
COMMAND
|
COMMAND
|
||||||
${CMAKE_COMMAND} -E make_directory ${OUTPUT_DIR}
|
${CMAKE_COMMAND} -E make_directory ${OUTPUT_DIR}
|
||||||
COMMAND
|
COMMAND
|
||||||
${CONVERT_ASSET}
|
${PYTHON3} ${CONVERT_ASSET}
|
||||||
${SKELETOOL64}
|
${SKELETOOL64}
|
||||||
${MODEL_FBX}
|
${MODEL_FBX}
|
||||||
${MODEL_FLAGS}
|
${MODEL_FLAGS}
|
||||||
|
@ -184,3 +196,73 @@ add_custom_target(
|
||||||
models
|
models
|
||||||
DEPENDS ${MODEL_GENERATED_FILES}
|
DEPENDS ${MODEL_GENERATED_FILES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Add commands for generating dynamic model lists
|
||||||
|
|
||||||
|
set(MODEL_GENERATED_HEADERS ${MODEL_GENERATED_FILES})
|
||||||
|
list(FILTER MODEL_GENERATED_HEADERS INCLUDE REGEX "\.h$")
|
||||||
|
|
||||||
|
set(DYNAMIC_MODEL_HEADERS "")
|
||||||
|
set(DYNAMIC_ANIMATED_MODEL_HEADERS "")
|
||||||
|
|
||||||
|
foreach(GENERATED_HEADER ${MODEL_GENERATED_HEADERS})
|
||||||
|
cmake_path(
|
||||||
|
RELATIVE_PATH GENERATED_HEADER
|
||||||
|
BASE_DIRECTORY "${CMAKE_BINARY_DIR}/${RELATIVE_CURRENT_DIR}"
|
||||||
|
OUTPUT_VARIABLE MODEL_NAME
|
||||||
|
)
|
||||||
|
cmake_path(
|
||||||
|
REMOVE_EXTENSION MODEL_NAME
|
||||||
|
OUTPUT_VARIABLE MODEL_NAME
|
||||||
|
)
|
||||||
|
|
||||||
|
if(MODEL_NAME IN_LIST DYNAMIC_MODELS)
|
||||||
|
list(APPEND DYNAMIC_MODEL_HEADERS ${GENERATED_HEADER})
|
||||||
|
elseif(MODEL_NAME IN_LIST DYNAMIC_ANIMATED_MODELS)
|
||||||
|
list(APPEND DYNAMIC_ANIMATED_MODEL_HEADERS ${GENERATED_HEADER})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(DYNAMIC_MODEL_LIST_OUT_DIR "${CMAKE_BINARY_DIR}/${RELATIVE_CURRENT_DIR}")
|
||||||
|
|
||||||
|
set(DYNAMIC_MODEL_LIST_H "${DYNAMIC_MODEL_LIST_OUT_DIR}/dynamic_model_list.h")
|
||||||
|
set(DYNAMIC_MODEL_LIST_C "${DYNAMIC_MODEL_LIST_OUT_DIR}/dynamic_model_list.c")
|
||||||
|
add_custom_command(
|
||||||
|
DEPENDS
|
||||||
|
${GEN_DYNAMIC_MODEL_LIST} ${MODEL_LIST_UTILS} ${DYNAMIC_MODEL_HEADERS}
|
||||||
|
OUTPUT
|
||||||
|
${DYNAMIC_MODEL_LIST_H} ${DYNAMIC_MODEL_LIST_C}
|
||||||
|
COMMAND
|
||||||
|
${NODEJS} ${GEN_DYNAMIC_MODEL_LIST}
|
||||||
|
${DYNAMIC_MODEL_LIST_H}
|
||||||
|
${DYNAMIC_MODEL_HEADERS}
|
||||||
|
COMMENT
|
||||||
|
"Generating dynamic model list"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
set(DYNAMIC_ANIMATED_MODEL_LIST_H "${DYNAMIC_MODEL_LIST_OUT_DIR}/dynamic_animated_model_list.h")
|
||||||
|
set(DYNAMIC_ANIMATED_MODEL_LIST_C "${DYNAMIC_MODEL_LIST_OUT_DIR}/dynamic_animated_model_list.c")
|
||||||
|
add_custom_command(
|
||||||
|
DEPENDS
|
||||||
|
${GEN_DYNAMIC_ANIM_MODEL_LIST} ${MODEL_LIST_UTILS} ${DYNAMIC_ANIMATED_MODEL_HEADERS}
|
||||||
|
OUTPUT
|
||||||
|
${DYNAMIC_ANIMATED_MODEL_LIST_H} ${DYNAMIC_ANIMATED_MODEL_LIST_C}
|
||||||
|
COMMAND
|
||||||
|
${NODEJS} ${GEN_DYNAMIC_ANIM_MODEL_LIST}
|
||||||
|
${DYNAMIC_ANIMATED_MODEL_LIST_H}
|
||||||
|
${DYNAMIC_ANIMATED_MODEL_HEADERS}
|
||||||
|
COMMENT
|
||||||
|
"Generating dynamic animated model list"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(
|
||||||
|
model_lists
|
||||||
|
DEPENDS
|
||||||
|
${MODEL_GENERATED_FILES}
|
||||||
|
${DYNAMIC_MODEL_LIST_H}
|
||||||
|
${DYNAMIC_MODEL_LIST_C}
|
||||||
|
${DYNAMIC_ANIMATED_MODEL_LIST_H}
|
||||||
|
${DYNAMIC_ANIMATED_MODEL_LIST_C}
|
||||||
|
)
|
||||||
|
|
|
@ -186,6 +186,8 @@ set(INSTRUMENT_BANKS
|
||||||
weapons/physcannon/energy_sing_loop4.ins
|
weapons/physcannon/energy_sing_loop4.ins
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(JSOX "${PROJECT_SOURCE_DIR}/tools/sound/jsox.js")
|
||||||
|
|
||||||
# TODO: remove
|
# TODO: remove
|
||||||
function(_add_sound_transform_command_direct SOUND_NAME ARGS OUTPUT_LIST)
|
function(_add_sound_transform_command_direct SOUND_NAME ARGS OUTPUT_LIST)
|
||||||
set(INPUT_FILE "${PAK_SOUND_DIR}/${SOUND_NAME}.wav")
|
set(INPUT_FILE "${PAK_SOUND_DIR}/${SOUND_NAME}.wav")
|
||||||
|
@ -251,7 +253,7 @@ function(_add_sound_transform_command_sox SOUND_SCRIPT INPUT_FILE OUTPUT_FILE)
|
||||||
COMMAND
|
COMMAND
|
||||||
${CMAKE_COMMAND} -E make_directory ${OUTPUT_DIR}
|
${CMAKE_COMMAND} -E make_directory ${OUTPUT_DIR}
|
||||||
COMMAND
|
COMMAND
|
||||||
${Python3_EXECUTABLE} ${CONVERT_ASSET} ${SOX} ${INPUT_FILE} ${SOUND_SCRIPT} ${OUTPUT_FILE}
|
${PYTHON3} ${CONVERT_ASSET} ${SOX} ${INPUT_FILE} ${SOUND_SCRIPT} ${OUTPUT_FILE}
|
||||||
COMMENT
|
COMMENT
|
||||||
"Transforming $<PATH:RELATIVE_PATH,${INPUT_FILE},${PROJECT_SOURCE_DIR}>"
|
"Transforming $<PATH:RELATIVE_PATH,${INPUT_FILE},${PROJECT_SOURCE_DIR}>"
|
||||||
VERBATIM
|
VERBATIM
|
||||||
|
@ -373,6 +375,8 @@ add_custom_target(
|
||||||
## Sound table generation ##
|
## Sound table generation ##
|
||||||
############################
|
############################
|
||||||
|
|
||||||
|
set(GEN_SOUND_IDS "${PROJECT_SOURCE_DIR}/tools/sound/generate_sound_ids.js")
|
||||||
|
|
||||||
set(SOUND_TABLE_DEPENDENCIES ${SOUNDS_CONVERTED})
|
set(SOUND_TABLE_DEPENDENCIES ${SOUNDS_CONVERTED})
|
||||||
set(SOUND_TABLE_INPUTS "")
|
set(SOUND_TABLE_INPUTS "")
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ set(EXPORT_SCRIPTS
|
||||||
${PROJECT_SOURCE_DIR}/tools/level_scripts/yaml_loader.lua
|
${PROJECT_SOURCE_DIR}/tools/level_scripts/yaml_loader.lua
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(GEN_LEVEL_LIST "${PROJECT_SOURCE_DIR}/tools/models/generate_level_list.js")
|
||||||
|
|
||||||
function(_add_level_export_command LEVEL_NAME OUTPUT_VARIABLE)
|
function(_add_level_export_command LEVEL_NAME OUTPUT_VARIABLE)
|
||||||
set(INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${LEVEL_NAME}/${LEVEL_NAME}.blend")
|
set(INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${LEVEL_NAME}/${LEVEL_NAME}.blend")
|
||||||
set(OUTPUT_FILE "${CMAKE_BINARY_DIR}/${RELATIVE_CURRENT_DIR}/${LEVEL_NAME}/${LEVEL_NAME}.fbx")
|
set(OUTPUT_FILE "${CMAKE_BINARY_DIR}/${RELATIVE_CURRENT_DIR}/${LEVEL_NAME}/${LEVEL_NAME}.fbx")
|
||||||
|
@ -144,7 +146,7 @@ set(LEVEL_LIST "${LEVEL_LIST_OUT_DIR}/level_list.h")
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
DEPENDS
|
DEPENDS
|
||||||
${GEN_LEVEL_LIST} ${LEVEL_GENERATED_HEADERS}
|
${GEN_LEVEL_LIST} ${MODEL_LIST_UTILS} ${LEVEL_GENERATED_HEADERS}
|
||||||
OUTPUT
|
OUTPUT
|
||||||
${LEVEL_LIST}
|
${LEVEL_LIST}
|
||||||
COMMAND
|
COMMAND
|
||||||
|
|
|
@ -13,7 +13,7 @@ add_dependencies(portal
|
||||||
|
|
||||||
# TODO: rework when including models in compilation
|
# TODO: rework when including models in compilation
|
||||||
level_list
|
level_list
|
||||||
models
|
model_lists
|
||||||
)
|
)
|
||||||
|
|
||||||
###############
|
###############
|
||||||
|
@ -159,10 +159,7 @@ target_sources(portal PRIVATE
|
||||||
sk64/skelatool_animator.c
|
sk64/skelatool_animator.c
|
||||||
sk64/skelatool_armature.c
|
sk64/skelatool_armature.c
|
||||||
util/assert.c
|
util/assert.c
|
||||||
util/dynamic_animated_asset_data.c
|
|
||||||
util/dynamic_asset_data.c
|
|
||||||
util/dynamic_asset_loader.c
|
util/dynamic_asset_loader.c
|
||||||
util/linked_list.c
|
|
||||||
util/memory.c
|
util/memory.c
|
||||||
util/profile.c
|
util/profile.c
|
||||||
util/rom.c
|
util/rom.c
|
||||||
|
|
|
@ -117,7 +117,7 @@ void levelLoad(int index) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LevelMetadata* metadata = &gLevelList[index];
|
struct LevelMetadata* metadata = &gLevels[index];
|
||||||
|
|
||||||
void* memory = malloc(metadata->segmentRomEnd - metadata->segmentRomStart);
|
void* memory = malloc(metadata->segmentRomEnd - metadata->segmentRomStart);
|
||||||
romCopy(metadata->segmentRomStart, memory, metadata->segmentRomEnd - metadata->segmentRomStart);
|
romCopy(metadata->segmentRomStart, memory, metadata->segmentRomEnd - metadata->segmentRomStart);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef __LEVEL_LIST_H__
|
#ifndef __LEVELS_H__
|
||||||
#define __LEVEL_LIST_H__
|
#define __LEVELS_H__
|
||||||
|
|
||||||
#include "physics/collision_object.h"
|
#include "physics/collision_object.h"
|
||||||
#include "level_definition.h"
|
#include "level_definition.h"
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
|
|
||||||
#include "../build/assets/models/dynamic_animated_model_list_data.h"
|
|
|
@ -1,2 +0,0 @@
|
||||||
|
|
||||||
#include "../build/assets/models/dynamic_model_list_data.h"
|
|
|
@ -6,9 +6,6 @@
|
||||||
#include "../build/assets/models/dynamic_model_list.h"
|
#include "../build/assets/models/dynamic_model_list.h"
|
||||||
#include "../build/assets/models/dynamic_animated_model_list.h"
|
#include "../build/assets/models/dynamic_animated_model_list.h"
|
||||||
|
|
||||||
extern struct DynamicAssetModel gDynamicModels[];
|
|
||||||
extern struct DynamicAnimatedAssetModel gDynamicAnimatedModels[];
|
|
||||||
|
|
||||||
Gfx* gLoadedModels[DYNAMIC_MODEL_COUNT];
|
Gfx* gLoadedModels[DYNAMIC_MODEL_COUNT];
|
||||||
u32 gModelPointerOffset[DYNAMIC_MODEL_COUNT];
|
u32 gModelPointerOffset[DYNAMIC_MODEL_COUNT];
|
||||||
|
|
||||||
|
|
|
@ -3,27 +3,11 @@
|
||||||
|
|
||||||
#include <ultra64.h>
|
#include <ultra64.h>
|
||||||
|
|
||||||
|
#include "dynamic_asset_model.h"
|
||||||
|
|
||||||
#include "../sk64/skelatool_armature.h"
|
#include "../sk64/skelatool_armature.h"
|
||||||
#include "../sk64/skelatool_clip.h"
|
#include "../sk64/skelatool_clip.h"
|
||||||
|
|
||||||
struct DynamicAssetModel {
|
|
||||||
void* addressStart;
|
|
||||||
void* addressEnd;
|
|
||||||
void* segmentStart;
|
|
||||||
Gfx* model;
|
|
||||||
char* name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DynamicAnimatedAssetModel {
|
|
||||||
void* addressStart;
|
|
||||||
void* addressEnd;
|
|
||||||
void* segmentStart;
|
|
||||||
struct SKArmatureDefinition* armature;
|
|
||||||
struct SKAnimationClip** clips;
|
|
||||||
short clipCount;
|
|
||||||
char* name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SKArmatureWithAnimations {
|
struct SKArmatureWithAnimations {
|
||||||
struct SKArmatureDefinition* armature;
|
struct SKArmatureDefinition* armature;
|
||||||
struct SKAnimationClip** clips;
|
struct SKAnimationClip** clips;
|
||||||
|
|
27
src/util/dynamic_asset_model.h
Normal file
27
src/util/dynamic_asset_model.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef __DYNAMIC_ASSET_MODEL_H__
|
||||||
|
#define __DYNAMIC_ASSET_MODEL_H__
|
||||||
|
|
||||||
|
#include <ultra64.h>
|
||||||
|
|
||||||
|
#include "../sk64/skelatool_armature.h"
|
||||||
|
#include "../sk64/skelatool_clip.h"
|
||||||
|
|
||||||
|
struct DynamicAssetModel {
|
||||||
|
void* addressStart;
|
||||||
|
void* addressEnd;
|
||||||
|
void* segmentStart;
|
||||||
|
Gfx* model;
|
||||||
|
char* name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicAnimatedAssetModel {
|
||||||
|
void* addressStart;
|
||||||
|
void* addressEnd;
|
||||||
|
void* segmentStart;
|
||||||
|
struct SKArmatureDefinition* armature;
|
||||||
|
struct SKAnimationClip** clips;
|
||||||
|
short clipCount;
|
||||||
|
char* name;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,104 +0,0 @@
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
function generateInclude(outputLocation, headerLocation) {
|
|
||||||
return `#include "${path.relative(path.dirname(outputLocation), headerLocation)}"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const InvalidTokenCharacter = /[^A-Za-z0-9_]/gim;
|
|
||||||
|
|
||||||
function getSegmentName(headerLocation) {
|
|
||||||
const levelName = path.basename(headerLocation);
|
|
||||||
const noExtension = levelName.slice(0, levelName.length - path.extname(levelName).length);
|
|
||||||
|
|
||||||
return noExtension.replace(InvalidTokenCharacter, '_');
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateArmatureName(outputLocation, headerLocation) {
|
|
||||||
const relative = path.relative(path.dirname(outputLocation), headerLocation).slice(0, -2);
|
|
||||||
return relative.replace(InvalidTokenCharacter, '_') + '_armature';
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateClipsName(outputLocation, headerLocation) {
|
|
||||||
const relative = path.relative(path.dirname(outputLocation), headerLocation).slice(0, -2);
|
|
||||||
return relative.replace(InvalidTokenCharacter, '_') + '_clips';
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateClipCountName(outputLocation, headerLocation) {
|
|
||||||
const relative = path.relative(path.dirname(outputLocation), headerLocation).slice(0, -2);
|
|
||||||
return relative.replace(InvalidTokenCharacter, '_').toUpperCase() + '_CLIP_COUNT';
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateDynamicModelName(outputLocation, headerLocation, index) {
|
|
||||||
const relative = path.relative(path.dirname(outputLocation), headerLocation).slice(0, -2);
|
|
||||||
return relative.replace(InvalidTokenCharacter, '_') + '_DYNAMIC_ANIMATED_MODEL';
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateMetadata(outputLocation, headerLocation) {
|
|
||||||
const segmentName = getSegmentName(headerLocation);
|
|
||||||
return ` {
|
|
||||||
_${segmentName}_geoSegmentRomStart,
|
|
||||||
_${segmentName}_geoSegmentRomEnd,
|
|
||||||
_${segmentName}_geoSegmentStart,
|
|
||||||
&${generateArmatureName(outputLocation, headerLocation)},
|
|
||||||
${generateClipsName(outputLocation, headerLocation)},
|
|
||||||
${generateClipCountName(outputLocation, headerLocation)},
|
|
||||||
"${segmentName}",
|
|
||||||
},`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateExterns(headerLocation) {
|
|
||||||
const segmentName = getSegmentName(headerLocation);
|
|
||||||
return `
|
|
||||||
extern char _${segmentName}_geoSegmentRomStart[];
|
|
||||||
extern char _${segmentName}_geoSegmentRomEnd[];
|
|
||||||
extern char _${segmentName}_geoSegmentStart[];
|
|
||||||
`;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateModelList(outputLocation, headerLocations) {
|
|
||||||
return `struct DynamicAnimatedAssetModel gDynamicAnimatedModels[] = {
|
|
||||||
${headerLocations.map(headerLocation => generateMetadata(outputLocation, headerLocation)).join('\n')}
|
|
||||||
};`
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateMetadataDeclaration(outputLocation, headerLocation, index) {
|
|
||||||
const segmentName = getSegmentName(headerLocation);
|
|
||||||
return `#define ${generateDynamicModelName(outputLocation, headerLocation).toUpperCase()} ${index}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateModelHeaderList(outputLocation, headerLocations) {
|
|
||||||
return headerLocations.map((headerLocation, index) => generateMetadataDeclaration(outputLocation, headerLocation, index)).join('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateData(outputLocation, headerLocations) {
|
|
||||||
return `#ifndef __DYNAMIC_ANIMATED_MODEL_LIST_DATA_H__
|
|
||||||
#define __DYNAMIC_ANIMATED_MODEL_LIST_DATA_H__
|
|
||||||
|
|
||||||
#include "util/dynamic_asset_loader.h"
|
|
||||||
|
|
||||||
${headerLocations.map(headerLocation => generateInclude(outputLocation, headerLocation)).join('\n')}
|
|
||||||
|
|
||||||
${headerLocations.map(generateExterns).join('\n')}
|
|
||||||
|
|
||||||
${generateModelList(outputLocation, headerLocations)}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateHeader(outputLocation, headerLocations) {
|
|
||||||
return `#ifndef __DYNAMIC_ANIMATED_MODEL_LIST_DEFINITION_H__
|
|
||||||
#define __DYNAMIC_ANIMATED_MODEL_LIST_DEFINITION_H__
|
|
||||||
|
|
||||||
#define DYNAMIC_ANIMATED_MODEL_COUNT ${headerLocations.length}
|
|
||||||
|
|
||||||
${generateModelHeaderList(outputLocation, headerLocations)}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeFileSync(process.argv[2], generateHeader(process.argv[2], process.argv.slice(4)));
|
|
||||||
fs.writeFileSync(process.argv[3], generateData(process.argv[3], process.argv.slice(4)));
|
|
|
@ -1,92 +0,0 @@
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
function generateInclude(outputLocation, headerLocation) {
|
|
||||||
return `#include "${path.relative(path.dirname(outputLocation), headerLocation)}"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const InvalidTokenCharacter = /[^A-Za-z0-9_]/gim;
|
|
||||||
|
|
||||||
function getSegmentName(headerLocation) {
|
|
||||||
const levelName = path.basename(headerLocation);
|
|
||||||
const noExtension = levelName.slice(0, levelName.length - path.extname(levelName).length);
|
|
||||||
|
|
||||||
return noExtension.replace(InvalidTokenCharacter, '_');
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateModelName(outputLocation, headerLocation) {
|
|
||||||
const relative = path.relative(path.dirname(outputLocation), headerLocation).slice(0, -2);
|
|
||||||
return relative.replace(InvalidTokenCharacter, '_') + '_model_gfx';
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateDynamicModelName(outputLocation, headerLocation, index) {
|
|
||||||
const relative = path.relative(path.dirname(outputLocation), headerLocation).slice(0, -2);
|
|
||||||
return relative.replace(InvalidTokenCharacter, '_') + '_dynamic_model';
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateMetadata(outputLocation, headerLocation) {
|
|
||||||
const segmentName = getSegmentName(headerLocation);
|
|
||||||
return ` {
|
|
||||||
_${segmentName}_geoSegmentRomStart,
|
|
||||||
_${segmentName}_geoSegmentRomEnd,
|
|
||||||
_${segmentName}_geoSegmentStart,
|
|
||||||
${generateModelName(outputLocation, headerLocation)},
|
|
||||||
"${segmentName}",
|
|
||||||
},`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateExterns(headerLocation) {
|
|
||||||
const segmentName = getSegmentName(headerLocation);
|
|
||||||
return `
|
|
||||||
extern char _${segmentName}_geoSegmentRomStart[];
|
|
||||||
extern char _${segmentName}_geoSegmentRomEnd[];
|
|
||||||
extern char _${segmentName}_geoSegmentStart[];
|
|
||||||
`;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateModelList(outputLocation, headerLocations) {
|
|
||||||
return `struct DynamicAssetModel gDynamicModels[] = {
|
|
||||||
${headerLocations.map(headerLocation => generateMetadata(outputLocation, headerLocation)).join('\n')}
|
|
||||||
};`
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateMetadataDeclaration(outputLocation, headerLocation, index) {
|
|
||||||
const segmentName = getSegmentName(headerLocation);
|
|
||||||
return `#define ${generateDynamicModelName(outputLocation, headerLocation).toUpperCase()} ${index}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateModelHeaderList(outputLocation, headerLocations) {
|
|
||||||
return headerLocations.map((headerLocation, index) => generateMetadataDeclaration(outputLocation, headerLocation, index)).join('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateData(outputLocation, headerLocations) {
|
|
||||||
return `#ifndef __DYNAMIC_MODEL_LIST_DATA_H__
|
|
||||||
#define __DYNAMIC_MODEL_LIST_DATA_H__
|
|
||||||
|
|
||||||
#include "util/dynamic_asset_loader.h"
|
|
||||||
|
|
||||||
${headerLocations.map(headerLocation => generateInclude(outputLocation, headerLocation)).join('\n')}
|
|
||||||
|
|
||||||
${headerLocations.map(generateExterns).join('\n')}
|
|
||||||
|
|
||||||
${generateModelList(outputLocation, headerLocations)}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateHeader(outputLocation, headerLocations) {
|
|
||||||
return `#ifndef __DYNAMIC_MODEL_LIST_DEFINITION_H__
|
|
||||||
#define __DYNAMIC_MODEL_LIST_DEFINITION_H__
|
|
||||||
|
|
||||||
#define DYNAMIC_MODEL_COUNT ${headerLocations.length}
|
|
||||||
|
|
||||||
${generateModelHeaderList(outputLocation, headerLocations)}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeFileSync(process.argv[2], generateHeader(process.argv[2], process.argv.slice(4)));
|
|
||||||
fs.writeFileSync(process.argv[3], generateData(process.argv[3], process.argv.slice(4)));
|
|
|
@ -1,69 +0,0 @@
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
function generateInclude(outputLocation, headerLocation) {
|
|
||||||
return `#include "${path.relative(path.dirname(outputLocation), headerLocation)}"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const InvalidTokenCharacter = /[^A-Za-z0-9_]/gim;
|
|
||||||
|
|
||||||
function getSegmentName(headerLocation) {
|
|
||||||
const levelName = path.basename(headerLocation);
|
|
||||||
const noExtension = levelName.slice(0, levelName.length - path.extname(levelName).length);
|
|
||||||
|
|
||||||
return noExtension.replace(InvalidTokenCharacter, '_');
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateLevelName(outputLocation, headerLocation) {
|
|
||||||
const relative = path.relative(path.dirname(outputLocation), headerLocation).slice(0, -2);
|
|
||||||
return relative.replace(InvalidTokenCharacter, '_') + '_level';
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateMetadata(outputLocation, headerLocation) {
|
|
||||||
const segmentName = getSegmentName(headerLocation);
|
|
||||||
return ` {
|
|
||||||
&${generateLevelName(outputLocation, headerLocation)},
|
|
||||||
_${segmentName}_geoSegmentRomStart,
|
|
||||||
_${segmentName}_geoSegmentRomEnd,
|
|
||||||
_${segmentName}_geoSegmentStart,
|
|
||||||
},`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateExterns(headerLocation) {
|
|
||||||
const segmentName = getSegmentName(headerLocation);
|
|
||||||
return `
|
|
||||||
extern char _${segmentName}_geoSegmentRomStart[];
|
|
||||||
extern char _${segmentName}_geoSegmentRomEnd[];
|
|
||||||
extern char _${segmentName}_geoSegmentStart[];
|
|
||||||
`;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateLevelList(outputLocation, headerLocations) {
|
|
||||||
return `struct LevelMetadata gLevelList[] = {
|
|
||||||
${headerLocations.map(headerLocation => generateMetadata(outputLocation, headerLocation)).join('\n')}
|
|
||||||
};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateData(outputLocation, headerLocations) {
|
|
||||||
return `#ifndef __BUILD_LEVEL_LIST_H__
|
|
||||||
#define __BUILD_LEVEL_LIST_H__
|
|
||||||
|
|
||||||
#include "levels/level_metadata.h"
|
|
||||||
|
|
||||||
${headerLocations.map(headerLocation => generateInclude(outputLocation, headerLocation)).join('\n')}
|
|
||||||
|
|
||||||
#define LEVEL_COUNT ${headerLocations.length}
|
|
||||||
|
|
||||||
${headerLocations.map(generateExterns).join('\n')}
|
|
||||||
|
|
||||||
${generateLevelList(outputLocation, headerLocations)}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = process.argv[2];
|
|
||||||
|
|
||||||
fs.writeFileSync(output, generateData(output, process.argv.slice(3)));
|
|
|
@ -1,6 +0,0 @@
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
for (const wav of fs.readdirSync(process.argv[2])) {
|
|
||||||
fs.writeFileSync(path.join(process.argv[3], wav.slice(0, -4)) + '.sox', process.argv[4]);
|
|
||||||
}
|
|
36
tools/models/generate_dynamic_animated_model_list.js
Normal file
36
tools/models/generate_dynamic_animated_model_list.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const util = require('./model_list_utils');
|
||||||
|
|
||||||
|
function generateModelListEntry(outputPath, modelHeader) {
|
||||||
|
const modelName = util.generateModelName(modelHeader);
|
||||||
|
return ` {
|
||||||
|
_${modelName}_geoSegmentRomStart,
|
||||||
|
_${modelName}_geoSegmentRomEnd,
|
||||||
|
_${modelName}_geoSegmentStart,
|
||||||
|
&${util.generateRelativeModelName(outputPath, modelHeader, '_armature')},
|
||||||
|
${util.generateRelativeModelName(outputPath, modelHeader, '_clips')},
|
||||||
|
${util.generateRelativeModelName(outputPath, modelHeader, '_clip_count').toUpperCase()},
|
||||||
|
"${modelName}",
|
||||||
|
},`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [outputHeaderFile, ...modelHeaders] = process.argv.slice(2);
|
||||||
|
const { dir: outputDir, name: outputName } = path.parse(outputHeaderFile);
|
||||||
|
const outputSourceFile = `${outputDir}/${outputName}.c`
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
modelHeaders,
|
||||||
|
modelGroup: "dynamic_animated_model",
|
||||||
|
modelType: "DynamicAnimatedAssetModel",
|
||||||
|
listEntryGenerator: generateModelListEntry
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.writeFileSync(
|
||||||
|
outputHeaderFile,
|
||||||
|
util.generateHeader(outputHeaderFile, config)
|
||||||
|
);
|
||||||
|
fs.writeFileSync(
|
||||||
|
outputSourceFile,
|
||||||
|
util.generateData(outputSourceFile, config)
|
||||||
|
);
|
34
tools/models/generate_dynamic_model_list.js
Normal file
34
tools/models/generate_dynamic_model_list.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const util = require('./model_list_utils');
|
||||||
|
|
||||||
|
function generateModelListEntry(outputPath, modelHeader) {
|
||||||
|
const modelName = util.generateModelName(modelHeader);
|
||||||
|
return ` {
|
||||||
|
_${modelName}_geoSegmentRomStart,
|
||||||
|
_${modelName}_geoSegmentRomEnd,
|
||||||
|
_${modelName}_geoSegmentStart,
|
||||||
|
${util.generateRelativeModelName(outputPath, modelHeader, '_model_gfx')},
|
||||||
|
"${modelName}",
|
||||||
|
},`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [outputHeaderFile, ...modelHeaders] = process.argv.slice(2);
|
||||||
|
const { dir: outputDir, name: outputName } = path.parse(outputHeaderFile);
|
||||||
|
const outputSourceFile = `${outputDir}/${outputName}.c`
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
modelHeaders,
|
||||||
|
modelGroup: "dynamic_model",
|
||||||
|
modelType: "DynamicAssetModel",
|
||||||
|
listEntryGenerator: generateModelListEntry
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.writeFileSync(
|
||||||
|
outputHeaderFile,
|
||||||
|
util.generateHeader(outputHeaderFile, config)
|
||||||
|
);
|
||||||
|
fs.writeFileSync(
|
||||||
|
outputSourceFile,
|
||||||
|
util.generateData(outputSourceFile, config)
|
||||||
|
);
|
42
tools/models/generate_level_list.js
Normal file
42
tools/models/generate_level_list.js
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const util = require('./model_list_utils');
|
||||||
|
|
||||||
|
function generateLevelListEntry(outputPath, levelHeader) {
|
||||||
|
const levelName = util.generateModelName(levelHeader);
|
||||||
|
return ` {
|
||||||
|
&${util.generateRelativeModelName(outputPath, levelHeader, '_level')},
|
||||||
|
_${levelName}_geoSegmentRomStart,
|
||||||
|
_${levelName}_geoSegmentRomEnd,
|
||||||
|
_${levelName}_geoSegmentStart,
|
||||||
|
},`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateHeader(outputPath, config) {
|
||||||
|
const { modelHeaders, modelGroup } = config;
|
||||||
|
|
||||||
|
return util.wrapWithIncludeGuard(outputPath,
|
||||||
|
`#include "levels/level_metadata.h"
|
||||||
|
|
||||||
|
${util.generateIncludes(outputPath, modelHeaders)}
|
||||||
|
|
||||||
|
${util.generateCount(modelGroup, modelHeaders)}
|
||||||
|
|
||||||
|
${util.generateExterns(modelHeaders)}
|
||||||
|
|
||||||
|
${util.generateModelList(outputPath, config)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [outputHeaderFile, ...modelHeaders] = process.argv.slice(2);
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
modelHeaders,
|
||||||
|
modelGroup: "level",
|
||||||
|
modelType: "LevelMetadata",
|
||||||
|
listEntryGenerator: generateLevelListEntry
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.writeFileSync(
|
||||||
|
outputHeaderFile,
|
||||||
|
generateHeader(outputHeaderFile, config)
|
||||||
|
);
|
132
tools/models/model_list_utils.js
Normal file
132
tools/models/model_list_utils.js
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const INVALID_TOKEN_CHARACTER = /[^A-Za-z0-9_]/gim;
|
||||||
|
|
||||||
|
// Common
|
||||||
|
|
||||||
|
function sanitize(s) {
|
||||||
|
return s.replace(INVALID_TOKEN_CHARACTER, '_');
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapWithIncludeGuard(outputPath, content) {
|
||||||
|
const outputName = path.basename(outputPath);
|
||||||
|
const includeGuardName = `__${sanitize(outputName).toUpperCase()}__`;
|
||||||
|
return `#ifndef ${includeGuardName}
|
||||||
|
#define ${includeGuardName}
|
||||||
|
|
||||||
|
${content}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateRelativeModelName(outputPath, modelHeader, suffix='') {
|
||||||
|
const outputDirName = path.dirname(outputPath);
|
||||||
|
const { dir: headerDirName, name: headerName } = path.parse(modelHeader);
|
||||||
|
|
||||||
|
const relative = path.join(
|
||||||
|
path.relative(outputDirName, headerDirName),
|
||||||
|
headerName
|
||||||
|
);
|
||||||
|
|
||||||
|
return sanitize(relative + suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateModelName(modelHeader) {
|
||||||
|
return generateRelativeModelName(modelHeader, modelHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateListDefinition(modelGroup, modelType) {
|
||||||
|
const groupPascalCase = modelGroup
|
||||||
|
.split('_')
|
||||||
|
.map(s => s && s.replace(/^(\w)/g, m => m.toUpperCase()))
|
||||||
|
.join('');
|
||||||
|
|
||||||
|
const listName = `g${groupPascalCase}s`;
|
||||||
|
return `struct ${modelType} ${listName}[]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header generation
|
||||||
|
|
||||||
|
function generateCount(modelGroup, modelHeaders) {
|
||||||
|
return `#define ${modelGroup.toUpperCase()}_COUNT ${modelHeaders.length}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateModelIndices(outputPath, modelHeaders, modelGroup) {
|
||||||
|
return modelHeaders.map((modelHeader, index) => {
|
||||||
|
const modelName = generateRelativeModelName(outputPath, modelHeader, `_${modelGroup}`);
|
||||||
|
return `#define ${modelName.toUpperCase()} ${index}`;
|
||||||
|
}).join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateListExtern(modelGroup, modelType) {
|
||||||
|
return `extern ${generateListDefinition(modelGroup, modelType)};`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateHeader(outputPath, config) {
|
||||||
|
const { modelHeaders, modelGroup, modelType } = config;
|
||||||
|
|
||||||
|
return wrapWithIncludeGuard(outputPath,
|
||||||
|
`#include "util/dynamic_asset_model.h"
|
||||||
|
|
||||||
|
${generateCount(modelGroup, modelHeaders)}
|
||||||
|
|
||||||
|
${generateModelIndices(outputPath, modelHeaders, modelGroup)}
|
||||||
|
|
||||||
|
${generateListExtern(modelGroup, modelType)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data generation
|
||||||
|
|
||||||
|
function generateIncludes(outputPath, modelHeaders) {
|
||||||
|
return modelHeaders.map(modelHeader => {
|
||||||
|
const relativePath = path.relative(path.dirname(outputPath), modelHeader);
|
||||||
|
return `#include "${relativePath}"`;
|
||||||
|
}).join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateExterns(modelHeaders) {
|
||||||
|
return modelHeaders.map(modelHeader => {
|
||||||
|
const modelName = generateModelName(modelHeader);
|
||||||
|
return `extern char _${modelName}_geoSegmentRomStart[];
|
||||||
|
extern char _${modelName}_geoSegmentRomEnd[];
|
||||||
|
extern char _${modelName}_geoSegmentStart[];`;
|
||||||
|
}).join('\n\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateModelList(outputPath, config) {
|
||||||
|
const { modelHeaders, modelGroup, modelType, listEntryGenerator } = config;
|
||||||
|
|
||||||
|
return `${generateListDefinition(modelGroup, modelType)} = {
|
||||||
|
${modelHeaders.map(modelHeader => listEntryGenerator(outputPath, modelHeader)).join('\n')}
|
||||||
|
};`
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateData(outputPath, config) {
|
||||||
|
const { name } = path.parse(outputPath);
|
||||||
|
const { modelHeaders } = config;
|
||||||
|
|
||||||
|
return `#include "${name}.h"
|
||||||
|
|
||||||
|
${generateIncludes(outputPath, modelHeaders)}
|
||||||
|
|
||||||
|
${generateExterns(modelHeaders)}
|
||||||
|
|
||||||
|
${generateModelList(outputPath, config)}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
wrapWithIncludeGuard,
|
||||||
|
generateRelativeModelName,
|
||||||
|
generateModelName,
|
||||||
|
|
||||||
|
generateCount,
|
||||||
|
generateHeader,
|
||||||
|
|
||||||
|
generateIncludes,
|
||||||
|
generateExterns,
|
||||||
|
generateModelList,
|
||||||
|
generateData
|
||||||
|
};
|
Loading…
Reference in a new issue