Add controller input and a laser-pointer-driven menu quad
build / build (push) Successful in 2m26s

- xr_input.c/h: an OpenXR action set (aim pose, trigger/select click, a
  menu-toggle button) plus ray/quad hit-testing, and a visible
  laser-pointer line drawn from the controller toward the hit point.
- xr_menu.c/h + MenuOverlay.java: a second composition-layer quad,
  toggled by a controller button, showing an off-screen, never-attached
  Android View tree (one "Keyboard" button so far) driven by synthetic
  touch events computed from the laser ray's hit UV.
- Migrate gl4es from a prebuilt binary baked into the Docker build-image
  to a vendored source snapshot (android/gl4es-src/) compiled from
  source at APK build time via CMake add_subdirectory(), patched through
  a new android/gl4es-patches/ (mirrors the existing engine-patches/
  pattern). This was needed to track down and fix a bug hit while
  building the menu: gl4es's fixed-pipeline emulation (fpe.c) was
  unconditionally substituting its own shader onto the menu's draw call
  (fpe_ReleventState() always sets alphafunc to a nonzero sentinel, so
  its fpe_IsEmpty() check could never see the state as empty), making
  the menu quad show the game's own rendering instead of its own
  content. Fixed by routing the menu's blit through a real
  glBlitFramebuffer() call instead of a shader-based draw, which gl4es's
  fpe.c has nothing to intercept - documented in README.md's new
  "Debugging notes" section.
- Renumber android/engine-patches/ to close the gap left by removing an
  unrelated diagnostic-only patch, and strip investigation-journal
  comments and dead diagnostic code (temporary tracing, env-var probes)
  left over from finding the bug above.
- Restructure README.md into numbered sections, document every
  engine/gl4es patch, add Android Studio dev/testing-cycle instructions,
  and generalize Quest-specific wording to any OpenXR headset. Update
  NOTICE.txt to match (gl4es is now vendored/patched source, not a
  prebuilt binary; add the OpenXR-SDK loader).
This commit is contained in:
ml
2026-08-02 06:27:49 +02:00
parent 2300d081c3
commit d2dc58391b
310 changed files with 141458 additions and 226 deletions
+112
View File
@@ -0,0 +1,112 @@
#!/usr/bin/env python
from collections import defaultdict
import re
import xml.etree.ElementTree as ET
import yaml
def etna_to_yml(xml):
defs = xml.find('functions')
functions = defaultdict(dict)
for f in defs.findall('function'):
name = f.get('name')
ret = f.find('return')
if ret is not None:
ret = ret.get('type')
if ret is None:
ret = 'void'
params = []
for p in f.findall('param'):
params.append('{} {}'.format(p.get('type'), p.get('name')))
functions[name] = [ret] + params
return functions
def lua_to_yml(xml):
typemap = xml.find('typemap')
types = {}
for t in typemap:
name = t.get('typename')
types[name] = t.get('C-lang', name)
defs = xml.find('functions').find('function-defs')
functions = defaultdict(dict)
for f in defs.findall('function'):
cat = f.get('category')
ret = f.get('return')
ret = types.get(ret, ret)
func = f.get('name')
params = []
for param in f.findall('param'):
typ = param.get('type')
typ = types.get(typ, typ)
name = param.get('name')
kind = param.get('kind')
if kind in ('array', 'reference', 'array[size]'):
typ = typ.rstrip()
if not typ.endswith('*') or kind == 'reference':
typ += ' *'
if not 'const' in typ and param.get('input', 'false') == 'true':
typ = 'const ' + typ
p = '{} {}'.format(typ, name)
p = p.replace('* ', '*')
params.append(p)
args = [ret]
args.extend(params)
functions[cat][func] = args
return functions
def khronos_to_yml(xml):
def extract(node):
return node.findtext('ptype') or node.text, node.findtext('name')
def clean(s):
return re.sub('\s+', ' ', s).strip()
defs = xml.find('commands')
functions = defaultdict(dict)
for f in defs.findall('command'):
proto = f.find('proto')
ret, name = extract(proto)
params = []
for param in f.findall('param'):
params.append(clean(' '.join((param.itertext()))))
functions[name] = [ret] + params
return functions
def to_yml(filename):
with open(filename, 'r') as f:
data = f.read()
data = re.sub(' xmlns="[^"]+"', '', data, count=1)
xml = ET.fromstring(data)
if xml.tag == 'root':
functions = etna_to_yml(xml)
elif xml.tag == 'specification':
functions = lua_to_yml(xml)
elif xml.tag == 'registry':
functions = khronos_to_yml(xml)
else:
print 'unrecognized root tag:', xml.tag
yml = yaml.dump(dict(functions))
with open(filename.replace('xml', 'yml'), 'w') as o:
o.write(yml)
if __name__ == '__main__':
import sys
if len(sys.argv) < 2:
print 'Usage: {} <file.xml> [file.xml...]'.format(sys.argv[0])
sys.exit(1)
for name in sys.argv[1:]:
to_yml(name)