|
|
from flask import Flask, request, jsonify, render_template, send_from_directory, send_file |
|
|
import cv2, json,base64,io,os,tempfile,logging, re |
|
|
import numpy as np |
|
|
from unstructured.partition.pdf import partition_pdf |
|
|
from PIL import Image |
|
|
|
|
|
from dotenv import load_dotenv |
|
|
import pytesseract |
|
|
from werkzeug.utils import secure_filename |
|
|
from langchain_groq import ChatGroq |
|
|
from langgraph.prebuilt import create_react_agent |
|
|
from pdf2image import convert_from_path, convert_from_bytes |
|
|
from concurrent.futures import ThreadPoolExecutor |
|
|
from pdf2image.exceptions import PDFInfoNotInstalledError |
|
|
from typing import Dict, TypedDict, Optional, Any |
|
|
from langgraph.graph import StateGraph, END |
|
|
import uuid |
|
|
import shutil, time, functools |
|
|
from langchain_experimental.open_clip.open_clip import OpenCLIPEmbeddings |
|
|
from langchain_core.utils.utils import secret_from_env |
|
|
|
|
|
from io import BytesIO |
|
|
from pathlib import Path |
|
|
import os |
|
|
from utils.block_relation_builder import block_builder, separate_scripts, transform_logic_to_action_flow, analyze_opcode_counts |
|
|
from langchain.chat_models import ChatOpenAI |
|
|
from langchain_openai import ChatOpenAI |
|
|
from pydantic import Field, SecretStr |
|
|
from difflib import get_close_matches |
|
|
import torch |
|
|
from transformers import AutoImageProcessor, AutoModel |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def log_execution_time(func): |
|
|
@functools.wraps(func) |
|
|
def wrapper(*args, **kwargs): |
|
|
start_time = time.time() |
|
|
result = func(*args, **kwargs) |
|
|
end_time = time.time() |
|
|
logger.info(f"⏱ {func.__name__} executed in {end_time - start_time:.2f} seconds") |
|
|
return result |
|
|
return wrapper |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
clip_embd = OpenCLIPEmbeddings() |
|
|
|
|
|
|
|
|
logging.basicConfig( |
|
|
level=logging.DEBUG, |
|
|
format="%(asctime)s [%(levelname)s] %(message)s", |
|
|
handlers=[ |
|
|
logging.FileHandler("/app/logs/app.log"), |
|
|
logging.StreamHandler() |
|
|
] |
|
|
) |
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
load_dotenv() |
|
|
|
|
|
groq_api_key = os.getenv("GROQ_API_KEY") |
|
|
|
|
|
llm = ChatGroq( |
|
|
model="meta-llama/llama-4-scout-17b-16e-instruct", |
|
|
temperature=0, |
|
|
max_tokens=None, |
|
|
) |
|
|
|
|
|
app = Flask(__name__) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pytesseract.pytesseract.tesseract_cmd = (r'/usr/bin/tesseract') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backdrop_images_path = r"app\blocks\Backdrops" |
|
|
sprite_images_path = r"app\blocks\sprites" |
|
|
code_blocks_image_path = r"app\blocks\code_blocks" |
|
|
|
|
|
count = 0 |
|
|
|
|
|
BASE_DIR = Path("/app") |
|
|
BLOCKS_DIR = BASE_DIR / "blocks" |
|
|
STATIC_DIR = BASE_DIR / "static" |
|
|
GEN_PROJECT_DIR = BASE_DIR / "generated_projects" |
|
|
BACKDROP_DIR = BLOCKS_DIR / "Backdrops" |
|
|
SPRITE_DIR = BLOCKS_DIR / "sprites" |
|
|
CODE_BLOCKS_DIR = BLOCKS_DIR / "code_blocks" |
|
|
|
|
|
OUTPUT_DIR = BASE_DIR / "outputs" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for d in ( |
|
|
BLOCKS_DIR, |
|
|
STATIC_DIR, |
|
|
GEN_PROJECT_DIR, |
|
|
BACKDROP_DIR, |
|
|
SPRITE_DIR, |
|
|
CODE_BLOCKS_DIR, |
|
|
OUTPUT_DIR, |
|
|
|
|
|
|
|
|
|
|
|
): |
|
|
d.mkdir(parents=True, exist_ok=True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GameState(TypedDict): |
|
|
project_json: dict |
|
|
description: str |
|
|
project_id: str |
|
|
project_image: str |
|
|
pseudo_code: dict |
|
|
action_plan: Optional[Dict] |
|
|
temporary_node: Optional[Dict] |
|
|
page_count: int |
|
|
processing: bool |
|
|
temp_pseudo_code: list |
|
|
|
|
|
|
|
|
SYSTEM_PROMPT = """ |
|
|
You are GameScratchAgent, an expert in Scratch 3.0 game development. |
|
|
Your task is to process OCR-extracted text from images of Scratch 3.0 code blocks and produce **precisely formatted pseudocode JSON**. |
|
|
|
|
|
### Core Role |
|
|
- Treat this as an OCR refinement task: the input may contain typos, spacing issues, or incomplete tokens. |
|
|
- Intelligently correct such OCR mistakes to align with valid Scratch 3.0 block syntax. |
|
|
- Always generate logically valid pseudocode consistent with Scratch semantics. |
|
|
|
|
|
### Responsibilities |
|
|
1. **Code-block detection** |
|
|
- If no Scratch code-blocks are detected → return `"No Code-blocks"`. |
|
|
- If code-blocks are present → refine into pseudocode. |
|
|
|
|
|
2. **Script ownership** |
|
|
- Extract the value from `"Script for:"`. |
|
|
- If it exactly matches any costume in `Stage_costumes`, set `"name_variable": "Stage"`. |
|
|
- Otherwise, keep the detected target name. |
|
|
|
|
|
3. **Pseudocode refinement** |
|
|
- Correct OCR artifacts automatically (e.g., “when cliked” → “when green flag clicked”). |
|
|
- Apply strict Scratch rules for variables, values, dropdowns, reporters, and booleans. |
|
|
- Ensure indentation of nested blocks (4 spaces). |
|
|
- Every hat block must end with `end`. |
|
|
- Do not include explanations or comments. |
|
|
|
|
|
4. **Formatting precautions** |
|
|
- Numbers → `(5)`, `(-130)` |
|
|
- Text/strings → `(hello)` |
|
|
- Variables → `[score v]` |
|
|
- Dropdowns → `[space v]`, `[Game Over v]` |
|
|
- Reporter blocks → `((x position))` |
|
|
- Boolean logic → `<condition>`, `<<cond1> and <cond2>>`, `<not <cond>>` |
|
|
- Operators → explicit, e.g. `(([speed v]) * (1.1))` |
|
|
|
|
|
### Critical Notes |
|
|
- Be robust to OCR noise: missing characters, misread symbols, or accidental merges. |
|
|
- Never output raw OCR mistakes—always normalize to valid Scratch pseudocode. |
|
|
- Output only the JSON object, nothing else. |
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SYSTEM_PROMPT_JSON_CORRECTOR =""" |
|
|
You are an assistant that outputs JSON responses strictly following the given schema. |
|
|
If the JSON you produce has any formatting errors, missing required fields, or invalid structure, you must identify the problems and correct them. |
|
|
Always return only valid JSON that fully conforms to the schema below, enclosed in triple backticks (```), without any extra text or explanation. |
|
|
|
|
|
If you receive an invalid or incomplete JSON response, fix it by: |
|
|
- Adding any missing required fields with appropriate values. |
|
|
- Correcting syntax errors such as missing commas, brackets, or quotes. |
|
|
- Ensuring the JSON structure matches the schema exactly. |
|
|
|
|
|
Remember: Your output must be valid JSON only, ready to be parsed without errors. |
|
|
""" |
|
|
|
|
|
|
|
|
agent = create_react_agent( |
|
|
model=llm, |
|
|
tools=[], |
|
|
prompt=SYSTEM_PROMPT |
|
|
) |
|
|
agent_2 = create_react_agent( |
|
|
model=llm2, |
|
|
tools=[], |
|
|
prompt=SYSTEM_PROMPT |
|
|
) |
|
|
agent_json_resolver = create_react_agent( |
|
|
model=llm, |
|
|
tools=[], |
|
|
prompt=SYSTEM_PROMPT_JSON_CORRECTOR |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _load_block_catalog(block_type: str) -> Dict: |
|
|
""" |
|
|
Loads the Scratch block catalog named '{block_type}_blocks.json' |
|
|
from the <project_root>/blocks/ folder. Returns {} on any error. |
|
|
""" |
|
|
catalog_path = BLOCKS_DIR / f"{block_type}.json" |
|
|
|
|
|
try: |
|
|
text = catalog_path.read_text() |
|
|
catalog = json.loads(text) |
|
|
logger.info(f"Successfully loaded block catalog from {catalog_path}") |
|
|
return catalog |
|
|
|
|
|
except FileNotFoundError: |
|
|
logger.error(f"Error: Block catalog file not found at {catalog_path}") |
|
|
except json.JSONDecodeError as e: |
|
|
logger.error(f"Error decoding JSON from {catalog_path}: {e}") |
|
|
except Exception as e: |
|
|
logger.error(f"Unexpected error loading {catalog_path}: {e}") |
|
|
|
|
|
def get_block_by_opcode(catalog_data: dict, opcode: str) -> dict | None: |
|
|
""" |
|
|
Search a single catalog (with keys "description" and "blocks": List[dict]) |
|
|
for a block whose 'op_code' matches the given opcode. |
|
|
Returns the block dict or None if not found. |
|
|
""" |
|
|
for block in catalog_data["blocks"]: |
|
|
if block.get("op_code") == opcode: |
|
|
return block |
|
|
return None |
|
|
|
|
|
|
|
|
def find_block_in_all(opcode: str, all_catalogs: list[dict]) -> dict | None: |
|
|
""" |
|
|
Search across multiple catalogs for a given opcode. |
|
|
Returns the first matching block dict or None. |
|
|
""" |
|
|
for catalog in all_catalogs: |
|
|
blk = get_block_by_opcode(catalog, opcode) |
|
|
if blk is not None: |
|
|
return blk |
|
|
return None |
|
|
|
|
|
def variable_intialization(project_data): |
|
|
""" |
|
|
Updates variable and broadcast definitions in a Scratch project JSON, |
|
|
populating the 'variables' and 'broadcasts' sections of the Stage target |
|
|
and extracting initial values for variables. |
|
|
|
|
|
Args: |
|
|
project_data (dict): The loaded JSON data of the Scratch project. |
|
|
|
|
|
Returns: |
|
|
dict: The updated project JSON data. |
|
|
""" |
|
|
|
|
|
stage_target = None |
|
|
for target in project_data['targets']: |
|
|
if target.get('isStage'): |
|
|
stage_target = target |
|
|
break |
|
|
|
|
|
if stage_target is None: |
|
|
print("Error: Stage target not found in the project data.") |
|
|
return project_data |
|
|
|
|
|
|
|
|
if "variables" not in stage_target: |
|
|
stage_target["variables"] = {} |
|
|
if "broadcasts" not in stage_target: |
|
|
stage_target["broadcasts"] = {} |
|
|
|
|
|
|
|
|
def process_dict(obj): |
|
|
if isinstance(obj, dict): |
|
|
|
|
|
if obj.get("opcode") == "data_setvariableto": |
|
|
variable_field = obj.get("fields", {}).get("VARIABLE") |
|
|
value_input = obj.get("inputs", {}).get("VALUE") |
|
|
|
|
|
if variable_field and isinstance(variable_field, list) and len(variable_field) == 2: |
|
|
var_name = variable_field[0] |
|
|
var_id = variable_field[1] |
|
|
|
|
|
initial_value = "" |
|
|
if value_input and isinstance(value_input, list) and len(value_input) > 1 and \ |
|
|
isinstance(value_input[1], list) and len(value_input[1]) > 1: |
|
|
if value_input[1][0] == 10: |
|
|
initial_value = str(value_input[1][1]) |
|
|
elif value_input[1][0] == 12 and len(value_input) > 2 and isinstance(value_input[2], list) and value_input[2][0] == 10: |
|
|
initial_value = str(value_input[2][1]) |
|
|
elif isinstance(value_input[1], (str, int, float)): |
|
|
initial_value = str(value_input[1]) |
|
|
stage_target["variables"][var_id] = [var_name, initial_value] |
|
|
|
|
|
for key, value in obj.items(): |
|
|
|
|
|
if key == "BROADCAST_INPUT" and isinstance(value, list) and len(value) == 2 and \ |
|
|
isinstance(value[1], list) and len(value[1]) == 3 and value[1][0] == 11: |
|
|
broadcast_name = value[1][1] |
|
|
broadcast_id = value[1][2] |
|
|
stage_target["broadcasts"][broadcast_id] = broadcast_name |
|
|
|
|
|
|
|
|
elif key == "BROADCAST_OPTION" and isinstance(value, list) and len(value) == 2: |
|
|
broadcast_name = value[0] |
|
|
broadcast_id = value[1] |
|
|
stage_target["broadcasts"][broadcast_id] = broadcast_name |
|
|
|
|
|
|
|
|
process_dict(value) |
|
|
|
|
|
elif isinstance(obj, list): |
|
|
for i, item in enumerate(obj): |
|
|
|
|
|
if isinstance(item, list) and len(item) == 3 and item[0] == 12: |
|
|
var_name = item[1] |
|
|
var_id = item[2] |
|
|
if var_id not in stage_target["variables"]: |
|
|
stage_target["variables"][var_id] = [var_name, ""] |
|
|
process_dict(item) |
|
|
|
|
|
|
|
|
for target in project_data['targets']: |
|
|
if "blocks" in target: |
|
|
for block_id, block_data in target["blocks"].items(): |
|
|
process_dict(block_data) |
|
|
|
|
|
return project_data |
|
|
|
|
|
def deduplicate_variables(project_data): |
|
|
""" |
|
|
Removes duplicate variable entries in the 'variables' dictionary of the Stage target, |
|
|
prioritizing entries with non-empty values. |
|
|
|
|
|
Args: |
|
|
project_data (dict): The loaded JSON data of the Scratch project. |
|
|
|
|
|
Returns: |
|
|
dict: The updated project JSON data with deduplicated variables. |
|
|
""" |
|
|
|
|
|
stage_target = None |
|
|
for target in project_data['targets']: |
|
|
if target.get('isStage'): |
|
|
stage_target = target |
|
|
break |
|
|
|
|
|
if stage_target is None: |
|
|
print("Error: Stage target not found in the project data.") |
|
|
return project_data |
|
|
|
|
|
if "variables" not in stage_target: |
|
|
return project_data |
|
|
|
|
|
|
|
|
|
|
|
resolved_variables = {} |
|
|
|
|
|
for var_id, var_info in stage_target["variables"].items(): |
|
|
var_name = var_info[0] |
|
|
var_value = var_info[1] |
|
|
|
|
|
if var_name not in resolved_variables: |
|
|
|
|
|
resolved_variables[var_name] = [var_id, var_name, var_value] |
|
|
else: |
|
|
|
|
|
existing_id, existing_name, existing_value = resolved_variables[var_name] |
|
|
|
|
|
|
|
|
if var_value != "" and existing_value == "": |
|
|
resolved_variables[var_name] = [var_id, var_name, var_value] |
|
|
|
|
|
|
|
|
|
|
|
elif var_value != "" and existing_value != "": |
|
|
|
|
|
|
|
|
|
|
|
resolved_variables[var_name] = [var_id, var_name, var_value] |
|
|
elif var_value == "" and existing_value == "": |
|
|
|
|
|
resolved_variables[var_name] = [var_id, var_name, var_value] |
|
|
|
|
|
|
|
|
|
|
|
new_variables_dict = {} |
|
|
for var_name, var_data in resolved_variables.items(): |
|
|
var_id_to_keep = var_data[0] |
|
|
var_name_to_keep = var_data[1] |
|
|
var_value_to_keep = var_data[2] |
|
|
new_variables_dict[var_id_to_keep] = [var_name_to_keep, var_value_to_keep] |
|
|
|
|
|
stage_target["variables"] = new_variables_dict |
|
|
|
|
|
return project_data |
|
|
|
|
|
def variable_adder_main(project_data): |
|
|
try: |
|
|
declare_variable_json= variable_intialization(project_data) |
|
|
print("declare_variable_json------->",declare_variable_json) |
|
|
except Exception as e: |
|
|
print(f"Error error in the variable initialization opcodes: {e}") |
|
|
try: |
|
|
processed_json= deduplicate_variables(declare_variable_json) |
|
|
print("processed_json------->",processed_json) |
|
|
return processed_json |
|
|
except Exception as e: |
|
|
print(f"Error error in the variable initialization opcodes: {e}") |
|
|
|
|
|
|
|
|
|
|
|
ALL_SCRATCH_BLOCKS_CATALOG = {} |
|
|
BLOCK_CATALOG_PATH = "blocks" |
|
|
HAT_BLOCKS_PATH = "hat_blocks" |
|
|
STACK_BLOCKS_PATH = "stack_blocks" |
|
|
REPORTER_BLOCKS_PATH = "reporter_blocks" |
|
|
BOOLEAN_BLOCKS_PATH = "boolean_blocks" |
|
|
C_BLOCKS_PATH = "c_blocks" |
|
|
CAP_BLOCKS_PATH = "cap_blocks" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hat_block_data = _load_block_catalog(HAT_BLOCKS_PATH) |
|
|
hat_description = hat_block_data["description"] |
|
|
|
|
|
|
|
|
hat_opcodes_functionalities = "\n".join([ |
|
|
|
|
|
f" - Opcode: {block.get('op_code', 'N/A')}, example: standalone use {block.get('example_standalone', 'N/A')}" |
|
|
for block in hat_block_data.get("blocks", []) |
|
|
]) if isinstance(hat_block_data.get("blocks"), list) else " No blocks information available." |
|
|
|
|
|
print("Hat blocks loaded successfully.", hat_description) |
|
|
|
|
|
boolean_block_data = _load_block_catalog(BOOLEAN_BLOCKS_PATH) |
|
|
boolean_description = boolean_block_data["description"] |
|
|
|
|
|
boolean_opcodes_functionalities = "\n".join([ |
|
|
|
|
|
f" - Opcode: {block.get('op_code', 'N/A')}, example: standalone use {block.get('example_standalone', 'N/A')}" |
|
|
for block in boolean_block_data.get("blocks", []) |
|
|
]) if isinstance(boolean_block_data.get("blocks"), list) else " No blocks information available." |
|
|
|
|
|
|
|
|
c_block_data = _load_block_catalog(C_BLOCKS_PATH) |
|
|
c_description = c_block_data["description"] |
|
|
|
|
|
c_opcodes_functionalities = "\n".join([ |
|
|
|
|
|
f" - Opcode: {block.get('op_code', 'N/A')}, example: standalone use {block.get('example_standalone', 'N/A')}" |
|
|
for block in c_block_data.get("blocks", []) |
|
|
]) if isinstance(c_block_data.get("blocks"), list) else " No blocks information available." |
|
|
|
|
|
|
|
|
cap_block_data = _load_block_catalog(CAP_BLOCKS_PATH) |
|
|
cap_description = cap_block_data["description"] |
|
|
|
|
|
cap_opcodes_functionalities = "\n".join([ |
|
|
|
|
|
f" - Opcode: {block.get('op_code', 'N/A')}, example: standalone use {block.get('example_standalone', 'N/A')}" |
|
|
for block in cap_block_data.get("blocks", []) |
|
|
]) if isinstance(cap_block_data.get("blocks"), list) else " No blocks information available." |
|
|
|
|
|
|
|
|
reporter_block_data = _load_block_catalog(REPORTER_BLOCKS_PATH) |
|
|
reporter_description = reporter_block_data["description"] |
|
|
|
|
|
reporter_opcodes_functionalities = "\n".join([ |
|
|
|
|
|
f" - Opcode: {block.get('op_code', 'N/A')}, example: standalone use {block.get('example_standalone', 'N/A')}" |
|
|
for block in reporter_block_data.get("blocks", []) |
|
|
]) if isinstance(reporter_block_data.get("blocks"), list) else " No blocks information available." |
|
|
|
|
|
|
|
|
stack_block_data = _load_block_catalog(STACK_BLOCKS_PATH) |
|
|
stack_description = stack_block_data["description"] |
|
|
|
|
|
stack_opcodes_functionalities = "\n".join([ |
|
|
|
|
|
f" - Opcode: {block.get('op_code', 'N/A')}, example: standalone use {block.get('example_standalone', 'N/A')}" |
|
|
for block in stack_block_data.get("blocks", []) |
|
|
]) if isinstance(stack_block_data.get("blocks"), list) else " No blocks information available." |
|
|
|
|
|
|
|
|
|
|
|
ALL_SCRATCH_BLOCKS_CATALOG = _load_block_catalog(BLOCK_CATALOG_PATH) |
|
|
|
|
|
|
|
|
def extract_json_from_llm_response(raw_response: str) -> dict: |
|
|
|
|
|
md = re.search(r"```(?:json)?\s*([\s\S]*?)\s*```", raw_response) |
|
|
json_string = md.group(1).strip() if md else raw_response |
|
|
|
|
|
|
|
|
first, last = json_string.find('{'), json_string.rfind('}') |
|
|
if 0 <= first < last: |
|
|
json_string = json_string[first:last+1] |
|
|
|
|
|
|
|
|
json_string = re.sub(r'\b\w+\s*{', '{', json_string) |
|
|
json_string = re.sub(r'"assistant"\s*:', '', json_string) |
|
|
json_string = re.sub(r'\b(false|true)"', r'\1', json_string) |
|
|
logger.debug("Ran pre‑cleanup for stray tokens and boolean quotes.") |
|
|
|
|
|
|
|
|
|
|
|
json_string = re.sub( |
|
|
r'("name"\s*:\s*")\s*"', |
|
|
r'\1', |
|
|
json_string |
|
|
) |
|
|
|
|
|
|
|
|
def _esc(m): |
|
|
prefix, body = m.group(1), m.group(2) |
|
|
return prefix + body.replace('"', r'\"') |
|
|
json_string = re.sub( |
|
|
r'("logic"\s*:\s*")([\s\S]+?)(?=",\s*"[A-Za-z_]\w*"\s*:\s*)', |
|
|
_esc, |
|
|
json_string |
|
|
) |
|
|
logger.debug("Escaped embedded quotes in logic fields.") |
|
|
|
|
|
logger.debug("Quoted unquoted keys.") |
|
|
|
|
|
|
|
|
json_string = re.sub(r',\s*(?=[}\],])', '', json_string) |
|
|
json_string = re.sub(r',\s*,', ',', json_string) |
|
|
logger.debug("Removed trailing commas.") |
|
|
|
|
|
|
|
|
ob, cb = json_string.count('{'), json_string.count('}') |
|
|
if cb > ob: |
|
|
excess = cb - ob |
|
|
json_string = json_string.rstrip()[:-excess] |
|
|
logger.debug(f"Stripped {excess} extra closing brace(s).") |
|
|
|
|
|
|
|
|
json_string = re.sub( |
|
|
r'"((?:[^"\\]|\\.)*?)"', |
|
|
lambda m: '"' + m.group(1).replace('\n', '\\n').replace('\r', '\\r') + '"', |
|
|
json_string, |
|
|
flags=re.DOTALL |
|
|
) |
|
|
logger.debug("Escaped newlines in strings.") |
|
|
|
|
|
|
|
|
try: |
|
|
return json.loads(json_string) |
|
|
except json.JSONDecodeError: |
|
|
logger.error("Sanitized JSON still invalid:\n%s", json_string) |
|
|
raise |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def reduce_image_size_to_limit(clean_b64_str: str, max_kb: int = 4000) -> str: |
|
|
""" |
|
|
Input: clean_b64_str = BASE64 STRING (no data: prefix) |
|
|
Output: BASE64 STRING (no data: prefix), sized as close as possible to max_kb KB. |
|
|
Guarantees: returns a valid base64 string (never None). May still be larger than max_kb |
|
|
if saving at lowest quality cannot get under the limit. |
|
|
""" |
|
|
|
|
|
clean = re.sub(r"\s+", "", clean_b64_str).strip() |
|
|
|
|
|
missing = len(clean) % 4 |
|
|
if missing: |
|
|
clean += "=" * (4 - missing) |
|
|
|
|
|
try: |
|
|
image_data = base64.b64decode(clean) |
|
|
except Exception as e: |
|
|
raise ValueError("Invalid base64 input to reduce_image_size_to_limit") from e |
|
|
|
|
|
try: |
|
|
img = Image.open(io.BytesIO(image_data)) |
|
|
img.load() |
|
|
except Exception as e: |
|
|
raise ValueError("Could not open image from base64") from e |
|
|
|
|
|
|
|
|
if img.mode in ("RGBA", "LA") or (img.mode == "P" and "transparency" in img.info): |
|
|
background = Image.new("RGB", img.size, (255, 255, 255)) |
|
|
background.paste(img, mask=img.split()[-1] if img.mode != "RGB" else None) |
|
|
img = background |
|
|
elif img.mode != "RGB": |
|
|
img = img.convert("RGB") |
|
|
|
|
|
low, high = 20, 95 |
|
|
best_bytes = None |
|
|
|
|
|
while low <= high: |
|
|
mid = (low + high) // 2 |
|
|
buf = io.BytesIO() |
|
|
try: |
|
|
img.save(buf, format="JPEG", quality=mid, optimize=True) |
|
|
except OSError: |
|
|
|
|
|
buf = io.BytesIO() |
|
|
img.save(buf, format="JPEG", quality=mid) |
|
|
size_kb = len(buf.getvalue()) / 1024.0 |
|
|
if size_kb <= max_kb: |
|
|
best_bytes = buf.getvalue() |
|
|
low = mid + 1 |
|
|
else: |
|
|
high = mid - 1 |
|
|
|
|
|
|
|
|
if best_bytes is None: |
|
|
buf = io.BytesIO() |
|
|
try: |
|
|
img.save(buf, format="JPEG", quality=20, optimize=True) |
|
|
except OSError: |
|
|
buf = io.BytesIO() |
|
|
img.save(buf, format="JPEG", quality=20) |
|
|
best_bytes = buf.getvalue() |
|
|
|
|
|
return base64.b64encode(best_bytes).decode("utf-8") |
|
|
|
|
|
|
|
|
def clean_base64_for_model(raw_b64, max_bytes_threshold=4000000) -> str: |
|
|
""" |
|
|
Accepts: raw_b64 can be: |
|
|
- a data URI 'data:image/png;base64,...' |
|
|
- a plain base64 string |
|
|
- a PIL Image |
|
|
- a list containing the above (take first) |
|
|
Returns: a data URI string 'data:<mime>;base64,<base64>' guaranteed to be syntactically valid. |
|
|
""" |
|
|
|
|
|
if not raw_b64: |
|
|
return "" |
|
|
|
|
|
if isinstance(raw_b64, list): |
|
|
raw_b64 = raw_b64[0] if raw_b64 else "" |
|
|
if not raw_b64: |
|
|
return "" |
|
|
|
|
|
if isinstance(raw_b64, Image.Image): |
|
|
buf = io.BytesIO() |
|
|
|
|
|
img = raw_b64.convert("RGB") |
|
|
img.save(buf, format="JPEG") |
|
|
clean_b64 = base64.b64encode(buf.getvalue()).decode("utf-8") |
|
|
mime = "image/jpeg" |
|
|
return f"data:{mime};base64,{clean_b64}" |
|
|
|
|
|
if not isinstance(raw_b64, str): |
|
|
raise TypeError(f"Expected base64 string or PIL Image, got {type(raw_b64)}") |
|
|
|
|
|
|
|
|
m = re.match(r"^data:(image\/[a-zA-Z0-9.+-]+);base64,(.+)$", raw_b64, flags=re.DOTALL) |
|
|
if m: |
|
|
mime = m.group(1) |
|
|
clean_b64 = m.group(2) |
|
|
else: |
|
|
|
|
|
mime = "image/png" |
|
|
clean_b64 = raw_b64 |
|
|
|
|
|
|
|
|
clean_b64 = re.sub(r"\s+", "", clean_b64).strip() |
|
|
missing = len(clean_b64) % 4 |
|
|
if missing: |
|
|
clean_b64 += "=" * (4 - missing) |
|
|
|
|
|
original_size_bytes = len(clean_b64.encode("utf-8")) |
|
|
|
|
|
print(f"Original base64 size (bytes): {original_size_bytes}, mime: {mime}") |
|
|
|
|
|
if original_size_bytes > max_bytes_threshold: |
|
|
|
|
|
reduced_clean = reduce_image_size_to_limit(clean_b64, max_kb=4000) |
|
|
|
|
|
print(f"Reduced base64 size (bytes): {original_size_bytes}, mime: {mime}") |
|
|
return f"data:image/jpeg;base64,{reduced_clean}" |
|
|
|
|
|
|
|
|
return f"data:{mime};base64,{clean_b64}" |
|
|
|
|
|
SCRATCH_OPCODES = [ |
|
|
'motion_movesteps', 'motion_turnright', 'motion_turnleft', 'motion_goto', |
|
|
'motion_gotoxy', 'motion_glideto', 'motion_glidesecstoxy', 'motion_pointindirection', |
|
|
'motion_pointtowards', 'motion_changexby', 'motion_setx', 'motion_changeyby', |
|
|
'motion_sety', 'motion_ifonedgebounce', 'motion_setrotationstyle', 'looks_sayforsecs', |
|
|
'looks_say', 'looks_thinkforsecs', 'looks_think', 'looks_switchcostumeto', |
|
|
'looks_nextcostume', 'looks_switchbackdropto', 'looks_switchbackdroptowait', |
|
|
'looks_nextbackdrop', 'looks_changesizeby', 'looks_setsizeto', 'looks_changeeffectby', |
|
|
'looks_seteffectto', 'looks_cleargraphiceffects', 'looks_show', 'looks_hide', |
|
|
'looks_gotofrontback', 'looks_goforwardbackwardlayers', 'sound_playuntildone', |
|
|
'sound_play', 'sound_stopallsounds', 'sound_changevolumeby', 'sound_setvolumeto', |
|
|
'event_broadcast', 'event_broadcastandwait', 'control_wait', 'control_wait_until', |
|
|
'control_stop', 'control_create_clone_of', 'control_delete_this_clone', |
|
|
'data_setvariableto', 'data_changevariableby', 'data_addtolist', 'data_deleteoflist', |
|
|
'data_insertatlist', 'data_replaceitemoflist', 'data_showvariable', 'data_hidevariable', |
|
|
'data_showlist', 'data_hidelist', 'sensing_askandwait', 'sensing_resettimer', |
|
|
'sensing_setdragmode', 'procedures_call', 'operator_lt', 'operator_equals', |
|
|
'operator_gt', 'operator_and', 'operator_or', 'operator_not', 'operator_contains', |
|
|
'sensing_touchingobject', 'sensing_touchingcolor', 'sensing_coloristouchingcolor', |
|
|
'sensing_keypressed', 'sensing_mousedown', 'data_listcontainsitem', 'control_repeat', |
|
|
'control_forever', 'control_if', 'control_if_else', 'control_repeat_until', |
|
|
'motion_xposition', 'motion_yposition', 'motion_direction', 'looks_costumenumbername', |
|
|
'looks_size', 'looks_backdropnumbername', 'sound_volume', 'sensing_distanceto', |
|
|
'sensing_answer', 'sensing_mousex', 'sensing_mousey', 'sensing_loudness', |
|
|
'sensing_timer', 'sensing_of', 'sensing_current', 'sensing_dayssince2000', |
|
|
'sensing_username', 'operator_add', 'operator_subtract', 'operator_multiply', |
|
|
'operator_divide', 'operator_random', 'operator_join', 'operator_letterof', |
|
|
'operator_length', 'operator_mod', 'operator_round', 'operator_mathop', |
|
|
'data_variable', 'data_list', 'data_itemoflist', 'data_lengthoflist', |
|
|
'data_itemnumoflist', 'event_whenflagclicked', 'event_whenkeypressed', |
|
|
'event_whenthisspriteclicked', 'event_whenbackdropswitchesto', 'event_whengreaterthan', |
|
|
'event_whenbroadcastreceived', 'control_start_as_clone', 'procedures_definition' |
|
|
] |
|
|
|
|
|
def validate_and_fix_opcodes(opcode_counts): |
|
|
""" |
|
|
Ensures all opcodes are valid. If an opcode is invalid, replace with closest match. |
|
|
""" |
|
|
corrected_list = [] |
|
|
for item in opcode_counts: |
|
|
opcode = item.get("opcode") |
|
|
count = item.get("count", 1) |
|
|
|
|
|
if opcode not in SCRATCH_OPCODES: |
|
|
|
|
|
match = get_close_matches(opcode, SCRATCH_OPCODES, n=1, cutoff=0.6) |
|
|
if match: |
|
|
print(f"Opcode '{opcode}' not found. Replacing with '{match[0]}'") |
|
|
opcode = match[0] |
|
|
else: |
|
|
print(f"Opcode '{opcode}' not recognized and no close match found. Skipping.") |
|
|
continue |
|
|
|
|
|
corrected_list.append({"opcode": opcode, "count": count}) |
|
|
|
|
|
|
|
|
merged = {} |
|
|
for item in corrected_list: |
|
|
merged[item["opcode"]] = merged.get(item["opcode"], 0) + item["count"] |
|
|
|
|
|
return [{"opcode": k, "count": v} for k, v in merged.items()] |
|
|
|
|
|
def format_scratch_pseudo_code(code_string): |
|
|
""" |
|
|
Parses and formats Scratch pseudo-code with correct indentation, |
|
|
specifically handling if/else/end structures correctly. |
|
|
|
|
|
Args: |
|
|
code_string (str): A string containing Scratch pseudo-code with |
|
|
potentially inconsistent indentation. |
|
|
|
|
|
Returns: |
|
|
str: The correctly formatted and indented pseudo-code string. |
|
|
""" |
|
|
lines = code_string.strip().split('\n') |
|
|
formatted_lines = [] |
|
|
indent_level = 0 |
|
|
|
|
|
|
|
|
indent_keywords = ['when', 'forever', 'if', 'repeat', 'else'] |
|
|
|
|
|
|
|
|
unindent_keywords = ['end', 'else'] |
|
|
|
|
|
for line in lines: |
|
|
stripped_line = line.strip() |
|
|
if not stripped_line: |
|
|
continue |
|
|
|
|
|
|
|
|
if any(keyword in stripped_line for keyword in unindent_keywords): |
|
|
|
|
|
if 'else' in stripped_line: |
|
|
|
|
|
indentation = ' ' * (indent_level -1) |
|
|
formatted_lines.append(indentation + stripped_line) |
|
|
continue |
|
|
|
|
|
|
|
|
indent_level = max(0, indent_level - 1) |
|
|
|
|
|
indentation = ' ' * indent_level |
|
|
formatted_lines.append(indentation + stripped_line) |
|
|
|
|
|
|
|
|
if any(keyword in stripped_line for keyword in indent_keywords): |
|
|
|
|
|
if 'else' not in stripped_line: |
|
|
indent_level += 1 |
|
|
|
|
|
return '\n'.join(formatted_lines) |
|
|
|
|
|
|
|
|
def pseudo_generator_node(state: GameState): |
|
|
logger.info("--- Running plan_logic_aligner_node ---") |
|
|
image = state.get("project_image", "") |
|
|
project_json = state["project_json"] |
|
|
cnt =state["page_count"] |
|
|
print(f"The page number recived at the pseudo_generator node:-----> {cnt}") |
|
|
|
|
|
|
|
|
target_names = [t["name"] for t in project_json["targets"]] |
|
|
stage_names = [t["name"] for t in project_json["targets"] if t.get("isStage")] |
|
|
sprite_names = [t["name"] for t in project_json["targets"] if not t.get("isStage")] |
|
|
|
|
|
stage_costumes = [ |
|
|
c["name"] |
|
|
for t in project_json["targets"] if t.get("isStage") |
|
|
for c in t.get("costumes", []) |
|
|
] |
|
|
|
|
|
refinement_prompt = f""" |
|
|
You are an expert in Scratch 3.0 game development, specializing in understanding block relationships (stacked, nested). |
|
|
"Analyze the Scratch code-block image and generate Pseudo-Code for what this logic appears to be doing." |
|
|
From Image, you also have to detect a value of Key given in Text form "Script for: ". Below is the example |
|
|
Example: "Script for: Bear", "Script for:" is a key and "Bear" is value and check if there is related target name available. |
|
|
|
|
|
**Special Rule for Stage Costumes:** |
|
|
If the value of "Script for:" exactly matches ANY costume name in the Stage_costumes list given below, |
|
|
then the `"name_variable"` in the output JSON must be set to `"Stage"` (not the costume name). |
|
|
|
|
|
**Targets in Game (Sprites and Stage) available in project_json:** |
|
|
Sprite_name:{', '.join(sprite_names)} |
|
|
Stage_name: Stage |
|
|
Stage_costumes: {', '.join(stage_costumes)} |
|
|
|
|
|
--- Scratch 3.0 Block Reference --- |
|
|
### Hat Blocks |
|
|
Description: {hat_description} |
|
|
Blocks: |
|
|
{hat_opcodes_functionalities} |
|
|
|
|
|
### Boolean Blocks |
|
|
Description: {boolean_description} |
|
|
Blocks: |
|
|
{boolean_opcodes_functionalities} |
|
|
|
|
|
### C Blocks |
|
|
Description: {c_description} |
|
|
Blocks: |
|
|
{c_opcodes_functionalities} |
|
|
|
|
|
### Cap Blocks |
|
|
Description: {cap_description} |
|
|
Blocks: |
|
|
{cap_opcodes_functionalities} |
|
|
|
|
|
### Reporter Blocks |
|
|
Description: {reporter_description} |
|
|
Blocks: |
|
|
{reporter_opcodes_functionalities} |
|
|
|
|
|
### Stack Blocks |
|
|
Description: {stack_description} |
|
|
Blocks: |
|
|
{stack_opcodes_functionalities} |
|
|
----------------------------------- |
|
|
|
|
|
Your task is to: |
|
|
If you don't find any "Code-Blocks" then, |
|
|
**Don't generate Pseudo Code, and pass the message "No Code-blocks" |
|
|
If you find any "Code-Blocks" then, |
|
|
1. **Refine the 'logic'**: Make it precise, accurate, and fully aligned with the Game Description. Use Scratch‑consistent verbs and phrasing. **Do NOT** use raw double‑quotes inside the logic string. |
|
|
|
|
|
2. **Structural requirements**: |
|
|
- **Numeric values** `(e.g., 0, 5, 0.2, -130)` **must** be in parentheses: `(0)`, `(5)`, `(0.2)`, `(-130)`. |
|
|
- **AlphaNumeric values** `(e.g., hello, say 5, 4, hi!)` **must** be in parentheses: `(hello)`, `(say 5)`, `(4)`, `(hi!)`. |
|
|
- **Variables** must be in the form `[variable v]` (e.g., `[score v]`), even when used inside expressions two example use `set [score v] to (1)` or `show variable ([speed v])`. |
|
|
- **Dropdown options** must be in the form `[option v]` (e.g., `[Game Start v]`, `[blue sky v]`). example use `when [space v] key pressed`. |
|
|
- **Reporter blocks** used as inputs must be double‑wrapped: `((x position))`, `((y position))`. example use `if <((y position)) = (-130)> then` or `(((x position)) * (1))`. |
|
|
- **Boolean blocks** in conditions must be inside `< >`, including nested ones: `<not <condition>>`, `<<cond1> and <cond2>>`,`<<cond1> or <cond2>>`. |
|
|
- **Other Boolean blocks** in conditions must be inside `< >`, including nested ones or values or variables: `<(block/value/variable) * (block/value/variable)>`,`<(block/value/variable) < (block/value/variable)>`, and example of another variable`<[apple v] contains [a v]?>`. |
|
|
- **Operator expressions** must use explicit Scratch operator blocks, e.g.: |
|
|
``` |
|
|
(([ballSpeed v]) * (1.1)) |
|
|
``` |
|
|
- **Every hat block script must end** with a final `end` on its own line. |
|
|
|
|
|
3. **Pseudo‑code formatting**: |
|
|
- Represent each block or nested block on its own line. |
|
|
- Auto-correct invalid OCR phrases to valid Scratch 3.0 block names using the **Scratch 3.0 Block Reference** above. |
|
|
- **Indent nested blocks by 4 spaces under their parent (`forever`, `if`, etc.).This is a critical requirement.** |
|
|
- No comments or explanatory text—just the block sequence. |
|
|
- a natural language breakdown of each step taken after the event, formatted as a multi-line string representing pseudo-code. Ensure clarity and granularity—each described action should map closely to a Scratch block or tight sequence. |
|
|
|
|
|
4. **Logic content**: |
|
|
- Build clear flow for mechanics (movement, jumping, flying, scoring, collisions). |
|
|
- Match each action closely to a Scratch block or tight sequence. |
|
|
- Do **NOT** include any justification or comments—only the raw logic. |
|
|
|
|
|
5. **Examples for reference**: |
|
|
**Correct** pattern for a simple start script: |
|
|
``` |
|
|
when green flag clicked |
|
|
switch backdrop to [blue sky v] |
|
|
set [score v] to (0) |
|
|
show variable [score v] |
|
|
broadcast [Game Start v] |
|
|
end |
|
|
``` |
|
|
**Correct** pattern for updating the high score variable handling: |
|
|
``` |
|
|
when I receive [Game Over v] |
|
|
if <((score)) > (([High Score v]))> then |
|
|
set [High Score v] to ([score v]) |
|
|
end |
|
|
switch backdrop to [Game Over v] |
|
|
end |
|
|
``` |
|
|
**Correct** pattern for level up and increase difficulty use: |
|
|
``` |
|
|
when I receive [Level Up v] |
|
|
change [level v] by (1) |
|
|
set [ballSpeed v] to ((([ballSpeed v]) * (1.1))) |
|
|
end |
|
|
``` |
|
|
**Correct** pattern for jumping mechanics use: |
|
|
``` |
|
|
when [space v] key pressed |
|
|
if <((y position)) = (-100)> then |
|
|
repeat (5) |
|
|
change y by (100) |
|
|
wait (0.1) seconds |
|
|
change y by (-100) |
|
|
wait (0.1) seconds |
|
|
end |
|
|
end |
|
|
end |
|
|
``` |
|
|
**Correct** pattern for continuos moving objects use: |
|
|
``` |
|
|
when green flag clicked |
|
|
go to x: (240) y: (-100) |
|
|
set [speed v] to (-5) |
|
|
show variable [speed v] |
|
|
forever |
|
|
change x by ([speed v]) |
|
|
if <((x position)) < (-240)> then |
|
|
go to x: (240) y: (-100) |
|
|
end |
|
|
end |
|
|
end |
|
|
``` |
|
|
6. **Donot** add any explaination of logic or comments to justify or explain just put the logic content in the json. |
|
|
7. **Output**: |
|
|
Return **only** a JSON object, using double quotes everywhere: |
|
|
```json |
|
|
{{ |
|
|
"refined_logic":{{ |
|
|
"name_variable": 'Value of "Sript for: "', |
|
|
"pseudocode":"…your fully‑formatted pseudo‑code here…", |
|
|
}} |
|
|
}} |
|
|
``` |
|
|
""" |
|
|
image_input = { |
|
|
"type": "image_url", |
|
|
"image_url": { |
|
|
|
|
|
"url": clean_base64_for_model(image[cnt]) |
|
|
} |
|
|
} |
|
|
|
|
|
content = [ |
|
|
{"type": "text", "text": refinement_prompt}, |
|
|
image_input |
|
|
] |
|
|
|
|
|
try: |
|
|
|
|
|
response = agent.invoke({"messages": [{"role": "user", "content": content}]}) |
|
|
llm_output_raw = response["messages"][-1].content.strip() |
|
|
print(f"llm_output_raw: {response}") |
|
|
parsed_llm_output = extract_json_from_llm_response(llm_output_raw) |
|
|
result = parsed_llm_output |
|
|
print(f"result:\n\n {result}") |
|
|
|
|
|
except json.JSONDecodeError as error_json: |
|
|
|
|
|
correction_prompt = ( |
|
|
"Your task is to correct the provided JSON string to ensure it is **syntactically perfect and adheres strictly to JSON rules**.\n" |
|
|
"It must be a JSON object with `refined_logic` (string) and `block_relationships` (array of objects).\n" |
|
|
f"- **Error Details**: {error_json}\n\n" |
|
|
"**Strict Instructions for your response:**\n" |
|
|
"1. **ONLY** output the corrected JSON. Do not include any other text or explanations.\n" |
|
|
"2. Ensure all keys and string values are enclosed in **double quotes**. Escape internal quotes (`\\`).\n" |
|
|
"3. No trailing commas. Correct nesting.\n\n" |
|
|
"Here is the problematic JSON string to correct:\n" |
|
|
f"```json\n{llm_output_raw}\n```\n" |
|
|
"Corrected JSON:\n" |
|
|
) |
|
|
try: |
|
|
correction_response = agent_json_resolver.invoke({"messages": [{"role": "user", "content": correction_prompt}]}) |
|
|
corrected_output = extract_json_from_llm_response(correction_response['messages'][-1].content) |
|
|
|
|
|
result = corrected_output |
|
|
print(f"result:\n\n {result}") |
|
|
except Exception as e_corr: |
|
|
logger.error(f"Failed to correct JSON output for even after retry: {e_corr}") |
|
|
|
|
|
|
|
|
|
|
|
state["pseudo_code"] = result |
|
|
state["temp_pseudo_code"] += [result] |
|
|
Data = state["temp_pseudo_code"] |
|
|
|
|
|
|
|
|
print(f"[OVREALL REFINED PSEUDO CODE LOGIC]: {result}") |
|
|
print(f"[OVREALL LISTS OF LOGICS]: {Data}") |
|
|
logger.info("Plan refinement and block relation analysis completed for all plans.") |
|
|
return state |
|
|
|
|
|
|
|
|
def node_optimizer(state: GameState): |
|
|
logger.info("--- Running Node Optimizer Node ---") |
|
|
project_json = state["project_json"] |
|
|
raw = state.get("pseudo_code", {}) |
|
|
refined_logic_data = raw.get("refined_logic", {}) |
|
|
sprite_name = refined_logic_data.get("name_variable", "<unknown>") |
|
|
pseudo = refined_logic_data.get("pseudocode", "") |
|
|
sprite_name = {} |
|
|
project_json_targets = state.get("project_json", {}).get("targets", []) |
|
|
for target in project_json_targets: |
|
|
sprite_name[target["name"]] = target["name"] |
|
|
action_flow = state.get("action_plan", {}) |
|
|
|
|
|
try: |
|
|
refined_logic_data["pseudocode"] = separate_scripts(str(pseudo)) |
|
|
|
|
|
state["pseudo_code"]["refined_logic"] = refined_logic_data |
|
|
print(f"[The pseudo_code generated here]: { state['pseudo_code']}") |
|
|
state["action_plan"] = transform_logic_to_action_flow(state["pseudo_code"]) |
|
|
print(f"[The action plan generated here]: { state['action_plan']}") |
|
|
|
|
|
action_flow = state.get("action_plan", {}) |
|
|
if action_flow.get("action_overall_flow", {}) == {}: |
|
|
plan_data = action_flow.items() |
|
|
else: |
|
|
plan_data = action_flow.get("action_overall_flow", {}).items() |
|
|
|
|
|
refined_flow: Dict[str, Any] = {} |
|
|
for sprite, sprite_data in plan_data: |
|
|
refined_plans = [] |
|
|
for plan in sprite_data.get("plans", []): |
|
|
logic = plan.get("logic", "") |
|
|
plan["opcode_counts"]= analyze_opcode_counts(str(logic)) |
|
|
refined_plans.append(plan) |
|
|
refined_flow[sprite] = { |
|
|
"description": sprite_data.get("description", ""), |
|
|
"plans": refined_plans |
|
|
} |
|
|
if refined_flow: |
|
|
state["action_plan"] = refined_flow |
|
|
logger.info("Node Optimization completed.") |
|
|
|
|
|
return state |
|
|
except Exception as e: |
|
|
logger.error(f"Error in Node Optimizer Node: {e}") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def overall_block_builder_node_2(state: GameState): |
|
|
logger.info("--- Running OverallBlockBuilderNode ---") |
|
|
print("--- Running OverallBlockBuilderNode ---") |
|
|
project_json = state["project_json"] |
|
|
targets = project_json["targets"] |
|
|
|
|
|
sprite_map = {target["name"]: target for target in targets if not target["isStage"]} |
|
|
stage_target = next((target for target in targets if target["isStage"]), None) |
|
|
if stage_target: |
|
|
sprite_map[stage_target["name"]] = stage_target |
|
|
|
|
|
action_plan = state.get("action_plan", {}) |
|
|
print("[Overall Action Plan received at the block generator]:", json.dumps(action_plan, indent=2)) |
|
|
if not action_plan: |
|
|
logger.warning("No action plan found in state. Skipping OverallBlockBuilderNode.") |
|
|
return state |
|
|
|
|
|
|
|
|
script_y_offset = {} |
|
|
script_x_offset_per_sprite = {name: 0 for name in sprite_map.keys()} |
|
|
|
|
|
|
|
|
if action_plan.get("action_overall_flow", {}) == {}: |
|
|
plan_data = action_plan.items() |
|
|
else: |
|
|
plan_data = action_plan.get("action_overall_flow", {}).items() |
|
|
|
|
|
|
|
|
all_sprite_names = list(sprite_map.keys()) |
|
|
all_variable_names = {} |
|
|
all_list_names = {} |
|
|
all_broadcast_messages = {} |
|
|
|
|
|
for target in targets: |
|
|
for var_id, var_info in target.get("variables", {}).items(): |
|
|
all_variable_names[var_info[0]] = var_id |
|
|
for list_id, list_info in target.get("lists", {}).items(): |
|
|
all_list_names[list_info[0]] = list_id |
|
|
for broadcast_id, broadcast_name in target.get("broadcasts", {}).items(): |
|
|
all_broadcast_messages[broadcast_name] = broadcast_id |
|
|
|
|
|
|
|
|
for sprite_name, sprite_actions_data in plan_data: |
|
|
if sprite_name in sprite_map: |
|
|
current_sprite_target = sprite_map[sprite_name] |
|
|
if "blocks" not in current_sprite_target: |
|
|
current_sprite_target["blocks"] = {} |
|
|
|
|
|
if sprite_name not in script_y_offset: |
|
|
script_y_offset[sprite_name] = 0 |
|
|
|
|
|
for plan_entry in sprite_actions_data.get("plans", []): |
|
|
logic_sequence = str(plan_entry["logic"]) |
|
|
opcode_counts = plan_entry.get("opcode_counts", {}) |
|
|
refined_indent_logic = format_scratch_pseudo_code(logic_sequence) |
|
|
print(f"\n--------------------------- refined indent logic: {refined_indent_logic}-------------------------------\n") |
|
|
try: |
|
|
generated_blocks = block_builder(opcode_counts, refined_indent_logic) |
|
|
|
|
|
|
|
|
if not isinstance(generated_blocks, dict): |
|
|
logger.error(f"block_builder for sprite '{sprite_name}' returned non-dict type: {type(generated_blocks)}. Skipping block update.") |
|
|
continue |
|
|
|
|
|
if "blocks" in generated_blocks and isinstance(generated_blocks["blocks"], dict): |
|
|
logger.warning(f"LLM returned nested 'blocks' key for {sprite_name}. Unwrapping.") |
|
|
generated_blocks = generated_blocks["blocks"] |
|
|
|
|
|
|
|
|
for block_id, block_data in generated_blocks.items(): |
|
|
if block_data.get("topLevel"): |
|
|
block_data["x"] = script_x_offset_per_sprite.get(sprite_name, 0) |
|
|
block_data["y"] = script_y_offset[sprite_name] |
|
|
script_y_offset[sprite_name] += 150 |
|
|
|
|
|
current_sprite_target["blocks"].update(generated_blocks) |
|
|
print(f"[current_sprite_target block updated]: {current_sprite_target['blocks']}") |
|
|
state["iteration_count"] = 0 |
|
|
logger.info(f"Action blocks added for sprite '{sprite_name}' by OverallBlockBuilderNode.") |
|
|
except Exception as e: |
|
|
logger.error(f"Error generating blocks for sprite '{sprite_name}': {e}") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
state["project_json"] = project_json |
|
|
|
|
|
|
|
|
|
|
|
return state |
|
|
|
|
|
|
|
|
def variable_adder_node(state: GameState): |
|
|
logger.info("--- Running Variable Adder Node ---") |
|
|
project_json = state["project_json"] |
|
|
try: |
|
|
updated_project_json = variable_adder_main(project_json) |
|
|
if updated_project_json is not None: |
|
|
print("Variable added inside the project successfully!") |
|
|
state["project_json"]=updated_project_json |
|
|
else: |
|
|
print("Variable adder unable to add any variable inside the project!") |
|
|
state["project_json"]=project_json |
|
|
state["page_count"] +=1 |
|
|
return state |
|
|
except Exception as e: |
|
|
logger.error(f"Error in variable adder node while updating project_json': {e}") |
|
|
raise |
|
|
|
|
|
|
|
|
def layer_order_correction(state: GameState): |
|
|
""" |
|
|
Ensures that all sprites (isStage: false) have unique layerOrder values >= 1. |
|
|
If duplicates are found, they are reassigned sequentially. |
|
|
""" |
|
|
logger.info("--- Running Layer Order Correction Node ---") |
|
|
try: |
|
|
project_json = state.get("project_json", {}) |
|
|
targets = project_json.get("targets", []) |
|
|
|
|
|
|
|
|
sprites = [t for t in targets if not t.get("isStage", False)] |
|
|
|
|
|
|
|
|
for idx, sprite in enumerate(sprites, start=1): |
|
|
old_lo = sprite.get("layerOrder", None) |
|
|
sprite["layerOrder"] = idx |
|
|
logger.debug(f"Sprite '{sprite.get('name')}' layerOrder: {old_lo} -> {idx}") |
|
|
|
|
|
|
|
|
for target in targets: |
|
|
if target.get("isStage", False): |
|
|
target["layerOrder"] = 0 |
|
|
|
|
|
|
|
|
state["project_json"]["targets"] = targets |
|
|
logger.info("Layer Order Correction completed successfully.") |
|
|
|
|
|
return state |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Error in Layer Order Correction Node: {e}") |
|
|
return state |
|
|
|
|
|
|
|
|
def processed_page_node(state: GameState): |
|
|
logger.info("--- Processing the Pages Node ---") |
|
|
image = state.get("project_image", "") |
|
|
cnt =state["page_count"] |
|
|
print(f"The page processed for page:--------------> {cnt}") |
|
|
if cnt<len(image): |
|
|
state["processing"]= True |
|
|
else: |
|
|
state["processing"]= False |
|
|
return state |
|
|
|
|
|
|
|
|
manipulated_json = {} |
|
|
img_elements = [] |
|
|
|
|
|
def extract_images_from_pdf(pdf_stream: io.BytesIO): |
|
|
''' Extract images from PDF and generate structured sprite JSON ''' |
|
|
try: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if isinstance(pdf_stream, io.BytesIO): |
|
|
|
|
|
pdf_id = uuid.uuid4().hex |
|
|
else: |
|
|
pdf_id = os.path.splitext(os.path.basename(pdf_stream))[0] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try: |
|
|
elements = partition_pdf( |
|
|
|
|
|
file=pdf_stream, |
|
|
strategy="hi_res", |
|
|
extract_image_block_types=["Image"], |
|
|
hi_res_model_name="yolox", |
|
|
extract_image_block_to_payload=True, |
|
|
) |
|
|
print(f"ELEMENTS") |
|
|
except Exception as e: |
|
|
raise RuntimeError( |
|
|
f"❌ Failed to extract images from PDF: {str(e)}") |
|
|
|
|
|
file_elements = [element.to_dict() for element in elements] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sprite_count = 1 |
|
|
for el in file_elements: |
|
|
img_b64 = el["metadata"].get("image_base64") |
|
|
if not img_b64: |
|
|
continue |
|
|
|
|
|
manipulated_json[f"Sprite {sprite_count}"] = { |
|
|
|
|
|
|
|
|
"base64": el["metadata"]["image_base64"], |
|
|
"file-path": pdf_id, |
|
|
|
|
|
} |
|
|
sprite_count += 1 |
|
|
return manipulated_json |
|
|
except Exception as e: |
|
|
raise RuntimeError(f"❌ Error in extract_images_from_pdf: {str(e)}") |
|
|
|
|
|
|
|
|
def similarity_matching(sprites_data: str, project_folder: str) -> str: |
|
|
logger.info("🔍 Running similarity matching…") |
|
|
os.makedirs(project_folder, exist_ok=True) |
|
|
|
|
|
|
|
|
|
|
|
backdrop_base_path = os.path.normpath(str(BACKDROP_DIR)) |
|
|
sprite_base_path = os.path.normpath(str(SPRITE_DIR)) |
|
|
code_blocks_path = os.path.normpath(str(CODE_BLOCKS_DIR)) |
|
|
|
|
|
|
|
|
project_json_path = os.path.join(project_folder, "project.json") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sprite_ids, sprite_base64 = [], [] |
|
|
for sid, sprite in sprites_data.items(): |
|
|
sprite_ids.append(sid) |
|
|
|
|
|
sprite_base64.append(sprite["base64"]) |
|
|
|
|
|
sprite_images_bytes = [] |
|
|
for b64 in sprite_base64: |
|
|
img = Image.open(BytesIO(base64.b64decode(b64.split(",")[-1]))).convert("RGB") |
|
|
buffer = BytesIO() |
|
|
img.save(buffer, format="PNG") |
|
|
buffer.seek(0) |
|
|
sprite_images_bytes.append(buffer) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
folder_image_paths = [ |
|
|
SPRITE_DIR / "Abby.sprite3" / "34a175600dc009a521eb46fdbbbeeb67.png" |
|
|
,SPRITE_DIR / "Abby.sprite3" / "45de34b47a2ce22f6f5d28bb35a44ff5.png" |
|
|
,SPRITE_DIR / "Abby.sprite3" / "809d9b47347a6af2860e7a3a35bce057.png" |
|
|
,SPRITE_DIR / "Abby.sprite3" / "920f14335615fff9b8c55fccb8971984.png" |
|
|
,SPRITE_DIR / "Amon.sprite3" / "60f720956ab1840431dcf0616ce98f14.png" |
|
|
,SPRITE_DIR / "Andie.sprite3" / "b36584db82bdd45014430aa918461ca0.png" |
|
|
,SPRITE_DIR / "Andie.sprite3" / "b3fc774e753fef520fb544127a48554b.png" |
|
|
,SPRITE_DIR / "Andie.sprite3" / "d92aaf6cf44921905d51ca4a10a4f3d6.png" |
|
|
,SPRITE_DIR / "Andie.sprite3" / "ded71c8a0f39852178f1695b622c2d89.png" |
|
|
,SPRITE_DIR / "Anina Dance.sprite3" / "105f4f3d260dcb8bea02ea9ee5d18cf4.png" |
|
|
,SPRITE_DIR / "Anina Dance.sprite3" / "2d208a34e74fdce9dab9d4c585dcfa2b.png" |
|
|
,SPRITE_DIR / "Anina Dance.sprite3" / "3948aad16f8169c013c956dd152a09a6.png" |
|
|
,SPRITE_DIR / "Anina Dance.sprite3" / "4931a363e3e4efa20230f6ff2991c6b4.png" |
|
|
,SPRITE_DIR / "Anina Dance.sprite3" / "62c50c90535b64f2ae130a5c680ddcb4.png" |
|
|
,SPRITE_DIR / "Anina Dance.sprite3" / "7bb9c790b02231e1272701167c26b17a.png" |
|
|
,SPRITE_DIR / "Anina Dance.sprite3" / "84c5e22b4303c7c1fb707125706c9aaa.png" |
|
|
,SPRITE_DIR / "Anina Dance.sprite3" / "b7693bd6250d4411ee622b67f8025924.png" |
|
|
,SPRITE_DIR / "Anina Dance.sprite3" / "ca27e001a263ee6b5852508f39d021db.png" |
|
|
,SPRITE_DIR / "Anina Dance.sprite3" / "d86bb27b4f8d7b70c39c96f29c6943b4.png" |
|
|
,SPRITE_DIR / "Anina Dance.sprite3" / "db6c03113f71b91f22a9f3351f90e5bf.png" |
|
|
,SPRITE_DIR / "Anina Dance.sprite3" / "e3698b76cb0864df2fbaba80e6bd8067.png" |
|
|
,SPRITE_DIR / "Anina Dance.sprite3" / "ed90e8b7a05c1552194af597ac0637cd.png" |
|
|
,SPRITE_DIR / "Apple.sprite3" / "3826a4091a33e4d26f87a2fac7cf796b.png" |
|
|
,SPRITE_DIR / "Arrow1.sprite3" / "65b8e977641885010a10a46512fb95b4.png" |
|
|
,SPRITE_DIR / "Arrow1.sprite3" / "70ffa0bae8693418459f21f370584f6d.png" |
|
|
,SPRITE_DIR / "Arrow1.sprite3" / "be8fcd10da0b082f8d4775088ef7bd52.png" |
|
|
,SPRITE_DIR / "Arrow1.sprite3" / "dafcdfda65af14e172809984710f31a9.png" |
|
|
,SPRITE_DIR / "Avery Walking.sprite3" / "3a935fe75ac999e22b93d06b3081a271.png" |
|
|
,SPRITE_DIR / "Avery Walking.sprite3" / "448e54fb14b13d492885fc247e76b7f4.png" |
|
|
,SPRITE_DIR / "Avery Walking.sprite3" / "8f439476a738251043d488d7a4bc6870.png" |
|
|
,SPRITE_DIR / "Avery Walking.sprite3" / "dc6a584704c09a3fbafb9825635a9fd4.png" |
|
|
,SPRITE_DIR / "Avery.sprite3" / "944385ea927e8f9d72b9e19620487999.png" |
|
|
,SPRITE_DIR / "Avery.sprite3" / "f52bde34d8027aab14b53f228fe5cc14.png" |
|
|
,SPRITE_DIR / "Ball.sprite3" / "1c44b7494dec047371f74c705f1d99fc.png" |
|
|
,SPRITE_DIR / "Ball.sprite3" / "3c6241985b581284ec191f9d1deffde8.png" |
|
|
,SPRITE_DIR / "Ball.sprite3" / "ad7dc51cafd73e8279073e33b0eab335.png" |
|
|
,SPRITE_DIR / "Ball.sprite3" / "db144b2a19f4f1ab31e30d58f00447dc.png" |
|
|
,SPRITE_DIR / "Ball.sprite3" / "f221a2edf87aff3615c0c003e616b31b.png" |
|
|
,SPRITE_DIR / "Ballerina.sprite3" / "4ccb1752a43f48aafe490c9c08e58c27.png" |
|
|
,SPRITE_DIR / "Ballerina.sprite3" / "5197d3778baf55da6b81b3ada1e10021.png" |
|
|
,SPRITE_DIR / "Ballerina.sprite3" / "5aae21aee33c3f1ae943af5ea11254bf.png" |
|
|
,SPRITE_DIR / "Ballerina.sprite3" / "fc02bf591dd3d91eeeb50c7424d08274.png" |
|
|
,SPRITE_DIR / "Balloon1.sprite3" / "63e5aea255610f9fdf0735e1e9a55a5c.png" |
|
|
,SPRITE_DIR / "Balloon1.sprite3" / "a2516ac2b8d7a348194908e630387ea9.png" |
|
|
,SPRITE_DIR / "Balloon1.sprite3" / "d7974f9e15000c16222f94ee32d8227a.png" |
|
|
,SPRITE_DIR / "Bananas.sprite3" / "e5d3d3eb61797f5999732a8f5efead24.png" |
|
|
,SPRITE_DIR / "Baseball.sprite3" / "74e08fc57820f925c7689e7b754c5848.png" |
|
|
,SPRITE_DIR / "Basketball.sprite3" / "6b0b2aaa12d655e96b5b34e92d9fbd4f.png" |
|
|
,SPRITE_DIR / "Bat.sprite3" / "4e4ced87ed37ee66c758bba077e0eae6.png" |
|
|
,SPRITE_DIR / "Bat.sprite3" / "60f5bfce5d9b11bfcd199a6aa5454b3f.png" |
|
|
,SPRITE_DIR / "Bat.sprite3" / "698c2a48e774f9959d57c9618b156c20.png" |
|
|
,SPRITE_DIR / "Bat.sprite3" / "bc6dd12fc9e407c7774959cdf427f8b5.png" |
|
|
,SPRITE_DIR / "Batter.sprite3" / "592ee9ab2aeefe65cb4fb95fcd046f33.png" |
|
|
,SPRITE_DIR / "Batter.sprite3" / "9d193bef6e3d6d8eba6d1470b8bf9351.png" |
|
|
,SPRITE_DIR / "Batter.sprite3" / "baseball_sprite_motion_1.png" |
|
|
,SPRITE_DIR / "Batter.sprite3" / "bd4fc003528acfa847e45ff82f346eee.png" |
|
|
,SPRITE_DIR / "Batter.sprite3" / "fdfde4bcbaca0f68e83fdf3f4ef0c660.png" |
|
|
,SPRITE_DIR / "Beachball.sprite3" / "5198b5a03ebae60698e0906f59a5fc15.png" |
|
|
,SPRITE_DIR / "Bear-walking.sprite3" / "0a38a860f2e573b8dc5b09f390d30fbd.png" |
|
|
,SPRITE_DIR / "Bear-walking.sprite3" / "36d06aa23c684fc996952adb0e76e6b4.png" |
|
|
,SPRITE_DIR / "Bear-walking.sprite3" / "6d4d06e3f4cd0c9455b777b9a40782b6.png" |
|
|
,SPRITE_DIR / "Bear-walking.sprite3" / "6d50c5fe63ab5f77d10144a68ca535a6.png" |
|
|
,SPRITE_DIR / "Bear-walking.sprite3" / "7453709bef16e33e6f989aee14d7fc07.png" |
|
|
,SPRITE_DIR / "Bear-walking.sprite3" / "d2a5f124f988def1d214e6d0813a48f3.png" |
|
|
,SPRITE_DIR / "Bear-walking.sprite3" / "e531b307381c2aa148be4ccc36db0333.png" |
|
|
,SPRITE_DIR / "Bear-walking.sprite3" / "f36c80d2e731be95df7ec6d07f89fa00.png" |
|
|
,SPRITE_DIR / "Bear.sprite3" / "6f303e972f33fcb7ef36d0d8012d0975.png" |
|
|
,SPRITE_DIR / "Bear.sprite3" / "bear_motion_2.png" |
|
|
,SPRITE_DIR / "Bear.sprite3" / "deef1eaa96d550ae6fc11524a1935024.png" |
|
|
,SPRITE_DIR / "Beetle.sprite3" / "46d0dfd4ae7e9bfe3a6a2e35a4905eae.png" |
|
|
,SPRITE_DIR / "Bell.sprite3" / "8c0234fe1bfd36f5a72e975fbbc18bfd.png" |
|
|
,SPRITE_DIR / "Ben.sprite3" / "165d993c30dfdb9e829d0d98867d7826.png" |
|
|
,SPRITE_DIR / "Ben.sprite3" / "2cd77b8a9961e7ad4da905e7731b7c1b.png" |
|
|
,SPRITE_DIR / "Ben.sprite3" / "9f9f88aea3457084d8d734040b0b9067.png" |
|
|
,SPRITE_DIR / "Ben.sprite3" / "acc208e29f0422c2bcffa3b8873abc63.png" |
|
|
,SPRITE_DIR / "Block-A.sprite3" / "ef3b01f6fc1ffa1270fbbf057f7ded42.png" |
|
|
,SPRITE_DIR / "Block-B.sprite3" / "1dc05fbaa37a6b41ffff459d0a776989.png" |
|
|
,SPRITE_DIR / "Block-C.sprite3" / "43090c4b423c977041542ce12017fda0.png" |
|
|
,SPRITE_DIR / "Block-D.sprite3" / "1fb3db31500d6f7da662e825157920fa.png" |
|
|
,SPRITE_DIR / "Block-E.sprite3" / "240aacc04444cef3b2ef8cfaf0dae479.png" |
|
|
,SPRITE_DIR / "Block-F.sprite3" / "d88d750ce848d7dbeeca3f02249350e2.png" |
|
|
,SPRITE_DIR / "Block-G.sprite3" / "989c76ae7f8c2e42ebeacdda961061ca.png" |
|
|
,SPRITE_DIR / "Block-H.sprite3" / "93426b2f313d1bdedff368d94fc989d6.png" |
|
|
,SPRITE_DIR / "Block-I.sprite3" / "f911b18605f59c75adf4d83e07811fd8.png" |
|
|
,SPRITE_DIR / "Block-J.sprite3" / "8580c990ac918577550165447f870542.png" |
|
|
,SPRITE_DIR / "Block-K.sprite3" / "d93a9fd4bfb5bc1e9790945fa756b748.png" |
|
|
,SPRITE_DIR / "Block-L.sprite3" / "579c90cbaf847e9adf4faf37f340b32d.png" |
|
|
,SPRITE_DIR / "Block-M.sprite3" / "6c5cf1fd0673f441b04e15e799685831.png" |
|
|
,SPRITE_DIR / "Block-N.sprite3" / "9eba5dd44d65e1d421c40686fecde906.png" |
|
|
,SPRITE_DIR / "Block-O.sprite3" / "8bbbde09c13a06015e554ab36fa178c0.png" |
|
|
,SPRITE_DIR / "Block-P.sprite3" / "0f920b99ac49421cf28e55c8d863bdc5.png" |
|
|
,SPRITE_DIR / "Block-Q.sprite3" / "67f8e80eabaec4883eb9c67c9527004a.png" |
|
|
,SPRITE_DIR / "Block-R.sprite3" / "9d0432c5575451e251990d89845f8d00.png" |
|
|
,SPRITE_DIR / "Block-S.sprite3" / "83c7486b08e78d099b4e776aaa2783fe.png" |
|
|
,SPRITE_DIR / "Block-T.sprite3" / "6c1b26611ec0483f601a648f59305aff.png" |
|
|
,SPRITE_DIR / "Block-U.sprite3" / "d02f77994789f528f0aaa7f211690151.png" |
|
|
,SPRITE_DIR / "Block-V.sprite3" / "0654cfcb6234406837336e90be7e419c.png" |
|
|
,SPRITE_DIR / "Block-W.sprite3" / "2b3145ae89c32793c4fcea9a6bcc6075.png" |
|
|
,SPRITE_DIR / "Block-X.sprite3" / "a73f354dc045bbbc5a491d9367192a80.png" |
|
|
,SPRITE_DIR / "Block-Y.sprite3" / "e13e79f106d32a3176dbcf5c1b35827d.png" |
|
|
,SPRITE_DIR / "Block-Z.sprite3" / "c57d371b291d43675f46601518098572.png" |
|
|
,SPRITE_DIR / "Bowl.sprite3" / "d147f16e3e2583719c073ac5b55fe3ca.png" |
|
|
,SPRITE_DIR / "Bowtie.sprite3" / "4b032ba44b8077439e73815542e7ed23.png" |
|
|
,SPRITE_DIR / "Bread.sprite3" / "585de1550446d4420f8a10fdecac995b.png" |
|
|
,SPRITE_DIR / "Broom.sprite3" / "556288a1c996345c751a3dc88b570cfa.png" |
|
|
,SPRITE_DIR / "Buildings.sprite3" / "148034b1557cc3dae39953e43ab50ff0.png" |
|
|
,SPRITE_DIR / "Buildings.sprite3" / "4212ff1769c169bfa0db043b18fdade8.png" |
|
|
,SPRITE_DIR / "Buildings.sprite3" / "80b120b7152ed72fded84fef485f4f79.png" |
|
|
,SPRITE_DIR / "Buildings.sprite3" / "8f64966be60d332b345598819c67a8b6.png" |
|
|
,SPRITE_DIR / "Buildings.sprite3" / "a8c977a3b85ffe8c8b453c9d668989b8.png" |
|
|
,SPRITE_DIR / "Buildings.sprite3" / "bb47a3d5d03a34937557c558c6cb5d18.png" |
|
|
,SPRITE_DIR / "Buildings.sprite3" / "d1fcce0aac589a17324943a3b759fc2a.png" |
|
|
,SPRITE_DIR / "Buildings.sprite3" / "e4764cfc384a499f92da3ea745bcebe2.png" |
|
|
,SPRITE_DIR / "Buildings.sprite3" / "e8c9508b1f6a0a432e09c10ef9ada67c.png" |
|
|
,SPRITE_DIR / "Buildings.sprite3" / "fcedb6b25a2db6de28b39130f978b0bf.png" |
|
|
,SPRITE_DIR / "Butterfly 1.sprite3" / "34b76c1835c6a7fc2c47956e49bb0f52.png" |
|
|
,SPRITE_DIR / "Butterfly 1.sprite3" / "49c9f952007d870a046cff93b6e5e098.png" |
|
|
,SPRITE_DIR / "Butterfly 1.sprite3" / "fe98df7367e314d9640bfaa54fc239be.png" |
|
|
,SPRITE_DIR / "Butterfly 2.sprite3" / "372ae0abd2e8e50a20bc12cb160d8746.png" |
|
|
,SPRITE_DIR / "Butterfly 2.sprite3" / "e96f4c6913107c9b790d37bb65507c14.png" |
|
|
,SPRITE_DIR / "Button1.sprite3" / "21fb7fa07eac4794fded0be4e18e20a2.png" |
|
|
,SPRITE_DIR / "Button2.sprite3" / "329bf3d86050ceaea2b27e2c5d2baec1.png" |
|
|
,SPRITE_DIR / "Button2.sprite3" / "af4cd54e776031bc9cc54ddd6892f97b.png" |
|
|
,SPRITE_DIR / "Button3.sprite3" / "5021f6b7d166873ef0711c4d4a351912.png" |
|
|
,SPRITE_DIR / "Button3.sprite3" / "a3b357ea21773bcb3545a227ee877e9a.png" |
|
|
,SPRITE_DIR / "Button4.sprite3" / "71ced7c192168c7b221d16b4eaff440e.png" |
|
|
,SPRITE_DIR / "Button4.sprite3" / "7d34ad26633abbc752c9cd93ace0a81f.png" |
|
|
,SPRITE_DIR / "Button5.sprite3" / "94957f2f79e8970d8b2cd0f74a0c1ffc.png" |
|
|
,SPRITE_DIR / "Button5.sprite3" / "a4bb9a9e06e65337798471035719985a.png" |
|
|
,SPRITE_DIR / "Cake.sprite3" / "862488bf66b67c5330cae9235b853b6e.png" |
|
|
,SPRITE_DIR / "Cake.sprite3" / "dfe9c5d40da0dcc386fad524c36d3579.png" |
|
|
,SPRITE_DIR / "Calvrett.sprite3" / "452683db3ad7a882f5ab9de496441592.png" |
|
|
,SPRITE_DIR / "Calvrett.sprite3" / "728ec1ebc275b53809023a36c66eeaa3.png" |
|
|
,SPRITE_DIR / "Casey.sprite3" / "50bd5162671b8a30fcfa3082a9e79ec4.png" |
|
|
,SPRITE_DIR / "Casey.sprite3" / "e09e5ef2bdeb69163a543f3216c1f54c.png" |
|
|
,SPRITE_DIR / "Casey.sprite3" / "e5a47371f3e9f853b36560cda35344b6.png" |
|
|
,SPRITE_DIR / "Casey.sprite3" / "ebc3de539e02801d420268eb189c5a47.png" |
|
|
,SPRITE_DIR / "Cassy Dance.sprite3" / "63483bbf72fc55719918a335e1a16426.png" |
|
|
,SPRITE_DIR / "Cassy Dance.sprite3" / "6cb3686db1fa658b6541cc9fa3ccfcc7.png" |
|
|
,SPRITE_DIR / "Cassy Dance.sprite3" / "aca39a47cf3affd8a83d3287d2856c29.png" |
|
|
,SPRITE_DIR / "Cassy Dance.sprite3" / "f801cec764da5ef6374e1d557296d14e.png" |
|
|
,SPRITE_DIR / "Cat 2.sprite3" / "7499cf6ec438d0c7af6f896bc6adc294.png" |
|
|
,SPRITE_DIR / "Cat Flying.sprite3" / "6667936a2793aade66c765c329379ad0.png" |
|
|
,SPRITE_DIR / "Cat Flying.sprite3" / "a1ab94c8172c3b97ed9a2bf7c32172cd.png" |
|
|
,SPRITE_DIR / "Cat.sprite3" / "0fb9be3e8397c983338cb71dc84d0b25.png" |
|
|
,SPRITE_DIR / "Cat.sprite3" / "bcf454acf82e4504149f7ffe07081dbc.png" |
|
|
,SPRITE_DIR / "Catcher.sprite3" / "895cdda4f2bd9d6f50ff07188e7ce395.png" |
|
|
,SPRITE_DIR / "Catcher.sprite3" / "8aa875f077c405e2045f5ab60705e712.png" |
|
|
,SPRITE_DIR / "Catcher.sprite3" / "99af13802e9bfd7b4a4bfb8ead825c0c.png" |
|
|
,SPRITE_DIR / "Catcher.sprite3" / "a31e30677637ae4de975d40b6d822853.png" |
|
|
,SPRITE_DIR / "Centaur.sprite3" / "2373556e776cad3ba4d6ee04fc34550b.png" |
|
|
,SPRITE_DIR / "Centaur.sprite3" / "c00ffa6c5dd0baf9f456b897ff974377.png" |
|
|
,SPRITE_DIR / "Centaur.sprite3" / "d722329bd9373ad80625e5be6d52f3ed.png" |
|
|
,SPRITE_DIR / "Centaur.sprite3" / "d7aa990538915b7ef1f496d7e8486ade.png" |
|
|
,SPRITE_DIR / "Champ99.sprite3" / "20318b14a332fd618ec91e7c1de8be9a.png" |
|
|
,SPRITE_DIR / "Champ99.sprite3" / "26fdff424232926001d20041c3d5673b.png" |
|
|
,SPRITE_DIR / "Champ99.sprite3" / "56f3220fa82d99dcfc7d27d433ed01e4.png" |
|
|
,SPRITE_DIR / "Champ99.sprite3" / "68453506ae4b6b60a3fc6817ba39d492.png" |
|
|
,SPRITE_DIR / "Champ99.sprite3" / "7b073f47fbd9421e0d60daacc157f506.png" |
|
|
,SPRITE_DIR / "Champ99.sprite3" / "a28ffc2b129fb359ff22c79c48341267.png" |
|
|
,SPRITE_DIR / "Champ99.sprite3" / "d6ae13605610aa008d48b0c8b25a57d3.png" |
|
|
,SPRITE_DIR / "Characters 1.sprite3" / "03bc23a9fa12c1244c83a07a81f20bfd.png" |
|
|
,SPRITE_DIR / "Characters 1.sprite3" / "0f18f9e90d0ed68ebec23da087eb2603.png" |
|
|
,SPRITE_DIR / "Characters 1.sprite3" / "1044a68cc743f83564e36a6bca16830b.png" |
|
|
,SPRITE_DIR / "Characters 1.sprite3" / "1e303bb57aac0cb4678e85de4251f3f4.png" |
|
|
,SPRITE_DIR / "Characters 1.sprite3" / "527ba82c5e82f43c8fca0be905dbe20a.png" |
|
|
,SPRITE_DIR / "Characters 1.sprite3" / "5e2f620e5687a36e1954414054c69ccc.png" |
|
|
,SPRITE_DIR / "Characters 1.sprite3" / "6be261800647c53becb1f93ed31ed13e.png" |
|
|
,SPRITE_DIR / "Characters 1.sprite3" / "6d5ddfc69f9c6a3f1d2ded1428237931.png" |
|
|
,SPRITE_DIR / "Characters 1.sprite3" / "6f78ce6a87d114162ed9fbef30f9a0fd.png" |
|
|
,SPRITE_DIR / "Characters 1.sprite3" / "984043e1e7c544999c31f952d1d43a56.png" |
|
|
,SPRITE_DIR / "Characters 1.sprite3" / "b37d0e0d46f07cb2cbdc5285e176bf62.png" |
|
|
,SPRITE_DIR / "Characters 1.sprite3" / "cc0be722cf93eef63726bd606ab11c5c.png" |
|
|
,SPRITE_DIR / "Characters 1.sprite3" / "f26b130c2c58b812be21d1a9745863a1.png" |
|
|
,SPRITE_DIR / "Characters 2.sprite3" / "1cf73a791959e07b5bafe18474f93b78.png" |
|
|
,SPRITE_DIR / "Characters 2.sprite3" / "67d425b11544caa0fe9228f355c6485b.png" |
|
|
,SPRITE_DIR / "Characters 2.sprite3" / "7084b3baab935de819cc5ab46f7cecf8.png" |
|
|
,SPRITE_DIR / "Characters 2.sprite3" / "93e035270675f933b94ee951d7e475e3.png" |
|
|
,SPRITE_DIR / "Characters 2.sprite3" / "bf0d808f7bf0c11c338b4fea0a735874.png" |
|
|
,SPRITE_DIR / "Characters 2.sprite3" / "db3f436fcb6fb28828a4c932b60feb5e.png" |
|
|
,SPRITE_DIR / "Characters 2.sprite3" / "df7cbf2913bcea721df2e0360644f193.png" |
|
|
,SPRITE_DIR / "Characters 2.sprite3" / "e0eacf1e575adc559c41e3a81a892168.png" |
|
|
,SPRITE_DIR / "Characters 2.sprite3" / "e8b44b0e904fd4bb7430c26b743f1520.png" |
|
|
,SPRITE_DIR / "Characters 2.sprite3" / "f4f2778df2840de5a6449a49f3efb599.png" |
|
|
,SPRITE_DIR / "Cheesy Puffs.sprite3" / "82772a61ec74974e84c686c61ea0b7d5.png" |
|
|
,SPRITE_DIR / "Chick.sprite3" / "5e23c8c28ffd390df7deb2414be37781.png" |
|
|
,SPRITE_DIR / "Chick.sprite3" / "77911bbe5e11ede35871e8002a26356d.png" |
|
|
,SPRITE_DIR / "Chick.sprite3" / "80abbc427366bca477ccf1ef0faf240a.png" |
|
|
,SPRITE_DIR / "City Bus.sprite3" / "7d7e26014a346b894db8ab1819f2167f.png" |
|
|
,SPRITE_DIR / "City Bus.sprite3" / "e9694adbff9422363e2ea03166015393.png" |
|
|
,SPRITE_DIR / "Cloud.sprite3" / "c9630e30e59e4565e785a26f58568904.png" |
|
|
,SPRITE_DIR / "Clouds.sprite3" / "0188b2c7c85176b462881c6bca7a7748.png" |
|
|
,SPRITE_DIR / "Clouds.sprite3" / "9105d7dd90b5f2a4b85a1e71aff8703f.png" |
|
|
,SPRITE_DIR / "Clouds.sprite3" / "9f2eccce13e3e5fd212efd59ff1d96a0.png" |
|
|
,SPRITE_DIR / "Clouds.sprite3" / "9f5958f46d21e33d3f6d7caffbe0daa9.png" |
|
|
,SPRITE_DIR / "Convertible 2.sprite3" / "621817ef84ad81f5690fac95adab2ede.png" |
|
|
,SPRITE_DIR / "Convertible.sprite3" / "5b883f396844ff5cfecd7c95553fa4fb.png" |
|
|
,SPRITE_DIR / "Crab.sprite3" / "49839aa1b0feed02a3c759db5f8dee71.png" |
|
|
,SPRITE_DIR / "Crab.sprite3" / "f7cdd2acbc6d7559d33be8675059c79e.png" |
|
|
,SPRITE_DIR / "Crystal.sprite3" / "0a7b872042cecaf30cc154c0144f002b.png" |
|
|
,SPRITE_DIR / "Crystal.sprite3" / "ecd1e7805b37db4caf207b7eef2b7a42.png" |
|
|
,SPRITE_DIR / "D-Money Dance.sprite3" / "05529eb3c09294bd15f57c6f10d5894e.png" |
|
|
,SPRITE_DIR / "D-Money Dance.sprite3" / "12db59633a1709a2c39534d35263791f.png" |
|
|
,SPRITE_DIR / "D-Money Dance.sprite3" / "19bd7995d37e3baade673b2fe7cb982b.png" |
|
|
,SPRITE_DIR / "D-Money Dance.sprite3" / "32ec7b5332cfebd1cfed7f6b79c76e67.png" |
|
|
,SPRITE_DIR / "D-Money Dance.sprite3" / "344384a6a3f1bdf494cc7af31e928d36.png" |
|
|
,SPRITE_DIR / "D-Money Dance.sprite3" / "3cdebabdb41f6c3e84561cf3ea87bac3.png" |
|
|
,SPRITE_DIR / "D-Money Dance.sprite3" / "50faf1630ea383c0b8c77f70a9329797.png" |
|
|
,SPRITE_DIR / "D-Money Dance.sprite3" / "70da166596bb484eae1bfbaad5c03d54.png" |
|
|
,SPRITE_DIR / "D-Money Dance.sprite3" / "729812366245c0dafd456339c9d94e08.png" |
|
|
,SPRITE_DIR / "D-Money Dance.sprite3" / "a22da98e5e63de7b2883355afd0184f0.png" |
|
|
,SPRITE_DIR / "D-Money Dance.sprite3" / "a4b5d644d9abdbcab236acf19b2a2e81.png" |
|
|
,SPRITE_DIR / "D-Money Dance.sprite3" / "dafbdfe454c5ec7029b5c1e07fcabc90.png" |
|
|
,SPRITE_DIR / "Dan.sprite3" / "307250744e230fb15e7062238bf2634c.png" |
|
|
,SPRITE_DIR / "Dan.sprite3" / "89b55d049f4b3811676311df00681385.png" |
|
|
,SPRITE_DIR / "Dani.sprite3" / "2cba86439098a7e0daa46e0ff8a59f7c.png" |
|
|
,SPRITE_DIR / "Dani.sprite3" / "6518333c95cf96a9aaf73a4a948e002f.png" |
|
|
,SPRITE_DIR / "Dani.sprite3" / "b5f989e21b56af371209369c331b821e.png" |
|
|
,SPRITE_DIR / "Dee.sprite3" / "1de3bbee2771b0ff16c4658d5ad98b0b.png" |
|
|
,SPRITE_DIR / "Dee.sprite3" / "320a892c86e9b039ba9d6d50a4897276.png" |
|
|
,SPRITE_DIR / "Dee.sprite3" / "43bd4c241a94b3aea883472d7dab5afc.png" |
|
|
,SPRITE_DIR / "Dee.sprite3" / "c57c4593701165cdea6de9b014c7c06d.png" |
|
|
,SPRITE_DIR / "Dee.sprite3" / "e4c6ada3509f7033d14bac2c0eea49dc.png" |
|
|
,SPRITE_DIR / "Devin.sprite3" / "5ab51aeaa296e955e75a7a3c103ebb99.png" |
|
|
,SPRITE_DIR / "Devin.sprite3" / "5f614017dba0ce6bff063f6c62041035.png" |
|
|
,SPRITE_DIR / "Devin.sprite3" / "9d7414a719d6cc5e0e9071ede200a29c.png" |
|
|
,SPRITE_DIR / "Devin.sprite3" / "bfc7c20b64f86d4b207780f3da695fa4.png" |
|
|
,SPRITE_DIR / "Dinosaur1.sprite3" / "22d94ee5daf557284465425a61186234.png" |
|
|
,SPRITE_DIR / "Dinosaur1.sprite3" / "45b02fbd582c15a50e1953830b59b377.png" |
|
|
,SPRITE_DIR / "Dinosaur1.sprite3" / "7f89417968116ada83d4ddaad22403b3.png" |
|
|
,SPRITE_DIR / "Dinosaur1.sprite3" / "af158d368bf3da576369be1130e18acd.png" |
|
|
,SPRITE_DIR / "Dinosaur2.sprite3" / "0e43f8e573bf232505b207b92efac2ac.png" |
|
|
,SPRITE_DIR / "Dinosaur2.sprite3" / "7799f2848136d11f48ca5f3105d336ef.png" |
|
|
,SPRITE_DIR / "Dinosaur2.sprite3" / "d926c5758d130fcfd9a7ae7dac47e47d.png" |
|
|
,SPRITE_DIR / "Dinosaur2.sprite3" / "e606ba27dfe94daf3d8e3fdf599e37cf.png" |
|
|
,SPRITE_DIR / "Dinosaur3.sprite3" / "5381feb0fc1b50ddc2793342daddffef.png" |
|
|
,SPRITE_DIR / "Dinosaur3.sprite3" / "ae98efa1c3c3700602e1344db86aaf72.png" |
|
|
,SPRITE_DIR / "Dinosaur3.sprite3" / "cf4fb77a4e9839f83d3fa5fc0982ccd3.png" |
|
|
,SPRITE_DIR / "Dinosaur3.sprite3" / "d85ec1b97f73564ef26fec73d5056c68.png" |
|
|
,SPRITE_DIR / "Dinosaur3.sprite3" / "e731d1f1ebf4bc0ea55b850ffe5a5f96.png" |
|
|
,SPRITE_DIR / "Dinosaur4.sprite3" / "723bd1559f8baae4184fa24a6513362b.png" |
|
|
,SPRITE_DIR / "Dinosaur4.sprite3" / "a98e3f93853513e7c00bab4c61752312.png" |
|
|
,SPRITE_DIR / "Dinosaur4.sprite3" / "ac99ef62e3e018b8db550bb2a187cbe9.png" |
|
|
,SPRITE_DIR / "Dinosaur4.sprite3" / "c63cca929380152b978d8671fe6003f7.png" |
|
|
,SPRITE_DIR / "Dinosaur5.sprite3" / "26fca11e4251d60ed7aa5d08f4ae2a69.png" |
|
|
,SPRITE_DIR / "Dinosaur5.sprite3" / "3b2cf97b1cc7fc535162ba5849a0e29c.png" |
|
|
,SPRITE_DIR / "Dinosaur5.sprite3" / "42e3bf118c775ba54239af4276800a0a.png" |
|
|
,SPRITE_DIR / "Dinosaur5.sprite3" / "5882227a9e2f0f3b2014c49328969762.png" |
|
|
,SPRITE_DIR / "Dinosaur5.sprite3" / "5a0832162a0cfa7adab6090c42e89714.png" |
|
|
,SPRITE_DIR / "Dinosaur5.sprite3" / "9d200a7c2e93eac8cf52ede3a87d7969.png" |
|
|
,SPRITE_DIR / "Dinosaur5.sprite3" / "c4044a3badea77ced4f2db69aff866ed.png" |
|
|
,SPRITE_DIR / "Dinosaur5.sprite3" / "f49b3b098a24474f20c8f4686681c611.png" |
|
|
,SPRITE_DIR / "Diver1.sprite3" / "a24f23a0f5d77cfb59721ef8f6bfe5c7.png" |
|
|
,SPRITE_DIR / "Diver2.sprite3" / "ef8136a42b7d20961756e551bc87b37f.png" |
|
|
,SPRITE_DIR / "Dog1.sprite3" / "35cd78a8a71546a16c530d0b2d7d5a7f.png" |
|
|
,SPRITE_DIR / "Dog1.sprite3" / "d5a72e1eb23a91df4b53c0b16493d1e6.png" |
|
|
,SPRITE_DIR / "Dog2.sprite3" / "4708bff29b3a295a03ac1d5e2d16ec75.png" |
|
|
,SPRITE_DIR / "Dog2.sprite3" / "66b435d333f34d02d5ae49a598bcc5b3.png" |
|
|
,SPRITE_DIR / "Dog2.sprite3" / "6afc06388d69f99e28d883126f9b2734.png" |
|
|
,SPRITE_DIR / "Donut.sprite3" / "316a67c9e966fd015b4538f54be456db.png" |
|
|
,SPRITE_DIR / "Dorian.sprite3" / "603d3dd151984c0eaa2822f70a234c28.png" |
|
|
,SPRITE_DIR / "Dorian.sprite3" / "7d20ec98603857c031c1f4ad2bd8ea51.png" |
|
|
,SPRITE_DIR / "Dorian.sprite3" / "8f2be2387efcbb5d4878886adaa2a88e.png" |
|
|
,SPRITE_DIR / "Dorian.sprite3" / "a9a064a1f28c9e22b594dcea1d46025b.png" |
|
|
,SPRITE_DIR / "Dot.sprite3" / "106461f60e34ce231b323e2dd2d9f05b.png" |
|
|
,SPRITE_DIR / "Dot.sprite3" / "21482022f9930400302bc8ec70643717.png" |
|
|
,SPRITE_DIR / "Dot.sprite3" / "9e5a6cc6970ce4932a09affba70a45b0.png" |
|
|
,SPRITE_DIR / "Dot.sprite3" / "fb047c94113ee4c6664305a338525e6a.png" |
|
|
,SPRITE_DIR / "Dove.sprite3" / "0f83ab55012a7affd94e38250d55a0a0.png" |
|
|
,SPRITE_DIR / "Dove.sprite3" / "778a699a044a0a8c10f44c3194e21ef2.png" |
|
|
,SPRITE_DIR / "Dragon.sprite3" / "12ead885460d96a19132e5970839d36d.png" |
|
|
,SPRITE_DIR / "Dragon.sprite3" / "3f672475ad4ca5d1f9331cffd4223140.png" |
|
|
,SPRITE_DIR / "Dragon.sprite3" / "e0aa0083fa0b97da97600d4dbb2055e5.png" |
|
|
,SPRITE_DIR / "Dragonfly.sprite3" / "17b864c1ddd4b349a6c4bd5709167307.png" |
|
|
,SPRITE_DIR / "Dragonfly.sprite3" / "5cdfe67af929e3fb095e83c9c4b0bd78.png" |
|
|
,SPRITE_DIR / "Dress.sprite3" / "4e22e6fd72500f0a25b959283bfd0a32.png" |
|
|
,SPRITE_DIR / "Dress.sprite3" / "c5fb135d89573570010b0d96c94bcec6.png" |
|
|
,SPRITE_DIR / "Dress.sprite3" / "ddbea537af6012ebac18d16d65c07479.png" |
|
|
,SPRITE_DIR / "Drum Kit.sprite3" / "3f4fb4836338c55f883607c403b2b25e.png" |
|
|
,SPRITE_DIR / "Drum Kit.sprite3" / "baf6344b6f55b074786a383c1097697d.png" |
|
|
,SPRITE_DIR / "Drum-cymbal.sprite3" / "08355ec8cc4b3263f502adfdea993cda.png" |
|
|
,SPRITE_DIR / "Drum-cymbal.sprite3" / "78398692e6fa226568df0374c4358da4.png" |
|
|
,SPRITE_DIR / "Drum-highhat.sprite3" / "15b2a31a57d0cd911ad0b1c265dcf59e.png" |
|
|
,SPRITE_DIR / "Drum-highhat.sprite3" / "866b3a49ee2a45998940e2d737c4c502.png" |
|
|
,SPRITE_DIR / "Drum-snare.sprite3" / "28298d93f5282041267a92bd67308107.png" |
|
|
,SPRITE_DIR / "Drum-snare.sprite3" / "c42bb05aab3cacddcd88712e33ab8df0.png" |
|
|
,SPRITE_DIR / "Drum.sprite3" / "47531b5675be696d0540eb120d5d0678.png" |
|
|
,SPRITE_DIR / "Drum.sprite3" / "ce6971317035091341ec40571c9056e9.png" |
|
|
,SPRITE_DIR / "Drums Conga.sprite3" / "2b2eacfce0fb1af023e6ca0f5ef6defe.png" |
|
|
,SPRITE_DIR / "Drums Conga.sprite3" / "bdad2f140cfbd021f38241fc9acc7fd2.png" |
|
|
,SPRITE_DIR / "Drums Tabla.sprite3" / "992d6359be830d977559dad91b04f698.png" |
|
|
,SPRITE_DIR / "Drums Tabla.sprite3" / "af071d9d714c5c622e2bb07133698ce3.png" |
|
|
,SPRITE_DIR / "Duck.sprite3" / "c9837d0454f5f0f73df290af2045359b.png" |
|
|
,SPRITE_DIR / "Earth.sprite3" / "7405b5efa96995bae6853667f8cd145e.png" |
|
|
,SPRITE_DIR / "Easel.sprite3" / "6a736beddc7844538be390c18b7c4361.png" |
|
|
,SPRITE_DIR / "Easel.sprite3" / "a4b3714322c11b350f09a75921ae606b.png" |
|
|
,SPRITE_DIR / "Easel.sprite3" / "caec09682a7fcdffef4647e8355ba004.png" |
|
|
,SPRITE_DIR / "Egg.sprite3" / "0d127490af16f8a4ca5ce3212b2391c2.png" |
|
|
,SPRITE_DIR / "Egg.sprite3" / "41535b4742f40e2630746b0c4bec98f2.png" |
|
|
,SPRITE_DIR / "Egg.sprite3" / "b0b6e88ec64b842398200bab562b53e3.png" |
|
|
,SPRITE_DIR / "Egg.sprite3" / "bb0505b802140a8cc200c9f8bfce4503.png" |
|
|
,SPRITE_DIR / "Egg.sprite3" / "f8ee449298c1446cb0ef281923a4e57a.png" |
|
|
,SPRITE_DIR / "Egg.sprite3" / "fbc629c3b062423e8c09cfacfb1e65f8.png" |
|
|
,SPRITE_DIR / "Elephant.sprite3" / "2c9b5e0125d95b8bc511f6bb09b5ea2f.png" |
|
|
,SPRITE_DIR / "Elephant.sprite3" / "b59873e9558c1c456200f50e5ab34770.png" |
|
|
,SPRITE_DIR / "Elf.sprite3" / "524406c2b1fe253c1565ff516309817e.png" |
|
|
,SPRITE_DIR / "Elf.sprite3" / "808c6fa2eb1cba0de1d17b18c6f41279.png" |
|
|
,SPRITE_DIR / "Elf.sprite3" / "92ff640b911a8348d2734c0e38bba68c.png" |
|
|
,SPRITE_DIR / "Elf.sprite3" / "e92abad171396a3198455df8557802e5.png" |
|
|
,SPRITE_DIR / "Elf.sprite3" / "ec458328a85f89f06866e2337076ac0a.png" |
|
|
,SPRITE_DIR / "Fairy.sprite3" / "40d726e17bfd2ffeb8c0aa5393ee1c77.png" |
|
|
,SPRITE_DIR / "Fairy.sprite3" / "902350bba0d4b4612db1e2e902b6f201.png" |
|
|
,SPRITE_DIR / "Fairy.sprite3" / "bea920473027f43e04c44e588c6cc39a.png" |
|
|
,SPRITE_DIR / "Fairy.sprite3" / "d4f6163a1610243f55dd9cf1c9875c61.png" |
|
|
,SPRITE_DIR / "Fairy.sprite3" / "decd31f829032b1d4dcf5efdbd362cb9.png" |
|
|
,SPRITE_DIR / "Fish.sprite3" / "4a3478b3cdc3e8688a671be88c2775fd.png" |
|
|
,SPRITE_DIR / "Fish.sprite3" / "7a0c31c0087f342867d4754f8dc57541.png" |
|
|
,SPRITE_DIR / "Fish.sprite3" / "886e0bb732453eb8d3a849b4eab54943.png" |
|
|
,SPRITE_DIR / "Fish.sprite3" / "a9b3d163756621f8395592ad77fb9369.png" |
|
|
,SPRITE_DIR / "Fishbowl.sprite3" / "17c53cf0296f24722ba5b001d513e58f.png" |
|
|
,SPRITE_DIR / "Fishbowl.sprite3" / "b3db01c5cda32fe3ea0b48dde5fa8130.png" |
|
|
,SPRITE_DIR / "Food Truck.sprite3" / "a77f9693f87288d023a4632cf019776e.png" |
|
|
,SPRITE_DIR / "Food Truck.sprite3" / "e850e3c93de767519f7f78b38f16ed1d.png" |
|
|
,SPRITE_DIR / "Food Truck.sprite3" / "f4150de2297a63c3efd125c8e12dd7cc.png" |
|
|
,SPRITE_DIR / "Football.sprite3" / "7ee31371b2eafba57cc5a78fc1a787fe.png" |
|
|
,SPRITE_DIR / "Football.sprite3" / "c717def72c8bd98749284d31b51d7097.png" |
|
|
,SPRITE_DIR / "Fortune Cookie.sprite3" / "c56dcaa1fa4e3c9740142b93d5982850.png" |
|
|
,SPRITE_DIR / "Fox.sprite3" / "2c256eacbb753be361e8e52a0eefde77.png" |
|
|
,SPRITE_DIR / "Fox.sprite3" / "9dd59a4514b5373d4f665db78e145636.png" |
|
|
,SPRITE_DIR / "Fox.sprite3" / "dd398ed81edb60c91ad4805f4437d2fa.png" |
|
|
,SPRITE_DIR / "Frank.sprite3" / "10d39bb7e31647a465e747cd243b8cd0.png" |
|
|
,SPRITE_DIR / "Frank.sprite3" / "26da9617218493f4f42a1592f21afee8.png" |
|
|
,SPRITE_DIR / "Frank.sprite3" / "d16b76a634f7367ce7d6112401a78e57.png" |
|
|
,SPRITE_DIR / "Frank.sprite3" / "e56e930cc0229d1042a673e7503209c5.png" |
|
|
,SPRITE_DIR / "Frog 2 .sprite3" / "0717f446c991aac7df2fe4d6590354e7.png" |
|
|
,SPRITE_DIR / "Frog 2 .sprite3" / "d9f69469090784d8dd68d94c0fd78a50.png" |
|
|
,SPRITE_DIR / "Frog 2 .sprite3" / "f2246c13e4540472c484119bc314d954.png" |
|
|
,SPRITE_DIR / "Frog.sprite3" / "390845c11df0924f3b627bafeb3f814e.png" |
|
|
,SPRITE_DIR / "Fruit Platter.sprite3" / "6c3252378da3334f63eebddbed3fae91.png" |
|
|
,SPRITE_DIR / "Fruit Salad.sprite3" / "2e6ef315101433b78e38719e8cc630c2.png" |
|
|
,SPRITE_DIR / "Ghost.sprite3" / "40ba3a0b5b3899a655fd8867229d4ee3.png" |
|
|
,SPRITE_DIR / "Ghost.sprite3" / "634744e3f98bee53e9cb477a63aa9b21.png" |
|
|
,SPRITE_DIR / "Ghost.sprite3" / "d1d89391f1d9c74557e504456d58a002.png" |
|
|
,SPRITE_DIR / "Ghost.sprite3" / "f522b08c5757569ad289d67bce290cd0.png" |
|
|
,SPRITE_DIR / "Gift.sprite3" / "0fdd104de718c5fc4a65da429468bdbd.png" |
|
|
,SPRITE_DIR / "Gift.sprite3" / "6cbeda5d391c6d107f0b853222f344d9.png" |
|
|
,SPRITE_DIR / "Giga Walking.sprite3" / "3afad833094d8dff1c4ff79edcaa13d0.png" |
|
|
,SPRITE_DIR / "Giga Walking.sprite3" / "d27716e022fb5f747d7b09fe6eeeca06.png" |
|
|
,SPRITE_DIR / "Giga Walking.sprite3" / "db55131bf54f96e8986d9b30730e42ce.png" |
|
|
,SPRITE_DIR / "Giga.sprite3" / "337b338b2b10176221e638ac537854e6.png" |
|
|
,SPRITE_DIR / "Giga.sprite3" / "92161a11e851ecda94cbbb985018fed6.png" |
|
|
,SPRITE_DIR / "Giga.sprite3" / "bc706a7648342aaacac9050378b40c43.png" |
|
|
,SPRITE_DIR / "Giga.sprite3" / "db15886cfdcb5e2f4459e9074e3990a1.png" |
|
|
,SPRITE_DIR / "Giraffe.sprite3" / "43e89629fb9df7051eaf307c695424fc.png" |
|
|
,SPRITE_DIR / "Giraffe.sprite3" / "cfd93a103479993aee4d680655e39d8d.png" |
|
|
,SPRITE_DIR / "Giraffe.sprite3" / "ef1fca2ae13d49d9dd2c6cfc211a687c.png" |
|
|
,SPRITE_DIR / "Glass Water.sprite3" / "ca70c69ef1f797d353581a3f76116ae3.png" |
|
|
,SPRITE_DIR / "Glass Water.sprite3" / "cbf21cf1b057852f91135d27ebbf11ce.png" |
|
|
,SPRITE_DIR / "Glasses.sprite3" / "705035328ac53d5ce1aa5a1ed1c2d172.png" |
|
|
,SPRITE_DIR / "Glasses.sprite3" / "9e2f75d3a09f3f10d554ba8380c3ae52.png" |
|
|
,SPRITE_DIR / "Glasses.sprite3" / "acd85b36e6b8d93ba4194ee2ea334207.png" |
|
|
,SPRITE_DIR / "Glasses.sprite3" / "f2a02d0e7431147b8a4a282e02a8e6a4.png" |
|
|
,SPRITE_DIR / "Glow-0.sprite3" / "64b59074f24d0e2405a509a45c0dadba.png" |
|
|
,SPRITE_DIR / "Glow-1.sprite3" / "9f75c26aa6c56168a3e5a4f598de2c94.png" |
|
|
,SPRITE_DIR / "Glow-2.sprite3" / "e8d8bf59db37b5012dd643a16a636042.png" |
|
|
,SPRITE_DIR / "Glow-3.sprite3" / "57f7afe3b9888cca56803b73a62e4227.png" |
|
|
,SPRITE_DIR / "Glow-4.sprite3" / "b8209e1980475b30ff11e60d7633446d.png" |
|
|
,SPRITE_DIR / "Glow-5.sprite3" / "aacb5b3cec637f192f080138b4ccd8d2.png" |
|
|
,SPRITE_DIR / "Glow-6.sprite3" / "84d9f26050c709e6b98706c22d2efb3d.png" |
|
|
,SPRITE_DIR / "Glow-7.sprite3" / "6194b9a251a905d0001a969990961724.png" |
|
|
,SPRITE_DIR / "Glow-8.sprite3" / "55e95fb9c60fbebb7d20bba99c7e9609.png" |
|
|
,SPRITE_DIR / "Glow-9.sprite3" / "0f53ee6a988bda07cba561d38bfbc36f.png" |
|
|
,SPRITE_DIR / "Glow-A.sprite3" / "fd470938cce54248aaf240b16e845456.png" |
|
|
,SPRITE_DIR / "Glow-B.sprite3" / "a699fa024889b681d8b8b6c5c86acb6d.png" |
|
|
,SPRITE_DIR / "Glow-C.sprite3" / "51b8a7dd7a8cddc5bc30e35824cc557a.png" |
|
|
,SPRITE_DIR / "Glow-D.sprite3" / "a3a66e37de8d7ebe0505594e036ef6d1.png" |
|
|
,SPRITE_DIR / "Glow-E.sprite3" / "80382a5db3fa556276068165c547b432.png" |
|
|
,SPRITE_DIR / "Glow-F.sprite3" / "67239f7d47f7b92bc38e2d8b275d54ab.png" |
|
|
,SPRITE_DIR / "Glow-G.sprite3" / "56839bc48957869d980c6f9b6f5a2a91.png" |
|
|
,SPRITE_DIR / "Glow-H.sprite3" / "d6016c6494153cd5735ee4b6a1b05277.png" |
|
|
,SPRITE_DIR / "Glow-I.sprite3" / "9077988af075c80cc403b1d6e5891528.png" |
|
|
,SPRITE_DIR / "Glow-J.sprite3" / "6c359eff57abf5bb6db55894d08757c3.png" |
|
|
,SPRITE_DIR / "Glow-K.sprite3" / "e932898d1e6fe3950a266fccaba0c3e6.png" |
|
|
,SPRITE_DIR / "Glow-L.sprite3" / "dcee9202cf20e0395971f1ee73c45d37.png" |
|
|
,SPRITE_DIR / "Glow-M.sprite3" / "26f81aa5990bf2371acaa8d76fe1e87f.png" |
|
|
,SPRITE_DIR / "Glow-N.sprite3" / "d55a04ada14958eccc4aef446a4dad57.png" |
|
|
,SPRITE_DIR / "Glow-O.sprite3" / "64b59074f24d0e2405a509a45c0dadba.png" |
|
|
,SPRITE_DIR / "Glow-P.sprite3" / "c6edc2603ad4db3aa0b29f80e3e38cff.png" |
|
|
,SPRITE_DIR / "Glow-Q.sprite3" / "e4ae18bf8b92ae375ce818d754588c76.png" |
|
|
,SPRITE_DIR / "Glow-R.sprite3" / "bb11b49e19c68452331e78d51081ab42.png" |
|
|
,SPRITE_DIR / "Glow-S.sprite3" / "6fd994b41bcf776fbf1f1521a879f1af.png" |
|
|
,SPRITE_DIR / "Glow-T.sprite3" / "d687543649a676a14f408b5890d45f05.png" |
|
|
,SPRITE_DIR / "Glow-U.sprite3" / "cb8ef2244400a57ba08e918cb4fe8bba.png" |
|
|
,SPRITE_DIR / "Glow-V.sprite3" / "c6edc1ac2c5979f389598537cfb28096.png" |
|
|
,SPRITE_DIR / "Glow-W.sprite3" / "2e0c2bb46c4ca3cf97779f749b1556f6.png" |
|
|
,SPRITE_DIR / "Glow-X.sprite3" / "0b98a63dcc55251072a95a6c6bf7f6f2.png" |
|
|
,SPRITE_DIR / "Glow-Y.sprite3" / "532494c9b5e6709f9982c00a48ce6870.png" |
|
|
,SPRITE_DIR / "Glow-Z.sprite3" / "2d94d83dcc9ee3a107e5ea7ef0dddeb0.png" |
|
|
,SPRITE_DIR / "Goalie.sprite3" / "59eedd0a23c3c983d386a0c125991c7f.png" |
|
|
,SPRITE_DIR / "Goalie.sprite3" / "63f2955298d59dd22dc7b7c6a9c521e2.png" |
|
|
,SPRITE_DIR / "Goalie.sprite3" / "a554f2a9b49a09ec67d1fd7ecfbcddcd.png" |
|
|
,SPRITE_DIR / "Goalie.sprite3" / "eb096e2b4234f5f8ee1f2c44429eaa1a.png" |
|
|
,SPRITE_DIR / "Goalie.sprite3" / "f2e7ba53f3a28c4359cb0d3e3cb4001a.png" |
|
|
,SPRITE_DIR / "Goblin.sprite3" / "2add9ef4eaa25f8915406dcfd8bafc9f.png" |
|
|
,SPRITE_DIR / "Goblin.sprite3" / "3f08380f25062b8055a1800f5dad14bd.png" |
|
|
,SPRITE_DIR / "Goblin.sprite3" / "afb9fe328adae617ee3375366fca02e7.png" |
|
|
,SPRITE_DIR / "Goblin.sprite3" / "b8604b8039d6b633015aaf17d74d5d5b.png" |
|
|
,SPRITE_DIR / "Gobo.sprite3" / "5c0896569305ab177d87caa31aad2a72.png" |
|
|
,SPRITE_DIR / "Gobo.sprite3" / "9d8021c216fb92cc708e1e96f3ed2b52.png" |
|
|
,SPRITE_DIR / "Gobo.sprite3" / "f505a4e9eab5e40e2669a4462dba4c90.png" |
|
|
,SPRITE_DIR / "Grasshopper.sprite3" / "529644c5ecdca63adafd87777e341ad7.png" |
|
|
,SPRITE_DIR / "Grasshopper.sprite3" / "93550d8abde130ad149904c4448f8b65.png" |
|
|
,SPRITE_DIR / "Grasshopper.sprite3" / "a7c638b8aa86f2a758830f8c2b0e4cf5.png" |
|
|
,SPRITE_DIR / "Grasshopper.sprite3" / "cf2ac769df444137b4c1eec472fa4b92.png" |
|
|
,SPRITE_DIR / "Grasshopper.sprite3" / "d4f3dfe69be6537e73544381408a820d.png" |
|
|
,SPRITE_DIR / "Grasshopper.sprite3" / "e7210a370837dd1e4ebc1a56a973b7f6.png" |
|
|
,SPRITE_DIR / "Green Flag.sprite3" / "2bbfd072183a67db5eddb923fe0726b3.png" |
|
|
,SPRITE_DIR / "Griffin.sprite3" / "102f6200c13bd60afa9538c712776fb0.png" |
|
|
,SPRITE_DIR / "Griffin.sprite3" / "157d3665cebcd41fa814b9217af99476.png" |
|
|
,SPRITE_DIR / "Griffin.sprite3" / "a31166d45903206b52cb0f0a0cb687b5.png" |
|
|
,SPRITE_DIR / "Griffin.sprite3" / "b8c8745820a341afec08e77f4a254551.png" |
|
|
,SPRITE_DIR / "Guitar-electric1.sprite3" / "57c6d7dc148576cb2f36e53dea49260a.png" |
|
|
,SPRITE_DIR / "Guitar-electric1.sprite3" / "677aed0b1168caf4b3ec565b9104dbe0.png" |
|
|
,SPRITE_DIR / "Guitar-electric2.sprite3" / "83db2d0e342257e534ccdf0ec17bf668.png" |
|
|
,SPRITE_DIR / "Guitar-electric2.sprite3" / "bb88e6a8a08a4034cc155b1137743ca1.png" |
|
|
,SPRITE_DIR / "Guitar.sprite3" / "8704489dcf1a3ca93c5db40ebe5acd38.png" |
|
|
,SPRITE_DIR / "Guitar.sprite3" / "e0423f4743f39456dade16fa1223d6b0.png" |
|
|
,SPRITE_DIR / "Hannah.sprite3" / "5fdce07935156bbcf943793fa84e826c.png" |
|
|
,SPRITE_DIR / "Hannah.sprite3" / "b983d99560313e38b4b3cd36cbd5f0d1.png" |
|
|
,SPRITE_DIR / "Hannah.sprite3" / "d0c3b4b24fbf1152de3ebb68f6b875ae.png" |
|
|
,SPRITE_DIR / "Hare.sprite3" / "7269593d83b6f9eae512997f541a7417.png" |
|
|
,SPRITE_DIR / "Hare.sprite3" / "85a3b8c151e10576fa531a4293fdac00.png" |
|
|
,SPRITE_DIR / "Hare.sprite3" / "c8dbb4302dd489a201938c203018c2f0.png" |
|
|
,SPRITE_DIR / "Harper.sprite3" / "3a0973a042ee16e816c568651316d5d4.png" |
|
|
,SPRITE_DIR / "Harper.sprite3" / "98ce6e6bb99f8ba116f127fdf2e739fd.png" |
|
|
,SPRITE_DIR / "Harper.sprite3" / "e407fa0ed992393d12d0a108c11e2fa6.png" |
|
|
,SPRITE_DIR / "Hat1 .sprite3" / "0aed53a86d92ec2283068000ac97a60b.png" |
|
|
,SPRITE_DIR / "Hat1 .sprite3" / "13e382ae3f05a9a23e0b64ca23230438.png" |
|
|
,SPRITE_DIR / "Hat1 .sprite3" / "6349e36da9897a2f89bdbf5c77dbdacb.png" |
|
|
,SPRITE_DIR / "Hat1 .sprite3" / "c632719725400c604fcadf0858ce2b2c.png" |
|
|
,SPRITE_DIR / "Hatchling.sprite3" / "0e5c295a043d5e183a98046e4f734b72.png" |
|
|
,SPRITE_DIR / "Hatchling.sprite3" / "55f7d457eb0af78cb309ca47497c490f.png" |
|
|
,SPRITE_DIR / "Hatchling.sprite3" / "f27d557be70a9522fae4392bfd4f5249.png" |
|
|
,SPRITE_DIR / "Heart Candy.sprite3" / "288976865e8c5db717d859e915606d82.png" |
|
|
,SPRITE_DIR / "Heart Candy.sprite3" / "3ee430ba825f41ae9913453d4932fb8b.png" |
|
|
,SPRITE_DIR / "Heart Candy.sprite3" / "51248e76be2aa7a0f0ed77bc94af1b3a.png" |
|
|
,SPRITE_DIR / "Heart Candy.sprite3" / "5fa8c4693cf8cba8cdbcbed72f4f58aa.png" |
|
|
,SPRITE_DIR / "Heart Face.sprite3" / "989770846f8cd1628b48bbe91d0a7d0d.png" |
|
|
,SPRITE_DIR / "Heart.sprite3" / "c77e640f6e023e7ce1e376da0f26e1eb.png" |
|
|
,SPRITE_DIR / "Heart.sprite3" / "e24731f5cf2759c2f289921bebb86ea2.png" |
|
|
,SPRITE_DIR / "Hedgehog.sprite3" / "1fcbba4a2252e96c52d2d8aa8e593e51.png" |
|
|
,SPRITE_DIR / "Hedgehog.sprite3" / "3251533232e7f44315512149c7f76214.png" |
|
|
,SPRITE_DIR / "Hedgehog.sprite3" / "3b0e1717859808cecf1a45e2a32dc201.png" |
|
|
,SPRITE_DIR / "Hedgehog.sprite3" / "42bac40ca828133600e0a9f7ba019adb.png" |
|
|
,SPRITE_DIR / "Hedgehog.sprite3" / "93c2d7a0abefaf26ee50d5038ac5bf61.png" |
|
|
,SPRITE_DIR / "Hen.sprite3" / "6c9e05f568862dbcea0a1652a210239b.png" |
|
|
,SPRITE_DIR / "Hen.sprite3" / "b02a33e32313cc9a75781a6fafd07033.png" |
|
|
,SPRITE_DIR / "Hen.sprite3" / "c9a4570a2d0ae09b9feeeb5607e4b9c7.png" |
|
|
,SPRITE_DIR / "Hen.sprite3" / "d055896a473bb12f4ec67af1fdb9c652.png" |
|
|
,SPRITE_DIR / "Hippo1.sprite3" / "5764a2c650f225bc27cc0e6c5db401ea.png" |
|
|
,SPRITE_DIR / "Hippo1.sprite3" / "911901dc568b56c15fe81819bc2af653.png" |
|
|
,SPRITE_DIR / "Home Button.sprite3" / "1ebdcb9f033fa6658259b52da376b7ac.png" |
|
|
,SPRITE_DIR / "Horse.sprite3" / "0e0fa871bea01c2dfb70e9955dc098be.png" |
|
|
,SPRITE_DIR / "Horse.sprite3" / "ad458251c5bf5b375870829f1762fa47.png" |
|
|
,SPRITE_DIR / "Jaime.sprite3" / "3ddc912edef87ae29121f57294fa0cb5.png" |
|
|
,SPRITE_DIR / "Jaime.sprite3" / "4b9d2162e30dbb924840575ed35fddb0.png" |
|
|
,SPRITE_DIR / "Jaime.sprite3" / "5883bdefba451aaeac8d77c798d41eb0.png" |
|
|
,SPRITE_DIR / "Jaime.sprite3" / "5a683f4536abca0f83a77bc341df4c9a.png" |
|
|
,SPRITE_DIR / "Jaime.sprite3" / "63e56d28cc3e3d9b735e1f1d51248cc0.png" |
|
|
,SPRITE_DIR / "Jaime.sprite3" / "7fb579a98d6db257f1b16109d3c4609a.png" |
|
|
,SPRITE_DIR / "Jaime.sprite3" / "d6cc9814f7a6640e4c2b1a4276987dc5.png" |
|
|
,SPRITE_DIR / "Jamal.sprite3" / "2408318e743873c7254db1623441b9c5.png" |
|
|
,SPRITE_DIR / "Jamal.sprite3" / "3c8d5e688450ad1e6bf024a32c55bcda.png" |
|
|
,SPRITE_DIR / "Jamal.sprite3" / "693748d763c8da4b119a5e4bee6a1768.png" |
|
|
,SPRITE_DIR / "Jamal.sprite3" / "92692e0c0f376797274392484ba74133.png" |
|
|
,SPRITE_DIR / "Jar.sprite3" / "33b537168f3c2eb3dafeb739c22f38a6.png" |
|
|
,SPRITE_DIR / "Jar.sprite3" / "e0f5ac773987470ff2467e3e01b9ab23.png" |
|
|
,SPRITE_DIR / "Jellyfish.sprite3" / "00c99df84f8385038461d6c42a5465ab.png" |
|
|
,SPRITE_DIR / "Jellyfish.sprite3" / "3158299771b3d34ed2c50a00fbab715e.png" |
|
|
,SPRITE_DIR / "Jellyfish.sprite3" / "4e259b7c08f05145fc7800b33e4f356e.png" |
|
|
,SPRITE_DIR / "Jellyfish.sprite3" / "5944a1e687fa31589517825b2144a17b.png" |
|
|
,SPRITE_DIR / "Jordyn.sprite3" / "00c8c464c19460df693f8d5ae69afdab.png" |
|
|
,SPRITE_DIR / "Jordyn.sprite3" / "768c4601174f0dfcb96b3080ccc3a192.png" |
|
|
,SPRITE_DIR / "Jordyn.sprite3" / "a7cc1e5f02b58ecc8095cfc18eef0289.png" |
|
|
,SPRITE_DIR / "Jordyn.sprite3" / "db4d97cbf24e2b8af665bfbf06f67fa0.png" |
|
|
,SPRITE_DIR / "Jouvi Dance.sprite3" / "01dd2f553c7262329ebaba2516e3a2b1.png" |
|
|
,SPRITE_DIR / "Jouvi Dance.sprite3" / "0ed4a09c41871d150c51119c1bceded2.png" |
|
|
,SPRITE_DIR / "Jouvi Dance.sprite3" / "2e2a6534d33883fdd2f8471a1adbebb7.png" |
|
|
,SPRITE_DIR / "Jouvi Dance.sprite3" / "3d3ea804243800981acabc7caba10939.png" |
|
|
,SPRITE_DIR / "Jouvi Dance.sprite3" / "6f68790ee3eb9bdccf8749305186b0dd.png" |
|
|
,SPRITE_DIR / "Jouvi Dance.sprite3" / "75ee2383fd83992b401c8a0730521d94.png" |
|
|
,SPRITE_DIR / "Jouvi Dance.sprite3" / "a12f40b18067bb31746f9cf461de88aa.png" |
|
|
,SPRITE_DIR / "Jouvi Dance.sprite3" / "a55fbb529c10f70bcb374aef8a63571b.png" |
|
|
,SPRITE_DIR / "Jouvi Dance.sprite3" / "a9fbc01a4124d555da12630312e46197.png" |
|
|
,SPRITE_DIR / "Jouvi Dance.sprite3" / "aabfedff0d11243386b6b0941e0f72e9.png" |
|
|
,SPRITE_DIR / "Jouvi Dance.sprite3" / "c2d5519e8a0f2214ff757117038c28dc.png" |
|
|
,SPRITE_DIR / "Jouvi Dance.sprite3" / "ea812b4c2b2405aa2b73158023298f71.png" |
|
|
,SPRITE_DIR / "Jouvi Dance.sprite3" / "efaa8eb6c8cf7dc35d4d37d546ebd333.png" |
|
|
,SPRITE_DIR / "Kai.sprite3" / "6e007fde15e49c66ee7996561f80b452.png" |
|
|
,SPRITE_DIR / "Kai.sprite3" / "c1e1149f6d7e308e3e4eba14ccc8a751.png" |
|
|
,SPRITE_DIR / "Key.sprite3" / "680d3e4dce002f922b32447fcf29743d.png" |
|
|
,SPRITE_DIR / "Keyboard.sprite3" / "0ad880b5e829578832c8927b3f6ef7f8.png" |
|
|
,SPRITE_DIR / "Keyboard.sprite3" / "6efd23c91dab070526feacdf72e2d3da.png" |
|
|
,SPRITE_DIR / "Kia.sprite3" / "b3d0a248adbc26b0d0826e042a81670a.png" |
|
|
,SPRITE_DIR / "Kia.sprite3" / "db6cd6b145bb6d8dc299475af7423d6e.png" |
|
|
,SPRITE_DIR / "Kia.sprite3" / "e56e480c994572323d88355b8733e1a3.png" |
|
|
,SPRITE_DIR / "Kiran.sprite3" / "2928e9fbd5ca08e326192b3a41bea691.png" |
|
|
,SPRITE_DIR / "Kiran.sprite3" / "78bd6de23d4929aef678ddf0f3f5c276.png" |
|
|
,SPRITE_DIR / "Kiran.sprite3" / "7912b6f378bd781f62683e003c574dbe.png" |
|
|
,SPRITE_DIR / "Kiran.sprite3" / "7c0bedab5404830a5147cc4a2d46e997.png" |
|
|
,SPRITE_DIR / "Kiran.sprite3" / "7f0bc123819fc2666321b6cd38069bdb.png" |
|
|
,SPRITE_DIR / "Kiran.sprite3" / "b0566e0eed7b5216b92d61468d21ecee.png" |
|
|
,SPRITE_DIR / "Knight.sprite3" / "188325c56b79ff3cd58497c970ba87a6.png" |
|
|
,SPRITE_DIR / "Ladybug1.sprite3" / "169c0efa8c094fdedddf8c19c36f0229.png" |
|
|
,SPRITE_DIR / "Ladybug2.sprite3" / "3f48228829b77fc47d6d89b5729b2957.png" |
|
|
,SPRITE_DIR / "Ladybug2.sprite3" / "457200f8dec8fea00d22473e9bd9175e.png" |
|
|
,SPRITE_DIR / "Laptop.sprite3" / "cd2d1f72275e676df5f82be74ae91dfa.png" |
|
|
,SPRITE_DIR / "LB Dance.sprite3" / "0725440743391e7c622bb5df6a94e1d4.png" |
|
|
,SPRITE_DIR / "LB Dance.sprite3" / "0a2461b3b9a4b8603e75565d78b1d4d7.png" |
|
|
,SPRITE_DIR / "LB Dance.sprite3" / "4423159d81378ada5ffd7f053d7ef471.png" |
|
|
,SPRITE_DIR / "LB Dance.sprite3" / "525285312925e1e6b4e237a119b61305.png" |
|
|
,SPRITE_DIR / "LB Dance.sprite3" / "563f86443cb102b9241cebb62eb2d81a.png" |
|
|
,SPRITE_DIR / "LB Dance.sprite3" / "5f176ef763be18f7c342dc2e2de7bf16.png" |
|
|
,SPRITE_DIR / "LB Dance.sprite3" / "63d099e94aa8a973dcfa4c5d8b4a3e7a.png" |
|
|
,SPRITE_DIR / "LB Dance.sprite3" / "645d6e2674452009df7a9a844a604791.png" |
|
|
,SPRITE_DIR / "LB Dance.sprite3" / "71dde8c43985815bffb5a5ed5632af58.png" |
|
|
,SPRITE_DIR / "LB Dance.sprite3" / "79ca528d13ffb557a236f0a35a0eb486.png" |
|
|
,SPRITE_DIR / "LB Dance.sprite3" / "b508808c087adb55ce156f5cfbdac61b.png" |
|
|
,SPRITE_DIR / "LB Dance.sprite3" / "cdd52259075b75628001672d375e4985.png" |
|
|
,SPRITE_DIR / "LB Dance.sprite3" / "e68d899e178309ff3eae3e1de8a8ec28.png" |
|
|
,SPRITE_DIR / "Lightning.sprite3" / "0ddd3a05a330925bcd2d048908ed40b8.png" |
|
|
,SPRITE_DIR / "Line.sprite3" / "e85305b47cfd92d971704dcb7ad6e17b.png" |
|
|
,SPRITE_DIR / "Lion.sprite3" / "91c64c5361d906fd36d5813ae27b85a8.png" |
|
|
,SPRITE_DIR / "Lion.sprite3" / "e88e83c8b3ca80c54540b5f0c5a0cc03.png" |
|
|
,SPRITE_DIR / "Lion.sprite3" / "f0d9ab3d82bbade6e279dc1c81e2e6db.png" |
|
|
,SPRITE_DIR / "Llama.sprite3" / "1f3aaeb598e121ad817143800d8c4a32.png" |
|
|
,SPRITE_DIR / "Llama.sprite3" / "ac80d75745315f052f7f7b4e62e4a850.png" |
|
|
,SPRITE_DIR / "Llama.sprite3" / "c97824f20a45adfa3ff362f82247a025.png" |
|
|
,SPRITE_DIR / "Luca.sprite3" / "18dfad514602a4907502c7c84861b24e.png" |
|
|
,SPRITE_DIR / "Luca.sprite3" / "90fa2ad340edc6e6ba963710feef940e.png" |
|
|
,SPRITE_DIR / "Luca.sprite3" / "963cb82687acaf5de53a22b287192723.png" |
|
|
,SPRITE_DIR / "Magic Wand.sprite3" / "89aa5332042d7bbf8368293a4efeafa4.png" |
|
|
,SPRITE_DIR / "Marian.sprite3" / "16893c6136292ae36e13dc72cc55719b.png" |
|
|
,SPRITE_DIR / "Marian.sprite3" / "221e9999b20ecc21b37c68fcdf09ab02.png" |
|
|
,SPRITE_DIR / "Marian.sprite3" / "3d2ecee35eab8c37d1c3eadfe50ce447.png" |
|
|
,SPRITE_DIR / "Marian.sprite3" / "64206b46c411e40926569cf3f5e587be.png" |
|
|
,SPRITE_DIR / "Marian.sprite3" / "e9577a1eb098905dd386135bb38c0398.png" |
|
|
,SPRITE_DIR / "Max.sprite3" / "5180649cfd62831c52f8994ce644d6ac.png" |
|
|
,SPRITE_DIR / "Max.sprite3" / "6b91183a4ad162e4950d95828a85144d.png" |
|
|
,SPRITE_DIR / "Max.sprite3" / "7b3d1324382032f87384ef2c8c618156.png" |
|
|
,SPRITE_DIR / "Max.sprite3" / "9669ce16eb6c6df6f26686598a59711d.png" |
|
|
,SPRITE_DIR / "Mermaid.sprite3" / "2a6274017350fab67ebec9157420ae96.png" |
|
|
,SPRITE_DIR / "Mermaid.sprite3" / "65419296861b1c7ee59075af0f949d67.png" |
|
|
,SPRITE_DIR / "Mermaid.sprite3" / "88a3b6b2f0b3ffa25cab97bc619f8386.png" |
|
|
,SPRITE_DIR / "Mermaid.sprite3" / "f903049308e2171178d889f5c4a7d466.png" |
|
|
,SPRITE_DIR / "Microphone.sprite3" / "c96578ffb9e314fee097862d69fde0af.png" |
|
|
,SPRITE_DIR / "Microphone.sprite3" / "d4d80e94e2cc759b8ca1d7b58f2a9052.png" |
|
|
,SPRITE_DIR / "Milk.sprite3" / "0f683f65c737bbcbb916df0895d8436e.png" |
|
|
,SPRITE_DIR / "Milk.sprite3" / "1fa49d62f8028a375470e7bac451e666.png" |
|
|
,SPRITE_DIR / "Milk.sprite3" / "4d3eabd3ef848b61c3120d796c274733.png" |
|
|
,SPRITE_DIR / "Milk.sprite3" / "6ec300ae45758eff12e9d47cf4f0d2a0.png" |
|
|
,SPRITE_DIR / "Milk.sprite3" / "aa5f1501805aa68d3ad74623f59e6135.png" |
|
|
,SPRITE_DIR / "Monet.sprite3" / "137bbc522701a96908667d1b1730d041.png" |
|
|
,SPRITE_DIR / "Monet.sprite3" / "138e6591f3317222521963ef3ce9a057.png" |
|
|
,SPRITE_DIR / "Monet.sprite3" / "4c6b016c55c4348b6dce29ba99e7ede4.png" |
|
|
,SPRITE_DIR / "Monet.sprite3" / "5b67cb843dcc9dabdc580b9e35e95659.png" |
|
|
,SPRITE_DIR / "Monet.sprite3" / "740276a8aa9ddd12dd4b30f369975d66.png" |
|
|
,SPRITE_DIR / "Monkey.sprite3" / "254926ee81bfa82f2db7009a80635061.png" |
|
|
,SPRITE_DIR / "Monkey.sprite3" / "de0405b0576ade1282bdfcd198922baa.png" |
|
|
,SPRITE_DIR / "Monkey.sprite3" / "ec6d62f0ff64bb5440ffdc662b6e46fa.png" |
|
|
,SPRITE_DIR / "Motorcycle.sprite3" / "6e960b3c6a60ebe192e36b235c50ae03.png" |
|
|
,SPRITE_DIR / "Motorcycle.sprite3" / "a70bdd403ace1f1ece2f2af0fbc3c720.png" |
|
|
,SPRITE_DIR / "Motorcycle.sprite3" / "b73447c2577b8f77b5e2eb1da6d6445a.png" |
|
|
,SPRITE_DIR / "Motorcycle.sprite3" / "c6f8179ff3e8f8ab08b01d50343eefc4.png" |
|
|
,SPRITE_DIR / "Mouse1.sprite3" / "8a7da35c473972f88896ca73b7df2188.png" |
|
|
,SPRITE_DIR / "Mouse1.sprite3" / "c5f76b65e30075c12d49ea8a8f7d6bad.png" |
|
|
,SPRITE_DIR / "Muffin.sprite3" / "afa34381db44e699d61f774911aab448.png" |
|
|
,SPRITE_DIR / "Muffin.sprite3" / "bd0581902cd6cc13888520776bf1620c.png" |
|
|
,SPRITE_DIR / "Nano.sprite3" / "8f2f4a70e87262ef478ce60567b6208a.png" |
|
|
,SPRITE_DIR / "Nano.sprite3" / "a4e2034751fa650fd5fd69432c110104.png" |
|
|
,SPRITE_DIR / "Nano.sprite3" / "a62e560863c0e49b12e5d57e13d084f1.png" |
|
|
,SPRITE_DIR / "Nano.sprite3" / "d12aead3e3c2917e7eba8b2b90a7afd2.png" |
|
|
,SPRITE_DIR / "Neigh Pony.sprite3" / "592816f56409d582603c485cbefcbbb8.png" |
|
|
,SPRITE_DIR / "Noor.sprite3" / "4cf233c6540e434aded60608ba316ce3.png" |
|
|
,SPRITE_DIR / "Noor.sprite3" / "975585ca9461f0730a285fc96df73425.png" |
|
|
,SPRITE_DIR / "Noor.sprite3" / "c1792bbd5970034b4595ff7e742d6e47.png" |
|
|
,SPRITE_DIR / "Octopus.sprite3" / "5d6e17d6260134d0402ba487a419d7c3.png" |
|
|
,SPRITE_DIR / "Octopus.sprite3" / "7d33a531087188b29deae879f23f76bc.png" |
|
|
,SPRITE_DIR / "Octopus.sprite3" / "9b5a2cd287229bf36ffcc176ed72cc0c.png" |
|
|
,SPRITE_DIR / "Octopus.sprite3" / "e22d9b633feffc1d026980a1f21e07d7.png" |
|
|
,SPRITE_DIR / "Octopus.sprite3" / "f582f162c4438d82c9e2a0a87a3e02ce.png" |
|
|
,SPRITE_DIR / "Orange.sprite3" / "d0a55aae1decb57152b454c9a5226757.png" |
|
|
,SPRITE_DIR / "Orange2.sprite3" / "27286ca08451bc512e1d611965dad061.png" |
|
|
,SPRITE_DIR / "Orange2.sprite3" / "b823f73a31e61fd362574e2c24dfc0c2.png" |
|
|
,SPRITE_DIR / "Outfielder.sprite3" / "10578b06f97b9fdc34f622e9e682c144.png" |
|
|
,SPRITE_DIR / "Outfielder.sprite3" / "175ddc7ed99cc5b72909098046d8f558.png" |
|
|
,SPRITE_DIR / "Outfielder.sprite3" / "9f31c772f88a5f32fe857d57b3bcb04c.png" |
|
|
,SPRITE_DIR / "Outfielder.sprite3" / "d0a8837867d39444a824b734d4cd5554.png" |
|
|
,SPRITE_DIR / "Owl.sprite3" / "236bb6b33e7db00834bcea89b03b8a5e.png" |
|
|
,SPRITE_DIR / "Owl.sprite3" / "806139207066cb5eaef727d54c1bb4ec.png" |
|
|
,SPRITE_DIR / "Owl.sprite3" / "a518f70b65ec489e709795209b43207a.png" |
|
|
,SPRITE_DIR / "Paddle.sprite3" / "15864fac7d38bb94c1ec3a199de96c26.png" |
|
|
,SPRITE_DIR / "Panther.sprite3" / "0e7c244f54b27058f8b17d9e0d3cee12.png" |
|
|
,SPRITE_DIR / "Panther.sprite3" / "4a762fd04901407544d8858adac2b3fa.png" |
|
|
,SPRITE_DIR / "Panther.sprite3" / "a7aee991f51636574625c1300f035bdd.png" |
|
|
,SPRITE_DIR / "Pants.sprite3" / "ac9c7259873e472c2c1a99339c694f16.png" |
|
|
,SPRITE_DIR / "Pants.sprite3" / "ef8b1576f183222a4c2d373a7bc194cc.png" |
|
|
,SPRITE_DIR / "Parrot.sprite3" / "036fad20b674197358f8c0b2dc64e17e.png" |
|
|
,SPRITE_DIR / "Parrot.sprite3" / "082f371c206f07d20e53595a9c69cc22.png" |
|
|
,SPRITE_DIR / "Party Hats.sprite3" / "1d14be44e4aa99a471115cd874204690.png" |
|
|
,SPRITE_DIR / "Party Hats.sprite3" / "8b43413906cf1ba1343580d3ca062048.png" |
|
|
,SPRITE_DIR / "Party Hats.sprite3" / "abefb98344ece228afeb462f46d6b750.png" |
|
|
,SPRITE_DIR / "Pencil.sprite3" / "b3d6eae85f285dd618bf9dcf609b9454.png" |
|
|
,SPRITE_DIR / "Pencil.sprite3" / "f017876452a24d118fc0b1753caefad9.png" |
|
|
,SPRITE_DIR / "Penguin 2.sprite3" / "280d2aa13f0c6774cc8828dc177aaf60.png" |
|
|
,SPRITE_DIR / "Penguin 2.sprite3" / "428772307d90f4b347d6cc3c0d8e76ef.png" |
|
|
,SPRITE_DIR / "Penguin 2.sprite3" / "780467f3d173dcb37fd65834841babc6.png" |
|
|
,SPRITE_DIR / "Penguin 2.sprite3" / "d485f5620d2dde69a6aa1cda7c897d12.png" |
|
|
,SPRITE_DIR / "Penguin.sprite3" / "6d11aedea7f316215aaa0d08617f4c31.png" |
|
|
,SPRITE_DIR / "Penguin.sprite3" / "c434b674f2da18ba13cdfe51dbc05ecc.png" |
|
|
,SPRITE_DIR / "Penguin.sprite3" / "dad5b0d82cb6e053d1ded2ef537a9453.png" |
|
|
,SPRITE_DIR / "Pico Walking.sprite3" / "22fb16ae7cc18187a7adaf2852f07884.png" |
|
|
,SPRITE_DIR / "Pico Walking.sprite3" / "52a60eccb624530fd3a24fc41fbad6e5.png" |
|
|
,SPRITE_DIR / "Pico Walking.sprite3" / "702bd644d01ea8eda2ea122daeea7d74.png" |
|
|
,SPRITE_DIR / "Pico Walking.sprite3" / "c8f58f31cabf4acabb3f828730061276.png" |
|
|
,SPRITE_DIR / "Pico.sprite3" / "a7597b1f0c13455d335a3d4fe77da528.png" |
|
|
,SPRITE_DIR / "Pico.sprite3" / "bcc0e8a5dda3a813608902b887c87bb4.png" |
|
|
,SPRITE_DIR / "Pico.sprite3" / "d6dfa2efe58939af4c85755feb3c0375.png" |
|
|
,SPRITE_DIR / "Pico.sprite3" / "e7ce31db37f7abd2901499db2e9ad83a.png" |
|
|
,SPRITE_DIR / "Pitcher.sprite3" / "049132404cb2cb157830aaf18aee6a24.png" |
|
|
,SPRITE_DIR / "Pitcher.sprite3" / "ae8aa57ce6e5729d30d8b785bec97774.png" |
|
|
,SPRITE_DIR / "Pitcher.sprite3" / "bceae719ba1ec230afec56f14a1e4d52.png" |
|
|
,SPRITE_DIR / "Pitcher.sprite3" / "fc955dec7f1e97f1ddd9f8245a80907e.png" |
|
|
,SPRITE_DIR / "Planet2.sprite3" / "50cde8a4a737da0eba1ab73eb263f836.png" |
|
|
,SPRITE_DIR / "Polar Bear.sprite3" / "11d00a06abd2c882672464f4867e90b6.png" |
|
|
,SPRITE_DIR / "Polar Bear.sprite3" / "5d7cd81aad80100368b8b77bf09ad576.png" |
|
|
,SPRITE_DIR / "Polar Bear.sprite3" / "d050a3394b61ade080f7963c40192e7d.png" |
|
|
,SPRITE_DIR / "Potion.sprite3" / "0eceab4561534dde827bf68233f47441.png" |
|
|
,SPRITE_DIR / "Potion.sprite3" / "d922ffdfe38fd30fd8787810c6bce318.png" |
|
|
,SPRITE_DIR / "Potion.sprite3" / "f8500e9530bf1136c6386f2a329519dd.png" |
|
|
,SPRITE_DIR / "Prince.sprite3" / "ada9c5ce11245c467c780bceb665c42d.png" |
|
|
,SPRITE_DIR / "Princess.sprite3" / "0721f5238a2bcde49d05f72ca9d21d9b.png" |
|
|
,SPRITE_DIR / "Princess.sprite3" / "23330150c0a09180083b597cbfeca99a.png" |
|
|
,SPRITE_DIR / "Princess.sprite3" / "39157d5d3280ab0b273260170d5436c2.png" |
|
|
,SPRITE_DIR / "Princess.sprite3" / "ba37f578cc6cabce6fe4d2864c9eb96f.png" |
|
|
,SPRITE_DIR / "Princess.sprite3" / "e59f55c86ea557bdbd88302012ce8db5.png" |
|
|
,SPRITE_DIR / "Pufferfish.sprite3" / "1b4f39763c9848cc840522b95cc6d8ae.png" |
|
|
,SPRITE_DIR / "Pufferfish.sprite3" / "2266c6bb2c3a8fb80783518a08852b4a.png" |
|
|
,SPRITE_DIR / "Pufferfish.sprite3" / "b8aa1bd46eacc054c695b89167c3ad28.png" |
|
|
,SPRITE_DIR / "Pufferfish.sprite3" / "e73e71718306f6c7085305dba142c315.png" |
|
|
,SPRITE_DIR / "Puppy.sprite3" / "05630bfa94501a3e5d61ce443a0cea70.png" |
|
|
,SPRITE_DIR / "Puppy.sprite3" / "2768d9e44a0aab055856d301bbc2b04e.png" |
|
|
,SPRITE_DIR / "Puppy.sprite3" / "c4aeb5c39b39ef57a3f18ace54cf7db1.png" |
|
|
,SPRITE_DIR / "Puppy.sprite3" / "c7817052ed9e78057f877d0d56b5c6a6.png" |
|
|
,SPRITE_DIR / "Rabbit.sprite3" / "137976ec71439e2f986caeaa70e4c932.png" |
|
|
,SPRITE_DIR / "Rabbit.sprite3" / "1ca3f829a2c9f7fa4d1df295fe5f787c.png" |
|
|
,SPRITE_DIR / "Rabbit.sprite3" / "49169d752f20d27fb71022b16044d759.png" |
|
|
,SPRITE_DIR / "Rabbit.sprite3" / "90677c6f16380ef077d6115f6a6371ff.png" |
|
|
,SPRITE_DIR / "Rabbit.sprite3" / "970f886bfa454e1daa6d6c30ef49a972.png" |
|
|
,SPRITE_DIR / "Radio.sprite3" / "828f0762d028605f6fe52f9287555b74.png" |
|
|
,SPRITE_DIR / "Radio.sprite3" / "e96676f038fc523b40392dc1676552dc.png" |
|
|
,SPRITE_DIR / "Rainbow.sprite3" / "033979eba12e4572b2520bd93a87583e.png" |
|
|
,SPRITE_DIR / "Referee.sprite3" / "1cd641a48499db84636d983916b62a83.png" |
|
|
,SPRITE_DIR / "Referee.sprite3" / "46dde2baba61a7e48463ae8e58441470.png" |
|
|
,SPRITE_DIR / "Referee.sprite3" / "5948c4160089fcc0975a867221ff2256.png" |
|
|
,SPRITE_DIR / "Referee.sprite3" / "7eeca5313c2e7d455482badff3079f64.png" |
|
|
,SPRITE_DIR / "Reindeer.sprite3" / "60993a025167e7886736109dca5d55e2.png" |
|
|
,SPRITE_DIR / "Retro Robot.sprite3" / "35070c1078c4eec153ea2769516c922c.png" |
|
|
,SPRITE_DIR / "Retro Robot.sprite3" / "53398a713b144ecda6ec32fb4a8d28e1.png" |
|
|
,SPRITE_DIR / "Retro Robot.sprite3" / "d139f89665962dcaab4cb2b246359ba1.png" |
|
|
,SPRITE_DIR / "Ripley.sprite3" / "043373c51689f3df8bf50eb12c4e3d39.png" |
|
|
,SPRITE_DIR / "Ripley.sprite3" / "3ab169f52ea3783270d28ef035a5a7c5.png" |
|
|
,SPRITE_DIR / "Ripley.sprite3" / "8e173178d886d1cb272877e8923d651b.png" |
|
|
,SPRITE_DIR / "Ripley.sprite3" / "90feaffe3d0c4d31287d57bd1bc64afa.png" |
|
|
,SPRITE_DIR / "Ripley.sprite3" / "e751d0a781694897f75046eb2810e9a5.png" |
|
|
,SPRITE_DIR / "Ripley.sprite3" / "f798adaf44e8891c5e2f1b2a82a613b2.png" |
|
|
,SPRITE_DIR / "Robot.sprite3" / "10060b3b58c77345cfe92288a46e5c20.png" |
|
|
,SPRITE_DIR / "Robot.sprite3" / "36d1098b880dbe47e58d93e7b2842381.png" |
|
|
,SPRITE_DIR / "Robot.sprite3" / "4f5441207afc9bc075b0b404dbba8b59.png" |
|
|
,SPRITE_DIR / "Robot.sprite3" / "89679608327ad572b93225d06fe9edda.png" |
|
|
,SPRITE_DIR / "Rocketship.sprite3" / "10f83786e5ee34f40ee43b49bba89ee2.png" |
|
|
,SPRITE_DIR / "Rocketship.sprite3" / "49ee475c516a444d8a512724063b8b98.png" |
|
|
,SPRITE_DIR / "Rocketship.sprite3" / "525c06ceb3a351244bcd810c9ba951c7.png" |
|
|
,SPRITE_DIR / "Rocketship.sprite3" / "5682c68af2cc8aea791f0373e9ed03d8.png" |
|
|
,SPRITE_DIR / "Rocketship.sprite3" / "a6ff2f1344a18cc0a4bcc945e00afaf4.png" |
|
|
,SPRITE_DIR / "Rocks.sprite3" / "55426ccbb5c49b1526e53586943f3ec3.png" |
|
|
,SPRITE_DIR / "Rooster.sprite3" / "0ae345deb1c81ec7f4f4644c26ac85fa.png" |
|
|
,SPRITE_DIR / "Rooster.sprite3" / "6490360bd5d6efd2b646fb24c19df6b1.png" |
|
|
,SPRITE_DIR / "Rooster.sprite3" / "bd5f701c99aa6512bac7b87c51e7cd46.png" |
|
|
,SPRITE_DIR / "Ruby.sprite3" / "c30210e8f719c3a4d2c7cc6917a39300.png" |
|
|
,SPRITE_DIR / "Ruby.sprite3" / "fc15fdbcc535473f6140cab28197f3be.png" |
|
|
,SPRITE_DIR / "Sailboat.sprite3" / "ca241a938a2c44a0de6b91230012ff39.png" |
|
|
,SPRITE_DIR / "Sam.sprite3" / "8208e99159b36c957fb9fbc187e51bc7.png" |
|
|
,SPRITE_DIR / "Sasha.sprite3" / "89bb25e1465eb9481d267e4f9df592af.png" |
|
|
,SPRITE_DIR / "Sasha.sprite3" / "a0b8890ce458aebed5e7002e1897508e.png" |
|
|
,SPRITE_DIR / "Sasha.sprite3" / "e26bf53469cafd730ca150e745ceeafc.png" |
|
|
,SPRITE_DIR / "Saxophone.sprite3" / "4414c51bdd03f60f40a1210e1d55cf57.png" |
|
|
,SPRITE_DIR / "Saxophone.sprite3" / "459a64bebb7a788395c70e5369ab4746.png" |
|
|
,SPRITE_DIR / "Scarf.sprite3" / "05b06ab8d2c6e2110896d70bb60a9fd7.png" |
|
|
,SPRITE_DIR / "Scarf.sprite3" / "213db212d5d0c602f85cb248719ce785.png" |
|
|
,SPRITE_DIR / "Scarf.sprite3" / "4a85e4e6232f12abf9802bec4aa419b3.png" |
|
|
,SPRITE_DIR / "Shark 2.sprite3" / "6182a0628eadf2d16624864bea964432.png" |
|
|
,SPRITE_DIR / "Shark 2.sprite3" / "7f4440b268358417aa79ccef06877c57.png" |
|
|
,SPRITE_DIR / "Shark 2.sprite3" / "8a8d551e951087050cfa88fc64f9b4db.png" |
|
|
,SPRITE_DIR / "Shark.sprite3" / "6c8008ae677ec51af8da5023fa2cd521.png" |
|
|
,SPRITE_DIR / "Shark.sprite3" / "b769db8fcbbf2609f0552db62ec1f94a.png" |
|
|
,SPRITE_DIR / "Shirt.sprite3" / "43e916bbe0ba7cecd08407d25ac3d104.png" |
|
|
,SPRITE_DIR / "Shoes.sprite3" / "1e813a1618f38212a6febaa7e6b8d712.png" |
|
|
,SPRITE_DIR / "Shoes.sprite3" / "71b5a444d482455e9956cfd52d20526a.png" |
|
|
,SPRITE_DIR / "Shoes.sprite3" / "724d9a8984279949ce452fc9b2e437a6.png" |
|
|
,SPRITE_DIR / "Shoes.sprite3" / "f89f1656251248f1591aa67ae946c047.png" |
|
|
,SPRITE_DIR / "Shorts.sprite3" / "4d5f7a13ed20dc4f8fd194a7eb3f625f.png" |
|
|
,SPRITE_DIR / "Shorts.sprite3" / "d5fc56b7247f079e5821d74d3e91e7a6.png" |
|
|
,SPRITE_DIR / "Shorts.sprite3" / "ea78ad682811f9c42731ec648ec7af3c.png" |
|
|
,SPRITE_DIR / "Singer1.sprite3" / "d6ff94dc7e24200c28015ee5d6373140.png" |
|
|
,SPRITE_DIR / "Skeleton.sprite3" / "3cfff37072a4138b977ba406c290b419.png" |
|
|
,SPRITE_DIR / "Skeleton.sprite3" / "67108e6b1d0f41aba2f94f81114ebf59.png" |
|
|
,SPRITE_DIR / "Skeleton.sprite3" / "c4d755c672a0826caa7b6fb767cc3f9b.png" |
|
|
,SPRITE_DIR / "Skeleton.sprite3" / "f4a00b2bd214b1d8412a2e89b2030354.png" |
|
|
,SPRITE_DIR / "Snake.sprite3" / "42519e0ee19d75def88a514d3c49ce37.png" |
|
|
,SPRITE_DIR / "Snake.sprite3" / "a0acb49efdf60b20cea0833eeedd44a1.png" |
|
|
,SPRITE_DIR / "Snake.sprite3" / "f0e6ebdbdc8571b42f8a48cc2aed3042.png" |
|
|
,SPRITE_DIR / "Snowflake.sprite3" / "083735cc9cd0e6d8c3dbab5ab9ee5407.png" |
|
|
,SPRITE_DIR / "Snowman.sprite3" / "0f109df620f935b94cb154101e6586d4.png" |
|
|
,SPRITE_DIR / "Soccer Ball.sprite3" / "5d973d7a3a8be3f3bd6e1cd0f73c32b5.png" |
|
|
,SPRITE_DIR / "Speaker.sprite3" / "697f6becae5321f77990636564ef0c97.png" |
|
|
,SPRITE_DIR / "Squirrel.sprite3" / "b86efb7f23387300cf9037a61f328ab9.png" |
|
|
,SPRITE_DIR / "Star.sprite3" / "551629f2a64c1f3703e57aaa133effa6.png" |
|
|
,SPRITE_DIR / "Starfish.sprite3" / "69dca6e42d45d3fef89f81de40b11bef.png" |
|
|
,SPRITE_DIR / "Starfish.sprite3" / "be2ca55a5688670302e7c3f79d5040d1.png" |
|
|
,SPRITE_DIR / "Stop.sprite3" / "1e2c3987e4cdb1f317b1773662719b13.png" |
|
|
,SPRITE_DIR / "Story-A.sprite3" / "3c46f5192d2c29f957381e0100c6085d.png" |
|
|
,SPRITE_DIR / "Story-A.sprite3" / "4b1beecd9a8892df0918242b2b5fbd4c.png" |
|
|
,SPRITE_DIR / "Story-A.sprite3" / "7a6fdf5e26fc690879f8e215bfdec4d5.png" |
|
|
,SPRITE_DIR / "Story-B.sprite3" / "22817ed2e4253787c78d7b696bbefdc1.png" |
|
|
,SPRITE_DIR / "Story-B.sprite3" / "5f8301434ce176ab328f5b658ee1ec05.png" |
|
|
,SPRITE_DIR / "Story-B.sprite3" / "a09376e1eacf17be3c9fbd268674b9f7.png" |
|
|
,SPRITE_DIR / "Story-C.sprite3" / "5e61610cbba50ba86f18830f61bbaecb.png" |
|
|
,SPRITE_DIR / "Story-C.sprite3" / "6bd5cb8bc3e4df5e055f4c56dd630855.png" |
|
|
,SPRITE_DIR / "Story-C.sprite3" / "f6ff602902affbae2f89b389f08df432.png" |
|
|
,SPRITE_DIR / "Story-D.sprite3" / "130cc4b9ad8dd8936d22c51c05ac6860.png" |
|
|
,SPRITE_DIR / "Story-D.sprite3" / "b28d76f648ad24932a18cb40c8d76bc5.png" |
|
|
,SPRITE_DIR / "Story-D.sprite3" / "dd713e3bf42d7a4fd8d2f12094db1c63.png" |
|
|
,SPRITE_DIR / "Story-E.sprite3" / "3005df22798da45f1daf1de7421bb91d.png" |
|
|
,SPRITE_DIR / "Story-E.sprite3" / "4e903ac41a7e16a52efff8477f2398c7.png" |
|
|
,SPRITE_DIR / "Story-E.sprite3" / "add5c5a8eec67eb010b5cbd44dea5c8d.png" |
|
|
,SPRITE_DIR / "Story-F.sprite3" / "4a3ae31dd3dd3b96239a0307cfdaa1b6.png" |
|
|
,SPRITE_DIR / "Story-F.sprite3" / "83565581ecc9f7d4010efd8683a99393.png" |
|
|
,SPRITE_DIR / "Story-F.sprite3" / "d4ec9a1827429f4e2f3dc239dcc15b95.png" |
|
|
,SPRITE_DIR / "Story-G.sprite3" / "648cfdd48a7f748e6198194669ba1909.png" |
|
|
,SPRITE_DIR / "Story-G.sprite3" / "85144902cc61fe98dca513b74276d7d8.png" |
|
|
,SPRITE_DIR / "Story-G.sprite3" / "8fb61932544adbe8c95b067ad1351758.png" |
|
|
,SPRITE_DIR / "Story-H.sprite3" / "70520daa9f82a2347c8a8fa9e7fe1a6e.png" |
|
|
,SPRITE_DIR / "Story-H.sprite3" / "99aae97a2b49904db7eeb813fa968582.png" |
|
|
,SPRITE_DIR / "Story-H.sprite3" / "eec286b1cfea3f219a5b486931abedd2.png" |
|
|
,SPRITE_DIR / "Story-I.sprite3" / "1bceea90292a51a7177abf581f28bf2c.png" |
|
|
,SPRITE_DIR / "Story-I.sprite3" / "2c156e20da1ad4e8e397a89ad8fb1c26.png" |
|
|
,SPRITE_DIR / "Story-I.sprite3" / "9cad752323aa81dfa8d8cf009057b108.png" |
|
|
,SPRITE_DIR / "Story-J.sprite3" / "2838de5d131785c985eb0eab25ec63af.png" |
|
|
,SPRITE_DIR / "Story-J.sprite3" / "7d7d6f257a6bf3668a0befa4199f16a0.png" |
|
|
,SPRITE_DIR / "Story-J.sprite3" / "d5b58ddd6f6b4fdcfdfd86d102853935.png" |
|
|
,SPRITE_DIR / "Story-K.sprite3" / "0cb908dbc38635cc595e6060afc1b682.png" |
|
|
,SPRITE_DIR / "Story-K.sprite3" / "17ef8f63a2a8f47258bd62cf642fd8d6.png" |
|
|
,SPRITE_DIR / "Story-K.sprite3" / "ecf86afea23fd95e27d4e63659adbfa6.png" |
|
|
,SPRITE_DIR / "Story-L.sprite3" / "0fc3ac08468935694255ef8a461d4d26.png" |
|
|
,SPRITE_DIR / "Story-L.sprite3" / "935c7cf21c35523c0a232013a6399a49.png" |
|
|
,SPRITE_DIR / "Story-L.sprite3" / "ec4d85a60c32c7637de31dbf503266a0.png" |
|
|
,SPRITE_DIR / "Story-M.sprite3" / "42e5468fa164e001925d5a49d372f4b1.png" |
|
|
,SPRITE_DIR / "Story-M.sprite3" / "643896fcad0a1bf6eb9f3f590094687c.png" |
|
|
,SPRITE_DIR / "Story-M.sprite3" / "9bf9e677da34528433d3c1acb945e2df.png" |
|
|
,SPRITE_DIR / "Story-N.sprite3" / "40ffad793f4042a5fe7b3aaa6bc175ae.png" |
|
|
,SPRITE_DIR / "Story-N.sprite3" / "80c8f32282b697097933837905a6f257.png" |
|
|
,SPRITE_DIR / "Story-N.sprite3" / "c2f77473dd16d1a3713218b05390a688.png" |
|
|
,SPRITE_DIR / "Story-O.sprite3" / "0bdd31ea2b3b78d0c39022795a49c69a.png" |
|
|
,SPRITE_DIR / "Story-O.sprite3" / "40bf3880b678beeda8cf708a51a4402d.png" |
|
|
,SPRITE_DIR / "Story-O.sprite3" / "43a89fc1442627ca48b1dc631c517942.png" |
|
|
,SPRITE_DIR / "Story-P.sprite3" / "1a41f74cd76d7202d8b22ffc7729e03f.png" |
|
|
,SPRITE_DIR / "Story-P.sprite3" / "377eac55366670a03c469705c6689f09.png" |
|
|
,SPRITE_DIR / "Story-P.sprite3" / "9cf707e83af27c47e74adb77496ffca5.png" |
|
|
,SPRITE_DIR / "Story-Q.sprite3" / "01acd1076994a4379a3fc9e034bc05fc.png" |
|
|
,SPRITE_DIR / "Story-Q.sprite3" / "84a6dc992bce018a1eac9be0173ad917.png" |
|
|
,SPRITE_DIR / "Story-Q.sprite3" / "efc27a91c30d6a511be4245e36684192.png" |
|
|
,SPRITE_DIR / "Story-R.sprite3" / "3c3f44aba3eff8856472e06b333a7201.png" |
|
|
,SPRITE_DIR / "Story-R.sprite3" / "4f217b14a161fcd9590614b0733100ea.png" |
|
|
,SPRITE_DIR / "Story-R.sprite3" / "5c1d38d02ae9c4df7851a6e9d52f25b4.png" |
|
|
,SPRITE_DIR / "Story-S.sprite3" / "47b9f910048ce4db93bdfbcd2638e19a.png" |
|
|
,SPRITE_DIR / "Story-S.sprite3" / "5a113fcacd35ababbf23c5a9289433d1.png" |
|
|
,SPRITE_DIR / "Story-S.sprite3" / "fd2a94481c3ef0c223784b2f3c6df874.png" |
|
|
,SPRITE_DIR / "Story-T.sprite3" / "001a2186db228fdd9bfbf3f15800bb63.png" |
|
|
,SPRITE_DIR / "Story-T.sprite3" / "66b22b0ff0a5c1c205a701316ab954cf.png" |
|
|
,SPRITE_DIR / "Story-T.sprite3" / "b61e1ac30aa2f35d4fd8c23fab1f76ea.png" |
|
|
,SPRITE_DIR / "Story-U.sprite3" / "51dd73c840ba3aca0f9770e13cb14fb3.png" |
|
|
,SPRITE_DIR / "Story-U.sprite3" / "cfb334b977b8f2a39aa56b1e0532829e.png" |
|
|
,SPRITE_DIR / "Story-U.sprite3" / "f6b7b4da5362fdac29d84f1fbf19e3f4.png" |
|
|
,SPRITE_DIR / "Story-V.sprite3" / "43a8993221848f90e9f37664e7832b4a.png" |
|
|
,SPRITE_DIR / "Story-V.sprite3" / "d5c20886e3eb0ca0f5430c9482b1d832.png" |
|
|
,SPRITE_DIR / "Story-V.sprite3" / "f27e7a4216665a6eab43fe9b4b5ec934.png" |
|
|
,SPRITE_DIR / "Story-W.sprite3" / "396e27d20d1a49edaa106ba6d667cedd.png" |
|
|
,SPRITE_DIR / "Story-W.sprite3" / "528df57da4490f6da8c75da06a1367f5.png" |
|
|
,SPRITE_DIR / "Story-W.sprite3" / "f21ba826cd88c376e868f079d6df273c.png" |
|
|
,SPRITE_DIR / "Story-X.sprite3" / "04be1176e562eff16f1159f69945a82e.png" |
|
|
,SPRITE_DIR / "Story-X.sprite3" / "ca4e3e84788bdeea42dd5ed952d5a66c.png" |
|
|
,SPRITE_DIR / "Story-X.sprite3" / "db0c1a6499169aac6639a1a0076658ce.png" |
|
|
,SPRITE_DIR / "Story-Y.sprite3" / "093a9410933f7d01f459f08bcb01735b.png" |
|
|
,SPRITE_DIR / "Story-Y.sprite3" / "59275f907633ce02074f787e5767bfde.png" |
|
|
,SPRITE_DIR / "Story-Y.sprite3" / "d7fabe2652c93dd1bf91d9064cf5a348.png" |
|
|
,SPRITE_DIR / "Story-Z.sprite3" / "23c24dbee23b1545afa8ee15ed339327.png" |
|
|
,SPRITE_DIR / "Story-Z.sprite3" / "34825a171f7b35962484fa53e99ff632.png" |
|
|
,SPRITE_DIR / "Story-Z.sprite3" / "665db4c356d7e010fa8d71cc291834e3.png" |
|
|
,SPRITE_DIR / "Strawberry.sprite3" / "10ed1486ff4bab3eebb3b8ae55d81ccd.png" |
|
|
,SPRITE_DIR / "Strawberry.sprite3" / "2fa57942dc7ded7eddc4d41554768d67.png" |
|
|
,SPRITE_DIR / "Strawberry.sprite3" / "662279c12965d2913a060a55aebec496.png" |
|
|
,SPRITE_DIR / "Strawberry.sprite3" / "aa4eae20c750900e4f63e6ede4083d81.png" |
|
|
,SPRITE_DIR / "Strawberry.sprite3" / "f5008785e74590689afca4b578d108a4.png" |
|
|
,SPRITE_DIR / "Sun.sprite3" / "406808d86aff20a15d592b308e166a32.png" |
|
|
,SPRITE_DIR / "Sunglasses1.sprite3" / "c95a05c3bed665027d267d93454c428a.png" |
|
|
,SPRITE_DIR / "Sunglasses1.sprite3" / "dc568ae1f8b9b6544f0634ef975a7098.png" |
|
|
,SPRITE_DIR / "Taco.sprite3" / "383ea1ef802bc2706670536cfa8271b7.png" |
|
|
,SPRITE_DIR / "Taco.sprite3" / "c97113d17afeaac9f461ea0ec257ef26.png" |
|
|
,SPRITE_DIR / "Takeout.sprite3" / "24cc271fd6cf55f25b71e78faf749a98.png" |
|
|
,SPRITE_DIR / "Takeout.sprite3" / "2b32d6a4a724c38bfaeb494d30827f19.png" |
|
|
,SPRITE_DIR / "Takeout.sprite3" / "40f63eb18230c4defa9051830beffb0f.png" |
|
|
,SPRITE_DIR / "Takeout.sprite3" / "9202a59888545c56c864bacb700c4297.png" |
|
|
,SPRITE_DIR / "Takeout.sprite3" / "e03cd6e668e0eeddb2da98a095e2f30f.png" |
|
|
,SPRITE_DIR / "Tatiana.sprite3" / "5cf65a9f942ca92c93915527ff9db1e6.png" |
|
|
,SPRITE_DIR / "Tatiana.sprite3" / "91fb7d056beaf553ccec03d61d72c545.png" |
|
|
,SPRITE_DIR / "Tatiana.sprite3" / "e207fd3f99e1db8c5d66f49446f27e37.png" |
|
|
,SPRITE_DIR / "Tatiana.sprite3" / "e2ea6bbc6066574d4836e808a1c5f849.png" |
|
|
,SPRITE_DIR / "Taylor.sprite3" / "a504d785629f2d1ca6b87e80b334d5e8.png" |
|
|
,SPRITE_DIR / "Taylor.sprite3" / "ae2eaae0882543dc276c8e7d56ff2e7b.png" |
|
|
,SPRITE_DIR / "Taylor.sprite3" / "e0082f49fc5d0d83d7fad6124ba82bb1.png" |
|
|
,SPRITE_DIR / "Ten80 Dance.sprite3" / "279bd5499329f98a68cf92c68014e198.png" |
|
|
,SPRITE_DIR / "Ten80 Dance.sprite3" / "377b8521c436f4f39ed2100fa1cb7c2f.png" |
|
|
,SPRITE_DIR / "Ten80 Dance.sprite3" / "3c9a7eac1d696ae74ee40c6efa8fa4dd.png" |
|
|
,SPRITE_DIR / "Ten80 Dance.sprite3" / "548bdf23904e409c1fcc0992f44d0b4c.png" |
|
|
,SPRITE_DIR / "Ten80 Dance.sprite3" / "580fba92f23d5592200eb5a9079dc38f.png" |
|
|
,SPRITE_DIR / "Ten80 Dance.sprite3" / "8313a2229d555bbdb8ce92dffed067ad.png" |
|
|
,SPRITE_DIR / "Ten80 Dance.sprite3" / "86602007ae2952236d47d7fd587a56b6.png" |
|
|
,SPRITE_DIR / "Ten80 Dance.sprite3" / "b2f75ac1cd84615efaea6a7d7a4ee205.png" |
|
|
,SPRITE_DIR / "Ten80 Dance.sprite3" / "ce2141ce97921ddc333bc65ff5bec27d.png" |
|
|
,SPRITE_DIR / "Ten80 Dance.sprite3" / "e06ac61e96e3a5abf4ca0863816f5d28.png" |
|
|
,SPRITE_DIR / "Ten80 Dance.sprite3" / "e51942bb4651e616549cfce1ad36ff83.png" |
|
|
,SPRITE_DIR / "Ten80 Dance.sprite3" / "f60f99278455c843b7833fb7615428dd.png" |
|
|
,SPRITE_DIR / "Ten80 Dance.sprite3" / "fea7045c09073700b88fae8d4d257cd1.png" |
|
|
,SPRITE_DIR / "Tennis Ball.sprite3" / "34fa36004be0340ec845ba6bbeb5e5d5.png" |
|
|
,SPRITE_DIR / "Tera.sprite3" / "18f9a11ecdbd3ad8719beb176c484d41.png" |
|
|
,SPRITE_DIR / "Tera.sprite3" / "2daca5f43efc2d29fb089879448142e9.png" |
|
|
,SPRITE_DIR / "Tera.sprite3" / "365d4de6c99d71f1370f7c5e636728af.png" |
|
|
,SPRITE_DIR / "Tera.sprite3" / "5456a723f3b35eaa946b974a59888793.png" |
|
|
,SPRITE_DIR / "Toucan.sprite3" / "72952d831d0b67c9d056b44a4bc3d0ae.png" |
|
|
,SPRITE_DIR / "Toucan.sprite3" / "9eef2e49b3bbf371603ae783cd82db3c.png" |
|
|
,SPRITE_DIR / "Toucan.sprite3" / "b6345d7386021ee85bb17f8aa4950eed.png" |
|
|
,SPRITE_DIR / "Trampoline.sprite3" / "8fa3c6fcff2f25f5fe7842d68dcfe5cf.png" |
|
|
,SPRITE_DIR / "Tree1.sprite3" / "d04b15886635101db8220a4361c0c88d.png" |
|
|
,SPRITE_DIR / "Trees.sprite3" / "04758bd432a8b1cab527bddf14432147.png" |
|
|
,SPRITE_DIR / "Trees.sprite3" / "551b3fae8eab06b49013f54009a7767a.png" |
|
|
,SPRITE_DIR / "Trisha.sprite3" / "2d06023ec09ec312ab49055530511134.png" |
|
|
,SPRITE_DIR / "Trisha.sprite3" / "55d31103bc86447c6a727b4f0664a5ea.png" |
|
|
,SPRITE_DIR / "Trisha.sprite3" / "c31dc8487a841f644889784ff437e2c5.png" |
|
|
,SPRITE_DIR / "Truck.sprite3" / "63b00424bdabc3459e5bc554c6c21e06.png" |
|
|
,SPRITE_DIR / "Truck.sprite3" / "aaa05abc5aa182a0d7bfdc6db0f3207a.png" |
|
|
,SPRITE_DIR / "Truck.sprite3" / "ce077e6db3573062017f94c2e4a8caea.png" |
|
|
,SPRITE_DIR / "Trumpet.sprite3" / "47a1ec267505be96b678df30b92ec534.png" |
|
|
,SPRITE_DIR / "Trumpet.sprite3" / "9a5c211622d6d2fed600c1809fccd21d.png" |
|
|
,SPRITE_DIR / "Unicorn 2.sprite3" / "dcbeac8e856c9ddd6c457376be6573c8.png" |
|
|
,SPRITE_DIR / "Unicorn Running.sprite3" / "1fb3d038e985c01899881bc5bb373c16.png" |
|
|
,SPRITE_DIR / "Unicorn Running.sprite3" / "4709966d11b37e8a11d24c800e8b2859.png" |
|
|
,SPRITE_DIR / "Unicorn Running.sprite3" / "8feaeec435125227c675dd95f69ff835.png" |
|
|
,SPRITE_DIR / "Unicorn Running.sprite3" / "e111350b8bedefffee0d5e7e2490d446.png" |
|
|
,SPRITE_DIR / "Unicorn Running.sprite3" / "f00efa25fc97f2cce2499771d6a5f809.png" |
|
|
,SPRITE_DIR / "Unicorn Running.sprite3" / "fa5fe4596494a43db8c7957d2254aee3.png" |
|
|
,SPRITE_DIR / "Unicorn.sprite3" / "1439d51d9878276362b123c9045af6b5.png" |
|
|
,SPRITE_DIR / "Wand.sprite3" / "c021f0c7e3086a11336421dd864b7812.png" |
|
|
,SPRITE_DIR / "Wanda.sprite3" / "0b008dabac95126132ab4e0c56d25400.png" |
|
|
,SPRITE_DIR / "Watermelon.sprite3" / "1ed1c8b78eae2ee7422074d7f883031d.png" |
|
|
,SPRITE_DIR / "Watermelon.sprite3" / "21d1340478e32a942914a7afd12b9f1a.png" |
|
|
,SPRITE_DIR / "Watermelon.sprite3" / "677738282686d2dcce35d731c3ddc043.png" |
|
|
,SPRITE_DIR / "Winter Hat.sprite3" / "2672323e34d6dc82fda8fc3b057fa5aa.png" |
|
|
,SPRITE_DIR / "Witch.sprite3" / "44cbaf358d2d8e66815e447c25a4b72e.png" |
|
|
,SPRITE_DIR / "Witch.sprite3" / "668c9dc76ba6a07bebabf5aed4623566.png" |
|
|
,SPRITE_DIR / "Witch.sprite3" / "a7e48fc790511fbd46b30b1cdcdc98fc.png" |
|
|
,SPRITE_DIR / "Witch.sprite3" / "b10fb75f426397e10c878fda19d92009.png" |
|
|
,SPRITE_DIR / "Wizard Girl.sprite3" / "4be145d338d921b2d9d6dfd10cda4a6c.png" |
|
|
,SPRITE_DIR / "Wizard Hat.sprite3" / "398e447e36465c2521fdb3a6917b0c65.png" |
|
|
,SPRITE_DIR / "Wizard-toad.sprite3" / "4041d5a2d1869e81268b9b92b49013a3.png" |
|
|
,SPRITE_DIR / "Wizard-toad.sprite3" / "ca3bb4d397ecf6cda3edc48340af908b.png" |
|
|
,SPRITE_DIR / "Wizard.sprite3" / "55ba51188af86ca16ef30267e874c1ed.png" |
|
|
,SPRITE_DIR / "Wizard.sprite3" / "91d495085eb4d02a375c42f6318071e7.png" |
|
|
,SPRITE_DIR / "Wizard.sprite3" / "df943c9894ee4b9df8c5893ce30c2a5f.png" |
|
|
,SPRITE_DIR / "Zebra.sprite3" / "0e3bc5073305b7079b5e9a8c7b7d7f9b.png" |
|
|
,SPRITE_DIR / "Zebra.sprite3" / "f3e322a25b9f79801066056de6f33fb1.png" |
|
|
,BACKDROP_DIR / "Arctic.sb3" / "67e0db3305b3c8bac3a363b1c428892e.png" |
|
|
,BACKDROP_DIR / "Arctic.sb3" / "8eb8790be5507fdccf73e7c1570bbbab.png" |
|
|
,BACKDROP_DIR / "Baseball 1.sb3" / "825d9b54682c406215d9d1f98a819449.png" |
|
|
,BACKDROP_DIR / "Baseball 2.sb3" / "7be1f5b3e682813dac1f297e52ff7dca.png" |
|
|
,BACKDROP_DIR / "Basketball 1.sb3" / "ae21eac3d1814aee1d37ae82ea287816.png" |
|
|
,BACKDROP_DIR / "Basketball 2.sb3" / "a5865738283613a2725b2c9dda6d8c78.png" |
|
|
,BACKDROP_DIR / "Beach Malibu.sb3" / "050615fe992a00d6af0e664e497ebf53.png" |
|
|
,BACKDROP_DIR / "Beach Rio.sb3" / "968f0ede6e70e1dbb763d6fd4c5003e0.png" |
|
|
,BACKDROP_DIR / "Bedroom 1.sb3" / "7aa6bbb2ddc4c10f901e1a50aeac1c7e.png" |
|
|
,BACKDROP_DIR / "Bedroom 2.sb3" / "e2f8b0dbd0a65d2ad8bfc21616662a6a.png" |
|
|
,BACKDROP_DIR / "Bedroom 3.sb3" / "8cc0b88d53345b3e337e8f028a32a4e7.png" |
|
|
,BACKDROP_DIR / "Bench With View.sb3" / "962201a2b712a302fb087f8f0dcb2076.png" |
|
|
,BACKDROP_DIR / "Blue Sky 2.sb3" / "8eb8790be5507fdccf73e7c1570bbbab.png" |
|
|
,BACKDROP_DIR / "Blue Sky.sb3" / "e7c147730f19d284bcd7b3f00af19bb6.png" |
|
|
,BACKDROP_DIR / "Boardwalk.sb3" / "de0e54cd11551566f044e7e6bc588b2c.png" |
|
|
,BACKDROP_DIR / "Canyon.sb3" / "c7c0b27b959193a0b570a9639cfe8158.png" |
|
|
,BACKDROP_DIR / "Castle 1.sb3" / "e1914ed7917267f1c2ef2b48004cade9.png" |
|
|
,BACKDROP_DIR / "Castle 2.sb3" / "951765ee7f7370f120c9df20b577c22f.png" |
|
|
,BACKDROP_DIR / "Castle 3.sb3" / "76fa99f67569fcd39b4be74ed38c33f3.png" |
|
|
,BACKDROP_DIR / "Castle 4.sb3" / "4f45f79af8e8dac3d41eb5a06ade61d4.png" |
|
|
,BACKDROP_DIR / "Chalkboard.sb3" / "a8a24b5aa717bbef09dbe31368914427.png" |
|
|
,BACKDROP_DIR / "Circles.sb3" / "c9847be305920807c5597d81576dd0c4.png" |
|
|
,BACKDROP_DIR / "City With Water.sb3" / "1ef98019fc94ea65a1b55d5521285c7a.png" |
|
|
,BACKDROP_DIR / "Colorful City.sb3" / "04d18ddd1b85f0ea30beb14b8da49f60.png" |
|
|
,BACKDROP_DIR / "Concert.sb3" / "c8d90320d2966c08af8cdd1c6a7a93b5.png" |
|
|
,BACKDROP_DIR / "Desert.sb3" / "d98a9526a34890cf4bad11b5409eae2a.png" |
|
|
,BACKDROP_DIR / "Farm.sb3" / "1e8a70bd07f1dcba3383883f3b948266.png" |
|
|
,BACKDROP_DIR / "Field At Mit.sb3" / "5b0a970202b464915915260c03f05455.png" |
|
|
,BACKDROP_DIR / "Flowers.sb3" / "25a6ede51a96d4e55de2ffb81ae96f8c.png" |
|
|
,BACKDROP_DIR / "Forest.sb3" / "92968ac16b2f0c3f7835a6dacd172c7b.png" |
|
|
,BACKDROP_DIR / "Galaxy.sb3" / "5fab1922f254ae9fd150162c3e392bef.png" |
|
|
,BACKDROP_DIR / "Garden-rock.sb3" / "4f66053598bea0905e1559ab9d5a6e31.png" |
|
|
,BACKDROP_DIR / "Greek Theater.sb3" / "93d71e8b8a96cc007b8d68f36acd338a.png" |
|
|
,BACKDROP_DIR / "Hall.sb3" / "ea86ca30b346f27ca5faf1254f6a31e3.png" |
|
|
,BACKDROP_DIR / "Hay Field.sb3" / "da102a69d135973e0fc139131dec785a.png" |
|
|
,BACKDROP_DIR / "Hearts.sb3" / "f98526ccb0eec3ac7d6c8f8ab502825e.png" |
|
|
,BACKDROP_DIR / "Hill.sb3" / "2129c842f28d6881f622fdc3497ff2da.png" |
|
|
,BACKDROP_DIR / "Jungle.sb3" / "f4f908da19e2753f3ed679d7b37650ca.png" |
|
|
,BACKDROP_DIR / "Jurassic.sb3" / "64025bdca5db4938f65597e3682fddcf.png" |
|
|
,BACKDROP_DIR / "Light.sb3" / "4b98c07876ed8997c3762e75790507b4.png" |
|
|
,BACKDROP_DIR / "Metro.sb3" / "0b4a15ba028bf205ec051390d6ac4de7.png" |
|
|
,BACKDROP_DIR / "Moon.sb3" / "0b1d2eaf22d62ef88de80ccde5578fba.png" |
|
|
,BACKDROP_DIR / "Mountain.sb3" / "f84989feee2cf462a1c597169777ee3c.png" |
|
|
,BACKDROP_DIR / "Mural.sb3" / "efb625f7e0b199b15f69e116cd053cea.png" |
|
|
,BACKDROP_DIR / "Nebula.sb3" / "9b5cdbd596da1b6149f56b794b6394f4.png" |
|
|
,BACKDROP_DIR / "Neon Tunnel.sb3" / "57d2b13b2f73d3d878c72810c137b0d6.png" |
|
|
,BACKDROP_DIR / "Night City With Street.sb3" / "14443ad7907b6479d7562a12b8ae0efb.png" |
|
|
,BACKDROP_DIR / "Night City.sb3" / "6fdc795ff487204f72740567be5f64f9.png" |
|
|
,BACKDROP_DIR / "Party.sb3" / "108160d0e44d1c340182e31c9dc0758a.png" |
|
|
,BACKDROP_DIR / "Pathway.sb3" / "5d747ec036755a4b129f0d5b978bc61c.png" |
|
|
,BACKDROP_DIR / "Playground.sb3" / "e5f794c8756ca0cead5cb7e7fe354c41.png" |
|
|
,BACKDROP_DIR / "Playing Field.sb3" / "2de108f3098e92f5c5976cf75d38e99d.png" |
|
|
,BACKDROP_DIR / "Pool.sb3" / "6cab934df643d2fc508cfa90c0c4059b.png" |
|
|
,BACKDROP_DIR / "Rays.sb3" / "87e963282db9e020e8c4d075891ea12b.png" |
|
|
,BACKDROP_DIR / "Refrigerator.sb3" / "98f053f9681e872f34fafd783ce72205.png" |
|
|
,BACKDROP_DIR / "Room 1.sb3" / "87ec29ad216c0074c731d581c7f40c39.png" |
|
|
,BACKDROP_DIR / "Room 1.sb3" / "a81668321aa3dcc0fc185d3e36ae76f6.png" |
|
|
,BACKDROP_DIR / "Room 2.sb3" / "05ae3e3bbea890a6e3552ffe8456775e.png" |
|
|
,BACKDROP_DIR / "Savanna.sb3" / "9b020b8c7cb6a9592f7303add9441d8f.png" |
|
|
,BACKDROP_DIR / "School.sb3" / "1dea69ac0f62cf538d368a7bde1372ac.png" |
|
|
,BACKDROP_DIR / "Slopes.sb3" / "63b6a69594a0a87888b56244bfa2ac1b.png" |
|
|
,BACKDROP_DIR / "Soccer 2.sb3" / "b0dc1268cb595aaeef405bce40d1639c.png" |
|
|
,BACKDROP_DIR / "Soccer.sb3" / "04a63154f04b09494354090f7cc2f1b9.png" |
|
|
,BACKDROP_DIR / "Space City 1.sb3" / "20344b0edcc498281e4cb80242a72667.png" |
|
|
,BACKDROP_DIR / "Space City 2.sb3" / "32b2316fd375faa18088f6c57ebb1c8d.png" |
|
|
,BACKDROP_DIR / "Space.sb3" / "84208d9a3718ec3c9fc5a32a792fa1d0.png" |
|
|
,BACKDROP_DIR / "Spaceship.sb3" / "0c450891306fa63ef02aa0fda7fd0ef9.png" |
|
|
,BACKDROP_DIR / "Spotlight.sb3" / "d26bf4c3980163d9106625cc2ea6c50d.png" |
|
|
,BACKDROP_DIR / "Stars.sb3" / "47282ff0f7047c6fab9c94b531abf721.png" |
|
|
,BACKDROP_DIR / "Stripes.sb3" / "a6a21f5c08d586e8daaebde37c97fb6f.png" |
|
|
,BACKDROP_DIR / "Theater 2.sb3" / "061a78ed83495dd0acd6d62e83e1b972.png" |
|
|
,BACKDROP_DIR / "Theater.sb3" / "c2b097bc5cdb6a14ef5485202bc5ee76.png" |
|
|
,BACKDROP_DIR / "Tree.sb3" / "a23fbf972001c94637b568992f8fd7bd.png" |
|
|
,BACKDROP_DIR / "Underwater 1.sb3" / "d3344650f594bcecdf46aa4a9441badd.png" |
|
|
,BACKDROP_DIR / "Underwater 2.sb3" / "1517c21786d2d0edc2f3037408d850bd.png" |
|
|
,BACKDROP_DIR / "Urban.sb3" / "1679049718869e1f548e1e8823e29c1c.png" |
|
|
,BACKDROP_DIR / "Wall 1.sb3" / "7e5327c68ff6ddabc48dbfe4717a04fe.png" |
|
|
,BACKDROP_DIR / "Wall 2.sb3" / "82d867fcd9f1b5f49e29c2f853d55665.png" |
|
|
,BACKDROP_DIR / "Water And Rocks.sb3" / "0015433a406a53f00b792424b823268c.png" |
|
|
,BACKDROP_DIR / "Wetland.sb3" / "ef9973bcff6d4cbc558e946028ec7d23.png" |
|
|
,BACKDROP_DIR / "Winter.sb3" / "5fa9385a60b904672d0e46e9d768bb32.png" |
|
|
,BACKDROP_DIR / "Witch House.sb3" / "30085b2d27beb5acdbe895d8b3e64b04.png" |
|
|
,BACKDROP_DIR / "Woods And Bench.sb3" / "4fcf7ed0de6c6b6e9b52c511b0650e9c.png" |
|
|
,BACKDROP_DIR / "Woods.sb3" / "f3eb165d6f3fd23370f97079f2e631bf.png" |
|
|
,BACKDROP_DIR / "Xy-grid-20px.sb3" / "4eec0e1db92b8dea3e5bee25105e8f46.png" |
|
|
,BACKDROP_DIR / "Xy-grid-30px.sb3" / "3b8bcabd0ac683b7cb3673208039764b.png" |
|
|
,BACKDROP_DIR / "Xy-grid.sb3" / "9838d02002d05f88dc54d96494fbc202.png", |
|
|
CODE_BLOCKS_DIR / "script1.jpg", |
|
|
CODE_BLOCKS_DIR / "script2.jpg", |
|
|
CODE_BLOCKS_DIR / "script3.jpg", |
|
|
CODE_BLOCKS_DIR / "script4.jpg", |
|
|
CODE_BLOCKS_DIR / "script5.jpg", |
|
|
CODE_BLOCKS_DIR / "script6.jpg"] |
|
|
folder_image_paths = [os.path.normpath(str(p)) for p in folder_image_paths] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for buf in sprite_images_bytes: |
|
|
try: |
|
|
buf.seek(0) |
|
|
except Exception: |
|
|
pass |
|
|
|
|
|
|
|
|
try: |
|
|
sprite_matrix = clip_embd.embed_image(sprite_images_bytes, batch_size=8) |
|
|
sprite_matrix = np.array(sprite_matrix, dtype=np.float32) |
|
|
except Exception: |
|
|
sprite_feats = [] |
|
|
for buf in sprite_images_bytes: |
|
|
buf.seek(0) |
|
|
try: |
|
|
feats = clip_embd.embed_image([buf])[0] |
|
|
except Exception: |
|
|
buf.seek(0) |
|
|
pil_img = Image.open(buf).convert("RGB") |
|
|
try: |
|
|
feats = clip_embd.embed_image([pil_img])[0] |
|
|
except Exception: |
|
|
pil_arr = np.array(pil_img) |
|
|
feats = clip_embd.embed_image([pil_arr])[0] |
|
|
sprite_feats.append(np.asarray(feats, dtype=np.float32)) |
|
|
sprite_matrix = np.vstack(sprite_feats) |
|
|
|
|
|
|
|
|
with open(f"{BLOCKS_DIR}/openclip_embeddings.json", "r") as f: |
|
|
embedding_json = json.load(f) |
|
|
|
|
|
img_matrix = np.array([img["embeddings"] for img in embedding_json], dtype=np.float32) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def l2_normalize_rows(x: np.ndarray, eps: float = 1e-10) -> np.ndarray: |
|
|
""" |
|
|
L2-normalize each row of a 2D numpy array. |
|
|
|
|
|
Args: |
|
|
x: Array of shape (N, D). |
|
|
eps: Small constant to avoid division by zero. |
|
|
|
|
|
Returns: |
|
|
Normalized array of shape (N, D) where each row has unit norm. |
|
|
""" |
|
|
norms = np.linalg.norm(x, axis=1, keepdims=True) |
|
|
return x / np.maximum(norms, eps) |
|
|
|
|
|
sprite_matrix = l2_normalize_rows(sprite_matrix) |
|
|
img_matrix = l2_normalize_rows(img_matrix) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
similarity = np.matmul(sprite_matrix, img_matrix.T) |
|
|
most_similar_indices = np.argmax(similarity, axis=1) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
project_data = [] |
|
|
copied_folders = set() |
|
|
|
|
|
for sprite_idx, matched_idx in enumerate(most_similar_indices): |
|
|
matched_image_path = folder_image_paths[matched_idx] |
|
|
matched_folder = os.path.dirname(matched_image_path) |
|
|
|
|
|
|
|
|
if not matched_folder.startswith(sprite_base_path): |
|
|
continue |
|
|
|
|
|
if matched_folder in copied_folders: |
|
|
continue |
|
|
copied_folders.add(matched_folder) |
|
|
logger.info(f"Matched sprite: {matched_image_path}") |
|
|
|
|
|
sprite_json_path = os.path.join(matched_folder, 'sprite.json') |
|
|
if not os.path.exists(sprite_json_path): |
|
|
logger.warning(f"No sprite.json in {matched_folder}") |
|
|
continue |
|
|
|
|
|
with open(sprite_json_path, 'r') as f: |
|
|
sprite_info = json.load(f) |
|
|
|
|
|
for fname in os.listdir(matched_folder): |
|
|
if fname in (os.path.basename(matched_image_path), 'sprite.json'): |
|
|
continue |
|
|
shutil.copy2(os.path.join(matched_folder, fname), |
|
|
os.path.join(project_folder, fname)) |
|
|
project_data.append(sprite_info) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backdrop_data = [] |
|
|
copied_backdrop_folders = set() |
|
|
for backdrop_idx, matched_idx in enumerate(most_similar_indices): |
|
|
matched_image_path = folder_image_paths[matched_idx] |
|
|
matched_folder = os.path.dirname(matched_image_path) |
|
|
matched_filename = os.path.basename(matched_image_path) |
|
|
|
|
|
|
|
|
if not matched_folder.startswith(backdrop_base_path): |
|
|
continue |
|
|
|
|
|
|
|
|
if matched_folder in copied_backdrop_folders: |
|
|
continue |
|
|
copied_backdrop_folders.add(matched_folder) |
|
|
|
|
|
logger.info(f"Matched backdrop: {matched_image_path}") |
|
|
|
|
|
|
|
|
try: |
|
|
shutil.copy2( |
|
|
matched_image_path, |
|
|
os.path.join(project_folder, matched_filename) |
|
|
) |
|
|
logger.info(f"✅ Copied matched backdrop image {matched_filename} to {project_folder}") |
|
|
except Exception as e: |
|
|
logger.error(f"❌ Failed to copy matched backdrop {matched_image_path}: {e}") |
|
|
|
|
|
|
|
|
for fname in os.listdir(matched_folder): |
|
|
|
|
|
if fname in {matched_filename, 'project.json'}: |
|
|
continue |
|
|
|
|
|
|
|
|
src = os.path.join(matched_folder, fname) |
|
|
dst = os.path.join(project_folder, fname) |
|
|
if os.path.isfile(src): |
|
|
try: |
|
|
shutil.copy2(src, dst) |
|
|
logger.info(f"Copied additional backdrop asset {fname} to project folder") |
|
|
except Exception as e: |
|
|
logger.error(f"Failed to copy {src}: {e}") |
|
|
|
|
|
|
|
|
pj = os.path.join(matched_folder, 'project.json') |
|
|
if os.path.exists(pj): |
|
|
with open(pj, 'r') as f: |
|
|
bd_json = json.load(f) |
|
|
for tgt in bd_json.get("targets", []): |
|
|
if tgt.get("isStage"): |
|
|
backdrop_data.append(tgt) |
|
|
else: |
|
|
logger.warning(f"No project.json in {matched_folder}") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final_project = { |
|
|
"targets": [], "monitors": [], "extensions": [], |
|
|
"meta": { |
|
|
"semver": "3.0.0", |
|
|
"vm": "11.3.0", |
|
|
"agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36" |
|
|
} |
|
|
} |
|
|
|
|
|
for spr in project_data: |
|
|
if not spr.get("isStage", False): |
|
|
final_project["targets"].append(spr) |
|
|
|
|
|
|
|
|
if backdrop_data: |
|
|
all_costumes, sounds = [], [] |
|
|
seen_costumes = set() |
|
|
for i, bd in enumerate(backdrop_data): |
|
|
for costume in bd.get("costumes", []): |
|
|
|
|
|
key = (costume.get("name"), costume.get("assetId")) |
|
|
if key not in seen_costumes: |
|
|
seen_costumes.add(key) |
|
|
all_costumes.append(costume) |
|
|
|
|
|
if i == 0: |
|
|
sounds = bd.get("sounds", []) |
|
|
stage_obj={ |
|
|
"isStage": True, |
|
|
"name": "Stage", |
|
|
"objName": "Stage", |
|
|
"variables": {}, |
|
|
"lists": {}, |
|
|
"broadcasts": {}, |
|
|
"blocks": {}, |
|
|
"comments": {}, |
|
|
"currentCostume": 1 if len(all_costumes) > 1 else 0, |
|
|
"costumes": all_costumes, |
|
|
"sounds": sounds, |
|
|
"volume": 100, |
|
|
"layerOrder": 0, |
|
|
"tempo": 60, |
|
|
"videoTransparency": 50, |
|
|
"videoState": "on", |
|
|
"textToSpeechLanguage": None |
|
|
} |
|
|
final_project["targets"].insert(0, stage_obj) |
|
|
else: |
|
|
logger.warning("⚠️ No backdrop matched. Using default static backdrop.") |
|
|
default_backdrop_path = BACKDROP_DIR / "cd21514d0531fdffb22204e0ec5ed84a.svg" |
|
|
default_backdrop_name = "cd21514d0531fdffb22204e0ec5ed84a.svg" |
|
|
|
|
|
default_backdrop_sound = BACKDROP_DIR / "83a9787d4cb6f3b7632b4ddfebf74367.wav" |
|
|
default_backdrop_sound_name = "cd21514d0531fdffb22204e0ec5ed84a.svg" |
|
|
try: |
|
|
shutil.copy2(default_backdrop_path, os.path.join(project_folder, default_backdrop_name)) |
|
|
logger.info(f"✅ Default backdrop copied to project: {default_backdrop_name}") |
|
|
|
|
|
shutil.copy2(default_backdrop_sound, os.path.join(project_folder, default_backdrop_sound_name)) |
|
|
logger.info(f"✅ Default backdrop sound copied to project: {default_backdrop_sound_name}") |
|
|
except Exception as e: |
|
|
logger.error(f"❌ Failed to copy default backdrop: {e}") |
|
|
|
|
|
stage_obj={ |
|
|
"isStage": True, |
|
|
"name": "Stage", |
|
|
"objName": "Stage", |
|
|
"variables": {}, |
|
|
"lists": {}, |
|
|
"broadcasts": {}, |
|
|
"blocks": {}, |
|
|
"comments": {}, |
|
|
"currentCostume": 0, |
|
|
"costumes": [ |
|
|
{ |
|
|
"assetId": default_backdrop_name.split(".")[0], |
|
|
"name": "defaultBackdrop", |
|
|
"md5ext": default_backdrop_name, |
|
|
"dataFormat": "png", |
|
|
"rotationCenterX": 240, |
|
|
"rotationCenterY": 180 |
|
|
} |
|
|
], |
|
|
"sounds": [ |
|
|
{ |
|
|
"name": "pop", |
|
|
"assetId": "83a9787d4cb6f3b7632b4ddfebf74367", |
|
|
"dataFormat": "wav", |
|
|
"format": "", |
|
|
"rate": 48000, |
|
|
"sampleCount": 1123, |
|
|
"md5ext": "83a9787d4cb6f3b7632b4ddfebf74367.wav" |
|
|
} |
|
|
], |
|
|
"volume": 100, |
|
|
"layerOrder": 0, |
|
|
"tempo": 60, |
|
|
"videoTransparency": 50, |
|
|
"videoState": "on", |
|
|
"textToSpeechLanguage": None |
|
|
} |
|
|
final_project["targets"].insert(0, stage_obj) |
|
|
|
|
|
with open(project_json_path, 'w') as f: |
|
|
json.dump(final_project, f, indent=2) |
|
|
|
|
|
return project_json_path |
|
|
|
|
|
def convert_pdf_stream_to_images(pdf_stream: io.BytesIO, dpi=300): |
|
|
|
|
|
pdf_stream.seek(0) |
|
|
|
|
|
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_pdf: |
|
|
tmp_pdf.write(pdf_stream.read()) |
|
|
tmp_pdf_path = tmp_pdf.name |
|
|
|
|
|
|
|
|
images = convert_from_path(tmp_pdf_path, dpi=dpi) |
|
|
return images |
|
|
|
|
|
def delay_for_tpm_node(state: GameState): |
|
|
logger.info("--- Running DelayForTPMNode ---") |
|
|
time.sleep(10) |
|
|
logger.info("Delay completed.") |
|
|
return state |
|
|
|
|
|
|
|
|
workflow = StateGraph(GameState) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
workflow.add_node("pseudo_generator", pseudo_generator_node) |
|
|
|
|
|
workflow.add_node("Node_optimizer", node_optimizer) |
|
|
workflow.add_node("layer_optimizer", layer_order_correction) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
workflow.add_node("block_builder", overall_block_builder_node_2) |
|
|
workflow.add_node("variable_initializer", variable_adder_node) |
|
|
workflow.add_node("page_processed", processed_page_node) |
|
|
|
|
|
workflow.set_entry_point("page_processed") |
|
|
|
|
|
def decide_next_step(state: GameState): |
|
|
if state.get("processing", False): |
|
|
return "pseudo_generator" |
|
|
else: |
|
|
return "layer_optimizer" |
|
|
|
|
|
workflow.add_conditional_edges( |
|
|
"page_processed", |
|
|
decide_next_step, |
|
|
{ |
|
|
"pseudo_generator": "pseudo_generator", |
|
|
"layer_optimizer": "layer_optimizer" |
|
|
|
|
|
} |
|
|
) |
|
|
|
|
|
|
|
|
workflow.add_edge("pseudo_generator", "Node_optimizer") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
workflow.add_edge("Node_optimizer", "block_builder") |
|
|
workflow.add_edge("block_builder", "variable_initializer") |
|
|
|
|
|
workflow.add_edge("variable_initializer", "page_processed") |
|
|
workflow.add_edge("layer_optimizer", END) |
|
|
|
|
|
app_graph = workflow.compile() |
|
|
|
|
|
|
|
|
def upscale_image(image: Image.Image, scale: int = 2) -> Image.Image: |
|
|
""" |
|
|
Upscales a PIL image by a given scale factor. |
|
|
""" |
|
|
try: |
|
|
width, height = image.size |
|
|
new_size = (width * scale, height * scale) |
|
|
upscaled_image = image.resize(new_size, Image.LANCZOS) |
|
|
logger.info(f"✅ Upscaled image to {new_size}") |
|
|
return upscaled_image |
|
|
except Exception as e: |
|
|
logger.error(f"❌ Error during image upscaling: {str(e)}") |
|
|
return image |
|
|
|
|
|
@log_execution_time |
|
|
def create_sb3_archive(project_folder, project_id): |
|
|
""" |
|
|
Zips the project folder and renames it to an .sb3 file. |
|
|
|
|
|
Args: |
|
|
project_folder (str): The path to the directory containing the project.json and assets. |
|
|
project_id (str): The unique ID for the project, used for naming the .sb3 file. |
|
|
|
|
|
Returns: |
|
|
str: The path to the created .sb3 file, or None if an error occurred. |
|
|
""" |
|
|
print(" --------------------------------------- create_sb3_archive INITIALIZE ---------------------------------------") |
|
|
|
|
|
|
|
|
output_filename = GEN_PROJECT_DIR / project_id |
|
|
print(" --------------------------------------- output_filename ---------------------------------------",output_filename) |
|
|
zip_path = None |
|
|
sb3_path = None |
|
|
try: |
|
|
zip_path = shutil.make_archive(output_filename, 'zip', root_dir=project_folder) |
|
|
print(" --------------------------------------- zip_path_str ---------------------------------------", output_filename, project_folder) |
|
|
logger.info(f"Project folder zipped to: {zip_path}") |
|
|
|
|
|
|
|
|
sb3_path = f"{output_filename}.sb3" |
|
|
os.rename(zip_path, sb3_path) |
|
|
print(" --------------------------------------- rename paths ---------------------------------------", zip_path, sb3_path) |
|
|
logger.info(f"Renamed {zip_path} to {sb3_path}") |
|
|
|
|
|
return sb3_path |
|
|
except Exception as e: |
|
|
logger.error(f"Error creating SB3 archive for {project_id}: {e}") |
|
|
|
|
|
if zip_path and os.path.exists(zip_path): |
|
|
os.remove(zip_path) |
|
|
if sb3_path and os.path.exists(sb3_path): |
|
|
os.remove(sb3_path) |
|
|
return sb3_path |
|
|
|
|
|
|
|
|
|
|
|
def save_pdf_to_generated_dir(pdf_stream: io.BytesIO, project_id: str) -> str: |
|
|
""" |
|
|
Copies the PDF at `pdf_stream` into GEN_PROJECT_DIR/project_id/, |
|
|
renaming it to <project_id>.pdf. |
|
|
|
|
|
Args: |
|
|
pdf_stream (io.BytesIO): Any existing stream to a PDF file. |
|
|
project_id (str): Your unique project identifier. |
|
|
|
|
|
Returns: |
|
|
str: Path to the copied PDF in the generated directory, |
|
|
or None if something went wrong. |
|
|
""" |
|
|
|
|
|
try: |
|
|
|
|
|
output_dir = GEN_PROJECT_DIR / project_id |
|
|
output_dir.mkdir(parents=True, exist_ok=True) |
|
|
print(f"\n--------------------------------output_dir {output_dir}") |
|
|
|
|
|
|
|
|
target_pdf = output_dir / f"{project_id}.pdf" |
|
|
print(f"\n--------------------------------target_pdf {target_pdf}") |
|
|
|
|
|
|
|
|
|
|
|
if isinstance(pdf_stream, io.BytesIO): |
|
|
with open(target_pdf, "wb") as f: |
|
|
f.write(pdf_stream.getbuffer()) |
|
|
else: |
|
|
shutil.copy2(pdf_stream, target_pdf) |
|
|
print(f"Copied PDF from {pdf_stream} → {target_pdf}") |
|
|
logger.info(f"Copied PDF from {pdf_stream} → {target_pdf}") |
|
|
|
|
|
|
|
|
|
|
|
return str(target_pdf) |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Failed to save PDF to generated dir: {e}", exc_info=True) |
|
|
return None |
|
|
|
|
|
@app.route('/') |
|
|
def index(): |
|
|
return render_template('app_index.html') |
|
|
|
|
|
@app.route("/download_sb3/<project_id>", methods=["GET"]) |
|
|
def download_sb3(project_id): |
|
|
sb3_path = GEN_PROJECT_DIR / f"{project_id}.sb3" |
|
|
if not sb3_path.exists(): |
|
|
return jsonify({"error": "Scratch project file not found"}), 404 |
|
|
|
|
|
return send_file( |
|
|
sb3_path, |
|
|
as_attachment=True, |
|
|
download_name=sb3_path.name |
|
|
) |
|
|
|
|
|
@app.route("/download_pdf/<project_id>", methods=["GET"]) |
|
|
def download_pdf(project_id): |
|
|
pdf_path = GEN_PROJECT_DIR / project_id / f"{project_id}.pdf" |
|
|
if not pdf_path.exists(): |
|
|
return jsonify({"error": "Scratch project file not found"}), 404 |
|
|
|
|
|
return send_file( |
|
|
pdf_path, |
|
|
as_attachment=True, |
|
|
download_name=pdf_path.name |
|
|
) |
|
|
|
|
|
|
|
|
@app.route('/process_pdf', methods=['POST']) |
|
|
def process_pdf(): |
|
|
try: |
|
|
logger.info("Received request to process PDF.") |
|
|
if 'pdf_file' not in request.files: |
|
|
logger.warning("No PDF file found in request.") |
|
|
return jsonify({"error": "Missing PDF file in form-data with key 'pdf_file'"}), 400 |
|
|
|
|
|
pdf_file = request.files['pdf_file'] |
|
|
if pdf_file.filename == '': |
|
|
return jsonify({"error": "Empty filename"}), 400 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
project_id = str(uuid.uuid4()).replace('-', '') |
|
|
|
|
|
project_folder = OUTPUT_DIR / project_id |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pdf_bytes = pdf_file.read() |
|
|
pdf_stream = io.BytesIO(pdf_bytes) |
|
|
logger.info(f"Saved uploaded PDF to: {pdf_stream}") |
|
|
|
|
|
|
|
|
start_time = time.time() |
|
|
pdf= save_pdf_to_generated_dir(pdf_stream, project_id) |
|
|
|
|
|
|
|
|
logger.info(f"Saved uploaded PDF to: {pdf_file}: {pdf}") |
|
|
print("--------------------------------pdf_file_path---------------------",pdf_file,pdf_stream) |
|
|
total_time = time.time() - start_time |
|
|
print(f"-----------------------------Execution Time save_pdf_to_generated_dir() : {total_time}-----------------------------\n") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
start_time = time.time() |
|
|
output_path = extract_images_from_pdf(pdf_stream) |
|
|
print(" --------------------------------------- zip_path_str ---------------------------------------", output_path) |
|
|
total_time = time.time() - start_time |
|
|
print(f"-----------------------------Execution Time extract_images_from_pdf() : {total_time}-----------------------------\n") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
start_time = time.time() |
|
|
project_output = similarity_matching(output_path, project_folder) |
|
|
logger.info("Received request to process PDF.") |
|
|
total_time = time.time() - start_time |
|
|
print(f"-----------------------------Execution Time similarity_matching() : {total_time}-----------------------------\n") |
|
|
|
|
|
with open(project_output, 'r') as f: |
|
|
project_skeleton = json.load(f) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if isinstance(pdf_stream, io.BytesIO): |
|
|
images = convert_pdf_stream_to_images(pdf_stream, dpi=300) |
|
|
else: |
|
|
images = convert_from_path(pdf_stream, dpi=300) |
|
|
|
|
|
|
|
|
initial_state_dict = { |
|
|
"project_json": project_skeleton, |
|
|
"description": "The pseudo code for the script", |
|
|
"project_id": project_id, |
|
|
|
|
|
"project_image": images, |
|
|
"action_plan": {}, |
|
|
"pseudo_code": {}, |
|
|
"temporary_node": {}, |
|
|
"processing":True, |
|
|
"page_count": 0, |
|
|
"temp_pseudo_code":[], |
|
|
} |
|
|
|
|
|
|
|
|
final_state_dict = app_graph.invoke(initial_state_dict,config={"recursion_limit": 200}) |
|
|
final_project_json = final_state_dict['project_json'] |
|
|
|
|
|
|
|
|
|
|
|
with open(project_output, "w") as f: |
|
|
json.dump(final_project_json, f, indent=2) |
|
|
logger.info(f"Final project JSON saved to {project_output}") |
|
|
|
|
|
|
|
|
sb3_file_path = create_sb3_archive(project_folder, project_id) |
|
|
|
|
|
if sb3_file_path: |
|
|
logger.info(f"Successfully created SB3 file: {sb3_file_path}") |
|
|
|
|
|
download_url = f"https://prthm11-scratch-vision-game.hf.space/download_sb3/{project_id}" |
|
|
pdf_url = f"https://prthm11-scratch-vision-game.hf.space/download_pdf/{project_id}" |
|
|
print(f"DOWNLOAD_URL: {download_url}") |
|
|
print(f"PDF_URL: {pdf_url}") |
|
|
|
|
|
return jsonify({ |
|
|
"message": "✅ PDF processed successfully", |
|
|
"output_json": "output_path", |
|
|
"sprites": "result", |
|
|
"project_output_json": "project_output", |
|
|
"test_url": download_url |
|
|
}) |
|
|
else: |
|
|
return jsonify(error="Failed to create SB3 archive"), 500 |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Error during processing the pdf workflow for project ID {project_id}: {e}", exc_info=True) |
|
|
return jsonify({"error": f"❌ Failed to process PDF: {str(e)}"}), 500 |
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
|
|
app.run(host='0.0.0.0', port=7860, debug=True) |