prthm11 commited on
Commit
727fc85
Β·
verified Β·
1 Parent(s): e6d4ed7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +225 -167
app.py CHANGED
@@ -1869,44 +1869,74 @@ def similarity_matching(sprites_data: dict, project_folder: str, top_k: int = 1,
1869
  matched_indices = sorted({idx for lst in per_sprite_matched_indices for idx in lst})
1870
  print("matched_indices------------------>",matched_indices)
1871
 
 
 
 
 
 
 
1872
  sprite_base_p = Path(sprite_base_path).resolve(strict=False)
1873
  backdrop_base_p = Path(backdrop_base_path).resolve(strict=False)
1874
  project_folder_p = Path(project_folder)
1875
  project_folder_p.mkdir(parents=True, exist_ok=True)
1876
 
 
 
 
1877
  def display_like_windows_no_lead(p: Path) -> str:
1878
- s = p.as_posix()
 
 
 
 
1879
  if s.startswith("/"):
1880
  s = s[1:]
1881
  return s.replace("/", "\\")
1882
 
1883
  def is_subpath(child: Path, parent: Path) -> bool:
 
1884
  try:
 
1885
  child.relative_to(parent)
1886
  return True
1887
  except Exception:
1888
  return False
1889
-
1890
- # Copy assets and build project data (unchanged from your version)
 
 
 
1891
  for matched_idx in matched_indices:
 
1892
  if not (0 <= matched_idx < len(paths_list)):
1893
  print(f" ⚠ matched_idx {matched_idx} out of range, skipping")
1894
  continue
 
1895
  matched_image_path = paths_list[matched_idx]
1896
- matched_path_p = Path(matched_image_path).resolve(strict=False)
1897
- matched_folder_p = matched_path_p.parent
1898
  matched_filename = matched_path_p.name
 
 
1899
  matched_folder_display = display_like_windows_no_lead(matched_folder_p)
 
1900
  print(f"Processing matched image: {matched_image_path}")
1901
  print(f" - Folder: {matched_folder_display}")
1902
-
 
 
 
 
1903
  folder_key = matched_folder_p.as_posix()
1904
-
1905
- # SPRITE
1906
  if is_subpath(matched_folder_p, sprite_base_p) and folder_key not in copied_sprite_folders:
1907
  print(f"Processing SPRITE folder: {matched_folder_display}")
1908
  copied_sprite_folders.add(folder_key)
 
1909
  sprite_json_path = matched_folder_p / "sprite.json"
 
 
1910
  if sprite_json_path.exists() and sprite_json_path.is_file():
1911
  try:
1912
  with sprite_json_path.open("r", encoding="utf-8") as f:
@@ -1917,15 +1947,19 @@ def similarity_matching(sprites_data: dict, project_folder: str, top_k: int = 1,
1917
  print(f" βœ— Failed to read sprite.json in {matched_folder_display}: {repr(e)}")
1918
  else:
1919
  print(f" ⚠ No sprite.json in {matched_folder_display}")
 
 
1920
  try:
1921
  sprite_files = list(matched_folder_p.iterdir())
1922
  except Exception as e:
1923
  sprite_files = []
1924
  print(f" βœ— Failed to list files in {matched_folder_display}: {repr(e)}")
 
1925
  print(f" Files in sprite folder: {[p.name for p in sprite_files]}")
1926
  for p in sprite_files:
1927
  fname = p.name
1928
  if fname in (matched_filename, "sprite.json"):
 
1929
  continue
1930
  if p.is_file():
1931
  dst = project_folder_p / fname
@@ -1934,11 +1968,17 @@ def similarity_matching(sprites_data: dict, project_folder: str, top_k: int = 1,
1934
  print(f" βœ“ Copied sprite asset: {p} -> {dst}")
1935
  except Exception as e:
1936
  print(f" βœ— Failed to copy sprite asset {p}: {repr(e)}")
1937
-
1938
- # BACKDROP
 
 
1939
  if is_subpath(matched_folder_p, backdrop_base_p) and folder_key not in copied_backdrop_folders:
1940
  print(f"Processing BACKDROP folder: {matched_folder_display}")
1941
  copied_backdrop_folders.add(folder_key)
 
 
 
 
1942
  backdrop_src = matched_folder_p / matched_filename
1943
  backdrop_dst = project_folder_p / matched_filename
1944
  if backdrop_src.exists() and backdrop_src.is_file():
@@ -1949,15 +1989,19 @@ def similarity_matching(sprites_data: dict, project_folder: str, top_k: int = 1,
1949
  print(f" βœ— Failed to copy matched backdrop image {backdrop_src}: {repr(e)}")
1950
  else:
1951
  print(f" ⚠ Matched backdrop source not found: {backdrop_src}")
 
 
1952
  try:
1953
  backdrop_files = list(matched_folder_p.iterdir())
1954
  except Exception as e:
1955
  backdrop_files = []
1956
  print(f" βœ— Failed to list files in {matched_folder_display}: {repr(e)}")
 
1957
  print(f" Files in backdrop folder: {[p.name for p in backdrop_files]}")
1958
  for p in backdrop_files:
1959
  fname = p.name
1960
  if fname in (matched_filename, "project.json"):
 
1961
  continue
1962
  if p.is_file():
1963
  dst = project_folder_p / fname
@@ -1966,18 +2010,28 @@ def similarity_matching(sprites_data: dict, project_folder: str, top_k: int = 1,
1966
  print(f" βœ“ Copied backdrop asset: {p} -> {dst}")
1967
  except Exception as e:
1968
  print(f" βœ— Failed to copy backdrop asset {p}: {repr(e)}")
 
 
 
 
1969
  pj = matched_folder_p / "project.json"
1970
  if pj.exists() and pj.is_file():
1971
  try:
1972
  with pj.open("r", encoding="utf-8") as f:
1973
  bd_json = json.load(f)
 
1974
  for tgt in bd_json.get("targets", []):
1975
  if tgt.get("isStage"):
1976
  backdrop_data.append(tgt)
 
 
1977
  except Exception as e:
1978
  print(f" βœ— Failed to read project.json in {matched_folder_display}: {repr(e)}")
1979
-
1980
- # Final project JSON creation (same as your code)
 
 
 
1981
  final_project = {
1982
  "targets": [], "monitors": [], "extensions": [],
1983
  "meta": {
@@ -1986,9 +2040,13 @@ def similarity_matching(sprites_data: dict, project_folder: str, top_k: int = 1,
1986
  "agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
1987
  }
1988
  }
 
 
 
1989
  for spr in project_data:
1990
  if not spr.get("isStage", False):
1991
  final_project["targets"].append(spr)
 
1992
  if backdrop_data:
1993
  all_costumes, sounds = [], []
1994
  seen_costumes = set()
@@ -2491,185 +2549,185 @@ def similarity_matching(sprites_data: dict, project_folder: str, top_k: int = 1,
2491
 
2492
  # # Flatten unique matched indices to process copying once per folder
2493
  # matched_indices = sorted({idx for lst in per_sprite_matched_indices for idx in lst})
2494
- # print("matched_indices------------------>",matched_indices)
2495
 
2496
- # import shutil
2497
- # import json
2498
- # import os
2499
- # from pathlib import Path
2500
 
2501
- # # normalize base paths once before the loop
2502
- # sprite_base_p = Path(sprite_base_path).resolve(strict=False)
2503
- # backdrop_base_p = Path(backdrop_base_path).resolve(strict=False)
2504
- # project_folder_p = Path(project_folder)
2505
- # project_folder_p.mkdir(parents=True, exist_ok=True)
2506
 
2507
- # copied_sprite_folders = set()
2508
- # copied_backdrop_folders = set()
2509
 
2510
- # def display_like_windows_no_lead(p: Path) -> str:
2511
- # """
2512
- # For human-readable logs only β€” convert Path to a string like:
2513
- # "app\\blocks\\Backdrops\\Castle 2.sb3" (no leading slash).
2514
- # """
2515
- # s = p.as_posix() # forward-slash string, safe for Path objects
2516
- # if s.startswith("/"):
2517
- # s = s[1:]
2518
- # return s.replace("/", "\\")
2519
 
2520
- # def is_subpath(child: Path, parent: Path) -> bool:
2521
- # """Robust membership test: is child under parent?"""
2522
- # try:
2523
- # # use non-strict resolve only if needed, but avoid exceptions
2524
- # child.relative_to(parent)
2525
- # return True
2526
- # except Exception:
2527
- # return False
2528
 
2529
- # # Flatten unique matched indices (if not already)
2530
- # matched_indices = sorted({idx for lst in per_sprite_matched_indices for idx in lst})
2531
- # print("matched_indices------------------>", matched_indices)
2532
 
2533
- # for matched_idx in matched_indices:
2534
- # # defensive check
2535
- # if not (0 <= matched_idx < len(paths_list)):
2536
- # print(f" ⚠ matched_idx {matched_idx} out of range, skipping")
2537
- # continue
2538
 
2539
- # matched_image_path = paths_list[matched_idx]
2540
- # matched_path_p = Path(matched_image_path).resolve(strict=False) # keep as Path
2541
- # matched_folder_p = matched_path_p.parent # Path object
2542
- # matched_filename = matched_path_p.name
2543
 
2544
- # # Prepare display-only string (do NOT reassign matched_folder_p)
2545
- # matched_folder_display = display_like_windows_no_lead(matched_folder_p)
2546
 
2547
- # print(f"Processing matched image: {matched_image_path}")
2548
- # print(f" - Folder: {matched_folder_display}")
2549
- # print(f" - Sprite path: {display_like_windows_no_lead(sprite_base_p)}")
2550
- # print(f" - Backdrop path: {display_like_windows_no_lead(backdrop_base_p)}")
2551
- # print(f" - Filename: {matched_filename}")
2552
 
2553
- # # Use a canonical string to store in the copied set (POSIX absolute-ish)
2554
- # folder_key = matched_folder_p.as_posix()
2555
 
2556
- # # ---------- SPRITE ----------
2557
- # if is_subpath(matched_folder_p, sprite_base_p) and folder_key not in copied_sprite_folders:
2558
- # print(f"Processing SPRITE folder: {matched_folder_display}")
2559
- # copied_sprite_folders.add(folder_key)
2560
 
2561
- # sprite_json_path = matched_folder_p / "sprite.json"
2562
- # print("sprite_json_path----------------------->", sprite_json_path)
2563
- # print("copied sprite folder----------------------->", copied_sprite_folders)
2564
- # if sprite_json_path.exists() and sprite_json_path.is_file():
2565
- # try:
2566
- # with sprite_json_path.open("r", encoding="utf-8") as f:
2567
- # sprite_info = json.load(f)
2568
- # project_data.append(sprite_info)
2569
- # print(f" βœ“ Successfully read sprite.json from {matched_folder_display}")
2570
- # except Exception as e:
2571
- # print(f" βœ— Failed to read sprite.json in {matched_folder_display}: {repr(e)}")
2572
- # else:
2573
- # print(f" ⚠ No sprite.json in {matched_folder_display}")
2574
 
2575
- # # copy non-matching files from the sprite folder (except matched image and sprite.json)
2576
- # try:
2577
- # sprite_files = list(matched_folder_p.iterdir())
2578
- # except Exception as e:
2579
- # sprite_files = []
2580
- # print(f" βœ— Failed to list files in {matched_folder_display}: {repr(e)}")
2581
 
2582
- # print(f" Files in sprite folder: {[p.name for p in sprite_files]}")
2583
- # for p in sprite_files:
2584
- # fname = p.name
2585
- # if fname in (matched_filename, "sprite.json"):
2586
- # print(f" Skipping {fname} (matched image or sprite.json)")
2587
- # continue
2588
- # if p.is_file():
2589
- # dst = project_folder_p / fname
2590
- # try:
2591
- # shutil.copy2(str(p), str(dst))
2592
- # print(f" βœ“ Copied sprite asset: {p} -> {dst}")
2593
- # except Exception as e:
2594
- # print(f" βœ— Failed to copy sprite asset {p}: {repr(e)}")
2595
- # else:
2596
- # print(f" Skipping {fname} (not a file)")
2597
 
2598
- # # ---------- BACKDROP ----------
2599
- # if is_subpath(matched_folder_p, backdrop_base_p) and folder_key not in copied_backdrop_folders:
2600
- # print(f"Processing BACKDROP folder: {matched_folder_display}")
2601
- # copied_backdrop_folders.add(folder_key)
2602
- # print("backdrop_base_path----------------------->", display_like_windows_no_lead(backdrop_base_p))
2603
- # print("copied backdrop folder----------------------->", copied_backdrop_folders)
2604
 
2605
- # # copy matched backdrop image
2606
- # backdrop_src = matched_folder_p / matched_filename
2607
- # backdrop_dst = project_folder_p / matched_filename
2608
- # if backdrop_src.exists() and backdrop_src.is_file():
2609
- # try:
2610
- # shutil.copy2(str(backdrop_src), str(backdrop_dst))
2611
- # print(f" βœ“ Copied matched backdrop image: {backdrop_src} -> {backdrop_dst}")
2612
- # except Exception as e:
2613
- # print(f" βœ— Failed to copy matched backdrop image {backdrop_src}: {repr(e)}")
2614
- # else:
2615
- # print(f" ⚠ Matched backdrop source not found: {backdrop_src}")
2616
 
2617
- # # copy other files from folder (skip project.json and matched image)
2618
- # try:
2619
- # backdrop_files = list(matched_folder_p.iterdir())
2620
- # except Exception as e:
2621
- # backdrop_files = []
2622
- # print(f" βœ— Failed to list files in {matched_folder_display}: {repr(e)}")
2623
 
2624
- # print(f" Files in backdrop folder: {[p.name for p in backdrop_files]}")
2625
- # for p in backdrop_files:
2626
- # fname = p.name
2627
- # if fname in (matched_filename, "project.json"):
2628
- # print(f" Skipping {fname} (matched image or project.json)")
2629
- # continue
2630
- # if p.is_file():
2631
- # dst = project_folder_p / fname
2632
- # try:
2633
- # shutil.copy2(str(p), str(dst))
2634
- # print(f" βœ“ Copied backdrop asset: {p} -> {dst}")
2635
- # except Exception as e:
2636
- # print(f" βœ— Failed to copy backdrop asset {p}: {repr(e)}")
2637
- # else:
2638
- # print(f" Skipping {fname} (not a file)")
2639
 
2640
- # # read project.json to extract Stage/targets
2641
- # pj = matched_folder_p / "project.json"
2642
- # if pj.exists() and pj.is_file():
2643
- # try:
2644
- # with pj.open("r", encoding="utf-8") as f:
2645
- # bd_json = json.load(f)
2646
- # stage_count = 0
2647
- # for tgt in bd_json.get("targets", []):
2648
- # if tgt.get("isStage"):
2649
- # backdrop_data.append(tgt)
2650
- # stage_count += 1
2651
- # print(f" βœ“ Successfully read project.json from {matched_folder_display}, found {stage_count} stage(s)")
2652
- # except Exception as e:
2653
- # print(f" βœ— Failed to read project.json in {matched_folder_display}: {repr(e)}")
2654
- # else:
2655
- # print(f" ⚠ No project.json in {matched_folder_display}")
2656
 
2657
- # print("---")
2658
 
2659
- # final_project = {
2660
- # "targets": [], "monitors": [], "extensions": [],
2661
- # "meta": {
2662
- # "semver": "3.0.0",
2663
- # "vm": "11.3.0",
2664
- # "agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
2665
- # }
2666
- # }
2667
 
2668
 
2669
- # # Add sprite targets (non-stage)
2670
- # for spr in project_data:
2671
- # if not spr.get("isStage", False):
2672
- # final_project["targets"].append(spr)
2673
 
2674
  # # then backdrop as the Stage
2675
  # if backdrop_data:
 
1869
  matched_indices = sorted({idx for lst in per_sprite_matched_indices for idx in lst})
1870
  print("matched_indices------------------>",matched_indices)
1871
 
1872
+ import shutil
1873
+ import json
1874
+ import os
1875
+ from pathlib import Path
1876
+
1877
+ # normalize base paths once before the loop
1878
  sprite_base_p = Path(sprite_base_path).resolve(strict=False)
1879
  backdrop_base_p = Path(backdrop_base_path).resolve(strict=False)
1880
  project_folder_p = Path(project_folder)
1881
  project_folder_p.mkdir(parents=True, exist_ok=True)
1882
 
1883
+ copied_sprite_folders = set()
1884
+ copied_backdrop_folders = set()
1885
+
1886
  def display_like_windows_no_lead(p: Path) -> str:
1887
+ """
1888
+ For human-readable logs only β€” convert Path to a string like:
1889
+ "app\\blocks\\Backdrops\\Castle 2.sb3" (no leading slash).
1890
+ """
1891
+ s = p.as_posix() # forward-slash string, safe for Path objects
1892
  if s.startswith("/"):
1893
  s = s[1:]
1894
  return s.replace("/", "\\")
1895
 
1896
  def is_subpath(child: Path, parent: Path) -> bool:
1897
+ """Robust membership test: is child under parent?"""
1898
  try:
1899
+ # use non-strict resolve only if needed, but avoid exceptions
1900
  child.relative_to(parent)
1901
  return True
1902
  except Exception:
1903
  return False
1904
+
1905
+ # Flatten unique matched indices (if not already)
1906
+ matched_indices = sorted({idx for lst in per_sprite_matched_indices for idx in lst})
1907
+ print("matched_indices------------------>", matched_indices)
1908
+
1909
  for matched_idx in matched_indices:
1910
+ # defensive check
1911
  if not (0 <= matched_idx < len(paths_list)):
1912
  print(f" ⚠ matched_idx {matched_idx} out of range, skipping")
1913
  continue
1914
+
1915
  matched_image_path = paths_list[matched_idx]
1916
+ matched_path_p = Path(matched_image_path).resolve(strict=False) # keep as Path
1917
+ matched_folder_p = matched_path_p.parent # Path object
1918
  matched_filename = matched_path_p.name
1919
+
1920
+ # Prepare display-only string (do NOT reassign matched_folder_p)
1921
  matched_folder_display = display_like_windows_no_lead(matched_folder_p)
1922
+
1923
  print(f"Processing matched image: {matched_image_path}")
1924
  print(f" - Folder: {matched_folder_display}")
1925
+ print(f" - Sprite path: {display_like_windows_no_lead(sprite_base_p)}")
1926
+ print(f" - Backdrop path: {display_like_windows_no_lead(backdrop_base_p)}")
1927
+ print(f" - Filename: {matched_filename}")
1928
+
1929
+ # Use a canonical string to store in the copied set (POSIX absolute-ish)
1930
  folder_key = matched_folder_p.as_posix()
1931
+
1932
+ # ---------- SPRITE ----------
1933
  if is_subpath(matched_folder_p, sprite_base_p) and folder_key not in copied_sprite_folders:
1934
  print(f"Processing SPRITE folder: {matched_folder_display}")
1935
  copied_sprite_folders.add(folder_key)
1936
+
1937
  sprite_json_path = matched_folder_p / "sprite.json"
1938
+ print("sprite_json_path----------------------->", sprite_json_path)
1939
+ print("copied sprite folder----------------------->", copied_sprite_folders)
1940
  if sprite_json_path.exists() and sprite_json_path.is_file():
1941
  try:
1942
  with sprite_json_path.open("r", encoding="utf-8") as f:
 
1947
  print(f" βœ— Failed to read sprite.json in {matched_folder_display}: {repr(e)}")
1948
  else:
1949
  print(f" ⚠ No sprite.json in {matched_folder_display}")
1950
+
1951
+ # copy non-matching files from the sprite folder (except matched image and sprite.json)
1952
  try:
1953
  sprite_files = list(matched_folder_p.iterdir())
1954
  except Exception as e:
1955
  sprite_files = []
1956
  print(f" βœ— Failed to list files in {matched_folder_display}: {repr(e)}")
1957
+
1958
  print(f" Files in sprite folder: {[p.name for p in sprite_files]}")
1959
  for p in sprite_files:
1960
  fname = p.name
1961
  if fname in (matched_filename, "sprite.json"):
1962
+ print(f" Skipping {fname} (matched image or sprite.json)")
1963
  continue
1964
  if p.is_file():
1965
  dst = project_folder_p / fname
 
1968
  print(f" βœ“ Copied sprite asset: {p} -> {dst}")
1969
  except Exception as e:
1970
  print(f" βœ— Failed to copy sprite asset {p}: {repr(e)}")
1971
+ else:
1972
+ print(f" Skipping {fname} (not a file)")
1973
+
1974
+ # ---------- BACKDROP ----------
1975
  if is_subpath(matched_folder_p, backdrop_base_p) and folder_key not in copied_backdrop_folders:
1976
  print(f"Processing BACKDROP folder: {matched_folder_display}")
1977
  copied_backdrop_folders.add(folder_key)
1978
+ print("backdrop_base_path----------------------->", display_like_windows_no_lead(backdrop_base_p))
1979
+ print("copied backdrop folder----------------------->", copied_backdrop_folders)
1980
+
1981
+ # copy matched backdrop image
1982
  backdrop_src = matched_folder_p / matched_filename
1983
  backdrop_dst = project_folder_p / matched_filename
1984
  if backdrop_src.exists() and backdrop_src.is_file():
 
1989
  print(f" βœ— Failed to copy matched backdrop image {backdrop_src}: {repr(e)}")
1990
  else:
1991
  print(f" ⚠ Matched backdrop source not found: {backdrop_src}")
1992
+
1993
+ # copy other files from folder (skip project.json and matched image)
1994
  try:
1995
  backdrop_files = list(matched_folder_p.iterdir())
1996
  except Exception as e:
1997
  backdrop_files = []
1998
  print(f" βœ— Failed to list files in {matched_folder_display}: {repr(e)}")
1999
+
2000
  print(f" Files in backdrop folder: {[p.name for p in backdrop_files]}")
2001
  for p in backdrop_files:
2002
  fname = p.name
2003
  if fname in (matched_filename, "project.json"):
2004
+ print(f" Skipping {fname} (matched image or project.json)")
2005
  continue
2006
  if p.is_file():
2007
  dst = project_folder_p / fname
 
2010
  print(f" βœ“ Copied backdrop asset: {p} -> {dst}")
2011
  except Exception as e:
2012
  print(f" βœ— Failed to copy backdrop asset {p}: {repr(e)}")
2013
+ else:
2014
+ print(f" Skipping {fname} (not a file)")
2015
+
2016
+ # read project.json to extract Stage/targets
2017
  pj = matched_folder_p / "project.json"
2018
  if pj.exists() and pj.is_file():
2019
  try:
2020
  with pj.open("r", encoding="utf-8") as f:
2021
  bd_json = json.load(f)
2022
+ stage_count = 0
2023
  for tgt in bd_json.get("targets", []):
2024
  if tgt.get("isStage"):
2025
  backdrop_data.append(tgt)
2026
+ stage_count += 1
2027
+ print(f" βœ“ Successfully read project.json from {matched_folder_display}, found {stage_count} stage(s)")
2028
  except Exception as e:
2029
  print(f" βœ— Failed to read project.json in {matched_folder_display}: {repr(e)}")
2030
+ else:
2031
+ print(f" ⚠ No project.json in {matched_folder_display}")
2032
+
2033
+ print("---")
2034
+
2035
  final_project = {
2036
  "targets": [], "monitors": [], "extensions": [],
2037
  "meta": {
 
2040
  "agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
2041
  }
2042
  }
2043
+
2044
+
2045
+ # Add sprite targets (non-stage)
2046
  for spr in project_data:
2047
  if not spr.get("isStage", False):
2048
  final_project["targets"].append(spr)
2049
+
2050
  if backdrop_data:
2051
  all_costumes, sounds = [], []
2052
  seen_costumes = set()
 
2549
 
2550
  # # Flatten unique matched indices to process copying once per folder
2551
  # matched_indices = sorted({idx for lst in per_sprite_matched_indices for idx in lst})
2552
+ # print("matched_indices------------------>",matched_indices)
2553
 
2554
+ # import shutil
2555
+ # import json
2556
+ # import os
2557
+ # from pathlib import Path
2558
 
2559
+ # # normalize base paths once before the loop
2560
+ # sprite_base_p = Path(sprite_base_path).resolve(strict=False)
2561
+ # backdrop_base_p = Path(backdrop_base_path).resolve(strict=False)
2562
+ # project_folder_p = Path(project_folder)
2563
+ # project_folder_p.mkdir(parents=True, exist_ok=True)
2564
 
2565
+ # copied_sprite_folders = set()
2566
+ # copied_backdrop_folders = set()
2567
 
2568
+ # def display_like_windows_no_lead(p: Path) -> str:
2569
+ # """
2570
+ # For human-readable logs only β€” convert Path to a string like:
2571
+ # "app\\blocks\\Backdrops\\Castle 2.sb3" (no leading slash).
2572
+ # """
2573
+ # s = p.as_posix() # forward-slash string, safe for Path objects
2574
+ # if s.startswith("/"):
2575
+ # s = s[1:]
2576
+ # return s.replace("/", "\\")
2577
 
2578
+ # def is_subpath(child: Path, parent: Path) -> bool:
2579
+ # """Robust membership test: is child under parent?"""
2580
+ # try:
2581
+ # # use non-strict resolve only if needed, but avoid exceptions
2582
+ # child.relative_to(parent)
2583
+ # return True
2584
+ # except Exception:
2585
+ # return False
2586
 
2587
+ # # Flatten unique matched indices (if not already)
2588
+ # matched_indices = sorted({idx for lst in per_sprite_matched_indices for idx in lst})
2589
+ # print("matched_indices------------------>", matched_indices)
2590
 
2591
+ # for matched_idx in matched_indices:
2592
+ # # defensive check
2593
+ # if not (0 <= matched_idx < len(paths_list)):
2594
+ # print(f" ⚠ matched_idx {matched_idx} out of range, skipping")
2595
+ # continue
2596
 
2597
+ # matched_image_path = paths_list[matched_idx]
2598
+ # matched_path_p = Path(matched_image_path).resolve(strict=False) # keep as Path
2599
+ # matched_folder_p = matched_path_p.parent # Path object
2600
+ # matched_filename = matched_path_p.name
2601
 
2602
+ # # Prepare display-only string (do NOT reassign matched_folder_p)
2603
+ # matched_folder_display = display_like_windows_no_lead(matched_folder_p)
2604
 
2605
+ # print(f"Processing matched image: {matched_image_path}")
2606
+ # print(f" - Folder: {matched_folder_display}")
2607
+ # print(f" - Sprite path: {display_like_windows_no_lead(sprite_base_p)}")
2608
+ # print(f" - Backdrop path: {display_like_windows_no_lead(backdrop_base_p)}")
2609
+ # print(f" - Filename: {matched_filename}")
2610
 
2611
+ # # Use a canonical string to store in the copied set (POSIX absolute-ish)
2612
+ # folder_key = matched_folder_p.as_posix()
2613
 
2614
+ # # ---------- SPRITE ----------
2615
+ # if is_subpath(matched_folder_p, sprite_base_p) and folder_key not in copied_sprite_folders:
2616
+ # print(f"Processing SPRITE folder: {matched_folder_display}")
2617
+ # copied_sprite_folders.add(folder_key)
2618
 
2619
+ # sprite_json_path = matched_folder_p / "sprite.json"
2620
+ # print("sprite_json_path----------------------->", sprite_json_path)
2621
+ # print("copied sprite folder----------------------->", copied_sprite_folders)
2622
+ # if sprite_json_path.exists() and sprite_json_path.is_file():
2623
+ # try:
2624
+ # with sprite_json_path.open("r", encoding="utf-8") as f:
2625
+ # sprite_info = json.load(f)
2626
+ # project_data.append(sprite_info)
2627
+ # print(f" βœ“ Successfully read sprite.json from {matched_folder_display}")
2628
+ # except Exception as e:
2629
+ # print(f" βœ— Failed to read sprite.json in {matched_folder_display}: {repr(e)}")
2630
+ # else:
2631
+ # print(f" ⚠ No sprite.json in {matched_folder_display}")
2632
 
2633
+ # # copy non-matching files from the sprite folder (except matched image and sprite.json)
2634
+ # try:
2635
+ # sprite_files = list(matched_folder_p.iterdir())
2636
+ # except Exception as e:
2637
+ # sprite_files = []
2638
+ # print(f" βœ— Failed to list files in {matched_folder_display}: {repr(e)}")
2639
 
2640
+ # print(f" Files in sprite folder: {[p.name for p in sprite_files]}")
2641
+ # for p in sprite_files:
2642
+ # fname = p.name
2643
+ # if fname in (matched_filename, "sprite.json"):
2644
+ # print(f" Skipping {fname} (matched image or sprite.json)")
2645
+ # continue
2646
+ # if p.is_file():
2647
+ # dst = project_folder_p / fname
2648
+ # try:
2649
+ # shutil.copy2(str(p), str(dst))
2650
+ # print(f" βœ“ Copied sprite asset: {p} -> {dst}")
2651
+ # except Exception as e:
2652
+ # print(f" βœ— Failed to copy sprite asset {p}: {repr(e)}")
2653
+ # else:
2654
+ # print(f" Skipping {fname} (not a file)")
2655
 
2656
+ # # ---------- BACKDROP ----------
2657
+ # if is_subpath(matched_folder_p, backdrop_base_p) and folder_key not in copied_backdrop_folders:
2658
+ # print(f"Processing BACKDROP folder: {matched_folder_display}")
2659
+ # copied_backdrop_folders.add(folder_key)
2660
+ # print("backdrop_base_path----------------------->", display_like_windows_no_lead(backdrop_base_p))
2661
+ # print("copied backdrop folder----------------------->", copied_backdrop_folders)
2662
 
2663
+ # # copy matched backdrop image
2664
+ # backdrop_src = matched_folder_p / matched_filename
2665
+ # backdrop_dst = project_folder_p / matched_filename
2666
+ # if backdrop_src.exists() and backdrop_src.is_file():
2667
+ # try:
2668
+ # shutil.copy2(str(backdrop_src), str(backdrop_dst))
2669
+ # print(f" βœ“ Copied matched backdrop image: {backdrop_src} -> {backdrop_dst}")
2670
+ # except Exception as e:
2671
+ # print(f" βœ— Failed to copy matched backdrop image {backdrop_src}: {repr(e)}")
2672
+ # else:
2673
+ # print(f" ⚠ Matched backdrop source not found: {backdrop_src}")
2674
 
2675
+ # # copy other files from folder (skip project.json and matched image)
2676
+ # try:
2677
+ # backdrop_files = list(matched_folder_p.iterdir())
2678
+ # except Exception as e:
2679
+ # backdrop_files = []
2680
+ # print(f" βœ— Failed to list files in {matched_folder_display}: {repr(e)}")
2681
 
2682
+ # print(f" Files in backdrop folder: {[p.name for p in backdrop_files]}")
2683
+ # for p in backdrop_files:
2684
+ # fname = p.name
2685
+ # if fname in (matched_filename, "project.json"):
2686
+ # print(f" Skipping {fname} (matched image or project.json)")
2687
+ # continue
2688
+ # if p.is_file():
2689
+ # dst = project_folder_p / fname
2690
+ # try:
2691
+ # shutil.copy2(str(p), str(dst))
2692
+ # print(f" βœ“ Copied backdrop asset: {p} -> {dst}")
2693
+ # except Exception as e:
2694
+ # print(f" βœ— Failed to copy backdrop asset {p}: {repr(e)}")
2695
+ # else:
2696
+ # print(f" Skipping {fname} (not a file)")
2697
 
2698
+ # # read project.json to extract Stage/targets
2699
+ # pj = matched_folder_p / "project.json"
2700
+ # if pj.exists() and pj.is_file():
2701
+ # try:
2702
+ # with pj.open("r", encoding="utf-8") as f:
2703
+ # bd_json = json.load(f)
2704
+ # stage_count = 0
2705
+ # for tgt in bd_json.get("targets", []):
2706
+ # if tgt.get("isStage"):
2707
+ # backdrop_data.append(tgt)
2708
+ # stage_count += 1
2709
+ # print(f" βœ“ Successfully read project.json from {matched_folder_display}, found {stage_count} stage(s)")
2710
+ # except Exception as e:
2711
+ # print(f" βœ— Failed to read project.json in {matched_folder_display}: {repr(e)}")
2712
+ # else:
2713
+ # print(f" ⚠ No project.json in {matched_folder_display}")
2714
 
2715
+ # print("---")
2716
 
2717
+ # final_project = {
2718
+ # "targets": [], "monitors": [], "extensions": [],
2719
+ # "meta": {
2720
+ # "semver": "3.0.0",
2721
+ # "vm": "11.3.0",
2722
+ # "agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
2723
+ # }
2724
+ # }
2725
 
2726
 
2727
+ # # Add sprite targets (non-stage)
2728
+ # for spr in project_data:
2729
+ # if not spr.get("isStage", False):
2730
+ # final_project["targets"].append(spr)
2731
 
2732
  # # then backdrop as the Stage
2733
  # if backdrop_data: