Skip to content

Commit

Permalink
(station) west square objects & bus stops, part II (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahyangyi authored Nov 1, 2024
1 parent f4949b0 commit f0af5b2
Show file tree
Hide file tree
Showing 32 changed files with 3,427 additions and 78 deletions.
9 changes: 9 additions & 0 deletions agrf/graphics/layered_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,12 @@ def resize(self, w, h):
self.yofs = (self.yofs * new_h + old_h // 2) // old_h
metadata_updated = True
return self

def to_rgb(self):
if self.rgb is not None:
return self
self.rgb = NUMPY_PALETTE[self.mask]
self.alpha = (self.mask != 0).astype(np.uint8) * 255
self.mask = None

return self
10 changes: 6 additions & 4 deletions agrf/graphics/spritesheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ def spritesheet_template(
angles,
bbox,
deltas,
ydeltas,
offsets,
yoffsets,
z_scale,
bbox_joggle=None,
bpps=(8, 32),
Expand Down Expand Up @@ -189,13 +191,13 @@ def get_rels(direction, scale):
yrel += offsets[direction][1] * offset * scale

if oydiff != 0:
xrel -= deltas[direction][0] * oydiff * scale
yrel += deltas[direction][1] * oydiff * scale
xrel += ydeltas[direction][0] * oydiff * scale
yrel += ydeltas[direction][1] * oydiff * scale

if road_mode and oyspan != 16:
offset = 16 - oyspan
xrel -= offsets[direction][0] * offset * scale
yrel += offsets[direction][1] * offset * scale
xrel += yoffsets[direction][0] * offset * scale
yrel += yoffsets[direction][1] * offset * scale

if bbox_joggle is not None:
xrel += bbox_joggle[direction][0] * scale
Expand Down
4 changes: 3 additions & 1 deletion agrf/graphics/voxel.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def update_config(self, new_config, suffix):
self.name,
prefix=os.path.join(self.prefix, suffix),
voxel_getter=self.voxel_getter,
config={**self.config, **new_config},
config={**deepcopy(self.config), **new_config},
)

@functools.cache
Expand Down Expand Up @@ -217,7 +217,9 @@ def spritesheet(self, xdiff=0, ydiff=0, zdiff=0, shift=0, xspan=16, yspan=16):
[x["angle"] for x in self.config["sprites"]],
bbox=self.config["size"],
deltas=self.config.get("agrf_deltas", None),
ydeltas=self.config.get("agrf_ydeltas", None),
offsets=self.config.get("agrf_offsets", None),
yoffsets=self.config.get("agrf_yoffsets", None),
z_scale=self.config.get("z_scale", 1.0),
bbox_joggle=self.config.get("agrf_bbox_joggle", None),
xdiff=real_xdiff,
Expand Down
32 changes: 30 additions & 2 deletions agrf/lib/building/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,16 @@ def graphics(self, scale, bpp, climate="temperate", subclimate="default"):
if self.sprite is grf.EMPTY_SPRITE:
ret = LayeredImage.empty()
else:
ret = LayeredImage.from_sprite(self.sprite.get_sprite(zoom=SCALE_TO_ZOOM[scale], bpp=bpp)).copy()
ret = None
sprite = self.sprite.get_sprite(zoom=SCALE_TO_ZOOM[scale], bpp=bpp)
if sprite is not None:
ret = LayeredImage.from_sprite(sprite).copy()

if ret is None and bpp == 32:
# Fall back to bpp=8
sprite = self.sprite.get_sprite(zoom=SCALE_TO_ZOOM[scale], bpp=8)
ret = LayeredImage.from_sprite(sprite).copy().to_rgb()
assert ret is not None
self.blend_graphics(ret, scale, bpp, climate=climate, subclimate=subclimate)
return ret

Expand Down Expand Up @@ -342,7 +351,17 @@ def to_action2(self, sprite_list):
] + [s for x in self.child_sprites for s in x.to_action2(sprite_list)]

def graphics(self, scale, bpp, climate="temperate", subclimate="default"):
ret = LayeredImage.from_sprite(self.sprite.get_sprite(zoom=SCALE_TO_ZOOM[scale], bpp=bpp)).copy()
ret = None
sprite = self.sprite.get_sprite(zoom=SCALE_TO_ZOOM[scale], bpp=bpp)
if sprite is not None:
ret = LayeredImage.from_sprite(sprite).copy()

if ret is None and bpp == 32:
# Fall back to bpp=8
sprite = self.sprite.get_sprite(zoom=SCALE_TO_ZOOM[scale], bpp=8)
ret = LayeredImage.from_sprite(sprite).copy().to_rgb()

assert ret is not None
self.blend_graphics(ret, scale, bpp, climate=climate, subclimate=subclimate)
return ret

Expand Down Expand Up @@ -414,6 +433,15 @@ def T(self):
self.sprite.T, self.extent, new_offset, child_sprites=[c.T for c in self.child_sprites], flags=self.flags
)

def move(self, xofs, yofs):
return AParentSprite(
self.sprite,
self.extent,
(self.offset[0] + xofs, self.offset[1] + yofs, self.offset[2]),
self.child_sprites,
self.flags,
)

@property
def sprites(self):
return unique_tuple((self.sprite,) + self.sprites_from_child)
Expand Down
33 changes: 33 additions & 0 deletions agrf/lib/building/slope.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from dataclasses import dataclass
from .symmetry import BuildingSymmetricalY, BuildingDiamond, BuildingCylindrical, BuildingDiagonalAlt, BuildingDiagonal


@dataclass
class SlopeType:
value: int


slope_types = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 23, 27, 29, 30]

flat = BuildingCylindrical.create_variants([SlopeType(0)])
ortho = BuildingSymmetricalY.create_variants([SlopeType(3), SlopeType(6), SlopeType(12), SlopeType(9)])
para = BuildingDiamond.create_variants([SlopeType(5), SlopeType(10)])
mono = BuildingDiagonalAlt.create_variants([SlopeType(1), SlopeType(4), SlopeType(8), SlopeType(2)])
tri = BuildingDiagonal.create_variants([SlopeType(7), SlopeType(14), SlopeType(11), SlopeType(13)])
steep = BuildingDiagonal.create_variants([SlopeType(23), SlopeType(30), SlopeType(27), SlopeType(29)])


def make_slopes(sprites, sym):
ret = {i: {} for i in sym.render_indices()}

for slopeGroup in [flat, ortho, para, mono, tri, steep]:
for slopeIndex, slopeType in zip(slopeGroup.render_indices(), slopeGroup.all_variants):
for i in sym.render_indices():
for slopeIndex2, slopeType2 in zip(slopeGroup.render_indices(), slopeGroup.all_variants):
if (
slopeType._symmetry_descriptor[slopeType.compose_symmetry_indices(slopeIndex2, i)]
== slopeType._symmetry_descriptor[slopeIndex]
):
ret[i][slopeType.value] = sprites[slopeType2.value].symmetry_index(i)
break
return ret
44 changes: 44 additions & 0 deletions agrf/lib/building/slope_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from dataclasses import dataclass
from symmetry import BuildingCylindrical, BuildingSymmetricalX, BuildingFull
from agrf.lib.building.slope import make_slopes, slope_types


@dataclass
class MockObject:
debug_id: int


def test_cylindrical():
sprites = {i: BuildingCylindrical.create_variants([MockObject(i)]) for i in slope_types}
ret = make_slopes(sprites, BuildingCylindrical)

for i in slope_types:
assert ret[0][i] is sprites[i]


def test_x():
sprites = {i: BuildingSymmetricalX.create_variants([MockObject(i * 4 + j) for j in range(4)]) for i in slope_types}
ret = make_slopes(sprites, BuildingSymmetricalX)

for i in slope_types:
assert ret[0][i] is sprites[i]
for j in [1, 4, 5]:
print(i, j)
assert i in ret[j]
assert ret[1][0] is sprites[0].M


def test_full():
sprites = {i: BuildingFull.create_variants([MockObject(i * 8 + j) for j in range(8)]) for i in slope_types}
ret = make_slopes(sprites, BuildingFull)

for i in slope_types:
assert ret[0][i] is sprites[i]
for j in range(1, 8):
assert i in ret[j]
assert ret[1][1] is sprites[4].M
assert ret[2][3] is sprites[12].R
assert ret[1][3] is sprites[6].M
assert ret[1][7] is sprites[7].M
assert ret[2][7] is sprites[14].R
assert ret[3][7] is sprites[14].R.M
2 changes: 1 addition & 1 deletion agrf/magic/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def __init__(self, code, ranges, default, *, feature=None, ref_id=None, related_
)

def fmap(self, f):
return Switch(
return type(self)(
self.code,
{(r.low, r.high): f(r.ref) for r in self._ranges},
f(self.default),
Expand Down
1 change: 1 addition & 0 deletions grfobject/lib/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .object import AObject
from .switch import GraphicalSwitch
26 changes: 23 additions & 3 deletions grfobject/lib/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@


class AObject(grf.SpriteGenerator):
def __init__(self, *, id, translation_name, layouts, callbacks=None, doc_layout=None, **props):
def __init__(
self, *, id, translation_name, layouts, purchase_layouts=None, callbacks=None, doc_layout=None, **props
):
super().__init__()
self.id = id
self.translation_name = translation_name
self.layouts = layouts
self.purchase_layouts = purchase_layouts
if callbacks is None:
callbacks = {}
self.callbacks = grf.make_callback_manager(grf.OBJECT, callbacks)
Expand Down Expand Up @@ -38,6 +41,13 @@ def get_sprites(self, g, sprites=None):
for i, layout in enumerate(self.layouts):
layouts.append(layout.to_action2(feature=grf.OBJECT, sprite_list=sprites))

if self.purchase_layouts is None:
purchase_layouts = layouts
else:
purchase_layouts = []
for i, layout in enumerate(self.purchase_layouts):
purchase_layouts.append(layout.to_action2(feature=grf.OBJECT, sprite_list=sprites))

default_graphics = Switch(
ranges={i: layouts[i] for i in range(len(layouts))},
default=layouts[0],
Expand All @@ -46,7 +56,9 @@ def get_sprites(self, g, sprites=None):
view
""",
)
purchase_graphics = Switch(ranges={i: layouts[i] for i in range(len(layouts))}, default=layouts[0], code="view")
purchase_graphics = Switch(
ranges={i: purchase_layouts[i] for i in range(len(layouts))}, default=layouts[0], code="view"
)
self.callbacks.graphics = grf.GraphicsCallback(default=default_graphics, purchase=purchase_graphics)
self.callbacks.set_flag_props(self._props)

Expand All @@ -62,4 +74,12 @@ def get_sprites(self, g, sprites=None):

@property
def sprites(self):
return [*dict.fromkeys([sub for l in self.layouts for sub in l.sprites])]
return [
*dict.fromkeys(
[
sub
for l in self.layouts + ([] if self.purchase_layouts is None else self.purchase_layouts)
for sub in l.sprites
]
)
]
13 changes: 13 additions & 0 deletions grfobject/lib/switch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from agrf.magic import Switch
from agrf.utils import unique_tuple


class GraphicalSwitch(Switch):
def __init__(self, code, ranges, default, *, feature=None, ref_id=None, related_scope=False, subroutines=None):
super().__init__(
code, ranges, default, feature=feature, ref_id=ref_id, related_scope=related_scope, subroutines=subroutines
)

@property
def sprites(self):
return unique_tuple([s for sw in [self.default] + [r.ref for r in self._ranges] for s in sw.sprites])
2 changes: 1 addition & 1 deletion install-go-dependencies.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash
export GOPATH=$PWD/gopath
go install github.com/ahyangyi/gorender/cmd@ad5c9c2
go install github.com/ahyangyi/gorender/cmd@cdca513
mv gopath/bin/cmd gopath/bin/gorender
go install github.com/ahyangyi/cargopositor/cmd@f9051fa
mv gopath/bin/cmd gopath/bin/positor
Expand Down
10 changes: 9 additions & 1 deletion roadstop/lib/roadstop.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import grf
from station.lib.utils import class_label_printable
from agrf.magic import Switch


class ARoadStop(grf.SpriteGenerator):
Expand Down Expand Up @@ -48,7 +49,14 @@ def get_sprites(self, g, sprites=None):
for s in self.sprites:
res.append(s)

self.callbacks.graphics = self.graphics.to_action2(feature=grf.ROAD_STOP, sprite_list=sprites)
graphics = self.graphics.to_action2(feature=grf.ROAD_STOP, sprite_list=sprites)
self.callbacks.graphics = Switch(
ranges={0: graphics},
default=graphics,
code="""
TEMP[0x03] = (terrain_type & 0x4) == 0x4
""",
)
self.callbacks.set_flag_props(self._props)

if self.is_waypoint:
Expand Down
2 changes: 1 addition & 1 deletion shaders/snow.txt
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,5 @@ float map(vec3 v) {
if (total >= m_colors) {
total = m_colors - 1;
}
return m_color + total;
return int(m_color + total) % 256;
}
4 changes: 3 additions & 1 deletion station/files/cns-gorender.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"tiling_mode": "repeat",
"hard_edge_threshold": 0.25,
"pad_to_full_length": false,
"solid_base": true,
"solid_base": false,
"soften_edges": 0.5,
"fade_to_black": false,
"sampler": "square",
Expand Down Expand Up @@ -70,5 +70,7 @@
"agrf_palette": "station/files/cns-palette.json",
"agrf_deltas": [[-2, -1], [2, -1], [-2, -1], [2, -1], [2, 1], [-2, 1], [2, 1], [-2, 1]],
"agrf_offsets": [[0, 0], [0, 0], [0, 0], [0, 0], [-2, -1], [2, -1], [-2, -1], [2, -1]],
"agrf_ydeltas": [[2, -1], [-2, -1], [-2, 1], [2, 1], [2, -1], [-2, -1], [-2, 1], [2, 1]],
"agrf_yoffsets": [[0, 0], [0, 0], [2, -1], [-2, -1], [0, 0], [0, 0], [2, -1], [-2, -1]],
"agrf_road_mode": true
}
Loading

0 comments on commit f0af5b2

Please sign in to comment.