Compare commits
12 Commits
415cc98758
...
v4.3
Author | SHA1 | Date | |
---|---|---|---|
f920cdcaf5 | |||
40cad381af | |||
0d20a1fe44 | |||
599e9a6ef0 | |||
e22b888bfc | |||
88ef1d3202 | |||
f2af90c876 | |||
4dba3c3a71 | |||
e31a677d83 | |||
35fcbe54b5 | |||
9e83fe0a10 | |||
33fb1a65d3 |
@ -50,7 +50,8 @@ class BBP_OT_game_resolution(bpy.types.Operator):
|
||||
name = "Resolution Kind",
|
||||
description = "The type of preset resolution.",
|
||||
items = _g_EnumHelper_ResolutionKind.generate_items(),
|
||||
default = _g_EnumHelper_ResolutionKind.to_selection(ResolutionKind.Normal)
|
||||
default = _g_EnumHelper_ResolutionKind.to_selection(ResolutionKind.Normal),
|
||||
translation_context = 'BBP_OT_game_resolution/property'
|
||||
) # type: ignore
|
||||
|
||||
def invoke(self, context, event):
|
||||
@ -185,37 +186,99 @@ class BBP_OT_game_camera(bpy.types.Operator):
|
||||
name = "Target Kind",
|
||||
description = "",
|
||||
items = _g_EnumHelper_TargetKind.generate_items(),
|
||||
default = _g_EnumHelper_TargetKind.to_selection(TargetKind.Cursor)
|
||||
default = _g_EnumHelper_TargetKind.to_selection(TargetKind.Cursor),
|
||||
translation_context = 'BBP_OT_game_camera/property'
|
||||
) # type: ignore
|
||||
|
||||
rotation_kind: bpy.props.EnumProperty(
|
||||
# YYC MAKR:
|
||||
# This property is not shown on UI layout,
|
||||
# but it should be translated because it is not PURE assistant property.
|
||||
name = "Rotation Angle Kind",
|
||||
description = "",
|
||||
items = _g_EnumHelper_RotationKind.generate_items(),
|
||||
default = _g_EnumHelper_RotationKind.to_selection(RotationKind.Preset)
|
||||
default = _g_EnumHelper_RotationKind.to_selection(RotationKind.Preset),
|
||||
translation_context = 'BBP_OT_game_camera/property'
|
||||
) # type: ignore
|
||||
preset_rotation_angle: bpy.props.EnumProperty(
|
||||
name = "Preset Rotation Angle",
|
||||
description = "",
|
||||
translation_context = 'BBP_OT_game_camera/property',
|
||||
options = {'HIDDEN'},
|
||||
items = _g_EnumHelper_RotationAngle.generate_items(),
|
||||
default = _g_EnumHelper_RotationAngle.to_selection(RotationAngle.Deg0)
|
||||
default = _g_EnumHelper_RotationAngle.to_selection(RotationAngle.Deg0),
|
||||
) # type: ignore
|
||||
def preset_rotation_angle_deg_getter(self, probe) -> bool:
|
||||
return _g_EnumHelper_RotationAngle.get_selection(self.preset_rotation_angle) == probe
|
||||
def preset_rotation_angle_deg_setter(self, val) -> None:
|
||||
self.preset_rotation_angle = _g_EnumHelper_RotationAngle.to_selection(val)
|
||||
return None
|
||||
preset_rotation_angle_deg0: bpy.props.BoolProperty(
|
||||
name = "0 Degree",
|
||||
translation_context = 'BBP_OT_game_camera/property',
|
||||
get = lambda self: BBP_OT_game_camera.preset_rotation_angle_deg_getter(self, RotationAngle.Deg0),
|
||||
set = lambda self, _: BBP_OT_game_camera.preset_rotation_angle_deg_setter(self, RotationAngle.Deg0)
|
||||
) # type: ignore
|
||||
preset_rotation_angle_deg45: bpy.props.BoolProperty(
|
||||
name = "45 Degree",
|
||||
translation_context = 'BBP_OT_game_camera/property',
|
||||
get = lambda self: BBP_OT_game_camera.preset_rotation_angle_deg_getter(self, RotationAngle.Deg45),
|
||||
set = lambda self, _: BBP_OT_game_camera.preset_rotation_angle_deg_setter(self, RotationAngle.Deg45)
|
||||
) # type: ignore
|
||||
preset_rotation_angle_deg90: bpy.props.BoolProperty(
|
||||
name = "90 Degree",
|
||||
translation_context = 'BBP_OT_game_camera/property',
|
||||
get = lambda self: BBP_OT_game_camera.preset_rotation_angle_deg_getter(self, RotationAngle.Deg90),
|
||||
set = lambda self, _: BBP_OT_game_camera.preset_rotation_angle_deg_setter(self, RotationAngle.Deg90)
|
||||
) # type: ignore
|
||||
preset_rotation_angle_deg135: bpy.props.BoolProperty(
|
||||
name = "135 Degree",
|
||||
translation_context = 'BBP_OT_game_camera/property',
|
||||
get = lambda self: BBP_OT_game_camera.preset_rotation_angle_deg_getter(self, RotationAngle.Deg135),
|
||||
set = lambda self, _: BBP_OT_game_camera.preset_rotation_angle_deg_setter(self, RotationAngle.Deg135)
|
||||
) # type: ignore
|
||||
preset_rotation_angle_deg180: bpy.props.BoolProperty(
|
||||
name = "180 Degree",
|
||||
translation_context = 'BBP_OT_game_camera/property',
|
||||
get = lambda self: BBP_OT_game_camera.preset_rotation_angle_deg_getter(self, RotationAngle.Deg180),
|
||||
set = lambda self, _: BBP_OT_game_camera.preset_rotation_angle_deg_setter(self, RotationAngle.Deg180)
|
||||
) # type: ignore
|
||||
preset_rotation_angle_deg225: bpy.props.BoolProperty(
|
||||
name = "225 Degree",
|
||||
translation_context = 'BBP_OT_game_camera/property',
|
||||
get = lambda self: BBP_OT_game_camera.preset_rotation_angle_deg_getter(self, RotationAngle.Deg225),
|
||||
set = lambda self, _: BBP_OT_game_camera.preset_rotation_angle_deg_setter(self, RotationAngle.Deg225)
|
||||
) # type: ignore
|
||||
preset_rotation_angle_deg270: bpy.props.BoolProperty(
|
||||
name = "270 Degree",
|
||||
translation_context = 'BBP_OT_game_camera/property',
|
||||
get = lambda self: BBP_OT_game_camera.preset_rotation_angle_deg_getter(self, RotationAngle.Deg270),
|
||||
set = lambda self, _: BBP_OT_game_camera.preset_rotation_angle_deg_setter(self, RotationAngle.Deg270)
|
||||
) # type: ignore
|
||||
preset_rotation_angle_deg315: bpy.props.BoolProperty(
|
||||
name = "315 Degree",
|
||||
translation_context = 'BBP_OT_game_camera/property',
|
||||
get = lambda self: BBP_OT_game_camera.preset_rotation_angle_deg_getter(self, RotationAngle.Deg315),
|
||||
set = lambda self, _: BBP_OT_game_camera.preset_rotation_angle_deg_setter(self, RotationAngle.Deg315)
|
||||
) # type: ignore
|
||||
custom_rotation_angle: bpy.props.FloatProperty(
|
||||
name = "Custom Rotation Angle",
|
||||
description = "The rotation angle of camera relative to 3D Cursor",
|
||||
description = "The rotation angle of camera relative to 3D Cursor or Active Object",
|
||||
subtype = 'ANGLE',
|
||||
min = 0, max = math.radians(360),
|
||||
step = 100,
|
||||
# MARK: What the fuck of the precision?
|
||||
# I set it to 2 but it doesn't work so I forcely set it to 100.
|
||||
precision = 100,
|
||||
translation_context = 'BBP_OT_game_camera/property'
|
||||
) # type: ignore
|
||||
|
||||
perspective_kind: bpy.props.EnumProperty(
|
||||
name = "Rotation Angle Kind",
|
||||
description = "",
|
||||
items = _g_EnumHelper_PerspectiveKind.generate_items(),
|
||||
default = _g_EnumHelper_PerspectiveKind.to_selection(PerspectiveKind.Ordinary)
|
||||
default = _g_EnumHelper_PerspectiveKind.to_selection(PerspectiveKind.Ordinary),
|
||||
translation_context = 'BBP_OT_game_camera/property'
|
||||
) # type: ignore
|
||||
|
||||
@classmethod
|
||||
@ -249,7 +312,19 @@ class BBP_OT_game_camera(bpy.types.Operator):
|
||||
rot_kind = _g_EnumHelper_RotationKind.get_selection(self.rotation_kind)
|
||||
match rot_kind:
|
||||
case RotationKind.Preset:
|
||||
layout.prop(self, 'preset_rotation_angle', text='')
|
||||
# for preset angles, we show a special layout (grid view)
|
||||
subgrid = layout.grid_flow(row_major=True, columns=3, even_columns=True, even_rows=True, align=True)
|
||||
subgrid.prop(self, 'preset_rotation_angle_deg315', toggle = 1)
|
||||
subgrid.prop(self, 'preset_rotation_angle_deg0', toggle = 1)
|
||||
subgrid.prop(self, 'preset_rotation_angle_deg45', toggle = 1)
|
||||
subgrid.prop(self, 'preset_rotation_angle_deg270', toggle = 1)
|
||||
subicon = subgrid.row()
|
||||
subicon.alignment = 'CENTER'
|
||||
subicon.label(text='', icon='MESH_CIRCLE') # show a 3d circle as icon
|
||||
subgrid.prop(self, 'preset_rotation_angle_deg90', toggle = 1)
|
||||
subgrid.prop(self, 'preset_rotation_angle_deg225', toggle = 1)
|
||||
subgrid.prop(self, 'preset_rotation_angle_deg180', toggle = 1)
|
||||
subgrid.prop(self, 'preset_rotation_angle_deg135', toggle = 1)
|
||||
case RotationKind.Custom:
|
||||
layout.prop(self, 'custom_rotation_angle', text='')
|
||||
|
||||
|
@ -137,7 +137,7 @@ class BBP_OT_legacy_align(bpy.types.Operator):
|
||||
return None
|
||||
|
||||
apply_flag: bpy.props.BoolProperty(
|
||||
# TR: Property not showen should not have name and desc.
|
||||
# I18N: Property not showen should not have name and desc.
|
||||
# name = "Apply Flag",
|
||||
# description = "Internal flag.",
|
||||
options = {'HIDDEN', 'SKIP_SAVE'},
|
||||
@ -145,14 +145,14 @@ class BBP_OT_legacy_align(bpy.types.Operator):
|
||||
update = apply_flag_updated
|
||||
) # type: ignore
|
||||
recursive_hinder: bpy.props.BoolProperty(
|
||||
# TR: Property not showen should not have name and desc.
|
||||
# I18N: Property not showen should not have name and desc.
|
||||
# name = "Recursive Hinder",
|
||||
# description = "An internal flag to prevent the loop calling to apply_flags's updator.",
|
||||
options = {'HIDDEN', 'SKIP_SAVE'},
|
||||
default = False
|
||||
) # type: ignore
|
||||
align_history : bpy.props.CollectionProperty(
|
||||
# TR: Property not showen should not have name and desc.
|
||||
# I18N: Property not showen should not have name and desc.
|
||||
# name = "Historys",
|
||||
# description = "Align history.",
|
||||
type = BBP_PG_legacy_align_history
|
||||
|
@ -43,7 +43,7 @@ class BBP_PG_ptrprop_resolver(bpy.types.PropertyGroup):
|
||||
translation_context = 'BBP_PG_ptrprop_resolver/property'
|
||||
) # type: ignore
|
||||
|
||||
# TR: Properties not showen should not have name and desc.
|
||||
# I18N: Properties not showen should not have name and desc.
|
||||
ioport_encodings: bpy.props.CollectionProperty(type = BBP_PG_bmap_encoding) # type: ignore
|
||||
active_ioport_encodings: bpy.props.IntProperty() # type: ignore
|
||||
|
||||
|
@ -954,6 +954,7 @@ class BBP_OT_preset_virtools_material(bpy.types.Operator):
|
||||
name = "Preset",
|
||||
description = "The preset which you want to apply.",
|
||||
items = _g_Helper_MtlPreset.generate_items(),
|
||||
translation_context = 'BBP_OT_preset_virtools_material/property'
|
||||
) # type: ignore
|
||||
|
||||
@classmethod
|
||||
|
@ -48,7 +48,7 @@ import bpy
|
||||
# - If we use `bpy.app.translations.pgettext` with other non-Blender functions, such as `print`.
|
||||
# * Use it as a normal function.
|
||||
#
|
||||
# All translation annotation are started with `TR:`
|
||||
# All translation annotation are started with `I18N:`
|
||||
#
|
||||
|
||||
# The universal translation context prefix for BBP_NG plugin.
|
||||
|
@ -1,18 +1,25 @@
|
||||
# Add Floor
|
||||
|
||||
!!! info "Not latest version"
|
||||
This translated page is not the latest version because the modification of source page. Please see source page of the latest version.
|
||||
!!! info "BME is extensible"
|
||||
BME's floor adder is extensible, each item in the menu is actually described by a set of JSON data. You can read the [Technical Information](./tech-infos.md) section to learn how we write this JSON, and you can even expand the types of floors that BME can create to suit your needs.
|
||||
|
||||
## Start Generating
|
||||
|
||||
### From Menu
|
||||
|
||||
In the 3D view, click `Add - Floors` to expand the Add Floors menu. The menu is shown below.
|
||||
|
||||

|
||||
|
||||
Click on the menu to see all supported floor types in the submenu that pops up. Their names and icons hint at the style and shape of the floor it is intended to create.
|
||||
Click on the menu to see all supported floor types by categories in the submenu that pops up. Their names and icons hint at the style and shape of the floor it is intended to create.
|
||||
|
||||
!!! info "BME is extensible"
|
||||
BME's floor adder is extensible, each item in the menu is actually described by a set of JSON data. You can read the [Technical Information](./tech-infos.md) section to learn how we write this JSON, and you can even expand the types of floors that BME can create to suit your needs.
|
||||
### From Sidebar
|
||||
|
||||
Additionally, you can press `N` on keyboard to expand the sidebar of 3D view and find `Ballance` tab inside it. You also can find these adder by clicking it and expanding `Floor` panel as presented in following image:
|
||||
|
||||

|
||||
|
||||
Comparing with menu, the advantage of this solution is that the sidebar is persistent in UI layout. It is more convenient and effective when adding multiple floors by reducing the time of repetitive opening add menu. Also, there is Rail and Component adder panels under this tab. This will not be introduced again in following chapters.
|
||||
|
||||
## Configure Floor
|
||||
|
||||
@ -26,11 +33,14 @@ Then it also asks us to provide the height of the platform, which defaults to 5,
|
||||
|
||||
Finally, it tells us which sides of the floor we need to configure to display. Note that Top and Bottom are the top and bottom surfaces along the height direction (Z axis), while Front, Back, Left, and Right are the front, back, left, and right surfaces when looking down with your head on the -X axis and your eyes on the -Z axis. You may notice that there is a perspective cube in the center of these six face buttons, and in fact the positions of these six face options correspond to the positions of the six faces of this perspective cube.
|
||||
|
||||
## Extra Transform
|
||||
|
||||
At the bottom of the BME configuration dialog, you can always find an area called Extra Transform. In this area, there are two options for configuration: extra translation and rotation. These fields are primarily intended for visual edit.
|
||||
|
||||
Before explaining the actual functions of these fields, it is important to understand that the floor created by BME is always generated based on the current position of the 3D cursor. In other words, wherever the 3D cursor is located, the newly created surface will be positioned accordingly. This design primarily considers visual edit, allowing users to first move the 3D cursor to the desired location for adding a floor, and then add the corresponding BME structure. This enables users to preview results in real-time while adjusting parameters. Sometimes, the position of your 3D cursor may not be entirely accurate, or the final generated structure may require certain rotation to meet your expectations. In such cases, Extra Transform fields can be utilized to apply extra translation and rotation to the generated structure in relation to the 3D cursor, ensuring it is accurately positioned. In this way, the correct results can be previewed when adjusting the parameters.
|
||||
|
||||
## Tips
|
||||
|
||||
Each floor type has a different number of configuration entries, so for different floor types, you will need to follow the configuration hint text to understand what the corresponding configuration does. Some floor types may have a large number of configuration entries, while others may have no configuration entries at all.
|
||||
|
||||
The default values for the floor type configuration are set to the values that were most commonly used when the floor was created. The values are reset to the defaults each time the floor type is switched or recreated.
|
||||
|
||||
|
||||
|
||||
|
@ -1,8 +1,5 @@
|
||||
# Compile and Distribute Plugin
|
||||
|
||||
!!! info "Not latest version"
|
||||
This translated page is not the latest version because the modification of source page. Please see source page of the latest version.
|
||||
|
||||
This page will guide you in compiling the plugin as well as distributing it.
|
||||
|
||||
## Compiling LibCmo with BMap
|
||||
@ -15,11 +12,93 @@ Then we need to configure PyBMap, which comes with LibCmo. Please follow the man
|
||||
|
||||
Then we need to copy the configured PyBMap to our project under `bbp_ng/PyBMap` to complete this step.
|
||||
|
||||
## Generate Thumbnails and Compress JSON
|
||||
## Generate Resources
|
||||
|
||||
BBP comes with a built-in set of custom icons, as well as the JSON files needed by its component BME to describe the structure. By batch generating thumbnails and compressing JSON operations, the size of these parts can be reduced, making them suitable for loading in Blender and easier to distribute.
|
||||
BBP needs some resoures to run, and these resources need to be processed before using them.
|
||||
|
||||
Go to the `bbp_ng/tools` folder and run `python3 build_icons.py` which will batch generate thumbnails (this requires the PIL library, please install it via pip in advance). It actually generates thumbnails from the original images in the `bbp_ng/raw_icons` directory and stores them in the `bbp_ng/icons` folder. Running `python3 build_jsons.py` will compress the JSON, which actually reads, compresses, and writes the raw JSON files from the `bbp_ng/raw_jsons` directory into the `bbp_ng/jsons` folder.
|
||||
For generating these resrouces, we firstly need to navigate to `scripts` directory, and execute `uv sync` to restore the environment for scripts (Astral UV required).
|
||||
|
||||
### Generate Thumbnails
|
||||
|
||||
BBP comes with a built-in set of custom icons, however these icons are stored as their original size in repository for keeping convenient editing and high quality. We need to reduce the size of these icons to make them are easy to be loaded on Blender and easy for distribution by generating thumbnails for them.
|
||||
|
||||
Execute `uv run build_icons.py` to generate thumbnails. It actually generates thumbnails from the original images in the `assets/icons` directory and stores them in the `bbp_ng/icons` folder.
|
||||
|
||||
### Generate JSONs
|
||||
|
||||
The BME component in BBP relies on a series of JSON files to describe the prototype. These profiles are stored in the library in JSON5 format, making them easy for writers to read and write. We converte these JSON5 files to JSON files and compressing their size makes them easier to load in Blender, as well as to facilitate plugin distribution, by batchly generating them.
|
||||
|
||||
If you are the plugin developer or writer of these prototypes, you need to do an additional thing before generating these JSON files: verify these JSON files. The BBP plugin will assume that these JSON files are correct when loading them. If you put a JSON file with errors (e.g. missing some fields or has some typos, etc.), it will cause Blender to throw an error when creating prototype. Therefore, it is necessary to verify these JSON files. Execute `uv run validate_jsons.py` to verify all prototype files. If there are no errors, it means that everything is okey. It is important to note that the validator is not perfect, it can only verify the data as much as possible to ensure that some common erros (e.g. typo in field name) will not occur. It can not make 100% sure about that there is no error inside these files.
|
||||
|
||||
For compilers, all you need to do is that execute `uv run build_jsons.py` to generate JSON files. It actually reads, compresses, and writes the original JSON5 files in `assets/jsons` directory to the `bbp_ng/jsons` folder in JSON format.
|
||||
|
||||
### Generate Element Meshes
|
||||
|
||||
BBP has built-in mesh data for all Ballance element placeholders. Execute `uv run build_jsons.py` to deploy these meshes, which simply copies the mesh files under `assets/jsons` folder to `bbp_ng/jsons` folder.
|
||||
|
||||
## Translation
|
||||
|
||||
The BBP plugin supports multilingual functionality, so we need to extract and update the content to be translated before the official release, and then proceed to the next step after translating all the content.
|
||||
|
||||
Blender's multilingual support for plugins is not satisfactory, and BBP's design is relatively special, so BBP adopts a different way to manage translations than the official recommended plugin translation management method of Blender: that is, use PO files to manage translations instead of the officially recommended Python script format.
|
||||
|
||||
!!! info "Do NOT submit translations in Python format"
|
||||
As mentioned above, BBP uses PO files to manage translations, rather than the Python source format recommended by Blender. However, this does not prevent Blender's multilingual plugins from writing translations in the Python source format into the plugin's source code. Submitting duplicate translations not only increases the repository size but also complicates management. Therefore, BBP requires you to delete the Python-format translations before submission.
|
||||
|
||||
The specific operational method is to open the `bbp_ng/UTIL_translation.py` file before submission and change the value of the translation tuple variable `translations_tuple` to an empty tuple (i.e., `translations_tuple = ()`).
|
||||
|
||||
### Extract Translation Template
|
||||
|
||||
Before translating, it is important to first recognize that the text requiring translation for BBP consists of two parts. One part is the BBP plugin itself, whose text to be translated can be extracted by Blender's built-in multilingual plugin. The other part is the JSON file in the BME component that describes the structure, where the names of various showcase fields need to be translated. However, this part cannot be handled by Blender's multilingual plugin, as it is dynamically loaded. Fortunately, we have written an extractor that can extract the relevant text to be translated from the BME's JSON file. To do this, execute `uv run extract_jsons.py` in the folder where the previous script was run, and the script will extract the text to be translated and write it into the `i18n/bme.pot` file. Therefore, the next task is simply to extract the translation for the plugin portion.
|
||||
|
||||
First, you need to enable Blender's built-in multilingual plugin, "Manage UI translations". To enable it, you may also need to download the source code and translation repository corresponding to your version of Blender. For specific instructions, please refer to the [official Blender Documentation](https://developer.blender.org/docs/handbook/translating/translator_guide/). Once you have enabled the plugin and configured the appropriate related paths in the preferences, you can find the "I18n Update Translation" panel under the "Render" panel. You can then proceed to extract the translations by following these steps:
|
||||
|
||||
1. First, ensure that all Blender processes are closed; otherwise, the plugin will remain in a loading state, and modifications to the translated tuple variables will not take effect.
|
||||
1. Change the value of the translation tuple variable `translations_tuple` in the plugin to an empty tuple (refer to the earlier mentioned submission notes). Setting the translation tuple to empty can reset the translation status of the plugin, ensuring that subsequent text extraction operations are not affected by any existing translations.
|
||||
1. Open Blender, go to the "I18n Update Translation" panel, click "Deselect All" to uncheck all languages, and then only check the boxes next to the following languages (as BBP currently supports a limited number of languages):
|
||||
* Simplified Chinese (简体中文)
|
||||
1. Click the "Refresh I18n Data" button at the bottom of the section, then in the pop-up window, select "Ballance Blender Plugin". After a short wait, the plugin will complete the extraction of the characters to be translated. At this point, the plugin merely extracts the translation fields into the source code of the plugin in a format recommended by Blender, using Python source code.
|
||||
1. In order to obtain the desired editable POT file, you need to click the "Export PO" button. In the pop-up window, select the "Ballance Blender Plugin", and you can choose any folder for saving the location (for example, the desktop, as it will generate many files, including our desired POT file). Uncheck the "Update Existing" option on the right and ensure that "Export POT" is checked, then proceed to save. After the export is complete, you will find a translation template file named `blender.pot` and numerous `.po` files named after language identifiers in the folder you selected.
|
||||
1. You need to copy `blender.pot` to the `i18n` folder and rename it to `bbp_ng.pot`. At this point, we have extracted all the content that needs to be translated.
|
||||
|
||||
### Merge Translation Template
|
||||
|
||||
There are currently two POT files in the `i18n` folder, which represent two sets of extracted text awaiting translation. We need to merge them. Execute `xgettext -o blender.pot bbp_ng.pot bme.pot` in the `i18n` folder to perform the merge. The merged `i18n/blender.pot` will serve as the translation template.
|
||||
|
||||
### Create New Language Translation
|
||||
|
||||
If BBP needs to support more languages in the future, you will need to create the corresponding PO translation files for the new languages from the POT files. You can create them through one of the following methods.
|
||||
|
||||
* By using software such as Poedit to open the POT file, select function like create new translation from it, and then save to create.
|
||||
* Create a new language PO translation file using commands such as `msginit -i blender.pot -o zh_HANS.po -l zh_CN.utf8`.
|
||||
|
||||
There are various ways to create, but the only point to note is that you need to set the file name (if the file name is incorrect, Blender will refuse to accept it) and the area name (which will be used when using `msginit`, with the purpose of ensuring UTF8 format encoding) as shown in the table below.
|
||||
|
||||
|Language|File Name|Area Name|
|
||||
|:---|:---|:---|
|
||||
|Simplified Chinese (简体中文)|`zh_HANS.po`|`zh_CN.utf8`|
|
||||
|
||||
### Update Language Translation
|
||||
|
||||
Creating new language translations is not common; a more common practice is to update existing language translation files based on translation templates. You can update them through one of the following methods.
|
||||
|
||||
* Open the PO file using software such as Poedit, and then select to update from the POT file.
|
||||
* Update using commands such as `msgmerge -U zh-HANS.po blender.pot --backup=none`.
|
||||
|
||||
### Start Translating
|
||||
|
||||
After updating the PO translation files for all languages, you may choose your preferred method for translation, such as using Poedit or editing directly.
|
||||
|
||||
The BBP requires the use of the KDE community's translation standards to standardize the translations of plugins. For example, you can find the KDE community's translation standards for Simplified Chinese on the [KDE China](https://kde-china.org/tutorial.html) website.
|
||||
|
||||
### Write Translation Back
|
||||
|
||||
The translation in PO format cannot be recognized by Blender. Therefore, after the translation is completed, you also need to utilize Blender's multilingual plugin to convert the PO file back into a translation in Python source code format that Blender can recognize. Due to issues with the design of Blender's multilingual plugin, we cannot directly use the "Import PO" function to convert the PO file back into Python source code format. You need to follow the steps below sequentially in order to import the PO translation into the plugin:
|
||||
|
||||
1. First, ensure that all Blender processes are closed; otherwise, the plugin will remain in a loading state, and modifications to the translated tuple variables will not take effect.
|
||||
1. Change the value of the translation tuple variable `translations_tuple` in the plugin to an empty tuple (refer to the earlier notes regarding submissions). The purpose of this step is to ensure that the entire plugin lacks translation entries, so that when using the "Import PO" feature, Blender's multilingual plugin will consider all fields stored in the PO file as needing translation, thereby preventing situations where only a portion of the translations is imported (as the translations for the BME portion were merged later).
|
||||
1. Open Blender, navigate to the "I18n Update Translation" panel, and following the procedure used when extracting the translation template, select only the languages that need to be translated from the language list.
|
||||
1. Click the "Import PO" button in the bottom row, then select the "Ballance Blender Plugin" in the pop-up window, and choose the `i18n` folder for import. In this way, we have completed the process of importing the PO file into a Python source code format recognizable by Blender.
|
||||
|
||||
## Packaging
|
||||
|
||||
@ -29,13 +108,11 @@ Assuming that the final output file is `redist/bbp_ng.zip`. If you are in the ro
|
||||
|
||||
Blender will package the plugin according to the instructions in `blender_manifest.toml` with the following files excluded:
|
||||
|
||||
* `bbp_ng/raw_icons`: raw thumbnail folder.
|
||||
* `bbp_ng/raw_jsons`: raw JSON folder.
|
||||
* `bbp_ng/tools`: tools for compiling.
|
||||
* `bbp_ng/.style.yapf`: code style description file.
|
||||
* `bbp_ng/.gitignore`: gitignore
|
||||
* `bbp_ng/icons/.gitkeep`: folder placeholder
|
||||
* `bbp_ng/jsons/.gitkeep`: folder placeholder
|
||||
* `__pycache__/`:Python cache.
|
||||
* `.style.yapf`:code style description file.
|
||||
* `.gitignore`:gitignore
|
||||
* `.gitkeep`:folder placeholder
|
||||
* `.md`:documentation
|
||||
|
||||
## Generating Help Documentation
|
||||
|
||||
|
@ -19,7 +19,9 @@ The BBP plugin currently has 2 settings to configure.
|
||||
|
||||
Please fill in the `Texture` directory of Ballance, from which the plugin will use the external texture files (i.e. the ones Ballance originally came with). Click on the folder button on the right to browse the folders and select it.
|
||||
|
||||
This is crucial for BBP to work properly, and only if it is filled out correctly will BBP not make errors during operation.
|
||||
This option is almost mandatory. If you don't fill it, various core functions like Virtools file import export, BME creation, rail creation, etc. will not be available (button is in grey color).
|
||||
|
||||
This is crucial for BBP to work properly, and only if it is filled correctly will BBP not make errors during operation.
|
||||
|
||||
### No Component Collection
|
||||
|
||||
|
@ -1,8 +1,5 @@
|
||||
# Import and Export Virtools Document
|
||||
|
||||
!!! info "Not latest version"
|
||||
This translated page is not the latest version because the modification of source page. Please see source page of the latest version.
|
||||
|
||||
!!! warning "This is experimental content"
|
||||
Native importing and exporting of Virtools documents is experimental content for the BBP plugin, it may have many problems, see the [Report Issue](./report-bugs.md) section to learn more. When problems are encountered, please report them. the authors of the BBP plugin are not responsible for any consequences resulting from problems with the BBP plugin.
|
||||
|
||||
@ -12,7 +9,7 @@ Virtools files can be imported by clicking `File - Import - Virtools File`. Impo
|
||||
|
||||
### Conflict Options
|
||||
|
||||
The Conflict Options section indicates what to do when the importer encounters duplicate object names. There are 4 levels, for Object, Mesh, Material and Texture. There are 2 ways to handle it: Rename and Use Current. When Rename is selected and a duplicate name is encountered, a suffix will be added to the name to make it unique. By choosing Use Current, the import of the item from the file will be ignored and the item with the same name will be used instead, which already exists in the Blender document.
|
||||
The Conflict Options section indicates what to do when the importer encounters duplicate object names. There are 5 levels, for Object, Light, Mesh, Material and Texture. There are 2 ways to handle it: Rename and Use Current. When Rename is selected and a duplicate name is encountered, a suffix will be added to the name to make it unique. By choosing Use Current, the import of the item from the file will be ignored and the item with the same name will be used instead, which already exists in the Blender document.
|
||||
|
||||
!!! info "Differences from Virtools conflict resolution"
|
||||
Compared to the conflict resolution dialog in Virtools, the conflict resolution options provided by the BBP plugin do not support replacement, and the granularity is not fine-tuned to individual instances, but only for an entire type. So you can't set a different conflict resolution for each instance of a conflict individually. However, this setting is sufficient for most scenarios.
|
||||
@ -21,7 +18,7 @@ The default values for the options in the Conflict Options section are the solut
|
||||
|
||||
### Virtools Params
|
||||
|
||||
It is well known that Virtools uses a system-based multi-byte character encoding to process documents, and is therefore prone to what is known as garbling; Blender itself does not suffer from garbling, however, if we do not read a Virtools document with the correct encoding, the characters stored in it may still appear garbled when the Virtools document is imported into Blender. The Encodings property in the Virtools Params section specifies the encodings for reading Virtools documents. Multiple encodings can be specified, separated by a `;` (semicolon). Some common encodings are listed below:
|
||||
It is well known that Virtools uses a system-based multi-byte character encoding to process documents, and is therefore prone to what is known as garbling; Blender itself does not suffer from garbling, however, if we do not read a Virtools document with the correct encoding, the characters stored in it may still appear garbled when the Virtools document is imported into Blender. The Encodings property in the Virtools Params section specifies the encodings for reading Virtools documents. Multiple encodings may be specified, with the encodings higher up in the list being prioritized for use. The next level of encoding will only be utilized when decoding with the current level fails. Some common encodings are listed below:
|
||||
|
||||
* cp1252: Western European encoding used by Ballance.
|
||||
* gbk: The default encoding for Chinese Windows system.
|
||||
@ -42,7 +39,12 @@ Virtools files can be exported by clicking `File - Export - Virtools File`. Clic
|
||||
|
||||
### Export Target
|
||||
|
||||
The Export Target section is used to determine which objects you need to export to a Virtools document. You can choose to export a collection or an object and select the corresponding collection or object below. Note that selecting a collection will export the objects in the internal collection as well, i.e. exporting nested collections is supported.
|
||||
The Export Target section is used to determine which objects you need to export to a Virtools document. You can choose 1 of 4 options:
|
||||
|
||||
* Object: Export single object. Select an object in following input box.
|
||||
* Collection: Export single collection. **This is the most commonly used option.** Select a collection in following input box. Note that selecting a collection will export the objects in the internal collection as well, i.e. exporting nested collections is supported.
|
||||
* Selected Object: Export selected objects. Select the objects to be exported before enter this dialog.
|
||||
* All Objects: Export all objects inside this document. This option should be used with caution. Because it brutely iterate the list of document objects to export, and it is likely to export many objects you don't need.
|
||||
|
||||
### Virtools Params
|
||||
|
||||
@ -59,3 +61,11 @@ The Ballance Params section contains parameters that optimize the export process
|
||||
Successive Sector is an option to work around a bug that occurs when exporting groups of sectors. For some reason, if there are no elements in a sector (actually, no objects are grouped in a sector group), the export plugin thinks that the sector group doesn't exist and misses the export. And since Ballance determines the final sector, i.e. the sector where the spaceships appears, by incrementing the number of sectors from 1 to the last sector group that exists, the combination of the two causes Ballance to incorrectly determine the number of sectors in the map, and thus display the spaceships in the wrong sector, which is an export bug. when this option is checked, the exported document will be pre-defined according to the number of sectors specified in the Ballance Map information in the current Blender file. When this option is checked, the exported document will pre-create all of the sectors according to the number of sectors specified in the Ballance map information in the current Blender file before exporting, so that you don't miss creating some sector groups, and the spaceships will be displayed in the correct sectors.
|
||||
|
||||
This option is usually checked when exporting playable maps, if you just want to export some models then you need to turn this option off, otherwise it will create a lot of useless sector groups in the final file.
|
||||
|
||||
## Can't Import or Export
|
||||
|
||||
In general, after you have properly installed and configured the plugin according to the previously introduced steps, you should theoretically be able to use the import and export functions for Virtools documents. However, unexpected issues may arise. The inability to import or export refers to the buttons for importing and exporting Virtools documents being greyed out and unclickable. You will need to follow the steps outlined below for checking. If you are referring to an error occurring during the import and export process, please refer to the warning information at the top of this page.
|
||||
|
||||
First, check whether you have correctly configured the `External Texture Folder` setting of the plugin in the [Configure Plugin](configure-plugin.md) section. If you have not configured it, you will naturally be unable to import or export Virtools files. This is because importing and exporting Virtools files relies on the original Ballance texture data. Please configure this setting carefully according to the tutorial.
|
||||
|
||||
If you are certain that you have set the correct texture path, you may try clicking the menu `Window - Toggle System Console` to open the console. There may be some relevant error messages outputted there, such as a failure to load the underlying BMap library, etc. The failure to load the underlying BMap library typically only occurs on machines with rare architectures, such as Windows systems using Snapdragon processors, as the plugin we packaged does not include the Virtools file underlying reading library BMap that supports these platforms. In this situation, you have two options: one is to report this to the developers and wait for support, and the other is to compile the library on yourself (this is only recommended for those with extensive computer knowledge).
|
||||
|
@ -3,6 +3,16 @@
|
||||
!!! info "May be Outdated"
|
||||
This document is translated from other languages and may not always be up to date.
|
||||
|
||||
<!---
|
||||
!!! info "Not latest version"
|
||||
This translated page is not the latest version because the modification of source page. Please see source page of the latest version.
|
||||
--->
|
||||
|
||||
<!---
|
||||
!!! info "No Translation"
|
||||
This page has not been translated. Please see source page of this page.
|
||||
--->
|
||||
|
||||
Welcome to the Ballance Blender Plugin, the user manual for the free and open source Ballance map creation suite.
|
||||
|
||||
Ballance Blender Plugin (aka BBP) is a plugin that focuses on the creation of Ballance custom maps. It offers a wide range of features that can be used to create Ballance maps by anyone from novice to experienced mappers. BBP provides the ability to import and export formats used in Ballance maps, and a series of convenient features tailored to the creation of Ballance maps: for novice mappers, you can quickly assemble a map with prefabricated road blocks, and for the experienced mappers, the mapping tools needed to build complex structures are also provided.
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
## Determining the Version
|
||||
|
||||
The principle of BBP's Blender support is to support the latest **LTS** version, and to spend some time migrating the plugin after the latest LTS version is released. The current plugin version **4.0** is based on Blender version **4.2.x**.
|
||||
The principle of BBP's Blender support is to support the latest **LTS** version, and to spend some time migrating the plugin after the latest LTS version is released. The current plugin version **4.3** is based on Blender version **4.5.x**.
|
||||
|
||||
Theoretically, BBP will work fine on other versions of Blender if no major changes have been made. For example you can try to run BBP plugin based on Blender 3.6 LTS on Blender 4.0. However, the developers of BBP do not deal with bugs that only appear in non-LTS versions. before installing the plugin, please select the appropriate version.
|
||||
|
||||
|
@ -14,9 +14,11 @@ Legacy alignment supports aligning multiple objects to a single object by first
|
||||
|
||||
In the panel, `Align Axis` specifies the axis you want to align to, you can multi-select here to specify more than one axis, without specifying any axis you will not be able to do the alignment operation, and thus you will not be able to click the `Apply` button.
|
||||
|
||||
`Current Object` is the alignment reference object, which is the active object in the scene, usually the last object you selected. This option specifies what value you need to reference for alignment, with `Min` (minimum value on axis), `Center (Bounding Box)` (center of the bounding box), `Center (Axis)` (origin of the object), and `Max` (maximum value on axis) available. These options are consistent with the alignment options in 3ds Max.
|
||||
`Current Object` indicates which instance was picked as the alignment reference. You may choose an active object in the scene, typically the last object you selected, or the 3D cursor. It is important to note that if you select active object mode, the active object will be excluded from the alignment operation and will not be moved, as the reference object is immovable. Conversely, if you select the 3D cursor, the active object will be included within the scope of the alignment operation.
|
||||
|
||||
The `Target Objects` are the objects that are being aligned, there may be many of them, in this option it is also specified what values you need to refer to them for alignment. The options have the same meaning as `Current Object`.
|
||||
`Current Object Align Mode` is the alignment mode for aligning to a reference object, which only appears when you select the active object in `Current Object`. Since the 3D cursor is merely a point, while objects occupy a certain space, we need to select a point in this space according to a specific pattern (described later) to be used for subsequent alignment operations. In this option, you specify what value you need to align to, with available selections including `Min` (minimum value on axis), `Center (Bounding Box)` (center of the bounding box), `Center (Axis)` (origin of the object), and `Max` (maximum value on axis). These options are consistent with the alignment options in 3ds Max.
|
||||
|
||||
The `Target Objects Align Mode` are the objects that are being aligned, there may be many of them, in this option it is also specified what values you need to refer to them for alignment. The options have the same meaning as `Current Object`.
|
||||
|
||||
The `Apply` button, when clicked, will press the current page's configuration into the operation stack and reset the settings above, allowing you to start a new round of alignment operations without having to perform a legacy alignment again. The number of operations in the stack is shown below the `Apply` button.
|
||||
|
||||
|
@ -1,8 +1,5 @@
|
||||
# Add Rail
|
||||
|
||||
!!! info "Not latest version"
|
||||
This translated page is not the latest version because the modification of source page. Please see source page of the latest version.
|
||||
|
||||
In the 3D view, click `Add - Rails` to expand the Add Rails menu. The menu is shown on the left side of the image below.
|
||||
|
||||

|
||||
@ -63,6 +60,8 @@ The first thing you need to do with an arc rail is to specify the Angle and Radi
|
||||
|
||||
Steps of the arc rail, the number of steps indicates the number of segments of the arc rail, the larger the number, the smoother the arc rail looks, relatively, the vertices will be more, the storage space and rendering requirements are also higher, so you need to choose a reasonable value.
|
||||
|
||||
The Flip option for arc rail allows you to flip (in other word, mirror) the generated structure along a specified axis, and the flip options available on all three axes can accommodate the generation of all possible arc rail structures.
|
||||
|
||||
Arc rails also support double-rail mono-rail selection, you can create mono-rail arc rails and double-rail arc rails. The capping attribute is also supported.
|
||||
|
||||
### Spiral Rail
|
||||
@ -73,7 +72,7 @@ Spiral rails have an Iterations property, which indicates how many times the rai
|
||||
|
||||
The spiral rail also needs to set the Steps property, which has the same meaning as the arc rail. However, it should be noted that the number of steps refers to the number of steps in each iteration, not the overall number of steps. Therefore, when adjusting the iteration attribute, you do not need to change the Steps attribute again.
|
||||
|
||||
Side Spiral Rail also has a capping property.
|
||||
Side Spiral Rail also has capping and flip property.
|
||||
|
||||
### Side Spiral Rail
|
||||
|
||||
@ -82,3 +81,9 @@ Side Spiral Rail, similar to spiral rail, but the ball is rolled along the side,
|
||||
Side Spiral Rail does not have a Screw property, because Side Spiral Rail is designed so that adjacent spins share a common edge, so the screw is fixed.
|
||||
|
||||
The Radius, Iterations and Steps attributes in the Side Spiral Rail settings have the same meaning as the spiral rail. Side Spiral Rail also have a capping attribute.
|
||||
|
||||
Spiral Rail also has capping and flip property.
|
||||
|
||||
## Extra Transform
|
||||
|
||||
When adding straight rails and curved rails, you can always set a property known as the Extra Transform. Its effect is consistent with the Extra Transform field in adding floors, both serving the purpose of visual edit.
|
||||
|
@ -1,8 +1,5 @@
|
||||
# Report Issue
|
||||
|
||||
!!! info "Not latest version"
|
||||
This translated page is not the latest version because the modification of source page. Please see source page of the latest version.
|
||||
|
||||
## What Can Go Wrong
|
||||
|
||||
BBP is not perfect, and since BBP's Virtools file import/export module is written in C++, BBP is more prone to errors than other plugins, and the consequences of errors can be more serious (including but not limited to memory leaks, accidental deletion of user files, etc.).
|
||||
@ -15,7 +12,7 @@ In Blender, you will observe if the plugin execution goes wrong:
|
||||
|
||||
## What Part Went Wrong
|
||||
|
||||
For the BBP plugin, if you observe something like `BMap operation failed` in the Python exception output, or the `IronPad.log` file in the `<Plugin-Install-Location>/PyBMap` folder, it means that The BBP plugin's BMap section, written in C++, is in error, and **you need to immediately save your current Blender document and exit Blender**. Because the plugin is in an abnormal state at this point, you should not continue any operations.
|
||||
For the BBP plugin, if you observe something like `BMap operation failed` in the Python exception output, or the `blender.exe.<xxx>.log` file (`<xxx>` is a string of numbers) in the `%LOCALAPPDATA%/CrashDumps` folder (`%LOCALAPPDATA%` is a Windows environment variable. If you are not familiar with its purpose, you can simply copy and paste this address directly into the Windows Explorer, which will automatically navigate you to the correct location), it means that The BBP plugin's BMap section, written in C++, is in error, and **you need to immediately save your current Blender document and exit Blender**. Because the plugin is in an abnormal state at this point, you should not continue any operations.
|
||||
|
||||
If there is no such thing as the above, then this is just a normal Python code execution error and you don't need to worry too much about it, but the error is still fatal and it is recommended to exit Blender and report the error after doing all the necessary operations.
|
||||
|
||||
@ -29,4 +26,4 @@ If you can't do that and you have proper way to contact with plugin author, then
|
||||
|
||||
First of all you need to describe in detail how you raise this error and what are the results of this error. If you can upload the documentation that led to the error, please try to do so (if it's not convenient to post it publicly, you can send it to the author through a private way such as email).
|
||||
|
||||
You also need to provide the Python stack report output in the Blender console (use `Window - Toggle System Console` to open the console). If your error is an error in the BMap section, you also need to provide the `IronPad.log` and `IronPad.dmp` files in the `<Plugin-Install-Location>/PyBMap` folder to make it easier for developers to locate the error.
|
||||
You also need to provide the Python stack report output in the Blender console (use `Window - Toggle System Console` to open the console). If your error is an error in the BMap section, you also need to provide the error log file `blender.exe.<xxx>.log` (where `<xxx>` represents a string of numbers) and the memory dump file `blender.exe.<xxx>.dmp` generated by the BMap module. These files can also be found in the `%LOCALAPPDATA%/CrashDumps` folder.
|
||||
|
@ -1,12 +1,30 @@
|
||||
# Technical Information
|
||||
|
||||
## Standards and Protocol Documentation
|
||||
|
||||
* BM File Specification: https://github.com/yyc12345/gist/blob/master/BMFileSpec/BMSpec_ZH.md
|
||||
* Mapping toolchain standards and format of files in the `meshes' folder: https://github.com/yyc12345/gist/blob/master/BMFileSpec/YYCToolsChainSpec_ZH.md
|
||||
* Format of the JSON file for BMERevenge: https://github.com/yyc12345/gist/blob/master/BMERevenge/DevDocument_v2.0_ZH.md
|
||||
|
||||
## Development Auxiliary Package
|
||||
|
||||
This plugin works with the `fake-bpy-module` module to implement type hinting to speed up development. Use the following command to install Blender's type hinting library.
|
||||
|
||||
* Blender 3.6: `pip install fake-bpy-module-latest==20230627`
|
||||
* Blender 4.2: `pip install fake-bpy-module-latest==20240716`
|
||||
* Blender 4.5: `pip install fake-bpy-module-latest==20250604`
|
||||
|
||||
The main reason for doing this is that `fake-bpy-module` doesn't release an official package for the given Blender version, so I had to install it by choosing the daily build closest to the release time of the corresponding Blender version.
|
||||
The primary reason for this is that the `fake-bpy-module` has not timely released packages suitable for the specified Blender version. Therefore, I can only install it by selecting the daily build version that is closest to the date of the corresponding Blender version leaving from the `main` branch (as daily builds only compile from the `main` branch).
|
||||
|
||||
!!! question "Why not use Blender's official bpy module?"
|
||||
Blender provides an official package named `bpy` on PyPI, but we will not adopt it as our development auxiliary package. This is because it basically repackages Blender into a module (which basically means you are downloading Blender again), allowing you to manipulate Blender through Python. This is contrary to our purpose of using a package that only provides type hints to assist in plugin development.
|
||||
|
||||
## Version Rule
|
||||
|
||||
The version number format of BBP follows [Semantic Versioning](https://semver.org), but with slight differences:
|
||||
|
||||
* The major version number is only increased when the entire plugin is reconstructed.
|
||||
* The minor version number is used for regular updates.
|
||||
* The patch version number is incremented when there is no modification for any functionalities. For example, version 4.2.1 only includes updates for macOS Blender without changing any features.
|
||||
|
||||
Before the formal release of BBP, there are typically three phased versions: Alpha version, Beta version, and RC version. The Alpha version focuses on functional updates, used to verify whether newly added or modified features are functioning correctly, and does not include documentation or translations. The Beta version is focus on plugin documentation, while the RC version concentrates on plugin translations. However, these three versions do not always exist; if the update content is minimal, some versions may be skipped, or a direct release may occur.
|
||||
|
@ -1,8 +1,5 @@
|
||||
# Virtools Properties
|
||||
|
||||
!!! info "Not latest version"
|
||||
This translated page is not the latest version because the modification of source page. Please see source page of the latest version.
|
||||
|
||||
## Virtools Group
|
||||
|
||||
The BBP plugin adds a new property to every Blender object, called Virtools Group. has the same functionality as Group in Virtools. Select an object and the `Virtools Group` panel can be found in the `Object` properties panel.
|
||||
@ -13,6 +10,8 @@ In the `Virtools Group` panel, you can click Add to group objects. After clickin
|
||||
|
||||
BBP also provides access to Virtools groups in Blender's other menus, see [Group Operation](./group-operations.md).
|
||||
|
||||
It is important to note that the Virtools group only works on mesh objects. When you open the Virtools group panel on other objects, you will see a warning message in the panel indicating that the Virtools group is invalid for that object. Although the Virtools group data set on non-mesh objects will be recognized and stored by Blender, it will not be saved to the Virtools file when exporting.
|
||||
|
||||
## Virtools Material
|
||||
|
||||
The plugin adds a new property to every Blender material, called Virtools Material, which bridges the gap between Virtools materials and Blender materials. Go to the `Material` properties panel and select a material to find the `Virtools Material` panel.
|
||||
@ -59,4 +58,12 @@ The BBP plugin adds a new property to all Blender meshes called Virtools Mesh. g
|
||||
|
||||

|
||||
|
||||
The Virtools Mesh is currently only used as a compatibility feature. It has only one property, Lit Mode, that can be set. Most early maps had black floor issue because they didn't know how to set the material correctly, so the Lit Mode was often set to Prelit to get the floor to show up properly. This attribute exists for compatibility with this compromise and the user usually does not need to set this option.
|
||||
The Virtools Mesh is currently only used as a compatibility feature. It has only one property, Lit Mode, that can be set. Most early maps had black floor issue because they didn't know how to set the material correctly, so the Lit Mode was often set to Prelit to get the floor to show up properly. This attribute exists for compatibility with this compromise and the user usually does not need to set this option.
|
||||
|
||||
## Virtools Light
|
||||
|
||||
The BBP plugin adds a new property called Virtools Light to all Blender lights. You can find the Virtools Light panel by navigating to the Data properties panel.
|
||||
|
||||

|
||||
|
||||
Similar to the materials in Virtools, the lighting system in Virtools differs significantly from that in Blender. The Virtools Light acts as a bridge, accurately reflecting the settings of Virtools, allowing for seamless storage within Blender files and providing necessary data during import and export. Additionally, this panel includes an Apply button to apply the Virtools lighting settings to Blender's lighting.
|
||||
|
@ -1,4 +1,37 @@
|
||||
# ZZQ Features
|
||||
|
||||
!!! info "No Translation"
|
||||
This page has not been translated. Please see source page of this page.
|
||||
This plugin received many suggestions from ZZQ during its development process, resulting in a rather disordered set of features, which are therefore described together on a separate page.
|
||||
|
||||
## Snoop Group then to Mesh
|
||||
|
||||
Snoop Group then to Mesh, fully referred to as: snoop and copy the Virtools Group infomations into corresponding curve object and convert it into mesh object. You can select certain objects and then right-click to find this function in the context menu of the object.
|
||||
|
||||
This function, as its name, converts the selected object into a mesh. If the selected object is a curve and there is a beveled object set, the grouping information of the beveled object will be assigned to the current curve (overriding the curve's current grouping settings). If the selected object is not a curve, or if it is a curve but lacks a beveled object, then this function is basically the same as executing a conversion to mesh. This function is extremely useful in loft modeling, as it only requires the correct grouping of the section object, after which using this function to convert the curve to a mesh will ensure that the grouping of the lofted object is correct.
|
||||
|
||||
## Game Camera
|
||||
|
||||
Many map makers often lack a clear concept of the size of their maps when creating them, which can easily lead to the production of maps that are either too large or too small. The in-game camera function of the menu item `Ballance - Game Camera` offers a way to preview the map from the perspective of the in-game camera within Blender, allowing map makers to better grasp the dimensions of the map.
|
||||
|
||||
In order to use this feature, there must first be a camera in your scene, set as the active camera of the scene (when no camera is present, a newly added camera through the add menu will be automatically set). Additionally, you will need an active object, which cannot be the same as this camera.
|
||||
|
||||
!!! question "Why is it necessary to have active object?"
|
||||
Due to the limitations of the Blender plugin, an active object is required since the in-game camera functionality supports targeting either the 3D cursor **or an active object**.
|
||||
|
||||
Typically, the situation where there are no active objects available only occurs in a blank Blender document, which consequently renders the functionality unavailable. In a custom map, there is no any lack of objects which can become active objects; simply clicking on any object is enough (when wishing to use the 3D cursor as a target).
|
||||
|
||||
After clicking this function, the view will automatically switch to the perspective of the active camera, facilitating your preview. You can adjust the relevant settings in the panel located at the bottom left.
|
||||
|
||||

|
||||
|
||||
First, select the target, which essentially means choosing the position of the player's ball. If 3D cursor is selected, it is treated as the origin of player's ball. If active object is selected, the player's ball is placed at the origin of the active object.
|
||||
|
||||
!!! info "The position of the player's ball is not that straightforward."
|
||||
Regardless of whether one chooses 3D cursor or active object, if no extremely fine adjustments are made, the preview results may have slight differences compared with in-game result.
|
||||
|
||||
When you use the 3D cursor mode and simply snap it to the ground, it does not represent the position of player ball. Since the radius of player ball is 2, you actually need to move 2 units in +Z direction to achieve the exact same perspective as in the game. However, this operation is too complex, and not performing this action does not cause a significant difference in the preview effect.
|
||||
|
||||
When using active object mode, it is important to note that the origin of the object corresponds to the position of the dot displayed in viewport when the object is selected. For most objects, this may not be what you desire, as they may be located inside or outside the object, and are not always positioned on the surface of the object or at the center of a particular face. To address this situation, I recommend using the 3D cursor as a target and, by entering edit mode, utilizing snapping and the `Shift + S` menu to place the cursor in the correct position.
|
||||
|
||||
Next is the selection of the camera's rotation angles. We offer 8 common used in-game preset angles, corresponding to 4 each for 90 degrees camera and 45 degrees camera. Furthermore, if these preset angles do not meet your requirements, you can also set custom angles.
|
||||
|
||||
Finally, there is the selection of camera perspectives, which can be divided into 3 types: Ordinary (standard perspective), Lift (perspective activated by holding the spacebar), and Easter Egg (special Easter Egg perspective).
|
||||
|
BIN
docs/docs/imgs/bme-adder-sidebar.png
Normal file
BIN
docs/docs/imgs/bme-adder-sidebar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 108 KiB |
Binary file not shown.
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 108 KiB |
BIN
docs/docs/imgs/game-camera.png
Normal file
BIN
docs/docs/imgs/game-camera.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 80 KiB |
@ -1,15 +1,25 @@
|
||||
# 添加路面
|
||||
|
||||
!!! info "BME是可扩展的"
|
||||
BME的路面添加器是可扩展的,菜单中的每一个项实际上都由一组JSON数据描述。您可以阅读[技术信息](./tech-infos.md)章节来了解我们是如何编写这些JSON的,甚至您还可以根据你的需求自行扩展BME可创建的路面种类。
|
||||
|
||||
## 开始生成
|
||||
|
||||
### 从添加菜单生成
|
||||
|
||||
在3D视图中,点击`Add - Floors`可展开添加路面菜单。菜单如下图所示。
|
||||
|
||||

|
||||
|
||||
点击菜单后可以在弹出的子菜单中查看所有受支持的路面类型。其名称和图标提示了它所要创建路面的样式与形状。
|
||||
点击菜单后可以在弹出的子菜单中按分类查看所有受支持的路面类型。其名称和图标提示了它所要创建路面的样式与形状。
|
||||
|
||||
!!! info "BME是可扩展的"
|
||||
BME的路面添加器是可扩展的,菜单中的每一个项实际上都由一组JSON数据描述。您可以阅读[技术信息](./tech-infos.md)章节来了解我们是如何编写这些JSON的,甚至您还可以根据你的需求自行扩展BME可创建的路面种类。
|
||||
### 从侧边栏生成
|
||||
|
||||
此外,还可以通过点按N键,打开3D视图的侧边栏,在其中找到Ballance选项卡,展开Floor面板也可找到,如下图所示:
|
||||
|
||||

|
||||
|
||||
该面板相较于添加菜单,其好处在于可常驻在界面之中,避免了在持续添加路面的操作中,频繁打开菜单寻找路面的麻烦。此外,该选项卡中还有用于添加钢轨和机关的面板可供展开,在后续章节中不再赘述。
|
||||
|
||||
## 配置路面
|
||||
|
||||
@ -27,7 +37,7 @@
|
||||
|
||||
在BME配置对话框的底部,您总是可以找到一个被称为额外变换的区域。在这个区域中,有额外移动和额外旋转两个选项可以配置。这些字段主要是为了可视化服务的。
|
||||
|
||||
在说明这些字段的实际作用前,你需要知道,BME创建的路面总是以当前3D游标的位置进行创建的,即3D游标在哪里,新创建的路面就在哪里。这主要是为了可视化来考虑到,用户可以先将3D游标移动到想要添加路面的位置,再添加对应的BME结构,便可以在调整参数的时候即时预览到结果。有时候你的3D游标的位置不是那么的准确,又或者最终生成的结构需要一定的旋转才是你期望的,此时就可以利用额外变换字段,为最终生成的结构,增加相对于3D游标的额外的移动和旋转,使之处于正确的位置,这样就可以在调整参数的时候实时预览到结果了。
|
||||
在说明这些字段的实际作用前,你需要知道,BME创建的路面总是以当前3D游标的位置进行创建的,即3D游标在哪里,新创建的路面就在哪里。这主要是为了可视化来考虑到,用户可以先将3D游标移动到想要添加路面的位置,再添加对应的BME结构,便可以在调整参数的时候即时预览到结果。有时候你的3D游标的位置不是那么的准确,又或者最终生成的结构需要一定的旋转才是你期望的,此时就可以利用额外变换字段,为最终生成的结构,增加相对于3D游标的额外的移动和旋转,使之处于正确的位置,这样就可以在调整参数的时候预览到正确的结果了。
|
||||
|
||||
## 小贴士
|
||||
|
||||
|
@ -69,8 +69,8 @@ Blender对于插件的多语言支持不尽如人意,且BBP的设计比较特
|
||||
|
||||
如果未来BBP需要支持更多语言,你需要从POT文件为新语言创建其对应的PO翻译文件。你可以通过以下方式之一来创建它们。
|
||||
|
||||
1. 通过使用Poedit等软件打开POT文件,选择创建新的翻译,再进行保存来创建。
|
||||
1. 通过诸如`msginit -i blender.pot -o zh_HANS.po -l zh_CN.utf8`的命令来创建新语言的PO翻译文件。
|
||||
* 通过使用Poedit等软件打开POT文件,选择创建新的翻译,再进行保存来创建。
|
||||
* 通过诸如`msginit -i blender.pot -o zh_HANS.po -l zh_CN.utf8`的命令来创建新语言的PO翻译文件。
|
||||
|
||||
创建的方式多种多样,唯一需要注意的是你需要按下表所示设定文件名(文件名错误,Blender会拒绝接受)和区域名称(使用`msginit`时会用到,目的是确保是UTF8格式编码的)。
|
||||
|
||||
@ -82,8 +82,8 @@ Blender对于插件的多语言支持不尽如人意,且BBP的设计比较特
|
||||
|
||||
创建新的语言翻译并不常见,更为常见的操作是根据翻译模板,对现有语言翻译文件进行更新。你可以通过以下方式之一来更新它们
|
||||
|
||||
1. 通过Poedit等软件打开PO文件,再选择从POT文件更新。
|
||||
1. 通过诸如`msgmerge -U zh-HANS.po blender.pot --backup=none`的命令来更新。
|
||||
* 通过Poedit等软件打开PO文件,再选择从POT文件更新。
|
||||
* 通过诸如`msgmerge -U zh-HANS.po blender.pot --backup=none`的命令来更新。
|
||||
|
||||
### 进行翻译
|
||||
|
||||
@ -108,14 +108,11 @@ PO格式的翻译并不能被Blender识别,因此在翻译完成后,你还
|
||||
|
||||
Blender会根据`blender_manifest.toml`的指示,在排除下列文件的情况下将插件打包:
|
||||
|
||||
* `bbp_ng/i18n`:翻译文件夹。
|
||||
* `bbp_ng/raw_icons`:原始图片文件夹。
|
||||
* `bbp_ng/raw_jsons`:原始JSON文件夹。
|
||||
* `bbp_ng/tools`:编译用工具。
|
||||
* `bbp_ng/.style.yapf`:代码风格描述文件
|
||||
* `bbp_ng/.gitignore`:gitignore
|
||||
* `bbp_ng/icons/.gitkeep`:文件夹占位符
|
||||
* `bbp_ng/jsons/.gitkeep`:文件夹占位符
|
||||
* `__pycache__/`:Python缓存
|
||||
* `.style.yapf`:代码风格描述文件
|
||||
* `.gitignore`:gitignore
|
||||
* `.gitkeep`:文件夹占位符
|
||||
* `.md`:文档
|
||||
|
||||
## 生成帮助文档
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
### 冲突解决选项
|
||||
|
||||
Conflict Options(冲突解决选项)章节指示了当导入器遇到物体名称重复的情况时,该如何处理。分为4个等级,分别针对Object(物体),Light(灯光),Mesh(网格),Material(材质),Texture(贴图)。处理方式则有2种:Rename(重命名)和Use Current(使用当前)。选择重命名后,当遇到重复名称时,将会自动为其添加名称后缀使其名称唯一化。而选择使用当前,则会忽略从文件中导入此项,转而使用Blender文档中已经存在的同名的项目。
|
||||
Conflict Options(冲突解决选项)章节指示了当导入器遇到物体名称重复的情况时,该如何处理。分为5个等级,分别针对Object(物体),Light(灯光),Mesh(网格),Material(材质),Texture(贴图)。处理方式则有2种:Rename(重命名)和Use Current(使用当前)。选择重命名后,当遇到重复名称时,将会自动为其添加名称后缀使其名称唯一化。而选择使用当前,则会忽略从文件中导入此项,转而使用Blender文档中已经存在的同名的项目。
|
||||
|
||||
!!! info "与Virtools冲突解决的不同"
|
||||
相比较于在Virtools的冲突解决对话框,BBP插件提供的冲突解决选项不支持替换功能,同时其粒度也不支持精细到单个实例,只能针对一整个类型进行设定。因此你无法单独为每一个冲突的实例设置不同的冲突解决方案。但目前这种设置已经能满足绝大对数的使用场景了。
|
||||
@ -39,7 +39,12 @@ Conflict Options(冲突解决选项)章节指示了当导入器遇到物体
|
||||
|
||||
### 导出目标
|
||||
|
||||
Export Target(导出目标)章节用于决定你需要将哪写物体导出到Virtools文档中。你可以选择导出一个集合或一个物体,并在下面选择对应的集合或物体。需要注意的是,选择集合的时候,会将内部集合中的物体也一起导出,即支持嵌套集合的导出。
|
||||
Export Target(导出目标)章节用于决定你需要将哪写物体导出到Virtools文档中。你可以在四种模式中选择其一,来决定需要导出的内容:
|
||||
|
||||
* Object:导出单个物体。选择后需要在下面选择需要导出的物体。
|
||||
* Collection:导出单个集合,**这是最常用的选项**。选择后需要在下面选择需要导出的集合。值得注意的是,该选项支持嵌套集合导出,即选择集合的时候,会将集合中的集合的物体也一起导出。
|
||||
* Selected Objects:导出选择的物体。你需要在导出前选择好需要导出的物体。
|
||||
* All Objects:导出该文档中的所有物体。该选项慎用,因为它是粗暴地遍历文档中的物体列表来进行导出,很可能会导出许多你不需要的物体。
|
||||
|
||||
### Virtools参数
|
||||
|
||||
@ -61,6 +66,6 @@ Successive Sector(小节连续)是一个解决导出小节组时出现的Bug
|
||||
|
||||
通常而言,在你正确按照之前介绍的步骤安装和配置插件后,你理论上就可以使用Virtools文档的导入导出功能了。但难免有意外发生。这里说的无法导入导出指的是导入和导出Virtools文档的按钮是灰色的,不可点击的。你需要按照下述步骤检查。如果你所指的是在导入导出过程中出错了,请参考本页页首的警告信息。
|
||||
|
||||
首先检查你是否已经在[配置插件](configure-plugin.md)章节正确配置了插件的`External Texture Folder`设置项。如果你没有配置,则自然无法导入导出Virtools文件。因为导入导出Virtools文件需要依赖Ballance原版关卡数据。请按教程认真配置这一设置项。
|
||||
首先检查你是否已经在[配置插件](configure-plugin.md)章节正确配置了插件的`External Texture Folder`设置项。如果你没有配置,则自然无法导入导出Virtools文件。因为导入导出Virtools文件需要依赖Ballance原版贴图数据。请按教程认真配置这一设置项。
|
||||
|
||||
如果你确定你已经设置了正确的贴图路径,你可以尝试点击菜单`Window - Toggle System Console`来打开控制台。在控制台中,可能会有一些相关的错误信息输出在其中,例如加载底层BMap库时失败等。加载底层BMap库失败通常只发生在一些罕见架构的机器上,例如使用Snapdragon处理器的Windows系统等,因为我们打包的插件中,并未包含支持这些平台的Virtools文件底层读取库BMap。在面对这种情况时,你有两个选择,一是汇报给开发者,等待开发者主动支持,二是自行编译该库(仅建议有丰富计算机知识的人这样做)。
|
||||
|
@ -14,9 +14,11 @@
|
||||
|
||||
在面板中,`Align Axis`指定了你要对齐的轴,此处可以多选以指定多个轴,不指定任何轴将无法进行对齐操作,因而也无法点击`Apply`按钮。
|
||||
|
||||
`Current Object`是对齐参考物体,也就是场景中的活动物体,通常也就是你选择的最后一个物体。在这个选项里指定你需要参考其什么数值进行对齐,分别有`Min`(轴上最小值)、`Center (Bounding Box)`(碰撞箱的中心)、`Center (Axis)`(物体的原点)、`Max`(轴上的最大值)可选。这些选项与3ds Max中的对齐选项是一致的。
|
||||
`Current Object`指示选择哪个实例作为对齐参考。你可以选择场景中的活动物体,通常也就是你选择的最后一个物体。或者是3D游标。需要注意的是,如果你选择活动物体模式,那么活动物体将排除在对齐操作之外,不会被移动,因为参考物体是不可动的。而如果你选择3D游标,则活动物体会被纳入对齐操作的范围之中。
|
||||
|
||||
`Target Objects`是正在被对齐的物体,可能有很多个,在这个选项里也是指定你需要参考其什么数值进行对齐。选项与`Current Object`含义一致。
|
||||
`Current Object Align Mode`是对齐参考物体的对齐模式,它只有在你选择活动物体作为对齐参考物体时才会出现。因为3D游标是一个单纯的点,而物体占有一定体积,我们需要按照某种模式(后文叙述)在空间中选择一个点作为后续对齐操作时使用的点。在这个选项里指定你需要参考其什么数值进行对齐,分别有`Min`(轴上最小值)、`Center (Bounding Box)`(碰撞箱的中心)、`Center (Axis)`(物体的原点)、`Max`(轴上的最大值)可选。这些选项与3ds Max中的对齐选项是一致的。
|
||||
|
||||
`Target Objects Align Mode`是正在被对齐的物体,可能有很多个,在这个选项里也是指定你需要参考其什么数值进行对齐。选项与`Current Object Align Mode`含义一致。
|
||||
|
||||
`Apply`按钮点击后将把当前页面的配置压入操作栈,并重置上面的设置,使得你可以开始新一轮对齐操作而无需再次执行传统对齐。操作栈中的操作个数在`Apply`按钮下方显示。
|
||||
|
||||
|
@ -1,9 +1,13 @@
|
||||
# 技术信息
|
||||
|
||||
## 标准与协议文档
|
||||
|
||||
* BM文件标准:https://github.com/yyc12345/gist/blob/master/BMFileSpec/BMSpec_ZH.md
|
||||
* 制图工具链标准及`meshes`文件夹下的文件的格式:https://github.com/yyc12345/gist/blob/master/BMFileSpec/YYCToolsChainSpec_ZH.md
|
||||
* BMERevenge的JSON文件的格式:https://github.com/yyc12345/gist/blob/master/BMERevenge/DevDocument_v2.0_ZH.md
|
||||
|
||||
## 开发辅助包
|
||||
|
||||
本插件配合了`fake-bpy-module`模块来实现类型提示以加快开发速度。使用如下命令来安装Blender的类型提示库。
|
||||
|
||||
* Blender 3.6: `pip install fake-bpy-module-latest==20230627`
|
||||
@ -11,3 +15,16 @@
|
||||
* Blender 4.5: `pip install fake-bpy-module-latest==20250604`
|
||||
|
||||
这么做主要是因为`fake-bpy-module`没有很及时地发布适用于指定Blender版本的包,因此我只能通过选择最接近Blender对应版本离开`main`主线时间的每日编译版本来安装它(因为每日编译版本只编译`main`主线)。
|
||||
|
||||
!!! question "为什么不采用Blender官方的bpy模块?"
|
||||
Blender在PyPI上提供了官方的名为`bpy`的包,但我们不会采用它作为我们的开发辅助包。因为它基本上就是将Blender打包成了一个模块(也就意味着你基本上又把Blender重新下载了一遍),使得你可以通过Python来操纵Blender。这与我们使用一个仅提供类型提示的包来辅助插件开发的目的相悖。
|
||||
|
||||
## 版本号规则
|
||||
|
||||
BBP的版本号格式遵循[语义化版本](https://semver.org/lang/zh-CN/)。但略有区别:
|
||||
|
||||
* 主版本号只在重构整个插件时提升。
|
||||
* 次版本号是常规更新使用。
|
||||
* 修订号则是在不修改任何功能的情况下递增的版本号。例如4.2.1版本仅增加了对macOS Blender的更新,不更改任何功能。
|
||||
|
||||
在BBP发布一个正式版前,通常有3个阶段性版本,分别是:Alpha版本,Beta版本和RC版本。Alpha版本专注于功能性更新,用于检验新添加或修改的功能是否正常工作,不包含文档和翻译。Beta版本则专注于插件文档,而RC版本则关注于插件翻译。但这三个版本并非总是存在,如果更新内容较少,则可能会跳过其中一些版本,或直接进行发布。
|
||||
|
@ -7,3 +7,31 @@
|
||||
窥视归组并转换为网格,其全称为:窥视并复制曲线倒角物体的Virtools归组信息后再转换为网格。你可以选中一些物体后右键,在物体上下文菜单中找到这一功能。
|
||||
|
||||
该功能正如其名,其将选中的物体转换为网格,如果选中的物体是曲线,且设置了倒角物体,则将倒角物体的归组信息赋予当前曲线(覆盖曲线当前归组设置)。如果选中的物体不是曲线,或者是曲线但没有倒角物体,那么该功能与执行转换为网格无异。该功能在放样建模时极为有用,因为只需要为截面物体进行正确的归组,然后再使用此功能将曲线转换为网格,就可以确保放样后的物体归组正确。
|
||||
|
||||
## 游戏内摄像机
|
||||
|
||||
许多制图者在制作地图时,往往对地图大小没有概念,很容易创建出过大或过小的地图。菜单项`Ballance - Game Camera`的游戏内摄像机功能则提供了一种在Blender内以游戏内摄像机视角预览地图的功能,方便制图者可以把握地图的大小。
|
||||
|
||||
为了使用该功能,你的场景中必须首先有一个摄像机,且被设置为场景的活动摄像机(无摄像机时,通过添加菜单新添加的摄像机会被自动设置)。然后你还需要一个活动物体,且该活动物体不能是这个摄像机。
|
||||
|
||||
!!! question "为什么一定需要活动物体?"
|
||||
由于Blender插件的限制,活动物体是必须的,因为游戏内摄像机功能支持以3D游标 **或活动物体** 为目标。
|
||||
|
||||
通常只有在一个空白的Blender文档中,才会出现无活动物体可用的情况,进而导致该功能不可用。对于一张自制地图,最不缺少的就是可成为活动物体的物体,只需要随便点击一个物体就可以得到(当想使用3D游标作为目标时)。
|
||||
|
||||
点击该功能后,视图将自动转为活动摄像机的视角,方便你进行预览。你可以在左下角的面板中调整相关设置。
|
||||
|
||||

|
||||
|
||||
首先是选择目标,实际上就是选择玩家球位于哪里。如果选择3D游标,则将3D游标视为玩家球。如果选择活动物体,则将玩家球放置在活动物体的原点。
|
||||
|
||||
!!! info "玩家球的位置并非那么简单"
|
||||
无论是选择3D游标,还是选择活动物体,如果不做特别精细的调整,其预览的结果和游戏中会有细微出入。
|
||||
|
||||
当你使用3D游标模式并将其简单地吸附到地面上时,它并非代表球的位置。因为玩家球是一个半径为2的球,实际上你需要向+Z方向移动2个单位长度才能够得到和游戏中一模一样的视角。但这个操作过于繁琐,不执行这个操作,预览的效果也不会偏差太多。
|
||||
|
||||
当你使用活动物体模式时,需要注意物体的原点是选择物体时显示的那个圆点的位置。对于大多数物体,这可能并非你想要的,因为他们可能位于物体内部或外部,并非总位于物体表面,或者某个面的中心。针对这种情况,我建议你改用3D游标作为目标,并通过进入编辑模式,灵活运用吸附和`Shift + S`菜单,来将游标放置在正确的位置。
|
||||
|
||||
然后是选择摄像机的旋转角度。我们提供了8种游戏内预设角度,分别对应90度和45度的各4种。此外如果这些预设角度不能满足你的需求,你还可以设置自定义角度。
|
||||
|
||||
最后是选择摄像机视角,分为Ordinary(常规视角),Lift(按住空格键的视角)和Easter Egg(彩蛋视角)三种。
|
||||
|
1709
i18n/blender.pot
1709
i18n/blender.pot
File diff suppressed because it is too large
Load Diff
1775
i18n/zh_HANS.po
1775
i18n/zh_HANS.po
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user