Created
November 2, 2019 00:39
-
-
Save bergwerf/e3f920392147d10fb44212d94ad897ab to your computer and use it in GitHub Desktop.
Attempt at Dart 2.0 Three.js interop with js_facade_gen
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
''' | |
Get ./js_facade_gen, and ./three.js | |
Comment out ./three.js/src/renderers/shaders/UniformsUtils.d.ts to avoid errors | |
Navigate to js_facade_gen | |
Under Zsh, run: node index.js --base-path=../three.js --destination=../dart-threejs ../three.js/src/**/*.ts | |
Navigate to ../dart-threejs | |
Add pubspec.yaml with package:js | |
Run this script twice to add the needed Dart SDK imports | |
''' | |
import os | |
import re | |
def find(name, root): | |
''' | |
Find filepath of file with [name] under [root]. | |
''' | |
for path, dirs, files in os.walk(root): | |
if name in files: | |
return os.path.join(path, name) | |
# Some types must be imported from the Dart core | |
import_types = { | |
'dart:html': [ | |
'MediaElement', | |
'MediaStream', | |
'VideoElement' | |
], | |
'dart:web_audio': [ | |
'AudioContext', | |
'GainNode', | |
'PannerNode', | |
'AudioBufferSourceNode' | |
], | |
'dart:typed_data': [ | |
'Float32List', | |
'Uint8List' | |
] | |
} | |
# Object name fixes (replace, by, exceptions). | |
change_names = [ | |
('Array', 'List', ['ArrayCamera']), | |
('ListLike', 'List', []), | |
('HTML', '', []) | |
] | |
# Iterate all Dart files. | |
root = './lib' | |
for path, dirs, files in os.walk(root): | |
for name in files: | |
if name.endswith('.dart'): | |
print(name) | |
f = open(os.path.join(path, name), 'r+') | |
whole_file = f.read() | |
# Recognize need for extra imports. | |
import_extra = [] | |
for lib, types in import_types.items(): | |
ns = lib.split(':')[1] | |
for type in types: | |
if (f'{ns}.{type}' in whole_file) and not (lib in whole_file): | |
import_extra.append(lib) | |
break | |
lines = whole_file.splitlines() | |
f.seek(0) | |
f.truncate() | |
ln = 0 | |
for line in lines: | |
ln += 1 | |
# Write extra import after first two lines. | |
if ln == 3 and (len(import_extra) > 0): | |
f.write('\n') | |
for lib in import_extra: | |
ns = lib.split(':')[1] | |
f.write(f"import '{lib}' as {ns};\n") | |
m1 = re.match(r'import "(\w+)\.dart"(.*);', line) | |
m2 = re.match(r'import "(.*)"(.*);', line) | |
m3 = re.match(r'export "(\w+)\.dart"(.*);', line) | |
if m1: # Expand path | |
fullPath = find(f'{m1.group(1)}.dart', root) | |
packagePath = fullPath.replace(root, 'package:threejs') | |
f.write(f"import '{packagePath}'{m1.group(2)};") | |
f.write('\n') | |
elif m2: # Vanity | |
f.write(f"import '{m2.group(1)}'{m2.group(2)};") | |
f.write('\n') | |
elif m3: # Expand path | |
fullPath = find(f'{m3.group(1)}.dart', root) | |
packagePath = fullPath.replace(root, 'package:threejs') | |
f.write(f"export '{packagePath}'{m3.group(2)};") | |
f.write('\n') | |
else: | |
# Fix names. | |
for subs in change_names: | |
contains_exception = False | |
for exception in subs[2]: | |
if exception in line: | |
contains_exception = True | |
break | |
if not contains_exception: | |
line = line.replace(subs[0], subs[1]) | |
# Add namespace for types that are imported from external | |
# packages (Dart SDK). | |
for lib, types in import_types.items(): | |
ns = lib.split(':')[1] | |
for type in types: | |
# Check if type is used in this line. | |
if (f' {type}' in line or f'({type}' in line) and not (f'{ns}.{type}' in line): | |
# If the type is used twice in this line, it | |
# could also be used as name | |
# (`AudioContext get AudioContext`). | |
# Prefix only the first instance. | |
line = line.replace( | |
f' {type}', f' {ns}.{type}', 1) | |
line = line.replace( | |
f'({type}', f'({ns}.{type}', 1) | |
f.write(line) | |
f.write('\n') | |
f.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment