From 86404f4883182ac1cd93ca651835082289de7721 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Thu, 22 Aug 2024 21:59:30 -0700 Subject: [PATCH 01/17] Add base UAT issue template (#625) * Added base issue template for user acceptance testing Meant to be part of the procedure for hand-validating releases now on. * Updated contributing guide for UAT steps and new release script --- .../User-Acceptance-Testing.yml | 66 +++++++++++++++++++ CONTRIBUTING.md | 30 ++++----- 2 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/User-Acceptance-Testing.yml diff --git a/.github/ISSUE_TEMPLATE/User-Acceptance-Testing.yml b/.github/ISSUE_TEMPLATE/User-Acceptance-Testing.yml new file mode 100644 index 00000000..42318e3b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/User-Acceptance-Testing.yml @@ -0,0 +1,66 @@ +name: User Acceptance Testing +description: Procedure for doing human QA release testing +labels: ["uat"] +body: + - type: markdown + attributes: + value: | + For each test below, check the box if it passes. If it fails, elaborate + and then either way, attach this issue to the final + - type: textarea + id: blender-versions + attributes: + label: Blender version(s) tested + validations: + required: true + - type: checkboxes + id: uat-tests + attributes: + label: Test cases + description: Go line by line and check the boxes for each test passed + options: + - label: Remove MCprep, restart blender, then Install MCprep, enable, disable, then enable again without errors + - label: Open Mineways or jmc2obj button (configure as necessary to make it run the executbale) + - label: Import any exported obj world, and verify that it imported into own collection, correct exporter was auto-selected, and on selecting one of the objects it contains the custome object properties which are appropriate + - label: Go into rendered mode to verify blurry/bad textures, then press prep materials and check they are fixed as expected + - label: Import a world with broken textures, then check that prep materials or Advanced/find missing works + - label: Select a block like lava, and use advanced > animate textures, press play to make sure it's now animated + - label: Go to the materials tab with any primitive object selected, load materials, then try applying lava - again selecting animate textures; ensure on play it's animated + - label: Try running mesh swap on the entire scene, veryfing at least one object is meshswaped (will be world dependant, typically tall grass should at least be there) + - label: Try advanced > combine materials and combine images, mostly making sure it doesn't error out + - label: Try sync materials (more advanced, you might need to make a custom material first in the addon lib folder) + - label: Enter rendered mode, then press Create MC sky, try once with each of the options (changing in the redo last options) in rendered mode and verifying that it reacts e.g. adding/removing shader/mesh moon/sun and adding/removing clouds per tick box + - label: Test pressing render panorama, picking a small resolution to make it fast + - label: Test changing the time of day (after having added one of the dynamic sky options) + - label: Try skin swapping (from file, username, and/or pre-installed list). Check that it applies to all children of a rig when the armature is selected, but only individual meshes if meshes are selected without the rig + - label: Try a mob spawn + - label: Try a (few) block spawns + - label: Try an item spawn (either from list and/or from a file on disk) + - label: Try each type of available effect spawn (weather geo, weather particle, tnt collection at different frames, and some particle) + - label: Try an entity spawn + - label: Try a meshswap spawn, especially animated ones like torches or lighting-based ones like jack_o_lanterns + + - type: textarea + id: test-failures + attributes: + label: Test failures + description: For each test failure, note the number here and describe what exactly failed + validations: + required: false + - type: textarea + id: automated-tests + attributes: + label: Automated test results + description: Paste the output of unit tests here, either local run or the github action result + validations: + required: false + + +My actual UAT results: +- Default imported fire renders black in eevee, should select alpha clip for both materials +- Same for campfires above +- Could not add the sun/moon mesh in 2.80 +- Render pano started with 1/6 done, should have started saying 0/6 done; also is rendeirng panos just broken entirely? Doesn't seem to go past the first one. Should try again in 4.x +- One crash on addin big particle. Reliably crashing blener in 2.80! Working fine in 4.2 though. +- The "furnace on" meshswap has a visible white box (probably for particle spawning) which should be changed to not be visible in render (in 4.2 both eevee and cycles) + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6d4cd52a..1d8e5d3b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -129,21 +129,20 @@ In order to run these tests, **you must ensure your git folder with your MCprep At the moment, only the project lead (TheDuckCow) should ever mint new releases for MCprep. However, the steps are noted here for completeness: -1. All releases need a corresponding milestone, like v3.3.1 -1. Make sure the version is the correct number for the release (should match a corresponding milestone). Make this commit on the dev branch. -1. Create a pull request and merge dev into master (without deleting the dev branch). Close out any remaining corresponding milestones. Add this pull request to the milestone, only merging when all other tasks are completed or moved out of the milestone. -1. Check out master, git pull -1. Make sure that `"dev" = False` in conf.py, so that prod resources are used for reporting (it should always be this way on the master branch without doing anything, even after doing a merge from dev; but *always* double check) -1. Create [a draft release](https://github.com/TheDuckCow/MCprep/releases/new) on GitHub - - Tag is in the form `3.3.1`, no leading `v`. - - The title however is in the form `MCprep v3.3.0 | ShortName` where version has a leading `v`. - - Copy the body fo the description from the prior release, and then update the text and splash screen (if a major release). Edit a prior release without making changes to get the raw markdown code, e.g. [from here](https://github.com/TheDuckCow/MCprep/releases/edit/3.3.0). -1. Run `bpy-addon-build.py` to build the addon -1. Run all tests, ideally on two different operating systems. Use the `./run_tests.sh -all` flag to run on all versions of blender -1. If all tests pass, again DOUBLE CHECK that "dev" = false in conf.py, then -1. Drag and drop the generated updated zip file onto github. -1. Rename so it's in the form including its version number, e.g. `MCprep_addon_v3.3.0.zip` -1. Press publish release + +1. Checkout dev, and commit the correct release version in `MCprep_addon/__init__.py` (should match a corresponding milestone) +1. Create a pull request to merge dev into master. This can be approved and merged without review, since all code is already reviewed - but only TheDuckCow may do this bypass with current repo permissions +1. Locally, check out master and run `git pull` +1. Run all local unit tests using `python run_tests.py -a` + - While we do have remote github unit tests, TheDuckCow has many more versions locally for wider testing to be more comprehensive. But, github action unittests can be used in a standin if necessary. +1. Create a new UAT issue from [issues here](https://github.com/Moo-Ack-Productions/MCprep/issues/new/choose) with the name of the corresponding milestone + - The automated test results above should be pasted into the last section of this UAT form. + - If not all UAT steps pass, consider halting the release and/or updating/creating new issues +1. If all UAT steps pass, the run `./push_latest.sh` in the repo root + - Follow the script's instructions and prompts for ensuring the release completes + - You will likely need to update POT files and the json mapping via `mcprep_data_refresh.py` which gets called from within this script. Make a new PR if appropriate. +1. After this script has finished, go to [github releases](https://github.com/Moo-Ack-Productions/MCprep/releases) and edit the draft release to hand hand-adjusted changelogs +1. Press release 1. **Immediately** download and install an old release MCprep, and install into blender (restart blender too) 1. Make sure that the trigger to update MCprep to the new version is working. 1. If it works, then **immediately update** the https://theduckcow.com/dev/blender/mcprep-download/ page to point to the new number (must be manually updated by TheDuckCow). @@ -152,7 +151,6 @@ At the moment, only the project lead (TheDuckCow) should ever mint new releases 1. git checkout dev, and then upversion the dev branch to a unique incremental version. So if you just released v3.3.1, then the dev branch should be updated to be (3, 3, 1, 1) so that we can tell official releases apart from dev versions. - ## Creating your blender_execs.txt Your `blender_execs.txt` defines where to find the executables used in the automated testing scripts. Only these executables will be used during automated testing, noting that the testing system only supports blender version 2.8+ (sadly, only manual testing is possible in blender 2.7 with the current setup). It could look like: From 797a5f6aec99c7a59e2d96eb6075cb9f28ecc486 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Fri, 23 Aug 2024 01:38:27 -0400 Subject: [PATCH 02/17] Rename Asset-Submission.yaml to Asset-Submission.yml Fixed to make it show up as a template --- .../{Asset-Submission.yaml => Asset-Submission.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/ISSUE_TEMPLATE/{Asset-Submission.yaml => Asset-Submission.yml} (100%) diff --git a/.github/ISSUE_TEMPLATE/Asset-Submission.yaml b/.github/ISSUE_TEMPLATE/Asset-Submission.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/Asset-Submission.yaml rename to .github/ISSUE_TEMPLATE/Asset-Submission.yml From b02feeacd7cb09d36078d0f66b54c4f748c50598 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Fri, 23 Aug 2024 01:42:26 -0400 Subject: [PATCH 03/17] Fixed User-Acceptance-Testing.yml Hopefully fixing for the issue template --- .../User-Acceptance-Testing.yml | 60 ++++++++----------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/User-Acceptance-Testing.yml b/.github/ISSUE_TEMPLATE/User-Acceptance-Testing.yml index 42318e3b..b62bcf5f 100644 --- a/.github/ISSUE_TEMPLATE/User-Acceptance-Testing.yml +++ b/.github/ISSUE_TEMPLATE/User-Acceptance-Testing.yml @@ -14,31 +14,31 @@ body: validations: required: true - type: checkboxes - id: uat-tests - attributes: - label: Test cases - description: Go line by line and check the boxes for each test passed - options: - - label: Remove MCprep, restart blender, then Install MCprep, enable, disable, then enable again without errors - - label: Open Mineways or jmc2obj button (configure as necessary to make it run the executbale) - - label: Import any exported obj world, and verify that it imported into own collection, correct exporter was auto-selected, and on selecting one of the objects it contains the custome object properties which are appropriate - - label: Go into rendered mode to verify blurry/bad textures, then press prep materials and check they are fixed as expected - - label: Import a world with broken textures, then check that prep materials or Advanced/find missing works - - label: Select a block like lava, and use advanced > animate textures, press play to make sure it's now animated - - label: Go to the materials tab with any primitive object selected, load materials, then try applying lava - again selecting animate textures; ensure on play it's animated - - label: Try running mesh swap on the entire scene, veryfing at least one object is meshswaped (will be world dependant, typically tall grass should at least be there) - - label: Try advanced > combine materials and combine images, mostly making sure it doesn't error out - - label: Try sync materials (more advanced, you might need to make a custom material first in the addon lib folder) - - label: Enter rendered mode, then press Create MC sky, try once with each of the options (changing in the redo last options) in rendered mode and verifying that it reacts e.g. adding/removing shader/mesh moon/sun and adding/removing clouds per tick box - - label: Test pressing render panorama, picking a small resolution to make it fast - - label: Test changing the time of day (after having added one of the dynamic sky options) - - label: Try skin swapping (from file, username, and/or pre-installed list). Check that it applies to all children of a rig when the armature is selected, but only individual meshes if meshes are selected without the rig - - label: Try a mob spawn - - label: Try a (few) block spawns - - label: Try an item spawn (either from list and/or from a file on disk) - - label: Try each type of available effect spawn (weather geo, weather particle, tnt collection at different frames, and some particle) - - label: Try an entity spawn - - label: Try a meshswap spawn, especially animated ones like torches or lighting-based ones like jack_o_lanterns + id: uat-tests + attributes: + label: Test cases + description: Go line by line and check the boxes for each test passed + options: + - label: Remove MCprep, restart blender, then Install MCprep, enable, disable, then enable again without errors + - label: Open Mineways or jmc2obj button (configure as necessary to make it run the executbale) + - label: Import any exported obj world, and verify that it imported into own collection, correct exporter was auto-selected, and on selecting one of the objects it contains the custome object properties which are appropriate + - label: Go into rendered mode to verify blurry/bad textures, then press prep materials and check they are fixed as expected + - label: Import a world with broken textures, then check that prep materials or Advanced/find missing works + - label: Select a block like lava, and use advanced > animate textures, press play to make sure it's now animated + - label: Go to the materials tab with any primitive object selected, load materials, then try applying lava - again selecting animate textures; ensure on play it's animated + - label: Try running mesh swap on the entire scene, veryfing at least one object is meshswaped (will be world dependant, typically tall grass should at least be there) + - label: Try advanced > combine materials and combine images, mostly making sure it doesn't error out + - label: Try sync materials (more advanced, you might need to make a custom material first in the addon lib folder) + - label: Enter rendered mode, then press Create MC sky, try once with each of the options (changing in the redo last options) in rendered mode and verifying that it reacts e.g. adding/removing shader/mesh moon/sun and adding/removing clouds per tick box + - label: Test pressing render panorama, picking a small resolution to make it fast + - label: Test changing the time of day (after having added one of the dynamic sky options) + - label: Try skin swapping (from file, username, and/or pre-installed list). Check that it applies to all children of a rig when the armature is selected, but only individual meshes if meshes are selected without the rig + - label: Try a mob spawn + - label: Try a (few) block spawns + - label: Try an item spawn (either from list and/or from a file on disk) + - label: Try each type of available effect spawn (weather geo, weather particle, tnt collection at different frames, and some particle) + - label: Try an entity spawn + - label: Try a meshswap spawn, especially animated ones like torches or lighting-based ones like jack_o_lanterns - type: textarea id: test-failures @@ -54,13 +54,3 @@ body: description: Paste the output of unit tests here, either local run or the github action result validations: required: false - - -My actual UAT results: -- Default imported fire renders black in eevee, should select alpha clip for both materials -- Same for campfires above -- Could not add the sun/moon mesh in 2.80 -- Render pano started with 1/6 done, should have started saying 0/6 done; also is rendeirng panos just broken entirely? Doesn't seem to go past the first one. Should try again in 4.x -- One crash on addin big particle. Reliably crashing blener in 2.80! Working fine in 4.2 though. -- The "furnace on" meshswap has a visible white box (probably for particle spawning) which should be changed to not be visible in render (in 4.2 both eevee and cycles) - From 94264ea6561934413065313cbf29e1d350b8231b Mon Sep 17 00:00:00 2001 From: Mahid Sheikh Date: Fri, 23 Aug 2024 15:05:01 -0500 Subject: [PATCH 04/17] fix: Gracefully handle exceptions during direct i18n loading If translations.py doesn't exist, MCprep moves to direct i18n, which directly uses MO files for translations (at the cost of some UI updating issues). However, if these MO files do not exist, then MCprep will throw an exception. Since this exception occurs in the creation of `MCprepEnv`, MCprep is rendered unusable. This patch adds a basic try-except statement to allow `MCprepEnv` to handle these exceptions gracefully. Signed-off-by: Mahid Sheikh --- MCprep_addon/conf.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/MCprep_addon/conf.py b/MCprep_addon/conf.py index 38bda7f6..b8cc5a95 100644 --- a/MCprep_addon/conf.py +++ b/MCprep_addon/conf.py @@ -143,15 +143,21 @@ def __init__(self): # i18n using Python's gettext module # # This only runs if translations.py does not exist - if not self.translations.exists(): - self.languages: dict[str, gettext.NullTranslations] = {} - for language in self.languages_folder.iterdir(): - self.languages[language.name] = gettext.translation("mcprep", - self.languages_folder, - fallback=True, - languages=[language.name]) + try: + if not self.translations.exists(): + self.languages: dict[str, gettext.NullTranslations] = {} + for language in self.languages_folder.iterdir(): + self.languages[language.name] = gettext.translation("mcprep", + self.languages_folder, + fallback=True, + languages=[language.name]) self.use_direct_i18n = True self.log("Loaded direct i18n!") + + except Exception: + self.languages = {} + self.log("Exception occured while loading translations!") + # This allows us to translate strings on the fly def _(self, msg: str) -> str: From e41dc417774fd00ccdd349463c966924c1a10ac7 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Fri, 23 Aug 2024 20:36:57 -0700 Subject: [PATCH 05/17] Using updated production bab build command --- push_latest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/push_latest.sh b/push_latest.sh index 885618e4..34c6f1f1 100755 --- a/push_latest.sh +++ b/push_latest.sh @@ -55,7 +55,7 @@ rm MCprep_addon/mcprep_addon_tracker.json rm mcprep_addon_trackerid.json echo "Building prod addon..." -bpy-addon-build -b translate # No --during-build dev to make it prod. +bab -b translate # No --during-build dev to make it prod. ls build/MCprep_addon.zip # ----------------------------------------------------------------------------- From 061bf150dc46084ab1f2c2270930998cde828240 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Fri, 23 Aug 2024 22:45:18 -0700 Subject: [PATCH 06/17] Add validator to ensure build completed successfully --- push_latest.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/push_latest.sh b/push_latest.sh index 34c6f1f1..d5b033ac 100755 --- a/push_latest.sh +++ b/push_latest.sh @@ -56,7 +56,13 @@ rm mcprep_addon_trackerid.json echo "Building prod addon..." bab -b translate # No --during-build dev to make it prod. -ls build/MCprep_addon.zip +if [ $? -eq 0 ]; then + echo "Build complete" + ls build/MCprep_addon.zip +else + echo "Build failed" + exit +fi # ----------------------------------------------------------------------------- # Cross check no local changes, such as updated translations From 74ef0d9530f8b92784a1a3ac70c52023f4f1a6e6 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Fri, 23 Aug 2024 22:53:18 -0700 Subject: [PATCH 07/17] Upversion for emergecy patch --- MCprep_addon/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCprep_addon/__init__.py b/MCprep_addon/__init__.py index f9aeea73..3aee06aa 100755 --- a/MCprep_addon/__init__.py +++ b/MCprep_addon/__init__.py @@ -41,7 +41,7 @@ bl_info = { "name": "MCprep", "category": "Object", - "version": (3, 6, 1), + "version": (3, 6, 1, 1), "blender": (2, 80, 0), "location": "3D window toolshelf > MCprep tab", "description": "Minecraft workflow addon for rendering and animation", From 74e6f22d86681803af74f6b359daaab2a3c3cda2 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Fri, 23 Aug 2024 23:28:44 -0700 Subject: [PATCH 08/17] Ensure the languages dict property is at least always defined --- MCprep_addon/conf.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/MCprep_addon/conf.py b/MCprep_addon/conf.py index b8cc5a95..ff4a62c4 100644 --- a/MCprep_addon/conf.py +++ b/MCprep_addon/conf.py @@ -143,14 +143,15 @@ def __init__(self): # i18n using Python's gettext module # # This only runs if translations.py does not exist + self.languages: dict[str, gettext.NullTranslations] = {} try: if not self.translations.exists(): - self.languages: dict[str, gettext.NullTranslations] = {} for language in self.languages_folder.iterdir(): - self.languages[language.name] = gettext.translation("mcprep", - self.languages_folder, - fallback=True, - languages=[language.name]) + self.languages[language.name] = gettext.translation( + "mcprep", + self.languages_folder, + fallback=True, + languages=[language.name]) self.use_direct_i18n = True self.log("Loaded direct i18n!") From 982d02906fb5706fba487d1e62fc9fb4e4d08482 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Fri, 23 Aug 2024 23:29:24 -0700 Subject: [PATCH 09/17] Other style cleanup of the conf style for pep8 --- MCprep_addon/conf.py | 81 ++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/MCprep_addon/conf.py b/MCprep_addon/conf.py index ff4a62c4..2b3a9151 100644 --- a/MCprep_addon/conf.py +++ b/MCprep_addon/conf.py @@ -27,6 +27,7 @@ import bpy from bpy.utils.previews import ImagePreviewCollection +import bpy.utils.previews # ----------------------------------------------------------------------------- @@ -57,20 +58,13 @@ class Engine(enum.Enum): Skin = Tuple[str, Path] Entity = Tuple[str, str, str] -# Represents an unknown location -# for MCprepError. Given a global +# Represents an unknown location +# for MCprepError. Given a global # constant to make it easier to use # and check for UNKNOWN_LOCATION = (-1, "UNKNOWN LOCATION") DEBUG_MODE = False -# check if custom preview icons available -try: - import bpy.utils.previews -except: - print("MCprep: No custom icons in this blender instance") - pass - # ----------------------------------------------------------------------------- # ADDON GLOBAL VARIABLES AND INITIAL SETTINGS @@ -81,11 +75,14 @@ class MCprepEnv: def __init__(self): self.data = None self.json_data: Optional[Dict] = None - self.json_path: Path = Path(os.path.dirname(__file__), "MCprep_resources", "mcprep_data.json") - self.json_path_update: Path = Path(os.path.dirname(__file__), "MCprep_resources", "mcprep_data_update.json") + self.json_path: Path = Path( + os.path.dirname(__file__), "MCprep_resources", "mcprep_data.json") + self.json_path_update: Path = Path( + os.path.dirname(__file__), "MCprep_resources", "mcprep_data_update.json") self.dev_file: Path = Path(os.path.dirname(__file__), "mcprep_dev.txt") - self.languages_folder: Path = Path(os.path.dirname(__file__), "MCprep_resources", "Languages") + self.languages_folder: Path = Path( + os.path.dirname(__file__), "MCprep_resources", "Languages") self.translations: Path = Path(os.path.dirname(__file__), "translations.py") self.last_check_for_updated = 0 @@ -137,7 +134,7 @@ def __init__(self): # that no reading has occurred. If lib not found, will update to []. # If ever changing the resource pack, should also reset to None. self.material_sync_cache: List = [] - + # Whether we use PO files directly or use the converted form self.use_direct_i18n = False # i18n using Python's gettext module @@ -159,7 +156,6 @@ def __init__(self): self.languages = {} self.log("Exception occured while loading translations!") - # This allows us to translate strings on the fly def _(self, msg: str) -> str: if not self.use_direct_i18n: @@ -258,14 +254,14 @@ def current_line_and_file(self) -> Tuple[int, str]: MCprepError. This function can not return an MCprepError value as doing - so would be more complicated for the caller. As such, if - this fails, we return values -1 and "UNKNOWN LOCATION" to - indicate that we do not know the line number or file path + so would be more complicated for the caller. As such, if + this fails, we return values -1 and "UNKNOWN LOCATION" to + indicate that we do not know the line number or file path the error occured on. Returns: - - If success: Tuple[int, str] representing the current - line and file path + - If success: Tuple[int, str] representing the current + line and file path - If fail: (-1, "UNKNOWN LOCATION") """ @@ -274,10 +270,10 @@ def current_line_and_file(self) -> Tuple[int, str]: cur_frame = inspect.currentframe() if not cur_frame: return UNKNOWN_LOCATION - + # Get the previous frame since the # current frame is made for this function, - # not the function/code that called + # not the function/code that called # this function prev_frame = cur_frame.f_back if not prev_frame: @@ -286,50 +282,45 @@ def current_line_and_file(self) -> Tuple[int, str]: frame_info = inspect.getframeinfo(prev_frame) return frame_info.lineno, frame_info.filename + @dataclass class MCprepError(object): """ - Object that is returned when + Object that is returned when an error occurs. This is meant - to give more information to the - caller so that a better error + to give more information to the + caller so that a better error message can be made Attributes ------------ err_type: BaseException - The error type; uses standard + The error type; uses standard Python exceptions - + line: int - Line the exception object was - created on. The preferred method - to do this is to use currentframe - and getframeinfo from the inspect + Line the exception object was + created on. The preferred method + to do this is to use currentframe + and getframeinfo from the inspect module file: str Path of file the exception object - was created in. The preferred way + was created in. The preferred way to get this is __file__ msg: Optional[str] - Optional message to display for an - exception. Use this if the exception + Optional message to display for an + exception. Use this if the exception type may not be so clear cut """ err_type: BaseException - line: int + line: int file: str msg: Optional[str] = None -# Requires Extension support and building with the proper wheels -if DEBUG_MODE and bpy.app.version >= (4, 2, 0): - import debugpy - debugpy.listen(("localhost", 5678)) - -env = MCprepEnv() def updater_select_link_function(self, tag): """Indicates what zip file to use for updating from a tag structure. @@ -348,6 +339,16 @@ def updater_select_link_function(self, tag): # GLOBAL REGISTRATOR INIT # ----------------------------------------------------------------------------- + +# Requires Extension support and building with the proper wheels +if DEBUG_MODE and bpy.app.version >= (4, 2, 0): + import debugpy + debugpy.listen(("localhost", 5678)) + + +env = MCprepEnv() + + def register(): global env if not env.json_data: From f0dae228094a98e32c904ea5dcc7c01c52e98cc3 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Sat, 24 Aug 2024 10:47:43 -0700 Subject: [PATCH 10/17] Correct indentation of translation loading mechanism --- MCprep_addon/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MCprep_addon/conf.py b/MCprep_addon/conf.py index 2b3a9151..7b2663de 100644 --- a/MCprep_addon/conf.py +++ b/MCprep_addon/conf.py @@ -149,8 +149,8 @@ def __init__(self): self.languages_folder, fallback=True, languages=[language.name]) - self.use_direct_i18n = True - self.log("Loaded direct i18n!") + self.use_direct_i18n = True + self.log("Loaded direct i18n!") except Exception: self.languages = {} From 4946d6a6f1ae634d71155650217ca622fc33c927 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Sat, 24 Aug 2024 17:09:47 -0700 Subject: [PATCH 11/17] Break down test runner timings and add translation step --- run_tests.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/run_tests.py b/run_tests.py index 2ca36091..2d3f7f3e 100644 --- a/run_tests.py +++ b/run_tests.py @@ -41,7 +41,7 @@ import time -COMPILE_CMD = ["bab", "-b", "dev"] +COMPILE_CMD = ["bab", "-b", "dev", "translate"] DATA_CMD = ["python", "mcprep_data_refresh.py", "-auto"] # TODO, include in build DCC_EXES = "blender_execs.txt" TEST_RUNNER = os.path.join("test_files", "test_runner.py") @@ -60,6 +60,7 @@ def __str__(self): def main(): + t0 = time.time() args = get_args() # Read arguments @@ -69,12 +70,21 @@ def main(): return # Compile the addon + if args.version: + # Just install into the only blender version we'll test anyways + COMPILE_CMD.extend(["-v", args.version]) + elif not args.all_execs: + # Just install into the first blender binary listed to match the tests + # TODO: get Blender version from the binary path at blender_execs[0] + # default_v = x + # COMPILE_CMD.extend(["-v", default_v]) + pass res = subprocess.check_output(COMPILE_CMD) print("Compile output:", res.decode("utf-8")) reset_test_file() # Loop over all binaries and run tests. - t0 = time.time() + t1 = time.time() any_failures = False for ind, binary in enumerate(blender_execs): run_all = args.all_execs is True @@ -104,15 +114,17 @@ def main(): if child.returncode != 0: any_failures = True - t1 = time.time() + t2 = time.time() # Especially ensure tracker files are removed after tests complete. remove_tracker_files() output_results() - round_s = round(t1 - t0) + compile_time = t1 - t0 + test_time = t2 - t1 exit_code = 1 if any_failures else 0 - print(f"tests took {round_s}s to run, ending with code {exit_code}") + print(f"Compiled in {compile_time:.1f}s, tests ran in {test_time:.1f}s") + print(f"Finished in {compile_time + test_time:.1f}s with code {exit_code}") sys.exit(exit_code) From b72a7a38bb79ae70ebffb464751344182ac4cfe6 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Sat, 24 Aug 2024 17:35:48 -0700 Subject: [PATCH 12/17] Adding translations test and some debug prints for troubleshooting Test is NOT yet passing/working, might need some peer assistance --- MCprep_addon/conf.py | 18 ++++++++--- test_files/addon_test.py | 66 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/MCprep_addon/conf.py b/MCprep_addon/conf.py index 7b2663de..39ee7c82 100644 --- a/MCprep_addon/conf.py +++ b/MCprep_addon/conf.py @@ -141,23 +141,31 @@ def __init__(self): # # This only runs if translations.py does not exist self.languages: dict[str, gettext.NullTranslations] = {} + self._load_translations() + + def _load_translations(self, prefix="") -> None: + """Loads in mo file translation maps""" try: if not self.translations.exists(): + print(prefix, "No translations.py, running in location: ", __file__, " with ", self.languages_folder) for language in self.languages_folder.iterdir(): + print(prefix, "In langdir:", language.name) self.languages[language.name] = gettext.translation( "mcprep", - self.languages_folder, + localedir=self.languages_folder, fallback=True, languages=[language.name]) + print(prefix, "Loaded: ", language.name) self.use_direct_i18n = True self.log("Loaded direct i18n!") - - except Exception: + except Exception as e: self.languages = {} - self.log("Exception occured while loading translations!") + self.log(f"Exception occured while loading translations! {e}") + print(prefix, "Exception", e) + #raise e - # This allows us to translate strings on the fly def _(self, msg: str) -> str: + """Allows us to translate strings on the fly""" if not self.use_direct_i18n: return msg if bpy.context.preferences.view.language in self.languages: diff --git a/test_files/addon_test.py b/test_files/addon_test.py index 60ab2bf2..49b038fd 100644 --- a/test_files/addon_test.py +++ b/test_files/addon_test.py @@ -16,14 +16,23 @@ # # ##### END GPL LICENSE BLOCK ##### +from pathlib import Path +import os import unittest import bpy +from MCprep_addon import conf + class AddonTest(unittest.TestCase): """Create addon level tests, and ensures enabled for later tests.""" + @staticmethod + def addon_path() -> Path: + scripts = bpy.utils.user_resource("SCRIPTS") + return Path(scripts, "addons", "MCprep_addon") + def test_enable(self): """Ensure the addon can be directly enabled.""" bpy.ops.preferences.addon_enable(module="MCprep_addon") @@ -33,6 +42,63 @@ def test_disable_enable(self): bpy.ops.preferences.addon_disable(module="MCprep_addon") bpy.ops.preferences.addon_enable(module="MCprep_addon") + def test_translations(self): + """Safely ensures translations are working fine still. + + Something go wrong, blender stuck in another language? Run in console: + bpy.context.preferences.view.language = "en_US" + """ + init_lang = bpy.context.preferences.view.language + try: + self._test_translation() + except Exception: + raise + finally: + bpy.context.preferences.view.language = init_lang + + def _test_translation(self): + """Ensure that creating the MCprep environment is error-free.""" + test_env = conf.MCprepEnv() + mcprep_dir = self.addon_path() + lang_folder = mcprep_dir / "MCprep_resources" / "Languages" + test_env.languages_folder = lang_folder + + print("Lang folder", lang_folder) + print("self.translations", test_env.use_direct_i18n) + print("Dir:", list(os.listdir(lang_folder))) + + # Don't assign translations, to force building the map in memory + # translations_py = mcprep_dir / "translations.py" + # test_env.translations = translations_py + + # Force load translations into this instance of MCprepEnv + test_env._load_translations(prefix=">>>\t") + + # TODO: Not working, above load encounters error + self.assertIn( + "en_US", test_env.languages, "Missing default translation key") + self.assertTrue( + test_env.use_direct_i18n, "use_direct_i18n should be True") + + # Magic string evaluations, will break if source po's change + test_translations = [ + ("ru_RU", "Restart blender", "Перезапустите блендер"), + ("zh_HANS", "Texture pack folder", "材质包文件夹"), + ("en_US", "Mob Spawner", "Mob Spawner"), + ] + for lang, src, dst in test_translations: + with self.subTest(lang): + # First ensure the mo files exist + self.assertTrue( + os.path.isfile( + lang_folder / lang / "LC_MESSAGES" / "mcprep.mo"), + f"Missing {lang}'s mo file") + + # TODO: Not working + bpy.context.preferences.view.language = lang + res = test_env._(src) + self.assertEqual(res, dst, f"Unexpected {lang} translation)") + if __name__ == '__main__': unittest.main(exit=False) From 524717e8ba05d8e773dfbcdc42d7b6f447aa7014 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Sat, 24 Aug 2024 18:36:45 -0700 Subject: [PATCH 13/17] Fixed US translation and backported support for zh_CN pre blender 4.0 Likewise made the gitignore a little more strict for what we want --- .gitignore | 9 +- .../Languages/en_US/LC_MESSAGES/mcprep.po | 2 +- .../MCprep_resources/Languages/mcprep.pot | 4 +- .../Languages/zh_CN/LC_MESSAGES/mcprep.po | 596 ++++++++++++++++++ MCprep_addon/conf.py | 7 +- run_tests.py | 4 +- test_files/addon_test.py | 11 +- 7 files changed, 613 insertions(+), 20 deletions(-) create mode 100644 MCprep_addon/MCprep_resources/Languages/zh_CN/LC_MESSAGES/mcprep.po diff --git a/.gitignore b/.gitignore index 063983ea..89b3e625 100644 --- a/.gitignore +++ b/.gitignore @@ -19,5 +19,12 @@ venv/ *.sublime-* MCprep_addon/import_bridge/conf MCprep_addon/import_bridge/nbt -MCprep_addon/MCprep_resources/ +MCprep_addon/MCprep_resources/*.blend +MCprep_addon/MCprep_resources/mcprep_data.json +MCprep_addon/MCprep_resources/effects +MCprep_addon/MCprep_resources/resourcepacks +MCprep_addon/MCprep_resources/rigs +MCprep_addon/MCprep_resources/skins +MCprep_addon/MCprep_resources/textures +!MCprep_addon/MCprep_resources/Languages/* MCprep_addon/.vscode diff --git a/MCprep_addon/MCprep_resources/Languages/en_US/LC_MESSAGES/mcprep.po b/MCprep_addon/MCprep_resources/Languages/en_US/LC_MESSAGES/mcprep.po index 81cd45e1..6cac66b6 100644 --- a/MCprep_addon/MCprep_resources/Languages/en_US/LC_MESSAGES/mcprep.po +++ b/MCprep_addon/MCprep_resources/Languages/en_US/LC_MESSAGES/mcprep.po @@ -14,7 +14,7 @@ msgstr "" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: MCprep_addon/mcprep_ui.py:98 diff --git a/MCprep_addon/MCprep_resources/Languages/mcprep.pot b/MCprep_addon/MCprep_resources/Languages/mcprep.pot index 942aff27..e0249fb7 100644 --- a/MCprep_addon/MCprep_resources/Languages/mcprep.pot +++ b/MCprep_addon/MCprep_resources/Languages/mcprep.pot @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 3.6.1\n" +"Project-Id-Version: 3.6.1.1\n" "Report-Msgid-Bugs-To: https://github.com/Moo-Ack-Productions/MCprep/issues\n" -"POT-Creation-Date: 2024-08-22 21:18-0700\n" +"POT-Creation-Date: 2024-08-24 18:31-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/MCprep_addon/MCprep_resources/Languages/zh_CN/LC_MESSAGES/mcprep.po b/MCprep_addon/MCprep_resources/Languages/zh_CN/LC_MESSAGES/mcprep.po new file mode 100644 index 00000000..5a7a5b14 --- /dev/null +++ b/MCprep_addon/MCprep_resources/Languages/zh_CN/LC_MESSAGES/mcprep.po @@ -0,0 +1,596 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-02-03 22:03-0600\n" +"PO-Revision-Date: 2024-02-03 22:16-0600\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.4.1\n" + +#: MCprep_addon/mcprep_ui.py:98 +msgid "Restart blender" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:100 +msgid "to complete update" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:109 +msgid "Mob Spawner" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:111 +msgid "Menu for placing in the shift-A add object menu" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:121 +msgid "Load mobs" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:150 +msgid "Meshswap Objects" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:157 +msgid "No meshswap blocks found!" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:179 +msgid "Item Spawner" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:185 +msgid "No items found!" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:202 +msgid "Effects Spawner" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:245 +msgid "Entity Spawner" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:252 +msgid "No entities found!" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:268 +msgid "Model Spawner" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:274 +msgid "No models found!" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:314 +msgid "Load spawners" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:516 +msgid "World Importing & Meshswapping" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:520 +msgid "Default Exporter:" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:525 +msgid "jmc2obj executable" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:530 +msgid "Mineways executable" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:535 +msgid "World OBJ Exports Folder" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:540 +msgid "Meshwap assets" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:546 MCprep_addon/mcprep_ui.py:871 +#: MCprep_addon/mcprep_ui.py:1337 MCprep_addon/mcprep_ui.py:1485 +msgid "MeshSwap file not found" +msgstr "未找到网格变形文件" + +#: MCprep_addon/mcprep_ui.py:550 +msgid "Entity assets" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:556 MCprep_addon/mcprep_ui.py:1435 +msgid "Entity file not found" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:562 MCprep_addon/mcprep_ui.py:1658 +msgid "Effects folder not found" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:566 +msgid "Texture / Resource packs" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:570 MCprep_addon/mcprep_ui.py:843 +#: MCprep_addon/mcprep_ui.py:1651 +msgid "Texture pack folder" +msgstr "材质包文件夹" + +#: MCprep_addon/mcprep_ui.py:575 +msgid "Install to folder" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:579 +msgid "Open texture pack folder" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:584 +msgid "Mob spawning" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:588 +msgid "Rig Folder" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:593 +msgid "Select/install mobs" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:596 +msgid "Install file for mob spawning" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:598 +msgid "Open rig folder" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:603 MCprep_addon/mcprep_ui.py:675 +msgid "Skin swapping" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:607 +msgid "Skin Folder" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:612 +msgid "Install skins" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:614 +msgid "Install skin file for swapping" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:616 +msgid "Open skin folder" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:621 +msgid "Effects" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:625 +msgid "Effect folder" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:631 +msgid "Open effects folder" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:643 +msgid "Using MCprep in experimental mode!" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:644 +msgid "Early access features and requests for feedback" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:645 +msgid "will be made visible. Thank you for contributing." +msgstr "" + +#: MCprep_addon/mcprep_ui.py:649 +msgid "Unsure on how to use the addon? Check out these resources" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:654 +msgid "MCprep page for instructions and updates" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:662 +msgid "Learn MCprep + Blender, 1-minute tutorials" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:669 +msgid "Import Minecraft worlds" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:672 +msgid "Mob (rig) spawning" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:681 +msgid "jmc2obj/Mineways" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:684 MCprep_addon/mcprep_ui.py:897 +msgid "World Tools" +msgstr "世界工具" + +#: MCprep_addon/mcprep_ui.py:687 +msgid "Tutorial Series" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:695 +msgid "Anonymous user tracking settings" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:704 +msgid "Opt into anonymous usage tracking" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:709 +msgid "Opt OUT of anonymous usage tracking" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:713 +msgid "For info on anonymous usage tracking:" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:716 +msgid "Open the Privacy Policy" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:725 +msgid "World Imports" +msgstr "导入地图" + +#: MCprep_addon/mcprep_ui.py:748 +msgid "World exporter" +msgstr "地图导出工具" + +#: MCprep_addon/mcprep_ui.py:759 MCprep_addon/mcprep_ui.py:787 +msgid "Select exporter!" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:769 +msgid "OBJ world import" +msgstr "导入 OBJ 世界" + +#: MCprep_addon/mcprep_ui.py:773 MCprep_addon/mcprep_ui.py:1879 +msgid "MCprep tools" +msgstr "MCprep 工具" + +#: MCprep_addon/mcprep_ui.py:774 +msgid "Prep Materials" +msgstr "准备材质" + +#: MCprep_addon/mcprep_ui.py:781 +msgid "OBJ incompatible with textureswap" +msgstr "OBJ与纹理交换不兼容" + +#: MCprep_addon/mcprep_ui.py:785 +msgid "Mesh Swap" +msgstr "网格变形" + +#: MCprep_addon/mcprep_ui.py:807 +msgid "(UI already improved)" +msgstr "(UI 已经改善)" + +#: MCprep_addon/mcprep_ui.py:810 +msgid "Improve UI" +msgstr "改善 UI" + +#: MCprep_addon/mcprep_ui.py:817 +msgid "Cycles Optimizer" +msgstr "Cycles 优化器" + +#: MCprep_addon/mcprep_ui.py:829 MCprep_addon/mcprep_ui.py:836 +#: MCprep_addon/mcprep_ui.py:1023 MCprep_addon/mcprep_ui.py:1030 +#: MCprep_addon/mcprep_ui.py:1112 MCprep_addon/mcprep_ui.py:1212 +#: MCprep_addon/mcprep_ui.py:1219 MCprep_addon/mcprep_ui.py:1320 +#: MCprep_addon/mcprep_ui.py:1325 MCprep_addon/mcprep_ui.py:1390 +#: MCprep_addon/mcprep_ui.py:1394 MCprep_addon/mcprep_ui.py:1470 +#: MCprep_addon/mcprep_ui.py:1474 MCprep_addon/mcprep_ui.py:1549 +#: MCprep_addon/mcprep_ui.py:1553 MCprep_addon/mcprep_ui.py:1638 +#: MCprep_addon/mcprep_ui.py:1642 +msgid "Advanced" +msgstr "高级" + +#: MCprep_addon/mcprep_ui.py:859 +msgid "Combine Materials" +msgstr "合并材质" + +#: MCprep_addon/mcprep_ui.py:861 +msgid "Combine Images" +msgstr "合并图像" + +#: MCprep_addon/mcprep_ui.py:863 +msgid "Meshswap source:" +msgstr "网格变形源:" + +#: MCprep_addon/mcprep_ui.py:869 +msgid "MeshSwap file must be .blend" +msgstr "网格变形文件必须是.blend格式" + +#: MCprep_addon/mcprep_ui.py:880 +msgid "World Bridge" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:911 +msgid "World settings and lighting" +msgstr "世界设置和光照" + +#: MCprep_addon/mcprep_ui.py:926 +msgid "Time of day" +msgstr "时间" + +#: MCprep_addon/mcprep_ui.py:933 +#, python-brace-format +msgid "{h}:{m}, day {d}" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:942 +msgid "No time controller," +msgstr "没有时间控制器," + +#: MCprep_addon/mcprep_ui.py:943 +msgid "add dynamic MC world." +msgstr "请添加动态MC世界。" + +#: MCprep_addon/mcprep_ui.py:952 +msgid "Skin Swapper" +msgstr "皮肤交换器" + +#: MCprep_addon/mcprep_ui.py:969 +msgid "Select skin" +msgstr "选择皮肤" + +#: MCprep_addon/mcprep_ui.py:986 +msgid "No skins found/loaded" +msgstr "未找到/加载皮肤" + +#: MCprep_addon/mcprep_ui.py:988 MCprep_addon/mcprep_ui.py:993 +msgid "Press to reload" +msgstr "\"按下重新加载" + +#: MCprep_addon/mcprep_ui.py:991 +msgid "Reload skins" +msgstr "重新加载皮肤" + +#: MCprep_addon/mcprep_ui.py:1011 +msgid "No skins found" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1013 +msgid "Skin from file" +msgstr "从文件导入皮肤" + +#: MCprep_addon/mcprep_ui.py:1015 +msgid "Skin from username" +msgstr "从用户名导入皮肤" + +#: MCprep_addon/mcprep_ui.py:1036 +msgid "Skin path" +msgstr "皮肤路径" + +#: MCprep_addon/mcprep_ui.py:1050 +msgid "Reload mobs below" +msgstr "重新加载下方的生物" + +#: MCprep_addon/mcprep_ui.py:1054 +msgid "Reload skins above" +msgstr "重新加载上方的皮肤" + +#: MCprep_addon/mcprep_ui.py:1064 +msgid "MCprep materials" +msgstr "MCprep 材质" + +#: MCprep_addon/mcprep_ui.py:1098 +msgid "No materials loaded" +msgstr "未加载材质" + +#: MCprep_addon/mcprep_ui.py:1107 +msgid "Load material" +msgstr "加载材质" + +#: MCprep_addon/mcprep_ui.py:1125 MCprep_addon/mcprep_ui.py:1398 +#: MCprep_addon/mcprep_ui.py:1557 +msgid "Resource pack" +msgstr "资源包" + +#: MCprep_addon/mcprep_ui.py:1141 +msgid "Enter object mode" +msgstr "进入对象模式" + +#: MCprep_addon/mcprep_ui.py:1142 +msgid "to use spawner" +msgstr "以使用生成器" + +#: MCprep_addon/mcprep_ui.py:1151 +msgid "Import pre-rigged mobs & players" +msgstr "导入预设置的生物和玩家" + +#: MCprep_addon/mcprep_ui.py:1170 +msgid "No mobs in category," +msgstr "该类别中没有生物," + +#: MCprep_addon/mcprep_ui.py:1171 +msgid "install a rig below or" +msgstr "安装一个下方的预设或" + +#: MCprep_addon/mcprep_ui.py:1172 +msgid "copy file to folder." +msgstr "将文件复制到文件夹中。" + +#: MCprep_addon/mcprep_ui.py:1178 +msgid "No mobs loaded" +msgstr "未加载生物" + +#: MCprep_addon/mcprep_ui.py:1182 MCprep_addon/mcprep_ui.py:1291 +#: MCprep_addon/mcprep_ui.py:1373 MCprep_addon/mcprep_ui.py:1449 +#: MCprep_addon/mcprep_ui.py:1527 MCprep_addon/mcprep_ui.py:1604 +msgid "Reload assets" +msgstr "重新加载资源" + +#: MCprep_addon/mcprep_ui.py:1226 +msgid "Mob spawner folder" +msgstr "生物生成器文件夹" + +#: MCprep_addon/mcprep_ui.py:1233 +msgid "Open mob folder" +msgstr "打开生物文件夹" + +#: MCprep_addon/mcprep_ui.py:1242 +msgid "Change mob icon" +msgstr "更改生物图标" + +#: MCprep_addon/mcprep_ui.py:1246 +msgid "Reload mobs" +msgstr "重新加载生物" + +#: MCprep_addon/mcprep_ui.py:1254 +msgid "Import pre-made blocks (e.g. lights)" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1268 +msgid "Meshswap file must be a .blend" +msgstr "网格变形文件必须是.blend格式" + +#: MCprep_addon/mcprep_ui.py:1273 MCprep_addon/mcprep_ui.py:1282 +msgid "Reset meshswap path" +msgstr "重置网格变形路径" + +#: MCprep_addon/mcprep_ui.py:1277 +msgid "Meshswap file not found" +msgstr "未找到网格变形文件" + +#: MCprep_addon/mcprep_ui.py:1286 +msgid "No blocks loaded" +msgstr "未加载方块" + +#: MCprep_addon/mcprep_ui.py:1310 +msgid "Place block" +msgstr "放置方块2" + +#: MCprep_addon/mcprep_ui.py:1329 +msgid "Meshswap file" +msgstr "网格变形文件" + +#: MCprep_addon/mcprep_ui.py:1335 MCprep_addon/mcprep_ui.py:1483 +msgid "MeshSwap file must be a .blend" +msgstr "网格变形文件必须是.blend格式" + +#: MCprep_addon/mcprep_ui.py:1348 +msgid "Generate items from textures" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1368 +msgid "No items loaded" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1379 +msgid "Place item" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1412 +msgid "Import pre-rigged entities" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1426 +msgid "Entity file must be a .blend" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1431 MCprep_addon/mcprep_ui.py:1440 +msgid "Reset entity path" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1444 +msgid "No entities loaded" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1461 +msgid "Spawn Entity" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1478 +msgid "Entity file" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1497 +msgid "Generate models from .json files" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1522 +msgid "No models loaded" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1573 +msgid "Load/generate effects" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1599 +msgid "No effects loaded" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1610 +msgid "Add effect" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1646 +msgid "Effects folder" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1660 +msgid "Effects/collection folder not found" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1662 +msgid "Effects/geonodes folder not found" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1664 +msgid "Effects/particle folder not found" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1672 +msgid "Spawner" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1682 +msgid "Click triangle to open" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1691 +msgid "Mob spawner" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1719 +msgid "Block (model) spawner" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1747 +msgid "Item spawner" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1776 +msgid "Effects + weather" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1804 +msgid "Entity spawner" +msgstr "" + +#: MCprep_addon/mcprep_ui.py:1832 +msgid "Meshswap spawner" +msgstr "" diff --git a/MCprep_addon/conf.py b/MCprep_addon/conf.py index 39ee7c82..efc7f872 100644 --- a/MCprep_addon/conf.py +++ b/MCprep_addon/conf.py @@ -143,26 +143,21 @@ def __init__(self): self.languages: dict[str, gettext.NullTranslations] = {} self._load_translations() - def _load_translations(self, prefix="") -> None: + def _load_translations(self) -> None: """Loads in mo file translation maps""" try: if not self.translations.exists(): - print(prefix, "No translations.py, running in location: ", __file__, " with ", self.languages_folder) for language in self.languages_folder.iterdir(): - print(prefix, "In langdir:", language.name) self.languages[language.name] = gettext.translation( "mcprep", localedir=self.languages_folder, fallback=True, languages=[language.name]) - print(prefix, "Loaded: ", language.name) self.use_direct_i18n = True self.log("Loaded direct i18n!") except Exception as e: self.languages = {} self.log(f"Exception occured while loading translations! {e}") - print(prefix, "Exception", e) - #raise e def _(self, msg: str) -> str: """Allows us to translate strings on the fly""" diff --git a/run_tests.py b/run_tests.py index 2d3f7f3e..e1201794 100644 --- a/run_tests.py +++ b/run_tests.py @@ -123,8 +123,8 @@ def main(): compile_time = t1 - t0 test_time = t2 - t1 exit_code = 1 if any_failures else 0 - print(f"Compiled in {compile_time:.1f}s, tests ran in {test_time:.1f}s") - print(f"Finished in {compile_time + test_time:.1f}s with code {exit_code}") + print(f"Compiled in {compile_time:.1f}s + tests ran in {test_time:.1f}s") + print(f"Total of {t2-t0:.1f}s with exit code {exit_code}") sys.exit(exit_code) diff --git a/test_files/addon_test.py b/test_files/addon_test.py index 49b038fd..211f0a2a 100644 --- a/test_files/addon_test.py +++ b/test_files/addon_test.py @@ -63,18 +63,13 @@ def _test_translation(self): lang_folder = mcprep_dir / "MCprep_resources" / "Languages" test_env.languages_folder = lang_folder - print("Lang folder", lang_folder) - print("self.translations", test_env.use_direct_i18n) - print("Dir:", list(os.listdir(lang_folder))) - # Don't assign translations, to force building the map in memory # translations_py = mcprep_dir / "translations.py" # test_env.translations = translations_py # Force load translations into this instance of MCprepEnv - test_env._load_translations(prefix=">>>\t") + test_env._load_translations() - # TODO: Not working, above load encounters error self.assertIn( "en_US", test_env.languages, "Missing default translation key") self.assertTrue( @@ -83,7 +78,8 @@ def _test_translation(self): # Magic string evaluations, will break if source po's change test_translations = [ ("ru_RU", "Restart blender", "Перезапустите блендер"), - ("zh_HANS", "Texture pack folder", "材质包文件夹"), + # Blender 4.0+ only has 'zh_HANS', 'zh_HANT' + ("zh_HANS" if bpy.app.version > (4, 0) else "zh_CN", "Texture pack folder", "材质包文件夹"), ("en_US", "Mob Spawner", "Mob Spawner"), ] for lang, src, dst in test_translations: @@ -94,7 +90,6 @@ def _test_translation(self): lang_folder / lang / "LC_MESSAGES" / "mcprep.mo"), f"Missing {lang}'s mo file") - # TODO: Not working bpy.context.preferences.view.language = lang res = test_env._(src) self.assertEqual(res, dst, f"Unexpected {lang} translation)") From a3ed89b933d1bb95207d159dc67a8f849105d147 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Sat, 24 Aug 2024 22:57:00 -0700 Subject: [PATCH 14/17] Simplified pathing with a resource folder constant --- MCprep_addon/conf.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MCprep_addon/conf.py b/MCprep_addon/conf.py index efc7f872..ea688584 100644 --- a/MCprep_addon/conf.py +++ b/MCprep_addon/conf.py @@ -65,6 +65,8 @@ class Engine(enum.Enum): UNKNOWN_LOCATION = (-1, "UNKNOWN LOCATION") DEBUG_MODE = False +MCPREP_RESOURCES: Path = Path(os.path.dirname(__file__), "MCprep_resources") + # ----------------------------------------------------------------------------- # ADDON GLOBAL VARIABLES AND INITIAL SETTINGS @@ -75,14 +77,12 @@ class MCprepEnv: def __init__(self): self.data = None self.json_data: Optional[Dict] = None - self.json_path: Path = Path( - os.path.dirname(__file__), "MCprep_resources", "mcprep_data.json") + self.json_path: Path = Path(MCPREP_RESOURCES, "mcprep_data.json") self.json_path_update: Path = Path( - os.path.dirname(__file__), "MCprep_resources", "mcprep_data_update.json") + MCPREP_RESOURCES, "mcprep_data_update.json") self.dev_file: Path = Path(os.path.dirname(__file__), "mcprep_dev.txt") - self.languages_folder: Path = Path( - os.path.dirname(__file__), "MCprep_resources", "Languages") + self.languages_folder: Path = Path(MCPREP_RESOURCES, "Languages") self.translations: Path = Path(os.path.dirname(__file__), "translations.py") self.last_check_for_updated = 0 From 2d14fd71e9969cb8f4efe56ed89f511b384c98c7 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Sat, 24 Aug 2024 22:57:54 -0700 Subject: [PATCH 15/17] Adding Blender 4.3 to the explicit list of supported versions --- bpy-build.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/bpy-build.yaml b/bpy-build.yaml index c3f6d68a..60a8551a 100644 --- a/bpy-build.yaml +++ b/bpy-build.yaml @@ -2,6 +2,7 @@ addon_folder: MCprep_addon build_name: MCprep_addon install_versions: + - 4.3 - 4.2 - 4.1 - 4.0 From a685dc127a70f0582104795437c5b6a891af4539 Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Sat, 24 Aug 2024 23:14:37 -0700 Subject: [PATCH 16/17] Upversion to v3.6.1.2 with updated POT file timestamp --- MCprep_addon/MCprep_resources/Languages/mcprep.pot | 2 +- MCprep_addon/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MCprep_addon/MCprep_resources/Languages/mcprep.pot b/MCprep_addon/MCprep_resources/Languages/mcprep.pot index e0249fb7..24854515 100644 --- a/MCprep_addon/MCprep_resources/Languages/mcprep.pot +++ b/MCprep_addon/MCprep_resources/Languages/mcprep.pot @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: 3.6.1.1\n" "Report-Msgid-Bugs-To: https://github.com/Moo-Ack-Productions/MCprep/issues\n" -"POT-Creation-Date: 2024-08-24 18:31-0700\n" +"POT-Creation-Date: 2024-08-24 22:58-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/MCprep_addon/__init__.py b/MCprep_addon/__init__.py index 3aee06aa..9e0c4bdb 100755 --- a/MCprep_addon/__init__.py +++ b/MCprep_addon/__init__.py @@ -41,7 +41,7 @@ bl_info = { "name": "MCprep", "category": "Object", - "version": (3, 6, 1, 1), + "version": (3, 6, 1, 2), "blender": (2, 80, 0), "location": "3D window toolshelf > MCprep tab", "description": "Minecraft workflow addon for rendering and animation", From 0d0bf910e79b4449acd9adffe8095cf3ef501caf Mon Sep 17 00:00:00 2001 From: "Patrick W. Crawford" Date: Sun, 25 Aug 2024 00:22:51 -0700 Subject: [PATCH 17/17] Dev upversion --- MCprep_addon/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCprep_addon/__init__.py b/MCprep_addon/__init__.py index 9e0c4bdb..bf002dee 100755 --- a/MCprep_addon/__init__.py +++ b/MCprep_addon/__init__.py @@ -41,7 +41,7 @@ bl_info = { "name": "MCprep", "category": "Object", - "version": (3, 6, 1, 2), + "version": (3, 6, 1, 3), "blender": (2, 80, 0), "location": "3D window toolshelf > MCprep tab", "description": "Minecraft workflow addon for rendering and animation",