Spaces:
Build error
Build error
Commit ·
9b15797
1
Parent(s): f8bd887
translator parser and mapper created
Browse files- app.py +22 -10
- translator/mapper.py +21 -0
- translator/parse.py +74 -0
app.py
CHANGED
|
@@ -1,8 +1,7 @@
|
|
| 1 |
import os
|
| 2 |
import gradio as gr
|
| 3 |
-
|
| 4 |
|
| 5 |
-
'''
|
| 6 |
#Initialize agent (will load mapping table)
|
| 7 |
agent = TranslationAgent()
|
| 8 |
|
|
@@ -14,11 +13,24 @@ def do_translate(csharp_code, target_format, model_choice):
|
|
| 14 |
title = "Unity -> Unreal Code Translator"
|
| 15 |
description = "Paste a Unity C# script and get suggested Unreal C++ (.h/.cpp) and an Unreal Python Blueprint-generator script."
|
| 16 |
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import os
|
| 2 |
import gradio as gr
|
| 3 |
+
from translator.agent import TranslationAgent
|
| 4 |
|
|
|
|
| 5 |
#Initialize agent (will load mapping table)
|
| 6 |
agent = TranslationAgent()
|
| 7 |
|
|
|
|
| 13 |
title = "Unity -> Unreal Code Translator"
|
| 14 |
description = "Paste a Unity C# script and get suggested Unreal C++ (.h/.cpp) and an Unreal Python Blueprint-generator script."
|
| 15 |
|
| 16 |
+
gradioInterface = gr.Interface(
|
| 17 |
+
#function
|
| 18 |
+
fn=do_translate,
|
| 19 |
+
#input field
|
| 20 |
+
inputs=[
|
| 21 |
+
gr.Textbox(lines=25, lable="Unity C# Code"),
|
| 22 |
+
gr.Radio(["cpp", "Blueprint","Both"], value="Both", lable="Target Code"),
|
| 23 |
+
gr.Radio(["hf_inference", "openai"], value="openai", lable="Model Backend")
|
| 24 |
+
],
|
| 25 |
+
#Output field
|
| 26 |
+
outputs=[
|
| 27 |
+
gr.Textbox(lines=20, lable="Unreal C++ (.h/.cpp"),
|
| 28 |
+
gr.Textbox(lines=20, lable="Unreal Blueprint generator (Python for Editor)")
|
| 29 |
+
],
|
| 30 |
+
title=title,
|
| 31 |
+
description=description,
|
| 32 |
+
allow_flagging="never",
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
if __name__ == "__main__":
|
| 36 |
+
gradioInterface.launch(share=True)
|
translator/mapper.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
|
| 4 |
+
DEFAULT_MAPPING = {
|
| 5 |
+
"MonoBehaviour": {"target_parent": "AActor"},
|
| 6 |
+
"Start": {"target": "BeginPlay"},
|
| 7 |
+
"Update": {"target": "Tick", "delta_time_arg": True},
|
| 8 |
+
"transform.position": {"target": "GetActorLocation()"},
|
| 9 |
+
"transform.Rotate": {"target": "AddActorLocalRotation"},
|
| 10 |
+
"Instantiate": {"target": "GetWorld()->SpawnActor"},
|
| 11 |
+
"Time.deltaTime": {"target": "DeltaTime"},
|
| 12 |
+
"Input.GetAxis": {"target": "GetInputAxisValue"},
|
| 13 |
+
"OnCollisionEnter": {"target": "NotifyHit / OnActorHit"}
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
def load_mapping(path="mapping_table.json"):
|
| 17 |
+
p = Path(path)
|
| 18 |
+
if p.exists():
|
| 19 |
+
return json.loads(p.read_text())
|
| 20 |
+
else:
|
| 21 |
+
return DEFAULT_MAPPING
|
translator/parse.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from tree_sitter import Parser
|
| 2 |
+
# tree-sitter-c-sharp pip package provides the C# language.
|
| 3 |
+
from tree_sitter_languages import get_language # helper wrapper (optional)
|
| 4 |
+
import re
|
| 5 |
+
|
| 6 |
+
def parse_csharp(code: str) -> dict:
|
| 7 |
+
"""
|
| 8 |
+
Returns a simple AST-like dict:
|
| 9 |
+
{
|
| 10 |
+
"classes": [
|
| 11 |
+
{"name": "Foo", "fields": [...], "methods": [{"name": "Update", "body": "..."}]}
|
| 12 |
+
]
|
| 13 |
+
}
|
| 14 |
+
"""
|
| 15 |
+
result = {"classes":[]}
|
| 16 |
+
try:
|
| 17 |
+
# try tree-sitter approach
|
| 18 |
+
from tree_sitter import Parser
|
| 19 |
+
from tree_sitter_c_sharp import CSHARP_LANGUAGE
|
| 20 |
+
parser = Parser()
|
| 21 |
+
parser.set_language(CSHARP_LANGUAGE)
|
| 22 |
+
tree = parser.parse(bytes(code, "utf8"))
|
| 23 |
+
root = tree.root_node
|
| 24 |
+
|
| 25 |
+
#find class declarations and method declarations
|
| 26 |
+
for node in root.walk():
|
| 27 |
+
if node.type == "class_declaration":
|
| 28 |
+
class_name = None
|
| 29 |
+
for child in node.children:
|
| 30 |
+
if child.type == "identifier":
|
| 31 |
+
class_name = code[child.start_byte:child.end_byte].decode("utf8") if isinstance(child.start_byte, bytes) else code[child.start_byte:child.end_byte]
|
| 32 |
+
methods = []
|
| 33 |
+
for child in node.children:
|
| 34 |
+
if child.type == "method_declaration":
|
| 35 |
+
#find identifier and body text
|
| 36 |
+
name = None
|
| 37 |
+
body = ""
|
| 38 |
+
for grand in child.children:
|
| 39 |
+
if grand.type == "identifier":
|
| 40 |
+
name = code[grand.start_byte:grand.end_byte]
|
| 41 |
+
if grand.type == "block":
|
| 42 |
+
body = code[grand.start_byte:grand.end_byte]
|
| 43 |
+
methods.append({"name": name, "body":body})
|
| 44 |
+
result["classes"].append({"name": class_name, "methods": methods})
|
| 45 |
+
return result
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
except Exception:
|
| 49 |
+
# Regex fallback (works for simple files)
|
| 50 |
+
classes = []
|
| 51 |
+
class_matches = re.finditer(r'class\s+(\w+)\s*:\s*MonoBehaviour\s*{', code)
|
| 52 |
+
for m in class_matches:
|
| 53 |
+
cls = m.group(1)
|
| 54 |
+
# find Update / Start blocks
|
| 55 |
+
methods = []
|
| 56 |
+
for mm in re.finditer(r'(void|public)\s+(Start|Update|FixedUpdate)\s*\([^\)]*\)\s*{', code):
|
| 57 |
+
method_name = mm.group(2)
|
| 58 |
+
# crudely extract method body until balancing braces (simple approach)
|
| 59 |
+
start = mm.end()
|
| 60 |
+
depth = 1
|
| 61 |
+
i = start
|
| 62 |
+
while i < len(code) and depth > 0:
|
| 63 |
+
if code[i] == '{':
|
| 64 |
+
depth += 1
|
| 65 |
+
elif code[i] == '}':
|
| 66 |
+
depth -= 1
|
| 67 |
+
i += 1
|
| 68 |
+
body = code[start:i-1].strip()
|
| 69 |
+
methods.append({"name": method_name, "body": body})
|
| 70 |
+
classes.append({"name": cls, "methods": methods})
|
| 71 |
+
result["classes"] = classes
|
| 72 |
+
return result
|
| 73 |
+
|
| 74 |
+
|