unityflow 0.9.1__tar.gz → 0.9.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {unityflow-0.9.1/src/unityflow.egg-info → unityflow-0.9.2}/PKG-INFO +1 -1
- {unityflow-0.9.1 → unityflow-0.9.2}/pyproject.toml +1 -1
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/asset_resolver.py +75 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/cli.py +28 -43
- {unityflow-0.9.1 → unityflow-0.9.2/src/unityflow.egg-info}/PKG-INFO +1 -1
- {unityflow-0.9.1 → unityflow-0.9.2}/LICENSE +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/README.md +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/setup.cfg +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/__init__.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/animation/__init__.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/animation/cli.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/animation/models.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/animation/mutate.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/animation/parser.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/animation/query.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/animation/writer.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/animator/__init__.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/animator/cli.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/animator/models.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/animator/parser.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/animator/query.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/animator/writer.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/asset_tracker.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/bridge/__init__.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/bridge/config.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/bridge/server.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/bridge/unity_client.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/builtin_schema.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/data/__init__.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/data/builtin_schemas.json +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/data/class_ids.json +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/dll_inspector.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/fast_parser.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/fbx_loader.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/formats.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/git_utils.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/hierarchy.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/merge.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/meta_generator.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/normalizer.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/parser.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/query.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/script_parser.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/semantic_diff.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/semantic_merge.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/sprite.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow/validator.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow.egg-info/SOURCES.txt +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow.egg-info/dependency_links.txt +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow.egg-info/entry_points.txt +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow.egg-info/requires.txt +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/src/unityflow.egg-info/top_level.txt +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_asset_resolver.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_asset_tracker.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_bridge.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_cli.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_dll_inspector.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_fbx_loader.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_formats.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_hierarchy.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_incremental.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_llm_helpers.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_merge.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_meta_generator.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_normalizer.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_parser.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_query.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_script_parser.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_semantic_diff.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_semantic_merge.py +0 -0
- {unityflow-0.9.1 → unityflow-0.9.2}/tests/test_validator.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "unityflow"
|
|
7
|
-
version = "0.9.
|
|
7
|
+
version = "0.9.2"
|
|
8
8
|
description = "Unity workflow automation - edit, diff, and merge prefabs, scenes, and assets without the Unity Editor"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -758,3 +758,78 @@ def get_asset_info(
|
|
|
758
758
|
pass
|
|
759
759
|
|
|
760
760
|
return info
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
def _is_reference_dict(value: Any) -> bool:
|
|
764
|
+
return isinstance(value, dict) and "fileID" in value
|
|
765
|
+
|
|
766
|
+
|
|
767
|
+
def _build_sprite_id_to_name(meta_path: Path) -> dict[int, str]:
|
|
768
|
+
from unityflow.sprite import parse_sprite_meta
|
|
769
|
+
|
|
770
|
+
info = parse_sprite_meta(meta_path)
|
|
771
|
+
if info is None or not info.is_multiple:
|
|
772
|
+
return {}
|
|
773
|
+
return {v: k for k, v in info.internal_id_table.items()}
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
def _humanize_single_reference(
|
|
777
|
+
ref: dict[str, Any],
|
|
778
|
+
guid_index: Any,
|
|
779
|
+
hierarchy: Any | None,
|
|
780
|
+
project_root: Path | None,
|
|
781
|
+
) -> Any:
|
|
782
|
+
file_id = ref.get("fileID", 0)
|
|
783
|
+
guid = ref.get("guid", "")
|
|
784
|
+
|
|
785
|
+
if file_id == 0 and not guid:
|
|
786
|
+
return ""
|
|
787
|
+
|
|
788
|
+
if guid:
|
|
789
|
+
asset_path = guid_index.get_path(guid) if guid_index else None
|
|
790
|
+
if asset_path is None:
|
|
791
|
+
return ref
|
|
792
|
+
|
|
793
|
+
suffix = asset_path.suffix.lower()
|
|
794
|
+
is_sprite_ext = suffix in (".png", ".jpg", ".jpeg", ".tga", ".psd", ".tiff", ".gif", ".bmp")
|
|
795
|
+
if is_sprite_ext and file_id != 21300000 and project_root:
|
|
796
|
+
meta_path = project_root / str(asset_path) / ".." / (asset_path.name + ".meta")
|
|
797
|
+
meta_path = (project_root / str(asset_path)).with_suffix(asset_path.suffix + ".meta")
|
|
798
|
+
id_to_name = _build_sprite_id_to_name(meta_path)
|
|
799
|
+
sprite_name = id_to_name.get(file_id)
|
|
800
|
+
if sprite_name:
|
|
801
|
+
return f"@{asset_path}:{sprite_name}"
|
|
802
|
+
|
|
803
|
+
return f"@{asset_path}"
|
|
804
|
+
|
|
805
|
+
if file_id and hierarchy:
|
|
806
|
+
ref_node = hierarchy._nodes_by_file_id.get(file_id)
|
|
807
|
+
if ref_node:
|
|
808
|
+
return f"#{ref_node.path}"
|
|
809
|
+
|
|
810
|
+
for n in hierarchy.iter_all():
|
|
811
|
+
for c in n.components:
|
|
812
|
+
if c.file_id == file_id:
|
|
813
|
+
return f"#{n.path}/{c.script_name or c.class_name}"
|
|
814
|
+
|
|
815
|
+
return ref
|
|
816
|
+
|
|
817
|
+
return ref
|
|
818
|
+
|
|
819
|
+
|
|
820
|
+
def humanize_references(
|
|
821
|
+
value: Any,
|
|
822
|
+
guid_index: Any,
|
|
823
|
+
hierarchy: Any | None = None,
|
|
824
|
+
project_root: Path | None = None,
|
|
825
|
+
) -> Any:
|
|
826
|
+
if _is_reference_dict(value):
|
|
827
|
+
return _humanize_single_reference(value, guid_index, hierarchy, project_root)
|
|
828
|
+
|
|
829
|
+
if isinstance(value, dict):
|
|
830
|
+
return {k: humanize_references(v, guid_index, hierarchy, project_root) for k, v in value.items()}
|
|
831
|
+
|
|
832
|
+
if isinstance(value, list):
|
|
833
|
+
return [humanize_references(item, guid_index, hierarchy, project_root) for item in value]
|
|
834
|
+
|
|
835
|
+
return value
|
|
@@ -2840,6 +2840,7 @@ def inspect_cmd(
|
|
|
2840
2840
|
import json as json_module
|
|
2841
2841
|
|
|
2842
2842
|
from unityflow import UnityYAMLDocument, build_hierarchy
|
|
2843
|
+
from unityflow.asset_resolver import humanize_references
|
|
2843
2844
|
from unityflow.asset_tracker import find_unity_project_root, get_lazy_guid_index
|
|
2844
2845
|
|
|
2845
2846
|
# Load document
|
|
@@ -2934,38 +2935,36 @@ def inspect_cmd(
|
|
|
2934
2935
|
script_path = guid_index.resolve_path(comp.script_guid)
|
|
2935
2936
|
if script_path:
|
|
2936
2937
|
comp_data["script_path"] = str(script_path)
|
|
2937
|
-
|
|
2938
|
+
filtered = {
|
|
2939
|
+
k: v
|
|
2940
|
+
for k, v in comp.data.items()
|
|
2941
|
+
if k
|
|
2942
|
+
not in {
|
|
2943
|
+
"m_ObjectHideFlags",
|
|
2944
|
+
"m_CorrespondingSourceObject",
|
|
2945
|
+
"m_PrefabInstance",
|
|
2946
|
+
"m_PrefabAsset",
|
|
2947
|
+
"m_GameObject",
|
|
2948
|
+
"m_Script",
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
comp_data["properties"] = humanize_references(filtered, guid_index, hier, resolved_project_root)
|
|
2938
2952
|
result["components"].append(comp_data)
|
|
2939
2953
|
|
|
2940
2954
|
click.echo(json_module.dumps(result, indent=2, default=str))
|
|
2941
2955
|
else:
|
|
2942
|
-
|
|
2943
|
-
def
|
|
2944
|
-
|
|
2945
|
-
if
|
|
2946
|
-
return "None"
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
# Try to find component by file_id
|
|
2955
|
-
for n in hier.iter_all():
|
|
2956
|
-
for c in n.components:
|
|
2957
|
-
if c.file_id == file_id:
|
|
2958
|
-
return f"{n.path}/{c.script_name or c.class_name}"
|
|
2959
|
-
|
|
2960
|
-
return f"(internal ref #{file_id})"
|
|
2961
|
-
|
|
2962
|
-
# External reference (different asset)
|
|
2963
|
-
if guid and guid_index:
|
|
2964
|
-
asset_path = guid_index.get_path(guid)
|
|
2965
|
-
if asset_path:
|
|
2966
|
-
return f"@{asset_path}"
|
|
2967
|
-
|
|
2968
|
-
return "(external ref)"
|
|
2956
|
+
|
|
2957
|
+
def format_value(value):
|
|
2958
|
+
resolved = humanize_references(value, guid_index, hier, resolved_project_root)
|
|
2959
|
+
if isinstance(resolved, str):
|
|
2960
|
+
return resolved if resolved else "None"
|
|
2961
|
+
if isinstance(resolved, dict):
|
|
2962
|
+
if "fileID" in resolved:
|
|
2963
|
+
return f"(unresolved ref fileID={resolved['fileID']})"
|
|
2964
|
+
return "{...}"
|
|
2965
|
+
if isinstance(resolved, list):
|
|
2966
|
+
return f"[{len(resolved)} items]"
|
|
2967
|
+
return str(resolved)
|
|
2969
2968
|
|
|
2970
2969
|
# Text output - Inspector-like format
|
|
2971
2970
|
click.echo(f"GameObject: {node.name}")
|
|
@@ -3062,21 +3061,7 @@ def inspect_cmd(
|
|
|
3062
3061
|
}
|
|
3063
3062
|
for key, value in comp.data.items():
|
|
3064
3063
|
if key not in skip_keys:
|
|
3065
|
-
|
|
3066
|
-
if isinstance(value, dict) and "fileID" in value:
|
|
3067
|
-
# Reference field - resolve to path
|
|
3068
|
-
file_id = value.get("fileID", 0)
|
|
3069
|
-
guid = value.get("guid", "")
|
|
3070
|
-
resolved = resolve_reference(file_id, guid)
|
|
3071
|
-
click.echo(f" {key}: {resolved}")
|
|
3072
|
-
elif isinstance(value, dict | list):
|
|
3073
|
-
# Complex value - show abbreviated
|
|
3074
|
-
if isinstance(value, list):
|
|
3075
|
-
click.echo(f" {key}: [{len(value)} items]")
|
|
3076
|
-
else:
|
|
3077
|
-
click.echo(f" {key}: {{...}}")
|
|
3078
|
-
else:
|
|
3079
|
-
click.echo(f" {key}: {value}")
|
|
3064
|
+
click.echo(f" {key}: {format_value(value)}")
|
|
3080
3065
|
|
|
3081
3066
|
click.echo()
|
|
3082
3067
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|