Skip to content

Commit 45f35ea

Browse files
authored
Merge pull request #357 from OpenNBS/development
3.10.0
2 parents d6bc649 + d3d30ab commit 45f35ea

File tree

1,936 files changed

+258721
-56138
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,936 files changed

+258721
-56138
lines changed

.gitattributes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
extensions/pygml/*.dll filter=lfs diff=lfs merge=lfs -text
2+
extensions/pygml/*.zip filter=lfs diff=lfs merge=lfs -text
3+
datafiles/ffmpeg.exe filter=lfs diff=lfs merge=lfs -text
4+
datafiles/ffprobe.exe filter=lfs diff=lfs merge=lfs -text

Minecraft Note Block Studio.yyp

Lines changed: 979 additions & 34 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

datafiles/Data/Python/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.venv/
2+
Lib/
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"python.defaultInterpreterPath": "${workspaceFolder}/.venv",
3+
"python.formatting.provider": "black",
4+
"python.languageServer": "Pylance",
5+
"python.linting.enabled": false,
6+
"python.linting.pylintEnabled": false,
7+
"python.linting.banditEnabled": false,
8+
"python.linting.flake8Enabled": false,
9+
"python.linting.mypyEnabled": false,
10+
"python.linting.prospectorEnabled": false,
11+
"python.linting.pycodestyleEnabled": false,
12+
"python.linting.pydocstyleEnabled": false,
13+
"python.linting.pylamaEnabled": false,
14+
"[python]": {
15+
"editor.tabSize": 4,
16+
"editor.formatOnSave": true,
17+
"editor.formatOnType": false,
18+
"editor.formatOnPaste": false,
19+
"editor.codeActionsOnSave": {
20+
"source.organizeImports": true
21+
}
22+
}
23+
}

datafiles/Data/Python/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Python extensions for Open Note Block Studio
2+
3+
This is a subproject of Open Note Block Studio, which holds the Python modules used for various export functions, as well as scripts for managing dependencies and packaging.
4+
5+
## Building
6+
7+
1. Make sure to install [Git LFS](https://git-lfs.github.com/) before cloning the project and/or contributing.
8+
9+
2. Make sure to install the **exact** Python version that `GMPython` was compiled with. This is currently 3.8.10 (32-bit). ([download](https://www.python.org/downloads/release/python-3810/))
10+
11+
3. This subproject uses [poetry](https://python-poetry.org/) for managing dependencies. Make sure to install it, and run the following command with the subproject's root (`datafiles/Data/Python`) as your current working directory:
12+
13+
```shell
14+
$ poetry env use 3.8 # if you have more than one Python version installed
15+
$ poetry install --no-dev
16+
```
17+
18+
4. Run `package.py`:
19+
20+
```shell
21+
$ python package.py
22+
```
23+
24+
This will prepare all dependencies to be packaged with Note Block Studio's executable.
25+
26+
5. Delete the `.venv` directory that was created.
27+
28+
6. Open the project in GameMaker, and save it so the included files are registered. **Do NOT commit the changes to the project file.**
29+
30+
7. You can now build the project in GameMaker!
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import subprocess
2+
from typing import Dict, Sequence, Union
3+
4+
5+
def patch_arguments(function, **patched_kwargs):
6+
def decorate_name(*args, **kwargs):
7+
kwargs.update(patched_kwargs)
8+
return function(*args, **kwargs)
9+
10+
return decorate_name
11+
12+
13+
def convert_to_int(kwargs: Dict[str, Union[float, int]], fields: Sequence[str]):
14+
for field in fields:
15+
kwargs[field] = int(kwargs[field])
16+
return kwargs
17+
18+
19+
def main(*args, **kwargs):
20+
21+
# Monkey-patch to avoid ffmpeg/ffprobe calls opening console window
22+
subprocess.Popen = patch_arguments(
23+
subprocess.Popen, creationflags=subprocess.CREATE_NO_WINDOW
24+
)
25+
26+
# Convert float arguments to int
27+
kwargs = convert_to_int(kwargs, ["sample_rate", "channels"])
28+
29+
import nbswave
30+
31+
nbswave.render_audio(*args, **kwargs)
32+
33+
34+
if __name__ == "__main__":
35+
main()

datafiles/Data/Python/package.py

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import compileall
2+
import os
3+
import shutil
4+
import sys
5+
import zipfile
6+
from pathlib import Path
7+
8+
9+
PYTHON_VERSION = "3.8.10"
10+
11+
12+
DO_NOT_ADD = [
13+
"__pycache__",
14+
"_distutils_hack",
15+
"pip",
16+
"pkg_resources",
17+
"setuptools",
18+
"wheel",
19+
"_virtualenv.py",
20+
]
21+
22+
BLACKLIST = ["numpy"] # Special case - can't be loaded from ZIP
23+
24+
DO_NOT_ADD.extend(BLACKLIST)
25+
26+
27+
ENV_PATH = Path(".venv")
28+
LIB_PATH = Path(ENV_PATH, "Lib", "site-packages")
29+
30+
OUT_PATH = Path("Lib", "site-packages")
31+
ZIP_PATH = Path("Lib", "site-packages.zip")
32+
REL_PATH = Path("Data", "Python", OUT_PATH)
33+
34+
35+
def pack_filter(path):
36+
fn = os.path.basename(path)
37+
return not (fn in DO_NOT_ADD or ".dist-info" in fn)
38+
39+
40+
copy_filter = shutil.ignore_patterns("__pycache__")
41+
42+
43+
def main():
44+
45+
# Check if the Python version is correct
46+
py_version = ".".join(str(s) for s in sys.version_info[:3])
47+
if py_version != PYTHON_VERSION:
48+
raise RuntimeError(
49+
f"This script must be run in Python {PYTHON_VERSION} "
50+
f"(you're running {py_version})"
51+
)
52+
53+
# Check the script is being run from the right subdirectory
54+
cwd = Path.cwd()
55+
if not cwd.parts[-3:] == ("datafiles", "Data", "Python"):
56+
raise RuntimeWarning(
57+
"This script must be run from the datafiles/Data/Python "
58+
"subfolder in the Open Note Block Studio root directory."
59+
)
60+
61+
if not os.path.exists(ENV_PATH):
62+
raise FileNotFoundError(
63+
"The .venv directory was not found. Have you ran"
64+
"poetry install before running this script?"
65+
)
66+
67+
# Delete previous build directory
68+
if Path.exists(OUT_PATH):
69+
print("Removing output directory")
70+
shutil.rmtree(OUT_PATH)
71+
72+
# Create output directory
73+
os.makedirs(OUT_PATH)
74+
75+
# Package dependencies
76+
package_count = 0
77+
with zipfile.PyZipFile(ZIP_PATH, mode="w") as zip_file:
78+
for path in os.listdir(LIB_PATH):
79+
lib_name = os.path.basename(path)
80+
lib_path = Path(LIB_PATH, lib_name)
81+
82+
# Pre-compile all modules without absolute paths
83+
path_prefix = REL_PATH
84+
if os.path.isdir(lib_path):
85+
compileall.compile_dir(
86+
lib_path, ddir=path_prefix, force=True, quiet=2, legacy=True
87+
)
88+
else:
89+
compileall.compile_file(
90+
str(lib_path), ddir=path_prefix, force=True, quiet=2, legacy=True
91+
)
92+
93+
# Write to ZIP
94+
try:
95+
zip_file.writepy(lib_path, filterfunc=pack_filter)
96+
except RuntimeError: # only directories or .py files accepted
97+
continue
98+
else:
99+
if pack_filter(lib_path):
100+
print(f"Packaging {lib_name}")
101+
package_count += 1
102+
103+
# Handle special cases
104+
for lib_name in BLACKLIST:
105+
print(f"Packaging {lib_name}")
106+
package_count += 1
107+
inpath = Path(LIB_PATH, lib_name)
108+
outpath = Path(OUT_PATH, lib_name)
109+
shutil.copytree(inpath, outpath, ignore=copy_filter)
110+
compileall.compile_dir(
111+
outpath, ddir=REL_PATH, force=True, quiet=True, legacy=True
112+
)
113+
# Remove corresponding .py files
114+
for root, _, files in os.walk(outpath):
115+
for filename in files:
116+
if filename.endswith(".py"):
117+
os.remove(os.path.join(root, filename))
118+
119+
print(f"Done! {package_count} packages were added.")
120+
print(
121+
f"Don't forget to delete the {ENV_PATH} directory before building the GameMaker project."
122+
)
123+
124+
125+
if __name__ == "__main__":
126+
main()

0 commit comments

Comments
 (0)