Skip to content

Instantly share code, notes, and snippets.

@GiovanH
Last active December 2, 2020 03:54
Show Gist options
  • Save GiovanH/10efb07957c29976cedddee74646fbcb to your computer and use it in GitHub Desktop.
Save GiovanH/10efb07957c29976cedddee74646fbcb to your computer and use it in GitHub Desktop.
Flask app for browsing through monobehaviors that reference each other. Use with something that exports monobehaviors as json with per-file directories, like https://github.com/GiovanH/AssetStudio/tree/UniqueID
from flask import Flask
import glob
import os
import json
from collections import namedtuple
import re
FileID = namedtuple("FileID", ["fileName", "pathId"])
def safe(x):
return x.replace('#', '$')
file_paths = sorted(glob.glob("*/MonoBehaviour/*"))
referencesTo = {}
referencedBy = {}
def findRefs(x):
if isinstance(x, dict):
if 'm_FileName' in x:
id_ = FileID(x['m_FileName'], x['m_PathID'])
yield id_
for k, v in x.items():
yield from findRefs(v)
elif isinstance(x, list):
for v in x:
yield from findRefs(v)
for path in file_paths:
(folder_name, path_id) = re.match(r"(.*?)\/.*\#(\d+)\.json", path.replace("\\", "/")).groups()
source = FileID(folder_name, path_id)
with open(os.path.join(path), 'r', encoding="utf-8") as fp:
parsed = json.load(fp)
# todo make this faster
for target in set(findRefs(parsed)):
referencedBy[target] = referencedBy.get(target, []) + [source]
def getReferencesHtml(file_id):
if file_id not in referencedBy:
return '<p>No references to this file</p>'
return "<p>Referenced by:</p>" + "\n".join(["<li>" + fileIdToLink(ref) + "</il>" for ref in referencedBy[file_id]])
def fileIdToLink(ref):
target_glob = os.path.join(ref.fileName, "MonoBehaviour", f"*{ref.pathId}.json")
targetNames = glob.glob(target_glob)
if targetNames:
targetName = targetNames[0].replace('\\', '/')
friendly_name = targetName.split("/")[-1]
link = safe(f"/file/{targetName}")
return f"<a href='{link}'>{ref.fileName}/{friendly_name}</a>"
app = Flask(__name__)
@app.route('/')
def index():
ret = '\n'.join(
'<p><a href={}>{}</a></p>'.format('"file/' + safe(f) + '"', f)
for f in file_paths
)
return f'<html><head></head><body>{ret}</body></html>', 200, {'Content-Type': 'text/html; charset=utf-8'}
@app.route('/file/<archive>/MonoBehaviour/<filename>')
def show(archive, filename):
filename = filename.replace('$', '#')
print(filename)
(path_id,) = re.match(r".*\#(\d+)\.json", filename).groups()
with open(os.path.join(archive, 'MonoBehaviour', filename)) as f:
parsed = json.load(f)
fileId = FileID(archive, int(path_id))
references = getReferencesHtml(fileId)
def traverse(x):
if isinstance(x, dict):
if 'm_FileName' in x:
filename = x['m_FileName']
path_id = x['m_PathID']
targetId = FileID(filename, path_id)
try:
x["ref"] = fileIdToLink(targetId)
except:
print("Failed ref", targetId)
for k, v in x.items():
traverse(v)
elif isinstance(x, list):
for v in x:
traverse(v)
traverse(parsed)
ret = f'<h1>{fileIdToLink(fileId)}</h1>{references}<pre>{json.dumps(parsed, indent=4, sort_keys=False)}</pre>'
return f'<html><head></head><body>{ret}</body></html>'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment