mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-10-19 22:27:36 -04:00
Work on CMake conversion: VPK extract and texture conversion
This commit is contained in:
parent
2f1171fccf
commit
b999e139fa
20
CMakeLists.txt
Normal file
20
CMakeLists.txt
Normal file
|
@ -0,0 +1,20 @@
|
|||
cmake_minimum_required(VERSION 3.28)
|
||||
project(portal64)
|
||||
|
||||
# Tools
|
||||
# TODO: find automatically
|
||||
# TODO: test on Windows
|
||||
set(IMAGEMAGICK_CONVERT "convert")
|
||||
set(VTF2PNG "vtf2png")
|
||||
set(PYTHON3 "python")
|
||||
set(VPK "vpk")
|
||||
set(CONVERT_ASSET "${PROJECT_SOURCE_DIR}/tools/convert_asset.py")
|
||||
|
||||
# Directories
|
||||
set(ASSETS_DIR "${PROJECT_SOURCE_DIR}/assets")
|
||||
set(PAK_DIR "${PROJECT_SOURCE_DIR}/portal_pak_dir")
|
||||
set(PAK_MODIFIED_DIR "${PROJECT_SOURCE_DIR}/portal_pak_modified")
|
||||
set(VPK_DIR "${PROJECT_SOURCE_DIR}/vpk")
|
||||
|
||||
add_subdirectory(${ASSETS_DIR})
|
||||
add_subdirectory(${VPK_DIR})
|
331
assets/CMakeLists.txt
Normal file
331
assets/CMakeLists.txt
Normal file
|
@ -0,0 +1,331 @@
|
|||
########################
|
||||
## Texture conversion ##
|
||||
########################
|
||||
|
||||
# All textures used from the original game
|
||||
set(TEXTURES
|
||||
materials/concrete/concrete_modular_ceiling001a
|
||||
materials/concrete/concrete_modular_floor001a
|
||||
materials/concrete/concrete_modular_wall001b
|
||||
materials/concrete/concrete_modular_wall001d
|
||||
materials/concrete/observationwall_001a
|
||||
materials/decals/orange_spot
|
||||
materials/effects/brightglow_y
|
||||
materials/effects/fleck_ash2
|
||||
materials/effects/light_rail_beam1
|
||||
materials/effects/portal_1_particle
|
||||
materials/effects/portal_2_particle
|
||||
materials/effects/portal_cleanser
|
||||
materials/gamepadui/portal_logo
|
||||
materials/glass/glasswindow_frosted_002
|
||||
materials/glass/refract01_dx8
|
||||
materials/metal/metalgrate018
|
||||
materials/metal/metal_modular_floor001
|
||||
materials/metal/metalwall048b
|
||||
materials/metal/metalwall_bts_006a
|
||||
materials/models/player/chell_body
|
||||
materials/models/player/chell_face
|
||||
materials/models/props/autoportal_frame/autoportal_frame
|
||||
materials/models/props/ball_catcher_sheet
|
||||
materials/models/props/bed01
|
||||
materials/models/props/button
|
||||
materials/models/props/combine_ball_launcher
|
||||
materials/models/props/door_01
|
||||
materials/models/props/door_02
|
||||
materials/models/props/elevatorshaft_wall/elevatorshaft_wall
|
||||
materials/models/props/elevator_caps/elevator_caps
|
||||
materials/models/props/lab_monitor/lab_monitor_screen_text
|
||||
materials/models/props/light_rail_endcap
|
||||
materials/models/props/metal_box
|
||||
materials/models/props/portal_cleanser
|
||||
materials/models/props/radio
|
||||
materials/models/props/round_elevator_sheet_1
|
||||
materials/models/props/round_elevator_sheet_2
|
||||
materials/models/props/round_elevator_sheet_3
|
||||
materials/models/props/security_camera
|
||||
materials/models/props/toilet
|
||||
materials/models/props_animsigns/awe_total
|
||||
materials/models/props_animsigns/newsignage_back02
|
||||
materials/models/props_c17/door01a_skin6
|
||||
materials/models/weapons/v_models/v_portalgun/v_portalgun
|
||||
materials/nature/hazard_liquid
|
||||
materials/plastic/plasticwall003a
|
||||
materials/plastic/plasticwall004a
|
||||
materials/signage/clock/clock_dots
|
||||
materials/signage/clock/countdown
|
||||
materials/signage/hazard_orange_03b
|
||||
materials/signage/indicator_lights/indicator_lights_corner_floor
|
||||
materials/signage/indicator_lights/indicator_lights_floor
|
||||
materials/signage/overlay_aperture_logo_worn
|
||||
materials/signage/signage_doorstate
|
||||
materials/signage/signage_exit
|
||||
materials/signage/signage_overlay_arrow
|
||||
materials/signage/signage_overlay_boxdispenser
|
||||
materials/signage/signage_overlay_boxhurt
|
||||
materials/signage/signage_overlay_catcher
|
||||
materials/signage/signage_overlay_dots1
|
||||
materials/signage/signage_overlay_dots2
|
||||
materials/signage/signage_overlay_dots3
|
||||
materials/signage/signage_overlay_dots4
|
||||
materials/signage/signage_overlay_energyball
|
||||
materials/signage/signage_overlay_fling1
|
||||
materials/signage/signage_overlay_fling2
|
||||
materials/signage/signage_overlay_fountain
|
||||
materials/signage/signage_overlay_midair1
|
||||
materials/signage/signage_overlay_midair2
|
||||
materials/signage/signage_overlay_toxic
|
||||
materials/sprites/grav_flare
|
||||
materials/sprites/hud/portal_crosshairs
|
||||
materials/tile/observation_tilefloor001a
|
||||
materials/vgui/chapters/chapter1
|
||||
materials/vgui/chapters/chapter2
|
||||
materials/vgui/chapters/chapter3
|
||||
materials/vgui/chapters/chapter4
|
||||
materials/vgui/chapters/chapter5
|
||||
materials/vgui/chapters/chapter6
|
||||
materials/vgui/chapters/chapter7
|
||||
materials/vgui/chapters/chapter8
|
||||
materials/vgui/chapters/chapter9
|
||||
materials/vgui/chapters/chapter10
|
||||
materials/vgui/chapters/chapter11
|
||||
)
|
||||
|
||||
function(_add_texture_convert_command INPUT_FILE OUTPUT_FILE)
|
||||
set(INPUT_FILE "${PAK_DIR}/${INPUT_FILE}.vtf")
|
||||
set(OUTPUT_FILE "${PAK_DIR}/${OUTPUT_FILE}.png")
|
||||
set(ARGS "${ARGN}")
|
||||
|
||||
if(NOT ARGS)
|
||||
get_source_file_property(FILE_ARGS ${INPUT_FILE} ARGS)
|
||||
if (FILE_ARGS)
|
||||
set(ARGS "${FILE_ARGS}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
cmake_path(
|
||||
RELATIVE_PATH INPUT_FILE
|
||||
BASE_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE RELATIVE_INPUT_FILE
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
DEPENDS
|
||||
extract_vpks
|
||||
OUTPUT
|
||||
${OUTPUT_FILE}
|
||||
COMMAND
|
||||
${VTF2PNG} ${ARGS} ${INPUT_FILE} ${OUTPUT_FILE}
|
||||
COMMENT
|
||||
"Converting ${RELATIVE_INPUT_FILE}"
|
||||
VERBATIM
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# Add commands for converting VTF textures to PNG
|
||||
# There are some special cases for VTFs with multiple frames
|
||||
|
||||
set_property(SOURCE ${PAK_DIR}/materials/signage/clock/countdown.vtf
|
||||
PROPERTY ARGS
|
||||
-f 60
|
||||
)
|
||||
|
||||
foreach(i RANGE 1 9)
|
||||
math(EXPR FRAME "60 - ${i}")
|
||||
|
||||
_add_texture_convert_command(
|
||||
materials/signage/clock/countdown
|
||||
materials/signage/clock/countdown_${i}
|
||||
-f ${FRAME}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
_add_texture_convert_command(
|
||||
materials/signage/signage_doorstate
|
||||
materials/signage/signage_doorstate_on
|
||||
-f 2
|
||||
)
|
||||
_add_texture_convert_command(
|
||||
materials/signage/indicator_lights/indicator_lights_corner_floor
|
||||
materials/signage/indicator_lights/indicator_lights_corner_floor_on
|
||||
-f 2
|
||||
)
|
||||
_add_texture_convert_command(
|
||||
materials/signage/indicator_lights/indicator_lights_floor
|
||||
materials/signage/indicator_lights/indicator_lights_floor_on
|
||||
-f 2
|
||||
)
|
||||
|
||||
foreach(TEXTURE ${TEXTURES})
|
||||
_add_texture_convert_command(${TEXTURE} ${TEXTURE})
|
||||
endforeach()
|
||||
|
||||
############################
|
||||
## Texture transformation ##
|
||||
############################
|
||||
|
||||
# Adding a new .ims implies a new texture, which necessitates updating the
|
||||
# TEXTURES list above, which will retrigger CMake on build and so the typical
|
||||
# glob pitfalls do not apply here.
|
||||
file(GLOB_RECURSE TEXTURE_SCRIPTS "materials/*.ims")
|
||||
|
||||
function(_get_texture_script_file_list TEXTURE_SCRIPT PROPERTY_NAME PARENT_DIR OUTPUT)
|
||||
get_source_file_property(FILE_LIST ${TEXTURE_SCRIPT} ${PROPERTY_NAME})
|
||||
|
||||
if (FILE_LIST)
|
||||
list(TRANSFORM FILE_LIST PREPEND "${PARENT_DIR}/" OUTPUT_VARIABLE FILE_LIST)
|
||||
list(TRANSFORM FILE_LIST APPEND ".png" OUTPUT_VARIABLE FILE_LIST)
|
||||
list(APPEND ${OUTPUT} "${FILE_LIST}")
|
||||
endif()
|
||||
|
||||
return(PROPAGATE ${OUTPUT})
|
||||
endfunction()
|
||||
|
||||
function(_add_texture_transform_command TEXTURE_SCRIPT OUTPUT_LIST)
|
||||
cmake_path(
|
||||
RELATIVE_PATH TEXTURE_SCRIPT
|
||||
BASE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE TEXTURE_NAME
|
||||
)
|
||||
cmake_path(
|
||||
REMOVE_EXTENSION TEXTURE_NAME
|
||||
OUTPUT_VARIABLE TEXTURE_NAME
|
||||
)
|
||||
|
||||
set(INPUT_FILE "${PAK_DIR}/${TEXTURE_NAME}.png")
|
||||
set(OUTPUT_FILE "${PAK_MODIFIED_DIR}/${TEXTURE_NAME}.png")
|
||||
|
||||
set(DEPENDENCY_FILES ${INPUT_FILE} ${TEXTURE_SCRIPT})
|
||||
_get_texture_script_file_list(${TEXTURE_SCRIPT} ADDITIONAL_DEPS ${PAK_DIR} DEPENDENCY_FILES)
|
||||
|
||||
set(OUTPUT_FILES ${OUTPUT_FILE})
|
||||
_get_texture_script_file_list(${TEXTURE_SCRIPT} ADDITIONAL_OUTPUTS ${PAK_MODIFIED_DIR} OUTPUT_FILES)
|
||||
|
||||
cmake_path(
|
||||
RELATIVE_PATH INPUT_FILE
|
||||
BASE_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE RELATIVE_INPUT_FILE
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
DEPENDS
|
||||
${CONVERT_ASSET} ${DEPENDENCY_FILES}
|
||||
OUTPUT
|
||||
${OUTPUT_FILES}
|
||||
COMMAND
|
||||
${PYTHON3} ${CONVERT_ASSET} ${IMAGEMAGICK_CONVERT} ${INPUT_FILE} ${TEXTURE_SCRIPT} ${OUTPUT_FILE}
|
||||
WORKING_DIRECTORY
|
||||
# TODO: Change this to PAK_MODIFIED_DIR and update .ims files with relative path
|
||||
${PROJECT_SOURCE_DIR}
|
||||
COMMENT
|
||||
"Transforming ${RELATIVE_INPUT_FILE}"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
list(APPEND ${OUTPUT_LIST} "${OUTPUT_FILES}")
|
||||
return(PROPAGATE ${OUTPUT_LIST})
|
||||
endfunction()
|
||||
|
||||
# Add commands for transforming converted PNG textures (crop, scale, etc.).
|
||||
# There are some special cases due to some conversion scripts reading textures
|
||||
# other than those they are named after (combining multiple textures), or
|
||||
# producing more than one output (texture splitting).
|
||||
|
||||
set_property(SOURCE materials/effects/portal_cleanser.ims
|
||||
PROPERTY ADDITIONAL_OUTPUTS
|
||||
materials/effects/spark
|
||||
)
|
||||
set_property(SOURCE materials/models/player/chell_body.ims
|
||||
PROPERTY ADDITIONAL_OUTPUTS
|
||||
materials/models/player/chell_back_logo
|
||||
materials/models/player/chell_pants
|
||||
)
|
||||
set_property(SOURCE materials/models/player/chell_face.ims
|
||||
PROPERTY ADDITIONAL_OUTPUTS
|
||||
materials/models/player/chell_head
|
||||
)
|
||||
set_property(SOURCE materials/models/props_animsigns/awe_total.ims
|
||||
PROPERTY ADDITIONAL_OUTPUTS
|
||||
materials/models/props_animsigns/awe_total_copy_0
|
||||
materials/models/props_animsigns/awe_total_copy_1
|
||||
materials/models/props_animsigns/awe_total_copy_2
|
||||
)
|
||||
set_property(SOURCE materials/models/props/ball_catcher_sheet.ims
|
||||
PROPERTY ADDITIONAL_OUTPUTS
|
||||
materials/models/props/ball_catcher_back
|
||||
)
|
||||
set_property(SOURCE materials/models/props/bed01.ims
|
||||
PROPERTY ADDITIONAL_OUTPUTS
|
||||
materials/models/props/bed01_screen
|
||||
)
|
||||
set_property(SOURCE materials/models/props/button.ims
|
||||
PROPERTY ADDITIONAL_OUTPUTS
|
||||
materials/models/props/button_base
|
||||
)
|
||||
set_property(SOURCE materials/models/props/round_elevator_sheet_1.ims
|
||||
PROPERTY ADDITIONAL_DEPS
|
||||
materials/models/props/round_elevator_sheet_3
|
||||
)
|
||||
set_property(SOURCE materials/models/props/round_elevator_sheet_1.ims
|
||||
PROPERTY ADDITIONAL_OUTPUTS
|
||||
materials/models/props/round_elevator_floor
|
||||
)
|
||||
set_property(SOURCE materials/models/props/round_elevator_sheet_3.ims
|
||||
PROPERTY ADDITIONAL_OUTPUTS
|
||||
materials/models/props/elevator_sign
|
||||
)
|
||||
set_property(SOURCE materials/signage/clock/countdown.ims
|
||||
PROPERTY ADDITIONAL_DEPS
|
||||
materials/signage/clock/countdown_1
|
||||
materials/signage/clock/countdown_2
|
||||
materials/signage/clock/countdown_3
|
||||
materials/signage/clock/countdown_4
|
||||
materials/signage/clock/countdown_5
|
||||
materials/signage/clock/countdown_6
|
||||
materials/signage/clock/countdown_7
|
||||
materials/signage/clock/countdown_8
|
||||
materials/signage/clock/countdown_9
|
||||
materials/signage/clock/clock_dots
|
||||
)
|
||||
set_property(SOURCE materials/signage/indicator_lights/indicator_lights_floor.ims
|
||||
PROPERTY ADDITIONAL_DEPS
|
||||
materials/signage/indicator_lights/indicator_lights_corner_floor
|
||||
)
|
||||
set_property(SOURCE materials/signage/indicator_lights/indicator_lights_floor_on.ims
|
||||
PROPERTY ADDITIONAL_DEPS
|
||||
materials/signage/indicator_lights/indicator_lights_corner_floor_on
|
||||
)
|
||||
set_property(SOURCE materials/signage/signage_exit.ims
|
||||
PROPERTY ADDITIONAL_DEPS
|
||||
materials/signage/signage_overlay_arrow
|
||||
materials/signage/signage_overlay_boxdispenser
|
||||
materials/signage/signage_overlay_boxhurt
|
||||
materials/signage/signage_overlay_energyball
|
||||
materials/signage/signage_overlay_catcher
|
||||
materials/signage/signage_overlay_toxic
|
||||
materials/signage/signage_overlay_fountain
|
||||
)
|
||||
set_property(SOURCE materials/signage/signage_overlay_fling1.ims
|
||||
PROPERTY ADDITIONAL_DEPS
|
||||
materials/signage/signage_overlay_fling2
|
||||
materials/signage/signage_overlay_dots1
|
||||
materials/signage/signage_overlay_dots2
|
||||
materials/signage/signage_overlay_dots3
|
||||
materials/signage/signage_overlay_dots4
|
||||
materials/signage/signage_overlay_toxic
|
||||
materials/signage/signage_overlay_fountain
|
||||
)
|
||||
set_property(SOURCE materials/signage/signage_overlay_midair1.ims
|
||||
PROPERTY ADDITIONAL_DEPS
|
||||
materials/signage/signage_overlay_midair2
|
||||
)
|
||||
|
||||
set(TEXTURES_TRANSFORMED "")
|
||||
|
||||
foreach(TEXTURE_SCRIPT ${TEXTURE_SCRIPTS})
|
||||
_add_texture_transform_command(${TEXTURE_SCRIPT} TEXTURES_TRANSFORMED)
|
||||
endforeach()
|
||||
|
||||
add_custom_target(
|
||||
all_textures
|
||||
DEPENDS ${TEXTURES_TRANSFORMED}
|
||||
)
|
36
tools/convert_asset.py
Normal file
36
tools/convert_asset.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
import shlex
|
||||
import sys
|
||||
|
||||
# Arguments to commands for converting assets are stored in text files
|
||||
#
|
||||
# This helper script allows calling the commands with the arguments from
|
||||
# such files in a cross-platform way.
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 5:
|
||||
print("Runs a specified command with the given input and output file paths")
|
||||
print("The command's arguments are read from a file")
|
||||
print()
|
||||
print(f"Usage: {sys.argv[0]} COMMAND INPUT_FILE ARGS_FILE OUTPUT_FILE")
|
||||
sys.exit(1)
|
||||
|
||||
command, input_file, args_file, output_file = sys.argv[1:]
|
||||
|
||||
output_parent_dir = os.path.dirname(output_file)
|
||||
if output_parent_dir:
|
||||
os.makedirs(output_parent_dir, exist_ok=True)
|
||||
|
||||
with open(args_file) as f:
|
||||
args = shlex.split(f.read().strip())
|
||||
|
||||
rc = subprocess.run([
|
||||
command,
|
||||
input_file,
|
||||
*args,
|
||||
output_file
|
||||
])
|
||||
sys.exit(rc.returncode)
|
63
vpk/CMakeLists.txt
Normal file
63
vpk/CMakeLists.txt
Normal file
|
@ -0,0 +1,63 @@
|
|||
# TODO: multiple languages
|
||||
set(VPKS_PORTAL
|
||||
Portal/portal/portal_pak_dir.vpk
|
||||
Portal/portal/portal_pak_000.vpk
|
||||
Portal/portal/portal_pak_001.vpk
|
||||
Portal/portal/portal_pak_002.vpk
|
||||
Portal/portal/portal_pak_003.vpk
|
||||
Portal/portal/portal_pak_004.vpk
|
||||
Portal/portal/portal_pak_005.vpk
|
||||
)
|
||||
|
||||
set(VPKS_HL2_MISC
|
||||
Portal/hl2/hl2_misc_dir.vpk
|
||||
Portal/hl2/hl2_misc_000.vpk
|
||||
Portal/hl2/hl2_misc_001.vpk
|
||||
Portal/hl2/hl2_misc_002.vpk
|
||||
Portal/hl2/hl2_misc_003.vpk
|
||||
)
|
||||
|
||||
set(VPKS_HL2_SOUND_MISC
|
||||
Portal/hl2/hl2_sound_misc_dir.vpk
|
||||
Portal/hl2/hl2_sound_misc_000.vpk
|
||||
Portal/hl2/hl2_sound_misc_001.vpk
|
||||
Portal/hl2/hl2_sound_misc_002.vpk
|
||||
)
|
||||
|
||||
set(VPK_LISTS
|
||||
VPKS_PORTAL
|
||||
VPKS_HL2_MISC
|
||||
VPKS_HL2_SOUND_MISC
|
||||
)
|
||||
|
||||
set(VPK_STAMP_FILES "")
|
||||
|
||||
foreach(VPK_LIST ${VPK_LISTS})
|
||||
# First VPK is the one to extract
|
||||
list(GET ${VPK_LIST} 0 MAIN_VPK)
|
||||
|
||||
cmake_path(GET MAIN_VPK STEM MAIN_VPK_NAME)
|
||||
set(MAIN_VPK_STAMP "${PAK_DIR}/${MAIN_VPK_NAME}.stamp")
|
||||
list(APPEND VPK_STAMP_FILES ${MAIN_VPK_STAMP})
|
||||
|
||||
add_custom_command(
|
||||
DEPENDS
|
||||
${${VPK_LIST}}
|
||||
OUTPUT
|
||||
${MAIN_VPK_STAMP}
|
||||
COMMAND
|
||||
${VPK} -x ${PAK_DIR} ${MAIN_VPK}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E touch ${MAIN_VPK_STAMP}
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
COMMENT
|
||||
"Extracting ${MAIN_VPK}"
|
||||
VERBATIM
|
||||
)
|
||||
endforeach()
|
||||
|
||||
add_custom_target(
|
||||
extract_vpks
|
||||
DEPENDS ${VPK_STAMP_FILES}
|
||||
)
|
Loading…
Reference in a new issue