Skip to content

Instantly share code, notes, and snippets.

@bergwerf
Created November 2, 2019 00:39
Show Gist options
  • Save bergwerf/e3f920392147d10fb44212d94ad897ab to your computer and use it in GitHub Desktop.
Save bergwerf/e3f920392147d10fb44212d94ad897ab to your computer and use it in GitHub Desktop.
Attempt at Dart 2.0 Three.js interop with js_facade_gen
#!/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