Skip to content
This repository has been archived by the owner on Sep 19, 2023. It is now read-only.

v1.1.0 Release #24

Merged
merged 5 commits into from
Sep 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dlasset/config/model/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# List supported types only
UnityType = Literal[
"MonoBehaviour",
"MonoScript",
"GameObject",
"AnimatorController",
"AnimatorOverrideController",
Expand Down
5 changes: 2 additions & 3 deletions dlasset/env/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import TYPE_CHECKING

from dlasset.enums import Locale
from dlasset.utils import export_json

if TYPE_CHECKING:
from dlasset.manifest import ManifestEntryBase
Expand Down Expand Up @@ -73,6 +74,4 @@ def update_index_files(self) -> None:
for locale, data in self._data.items():
file_path = self.get_index_file_path(locale)

with open(file_path, "w+", encoding="utf-8") as f:
# `separators` argument for minify
json.dump(data, f, separators=(",", ":"))
export_json(file_path, data, separators=(",", ":"))
2 changes: 1 addition & 1 deletion dlasset/export/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Implementations for exporting Unity assets."""
from .main import export_asset
from .model import ExportInfo
from .model import ExportInfo, ObjectInfo
from .raw import export_raw_by_task
from .task import export_by_task
from .types import * # noqa
1 change: 1 addition & 0 deletions dlasset/export/functions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Functions to export the asset objects."""
from .game_object import export_game_object
from .image import export_image
from .image_alpha import export_image_alpha
from .image_story import export_image_story
Expand Down
67 changes: 67 additions & 0 deletions dlasset/export/functions/game_object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""Implementations to export ``GameObject`` and its component into a single script."""
import os
from typing import TYPE_CHECKING

from dlasset.export.types import MonoBehaviourTree
from dlasset.log import log
from dlasset.utils import export_json

if TYPE_CHECKING:
from dlasset.export import ExportInfo, ObjectInfo

__all__ = ("export_game_object",)


def export_single_game_obj(export_info: "ExportInfo", game_obj_info: "ObjectInfo") -> None:
"""Export a single game object."""
tree_export: MonoBehaviourTree = {}

object_tree = game_obj_info.obj.read_typetree()

components = [
export_info.get_obj_info(component["component"]["m_PathID"]).obj
for component in object_tree["m_Component"][1:] # 1st component is always a `Transform` which is omitted
]

tree_name = object_tree["m_Name"]
tree_components = []
for component in components:
component_tree = component.read_typetree()

script_path_id = component_tree["m_Script"]["m_PathID"]
if script_path_id:
# Attach script type name if available
attachment = {
"$Script": export_info.get_obj_info(component_tree["m_Script"]["m_PathID"]).obj.name
}
else:
# Otherwise, attach component name
attachment = {"$Name": component_tree["m_Name"]}

tree_components.append(attachment | component_tree)

tree_export["Name"] = tree_name
tree_export["Components"] = tree_components

export_path: str = os.path.join(export_info.get_export_dir_of_obj(game_obj_info), f"{tree_name}.prefab.json")

export_json(export_path, tree_export)


def export_game_object(export_info: "ExportInfo") -> None:
"""Export components in ``export_info`` info a single script for each game object."""
game_obj_info_list = [obj_info for obj_info in export_info.objects if obj_info.obj.type == "GameObject"]

if not game_obj_info_list:
log("WARNING", f"No exportable `GameObject` from {export_info}")
return

for idx, game_obj_info in enumerate(game_obj_info_list):
export_single_game_obj(export_info, game_obj_info)

if idx % 50 == 0:
log(
"INFO",
f"{idx} / {len(game_obj_info_list)} ({idx / len(game_obj_info_list):.2%}) objects exported "
f"- {export_info}"
)
6 changes: 3 additions & 3 deletions dlasset/export/functions/monobehaviour.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
"""Implementations to export ``MonoBehaviour``."""
import json
import os
from typing import TYPE_CHECKING

from dlasset.export.types import MonoBehaviourTree
from dlasset.log import log
from dlasset.utils import export_json

if TYPE_CHECKING:
from dlasset.export import ExportInfo
Expand Down Expand Up @@ -32,8 +32,8 @@ def export_mono_behaviour(export_info: "ExportInfo") -> list[MonoBehaviourTree]:
continue

tree = obj.read_typetree()
with open(export_path, "w+", encoding="utf-8") as f:
f.write(json.dumps(tree, ensure_ascii=False, indent=2))

export_json(export_path, tree)

trees.append(tree)

Expand Down
6 changes: 3 additions & 3 deletions dlasset/export/lookup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Exporting function index."""
from dlasset.config import ExportType, UnityType
from .functions import export_image, export_image_alpha, export_image_story, export_mono_behaviour
from .functions import export_game_object, export_image, export_image_alpha, export_image_story, export_mono_behaviour
from .types import ExportFunction

__all__ = ("EXPORT_FUNCTIONS", "TYPES_TO_INCLUDE")
Expand All @@ -11,7 +11,7 @@
"Texture2D-Alpha": export_image_alpha,
"Texture2D-Story": export_image_story,
"Sprite": export_image,
"GameObject": export_mono_behaviour,
"GameObject": export_game_object,
"AnimatorController": export_mono_behaviour,
"AnimatorOverrideController": export_mono_behaviour,
}
Expand All @@ -22,7 +22,7 @@
"Texture2D-Alpha": ("Texture2D", "Material"),
"Texture2D-Story": ("Texture2D", "Material", "MonoBehaviour"),
"Sprite": ("Sprite",),
"GameObject": ("GameObject",),
"GameObject": ("GameObject", "MonoBehaviour", "MonoScript"),
"AnimatorController": ("AnimatorController",),
"AnimatorOverrideController": ("AnimatorOverrideController",),
}
12 changes: 11 additions & 1 deletion dlasset/export/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,16 @@ def export_objects(
"""
obj_info_to_export: list[ObjectInfo] = []

for obj_info in obj_export:
for idx, obj_info in enumerate(obj_export):
obj = obj_info.read_obj()

if idx > 0 and idx % 500 == 0:
log(
"INFO",
f"Reading {idx} / {len(obj_export)} ({idx / len(obj_export):.2%}) object "
f"of {asset_name} ({container_fallback})..."
)

if (
obj_info.is_from_main
and filters
Expand All @@ -105,6 +112,9 @@ def export_objects(

obj_info_to_export.append(obj_info)

if len(obj_export) > 1000:
log("INFO", f"Read {len(obj_export)} objects and picked {len(obj_info_to_export)} objects to export.")

export_info = ExportInfo(
export_dir=export_dir,
obj_info_list=obj_info_to_export,
Expand Down
11 changes: 2 additions & 9 deletions dlasset/export/types.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
"""Type definitions for exporting the assets."""
from typing import Any, Callable, Union
from typing import Any, Callable, Optional, Union

from .model import ExportInfo

__all__ = ("ExportFunction", "ExportReturn", "MonoBehaviourTree")

MonoBehaviourTree = dict[Any, Any]

MonoBehaviourExportFunction = Callable[[ExportInfo], list[MonoBehaviourTree]]

Texture2DExportFunction = Callable[[ExportInfo], None]

ExportFunction = Union[
MonoBehaviourExportFunction,
Texture2DExportFunction
]
ExportFunction = Callable[[ExportInfo], Optional[list[MonoBehaviourTree]]]

ExportReturn = Union[
MonoBehaviourTree
Expand Down
1 change: 1 addition & 0 deletions dlasset/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Various utility functions."""
from .execution import concurrent_run, concurrent_run_no_return, time_exec
from .export import export_json
from .image import crop_image, merge_y_cb_cr_a
52 changes: 52 additions & 0 deletions dlasset/utils/export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Utility function for exporting."""
import json
from typing import Any, Optional

__all__ = ("export_json",)


def round_floats(obj: Any) -> Any:
"""Round the ``float`` in ``obj``."""
if isinstance(obj, float):
return float(format(obj, ".9g"))

if isinstance(obj, dict):
return {k: round_floats(v) for k, v in obj.items()}

if isinstance(obj, (list, tuple)):
return [round_floats(x) for x in obj]

return obj


def export_json(export_path: str, obj: Any, /, separators: Optional[tuple[str, str]] = None) -> None:
"""
Export the object ``obj`` to ``export_path``.
It was tested that the solutions below are slower:
>>> with open(export_path, "w+", encoding="utf-8") as f:
>>> f.write(json.dumps(
>>> json.loads(
>>> json.dumps(obj),
>>> parse_float=lambda x: f"{float(x):.9g}"
>>> )
>>> ))
The solution above was about on par.
>>> with open(export_path, "w+", encoding="utf-8") as f:
>>> json.dump(round_floats(obj), f)
The solution above is about 3x slower.
>>> with open(export_path, "w+", encoding="utf-8") as f:
>>> json.dump(
>>> json.loads(json.dumps(obj), parse_float=lambda x: f"{float(x):.9g}"),
>>> f,
>>> )
The solution above is about 3x slower.
"""
with open(export_path, "w+", encoding="utf-8") as f:
f.write(json.dumps(round_floats(obj), ensure_ascii=False, indent=2, separators=separators))