Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Externalize script files #356

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions desktop_version/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Generated script code
*.vsc.cpp

# Build objects
build/
flibitBuild/
Expand Down
8 changes: 7 additions & 1 deletion desktop_version/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ SET(VVV_SRC
src/Scripts.cpp
src/SoundSystem.cpp
src/Spacestation2.cpp
src/TerminalScripts.cpp
src/Textbox.cpp
src/Tower.cpp
src/UtilityClass.cpp
Expand Down Expand Up @@ -148,6 +147,13 @@ ELSE()
ADD_EXECUTABLE(VVVVVV ${VVV_SRC})
ENDIF()

# Regenerate script code before building, if needed
ADD_CUSTOM_TARGET(GENERATED_SCRIPTS
COMMAND ${CMAKE_COMMAND} -P "${PROJECT_SOURCE_DIR}/cmake/GenerateScriptCode.cmake"
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
)
ADD_DEPENDENCIES(VVVVVV GENERATED_SCRIPTS)

# Build options
IF(ENABLE_WARNINGS)
# The weird syntax is due to CMake generator expressions.
Expand Down
40 changes: 40 additions & 0 deletions desktop_version/cmake/GenerateScriptCode.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
SET(SCRIPTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/scripts")
SET(OUT_DIR "${SCRIPTS_DIR}/generated")

# Generate code for script files so they can be #included
FILE(GLOB SCRIPTS "${SCRIPTS_DIR}/*.vsc")
FOREACH(SCRIPT_FILE ${SCRIPTS})
GET_FILENAME_COMPONENT(SCRIPT_NAME "${SCRIPT_FILE}" NAME_WE)

GET_FILENAME_COMPONENT(OUT_FILE "${SCRIPT_FILE}" NAME)
SET(OUT_FILE "${OUT_DIR}/${OUT_FILE}.cpp")

# Only regenerate what changed
IF(EXISTS "${OUT_FILE}" AND "${OUT_FILE}" IS_NEWER_THAN "${SCRIPT_FILE}")
CONTINUE()
ENDIF()

FILE(READ ${SCRIPT_FILE} SCRIPT_CONTENT)

# Wrap script in initialization code
STRING(REGEX REPLACE "\r?\n" ";" SCRIPT_LINES "${SCRIPT_CONTENT}")
SET(SCRIPT_CONTENT "if (SDL_strcmp(t, \"${SCRIPT_NAME}\") == 0) {\n\tstatic const char* lines[] = {\n")
FOREACH(LINE ${SCRIPT_LINES})
# Skip comment lines
IF (LINE MATCHES "^#")
CONTINUE()
ENDIF()

# Remove inline comments
STRING(REGEX REPLACE "#.+$" "" LINE "${LINE}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's nice that you specifically added code to deal with comments (and want to preserve them), but the scripting engine simply ignores all invalid commands, including comments. So I'm not really sure how necessary this is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's good to know. One additional benefit of this is that the size of the static string arrays will be (marginally) smaller. In any case, leaving the comments out of the generated code is cleaner to me but I could go either way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the scripting engine ignore invalid text at the end of an otherwise valid line?

Copy link
Contributor

@InfoTeddy InfoTeddy Jul 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, as long as you always close the arguments to the command with a parenthesis at the end.

That's 'cause it splits lines into arguments, using an argument separator token, which can be any one of (, ,, or ) (normal language rules like having to match parentheses don't apply, delay,5( is a valid script line). If you go with the "proper" style, usually you'll have a parenthesis at the end closing off the arguments, e.g. delay(5). And if you have a comment, then it's fine, because delay(5) # comment gets parsed as delay, 5, and #comment (the engine also strips out spaces as well), and delay() ignores the second argument so it's all good. But if you have delay(5 # comment, it gets parsed as delay and 5#comment, which isn't what you want (but funnily enough it's fine enough because number parsing in scripts uses ss_toi(), which takes in as many digit characters as it can until it doesn't find any more, so it correctly identities that you want to delay for 5 frames).

Hence my recommendation above.


# Surround each line in quotes and end with a comma
STRING(REGEX REPLACE "^(.+)$" "\t\t\"\\1\"," LINE "${LINE}")
SET(SCRIPT_CONTENT "${SCRIPT_CONTENT}\n${LINE}")
ENDFOREACH()
SET(SCRIPT_CONTENT "${SCRIPT_CONTENT}\n\t};\n\tfilllines(lines);\n\treturn;\n}")

# Save generated file
FILE(WRITE "${OUT_FILE}" "${SCRIPT_CONTENT}")
MESSAGE(STATUS "Wrote ${OUT_FILE}")
ENDFOREACH()
Loading