Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Implementing CommonMCOBJ Support #555

Merged
merged 50 commits into from
Jul 7, 2024
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
487bfcb
Added msg field to MCprepError
StandingPadAnimations Feb 29, 2024
936cb84
refactor: have convert_mtl use MCprepError
StandingPadAnimations Feb 29, 2024
f29d308
refactor: General refactoring of world.py
StandingPadAnimations Mar 1, 2024
d57a48e
refactor: util.py refactoring for new error type
StandingPadAnimations Mar 1, 2024
49e5bbb
Removed default_materials.py
StandingPadAnimations Mar 1, 2024
4a8cc63
refactor: Refactored find_from_texture_pack
StandingPadAnimations Mar 8, 2024
fddbe9c
feat: Implemented CommonMCOBJ handling for imports
StandingPadAnimations Mar 24, 2024
61eff57
refactor: updated UI to use new exporter handling
StandingPadAnimations Mar 24, 2024
8e98cfb
Fixed typo in export_bounds_* keys
StandingPadAnimations Mar 24, 2024
373ae95
Fixed typo in export_bounds_* keys
StandingPadAnimations Mar 24, 2024
a419189
Added guard statement in get_exporter
StandingPadAnimations Mar 24, 2024
0454218
refactor: Migrated remaining pure string checks
StandingPadAnimations Mar 24, 2024
d5760d1
Updated is_atlas_export
StandingPadAnimations Mar 24, 2024
12123ef
Fixed incorrect keyword args in parser
StandingPadAnimations Mar 24, 2024
ab2e163
fix: Reduced memory usage of header parser
StandingPadAnimations Mar 26, 2024
2da614e
Added BSD license to commonmcobj_parser.py
StandingPadAnimations Mar 30, 2024
8d4efc0
Added email to copyright in commonmcobj_parser.py
StandingPadAnimations Mar 30, 2024
5d8ff42
Added licensing information for other components
StandingPadAnimations Mar 30, 2024
c7b82e2
Cleaned up LICENSE-3RD-PARTY.txt a little
StandingPadAnimations Mar 30, 2024
383f71e
Removed extra .txt in README
StandingPadAnimations Mar 30, 2024
e3b75a7
reft: updated uses of find_from_texturepack
StandingPadAnimations Apr 7, 2024
0b25c43
doc: updated docstring for detect_form
StandingPadAnimations Apr 7, 2024
5ba5556
feat: added basic forward compat for headers
StandingPadAnimations Apr 15, 2024
4b920a4
Merge branch 'common-mc-obj-v1' into refactoring-3-6-0
StandingPadAnimations May 1, 2024
76a6d4d
chore: Merge refactoring-3-6-0
StandingPadAnimations May 1, 2024
74a5367
build: Added Blender 4.1 and 4.2 to build config
StandingPadAnimations May 3, 2024
62ceb23
cmcobj: Header info is now stored inside an empty
StandingPadAnimations May 9, 2024
6b9257f
tracking: Re-enabled exporter tracking
StandingPadAnimations May 9, 2024
d4c711c
Merge branch 'dev' into common-mc-obj-v1
StandingPadAnimations May 10, 2024
07a5b92
style: Moved update_matrices to util.py
StandingPadAnimations May 10, 2024
841db9e
feat(CommonMCOBJ): Hide OBJ empty in viewport
StandingPadAnimations May 10, 2024
a4328a2
fix: Fixed missing variables for exporter tracking
StandingPadAnimations May 13, 2024
cb347b2
Merge remote-tracking branch 'origin/dev' into common-mc-obj-v1
StandingPadAnimations Jun 9, 2024
ddb92f7
fix: Parent empty to all OBJs
StandingPadAnimations Jun 9, 2024
b5ea9e8
Updated several partial migrations to use pathlib, fixes some tests
TheDuckCow Jun 9, 2024
0d65ffd
Moving the added empty to the same collection as the rest of the world
TheDuckCow Jun 9, 2024
0afc1c9
Added new test world save and exports from jmc2obj and mineways
TheDuckCow Jun 25, 2024
23d4fa4
Fix obj file header parsing from being cleared and some pep8 cleanup
TheDuckCow Jun 25, 2024
1fec0da
refactor: Remove bv28
StandingPadAnimations Jun 25, 2024
f678b9f
style: set MCprepEnv.material_sync_cache to typing.List
StandingPadAnimations Jun 25, 2024
ef36932
Merge branch 'dev' into common-mc-obj-v1
StandingPadAnimations Jun 28, 2024
c2269b0
fix: Add filepath to "File not found" error
StandingPadAnimations Jun 28, 2024
4e664ee
test: Fix test_convert_mtl_simple with convert_mtl return types
StandingPadAnimations Jun 29, 2024
2b4418f
fix: Don't disable textureswap with WorldExporter.Unknown
StandingPadAnimations Jun 29, 2024
1b38d08
style: Return bool for convert_mtl instead of None
StandingPadAnimations Jul 2, 2024
f141844
fix: Add Khronos PBR Neutral and AgX to natively supported spaces
StandingPadAnimations Jul 2, 2024
6f2c226
Resolve 2x tests with more consistent use of world WorldExporter
TheDuckCow Jul 6, 2024
3a30cfe
revert: Add nuance back to get_exporter return value
StandingPadAnimations Jul 6, 2024
acec9ea
Fixing the mapping test code to use the generalize functions.
TheDuckCow Jul 7, 2024
a0a2f29
rc-files: Update patches for MCprep 3.6 RC-3
StandingPadAnimations Jul 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.mtl filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
32 changes: 32 additions & 0 deletions LICENSE-3RD-PARTY.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
-----------------------------------------------------------------------------
The BSD 3-Clause License

Applies to:
commonmcobj_parser.py Copyright (c) 2024, Mahid Sheikh

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-----------------------------------------------------------------------------
252 changes: 252 additions & 0 deletions MCprep_addon/commonmcobj_parser.py
Copy link
Member

Choose a reason for hiding this comment

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

A note to self that we should create unit tests for this, I can take that in a follow up since I know you're having trouble running this currently. I'm planning to have both a mineways and jmc2obj sample for this.

Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
# BSD 3-Clause License
#
# Copyright (c) 2024, Mahid Sheikh <[email protected]>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# The parser is under a more permissive BSD 3-Clause license to make it easier
# for developers to use in non-GPL code. Normally, I wouldn't do dual licensing,
# but in this case, it makes sense as it would allow developers to reuse this
# parser for their own uses under more permissive terms. This doesn't change anything
# related to MCprep, which is GPL, as BSD 3-Clause is compatible with GPL. The
# only part that might conflict is Clause 3, but it could be argued that one
# can't do that under GPL anyway, or any license for that matter, and that
# Clause 3 is just a reminder to developers.
#
# - Mahid Sheikh

from dataclasses import dataclass
from enum import Enum
from typing import List, Optional, Tuple, TextIO

MAX_SUPPORTED_VERSION = 1

class CommonMCOBJTextureType(Enum):
ATLAS = "ATLAS"
INDIVIDUAL_TILES = "INDIVIDUAL_TILES"

@dataclass
class CommonMCOBJ:
StandingPadAnimations marked this conversation as resolved.
Show resolved Hide resolved
"""
Python representation of the CommonMCOBJ header
"""
# Version of the CommonMCOBJ spec
version: int

# Exporter name in all lowercase
exporter: str

# Name of source world
world_name: str

# Path of source world*
world_path: str

# Min values of the selection bounding box
export_bounds_min: Tuple[int, int, int]

# Max values of the selection bounding box
export_bounds_max: Tuple[int, int, int]

# Offset from (0, 0, 0)
export_offset: Tuple[float, float, float]

# Scale of each block in meters; by default, this should be 1 meter
block_scale: float

# Coordinate offset for blocks
block_origin_offset: Tuple[float, float, float]

# Is the Z axis of the OBJ considered up?
z_up: bool

# Are the textures using large texture atlases or
# individual textures?
texture_type: CommonMCOBJTextureType

# Are blocks split by type?
has_split_blocks: bool

# Original header
original_header: Optional[str]

def parse_common_header(header_lines: list[str]) -> CommonMCOBJ:
"""
Parses the CommonMCOBJ header information from a list of strings.

header_lines list[str]:
list of strings representing each line of the header.

returns:
CommonMCOBJ object
"""

# Split at the colon and clean up formatting
def clean_and_extract(line: str) -> Tuple[str, str]:
split = line.split(':', 1)
pos = 0
for i,x in enumerate(split[0]):
if x.isalpha():
pos = i
break
return (split[0][pos:], split[1].strip())

# Basic values
header = CommonMCOBJ(
version=0,
exporter="NULL",
world_name="NULL",
world_path="NULL",
export_bounds_min=(0, 0, 0),
export_bounds_max=(0, 0, 0),
export_offset=(0, 0, 0),
block_scale=0,
block_origin_offset=(0, 0, 0),
z_up=False,
texture_type=CommonMCOBJTextureType.ATLAS,
has_split_blocks=False,
original_header=None
)

# Keys whose values do not need extra processing
NO_VALUE_PARSE = [
"exporter",
"world_name",
"world_path",
]

# Keys whose values are tuples
TUPLE_PARSE_INT = [
"export_bounds_min",
"export_bounds_max",
]

TUPLE_PARSE_FLOAT = [
"export_offset",
"block_origin_offset"
]

# Keys whose values are booleans
BOOLEAN_PARSE = [
"z_up",
"has_split_blocks"
]

# Although CommonMCOBJ states that
# order does matter in the header,
# future versions may change the order
# of some values, so it's best to
# use a non-order specific parser
for line in header_lines:
if ":" not in line:
continue
key, value = clean_and_extract(line)

if key == "version":
try:
header.version = int(value)
if header.version > MAX_SUPPORTED_VERSION:
header.original_header = "\n".join(header_lines)
except Exception:
pass

elif key == "block_scale":
try:
header.block_scale = float(value)
except Exception:
pass

elif key == "texture_type":
try:
header.texture_type = CommonMCOBJTextureType[value]
except Exception:
pass

# All of these are parsed the same, with
# no parsing need to value
#
# No keys here will be classed as failed
elif key in NO_VALUE_PARSE:
setattr(header, key, value)

# All of these are parsed the same, with
# parsing the value to a tuple
elif key in TUPLE_PARSE_INT:
try:
setattr(header, key, tuple(map(int, value[1:-1].split(', '))))
except Exception:
pass

elif key in TUPLE_PARSE_FLOAT:
try:
setattr(header, key, tuple(map(float, value[1:-1].split(', '))))
except Exception:
pass

elif key in BOOLEAN_PARSE:
try:
setattr(header, key, value == "true")
except Exception:
pass

return header


def parse_header(f: TextIO) -> Optional[CommonMCOBJ]:
"""
Parses a file and returns a CommonMCOBJ object if the header exists.

f: TextIO
File object

Returns:
- CommonMCOBJ object if header exists
- None otherwise
"""

header: List[str] = []
found_header = False

# Read in the header
lines_read = 0
for _l in f:
tl = " ".join(_l.rstrip().split())
lines_read += 1
if lines_read > 100 and tl and not tl.startswith("#"):
StandingPadAnimations marked this conversation as resolved.
Show resolved Hide resolved
break # no need to parse further than the true header area
elif tl == "# COMMON_MC_OBJ_START":
header.append(tl)
found_header = True
continue
elif tl == "# COMMON_MC_OBJ_END":
header.append(tl)
break
if not found_header or tl == "#":
continue
header.append(tl)
if not len(header):
return None
return parse_common_header(header)
8 changes: 7 additions & 1 deletion MCprep_addon/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def __init__(self):
# list of material names, each is a string. None by default to indicate
# 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 = []
self.material_sync_cache: List = []

# Whether we use PO files directly or use the converted form
self.use_direct_i18n = False
Expand Down Expand Up @@ -305,10 +305,16 @@ class MCprepError(object):
Path of file the exception object
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
type may not be so clear cut
"""
err_type: BaseException
line: int
file: str
msg: Optional[str] = None

env = MCprepEnv()

Expand Down
Loading
Loading