feat: render shoulders, chest, bust in description and output pins
This commit is contained in:
@@ -164,7 +164,8 @@ _EXTRA_TIP = "Free text appended to the description as-is, comma-separated. Clo
|
||||
|
||||
RETURN_NAMES = ("description", "sex", "age", "nationality", "complexion",
|
||||
"face", "hair", "facial_hair", "body_type",
|
||||
"expression", "accessories", "makeup", "seed")
|
||||
"expression", "accessories", "makeup",
|
||||
"shoulders", "chest", "bust", "seed")
|
||||
|
||||
|
||||
# -- Selection logic -----------------------------------------------------------
|
||||
@@ -283,7 +284,8 @@ def build_description(sex, nat, age, skin_texture,
|
||||
face_shape, complexion, eyes, nose_shape, mouth_shape, face_feature,
|
||||
hair_color, hair_style, hair_length, facial_hair,
|
||||
body, expression, accessories, makeup, extra_attributes="",
|
||||
eye_shape=None, eyebrows=None):
|
||||
eye_shape=None, eyebrows=None,
|
||||
shoulders=None, chest=None, bust_size=None, bust_shape=None):
|
||||
"""Produce a single comma-separated descriptor string."""
|
||||
parts = []
|
||||
|
||||
@@ -333,6 +335,16 @@ def build_description(sex, nat, age, skin_texture,
|
||||
build_str = d(body)
|
||||
parts.append(build_str if build_str.lower().endswith("build") else f"{build_str} build")
|
||||
|
||||
add(shoulders)
|
||||
add(chest)
|
||||
|
||||
size_str = d(bust_size).strip() if bust_size else ""
|
||||
shape_str = d(bust_shape).strip() if bust_shape else ""
|
||||
if size_str and shape_str:
|
||||
parts.append(f"a {size_str}, {shape_str} bust")
|
||||
elif size_str or shape_str:
|
||||
parts.append(f"a {size_str or shape_str} bust")
|
||||
|
||||
add(expression)
|
||||
add(accessories)
|
||||
add(makeup)
|
||||
@@ -376,7 +388,9 @@ def generate_person(seed, randomize, sex, category_args,
|
||||
p["face_shape"], p["complexion"], p["eyes"], p["nose_shape"], p["mouth_shape"], p["face_feature"],
|
||||
p["hair_color"], p["hair_style"], p["hair_length"], p["facial_hair"],
|
||||
p["body_type"], p["expression"], p["accessories"], p["makeup"],
|
||||
extra_attributes, eye_shape=p["eye_shape"], eyebrows=p["eyebrows"])
|
||||
extra_attributes, eye_shape=p["eye_shape"], eyebrows=p["eyebrows"],
|
||||
shoulders=p["shoulders"], chest=p["chest"],
|
||||
bust_size=p["bust_size"], bust_shape=p["bust_shape"])
|
||||
|
||||
def dd(key, sub_key="description"):
|
||||
item = p[key]
|
||||
@@ -404,9 +418,19 @@ def generate_person(seed, randomize, sex, category_args,
|
||||
dd("face_feature"),
|
||||
]))
|
||||
|
||||
size_str = dd("bust_size")
|
||||
shape_str = dd("bust_shape")
|
||||
if size_str and shape_str:
|
||||
out_bust = f"a {size_str}, {shape_str} bust"
|
||||
elif size_str or shape_str:
|
||||
out_bust = f"a {size_str or shape_str} bust"
|
||||
else:
|
||||
out_bust = ""
|
||||
|
||||
return (description, resolved_sex, out_age, out_nat, out_comp,
|
||||
out_face, out_hair, dd("facial_hair"), dd("body_type"),
|
||||
dd("expression"), dd("accessories"), dd("makeup"), seed)
|
||||
dd("expression"), dd("accessories"), dd("makeup"),
|
||||
dd("shoulders"), dd("chest"), out_bust, seed)
|
||||
|
||||
|
||||
def _collect_category_args(kwargs):
|
||||
|
||||
@@ -192,6 +192,44 @@ class TestBodyData(unittest.TestCase):
|
||||
for key in self.BODY_KEYS:
|
||||
self.assertIn(key, core.SEX_GATED, key)
|
||||
|
||||
def test_chest_in_description_male(self):
|
||||
out = run(sex="male", chest=("fixed", "", "broad"))
|
||||
self.assertIn("a broad chest", out[0])
|
||||
|
||||
def test_bust_combines_size_and_shape_female(self):
|
||||
out = run(sex="female",
|
||||
bust_size=("fixed", "", "full"),
|
||||
bust_shape=("fixed", "", "round"))
|
||||
self.assertIn("a full, round bust", out[0])
|
||||
|
||||
def test_bust_size_only_female(self):
|
||||
out = run(sex="female", bust_size=("fixed", "", "petite"),
|
||||
bust_shape=("off", "", "(none)"))
|
||||
self.assertIn("a petite bust", out[0])
|
||||
|
||||
def test_shoulders_pin_present(self):
|
||||
names = core.RETURN_NAMES
|
||||
self.assertIn("shoulders", names)
|
||||
self.assertIn("chest", names)
|
||||
self.assertIn("bust", names)
|
||||
out = run(sex="male", shoulders=("fixed", "", "broad"))
|
||||
idx = names.index("shoulders")
|
||||
self.assertEqual(out[idx], "broad shoulders")
|
||||
|
||||
def test_male_never_grows_bust(self):
|
||||
for seed in range(30):
|
||||
out = run(seed=seed, sex="male",
|
||||
bust_size=("random", "", "(none)"),
|
||||
bust_shape=("random", "", "(none)"))
|
||||
bust_idx = core.RETURN_NAMES.index("bust")
|
||||
self.assertEqual(out[bust_idx], "", seed)
|
||||
|
||||
def test_female_never_grows_chest(self):
|
||||
for seed in range(30):
|
||||
out = run(seed=seed, sex="female", chest=("random", "", "(none)"))
|
||||
chest_idx = core.RETURN_NAMES.index("chest")
|
||||
self.assertEqual(out[chest_idx], "", seed)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user