levelbuild texture names mean the same picture on every base level (matched by pixels, missing village textures copied over in the java builder, clear error otherwise), editor texture choices follow the base
This commit is contained in:
1 parent
d56f3c604f
commit
987b0104fa
14 files changed
+534
-42
No files matched your search
+45
-2
@@ -13,7 +13,8 @@ ambient occlusion) and object placement (strats by type name, parameters from th
|
||||
Coordinates (as in the game / for strats): x east, y up, z = grid row
|
||||
(positive). 1 unit = 1 grid cell. The base level's grid is 96x96 (x,z in 0..96).
|
||||
Angles in degrees (0..360) about the y axis.
|
||||
Texture names (TEX/FLAT below) are German keys and part of the level script API.
|
||||
Texture names (TEX/FLAT below) are German keys and part of the level script API; TEX indices are
|
||||
village indices, other bases (--base) map a name to the same picture or reject it.
|
||||
Docs: ../notes/levelbau.md
|
||||
"""
|
||||
import argparse
|
||||
@@ -97,6 +98,21 @@ def to_exp(p):
|
||||
return (p[0], p[1], -p[2])
|
||||
|
||||
|
||||
def _tex_fingerprints(pages, texs):
|
||||
"""Per texture entry: hash of page format + pixel rectangle, None for flat colours."""
|
||||
cache, out = {}, []
|
||||
for t in texs:
|
||||
pg = t['page']
|
||||
if t['flags'] & 1 or pg < 0 or pg >= len(pages) or t['u1'] < t['u0'] or t['v1'] < t['v0']:
|
||||
out.append(None)
|
||||
continue
|
||||
if pg not in cache:
|
||||
cache[pg] = G.page_rgba(pages[pg])
|
||||
a = cache[pg][t['v0']:t['v1'] + 1, t['u0']:t['u1'] + 1]
|
||||
out.append(hashlib.md5(bytes([pages[pg]['flags'] & 0x7f]) + str(a.shape).encode() + a.tobytes()).hexdigest())
|
||||
return out
|
||||
|
||||
|
||||
class Level:
|
||||
"""Construction kit. All methods take game coordinates (x, z = grid cell, y up)."""
|
||||
|
||||
@@ -150,6 +166,29 @@ class Level:
|
||||
self.protos[nm] = [tuple(s)]
|
||||
self.foreign_params[nm] = prm
|
||||
|
||||
def _base_names(self):
|
||||
"""TEX names on this base: same picture (page format + pixels) at the village index or elsewhere
|
||||
(Java: levelbuild.BaseTextures)."""
|
||||
if getattr(self, '_names', None) is None:
|
||||
if os.path.abspath(self.base) == os.path.abspath(BASE):
|
||||
self._names = dict(TEX)
|
||||
else:
|
||||
vp, vt = G.parse_text(G.wad_get(G.wad_read(BASE), 'TEXT'))
|
||||
own = _tex_fingerprints(self.pages, self.texs)
|
||||
vfp = _tex_fingerprints(vp, vt)
|
||||
first = {}
|
||||
for i, f in enumerate(own):
|
||||
if f is not None and (f not in first or (self.texs[i]['flags'] == 0x104
|
||||
and self.texs[first[f]]['flags'] != 0x104)):
|
||||
first[f] = i
|
||||
self._names = {}
|
||||
for n, i in TEX.items():
|
||||
if i < len(own) and own[i] is not None and own[i] == vfp[i]:
|
||||
self._names[n] = i
|
||||
elif vfp[i] in first:
|
||||
self._names[n] = first[vfp[i]]
|
||||
return self._names
|
||||
|
||||
def types(self):
|
||||
return sorted(self.protos)
|
||||
|
||||
@@ -162,7 +201,11 @@ class Level:
|
||||
FLAT.setdefault(key, t)
|
||||
t = key
|
||||
if t in TEX:
|
||||
return TEX[t]
|
||||
names = self._base_names()
|
||||
if t not in names:
|
||||
raise KeyError('texture %r is a village texture the base level does not have (use an index, a flat '
|
||||
'colour, or the Java builder, which copies it over)' % t)
|
||||
return names[t]
|
||||
if t in FLAT:
|
||||
if t not in self.flats_used:
|
||||
self.flats_used[t] = len(self.texs) + len(self.flats_used)
|
||||
|
||||
Reference in new issue
Block a user