diff --git a/api/manifest.json b/api/manifest.json index f29e299..f0c08ad 100644 --- a/api/manifest.json +++ b/api/manifest.json @@ -1 +1 @@ -{"commit":"b6720f6","dirty":false,"functions":{"bresenham":{"doc_sha":"ee2d0f7a54a664f5","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"bresenham(start, end, include_start=True, include_end=True) -> list[tuple[int, int]]"},"end_benchmark":{"doc_sha":"5d783c5dabb7a4e9","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"end_benchmark() -> str"},"exit":{"doc_sha":"7572d4d6b1a1c8a4","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"exit() -> None"},"find":{"doc_sha":"364b95807edcf8b4","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"find(name: str, scene: str = None) -> UIDrawable | None"},"find_all":{"doc_sha":"b4a278f16b172131","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"find_all(pattern: str, scene: str = None) -> list"},"get_metrics":{"doc_sha":"017f3b466a3911c8","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"get_metrics() -> dict"},"lock":{"doc_sha":"e42989cabc81d080","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"lock() -> _LockContext"},"log_benchmark":{"doc_sha":"4564bf7321366a0a","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"log_benchmark(message: str) -> None"},"set_dev_console":{"doc_sha":"940ed19ff4f5243f","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"set_dev_console(enabled: bool) -> None"},"set_scale":{"doc_sha":"b565b441a326af48","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"set_scale(multiplier: float) -> None"},"start_benchmark":{"doc_sha":"783957f3517518fe","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"start_benchmark() -> None"},"step":{"doc_sha":"90dec8ed10ee644f","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"step(dt: float = None) -> float"}},"objects":{"AStarPath":{"doc_sha":"60dd12bb4a54f3dd","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"destination":{"doc_sha":"62a81c7267ad9ed9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"c7dd130b8d4ef800","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"peek":{"doc_sha":"14054f10b4d9dda0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"peek() -> Vector"},"remaining":{"doc_sha":"c193adc4bbfa3564","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"walk":{"doc_sha":"3fb64b239109d301","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"walk() -> Vector"}}},"Alignment":{"doc_sha":"77d93d03c8994f84","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Arc":{"doc_sha":"8323f4b7101509e9","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center":{"doc_sha":"abf1643dda106bf8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"color":{"doc_sha":"bdf932405b56c319","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"end_angle":{"doc_sha":"74f9704909a3a23d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"9df77e9a996208ba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"e32208817299dfe9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"0cc0684f26d8a660","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"f2ef657aaf8b6c68","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"6612fa35c43918e7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"radius":{"doc_sha":"f9c2310b775f1e5a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"start_angle":{"doc_sha":"6b91f175ebe5ecb4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"thickness":{"doc_sha":"f8eba89682554e6d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"67dd517aa153c158","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"AutoRuleSet":{"doc_sha":"49ab716632a44f06","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"apply":{"doc_sha":"701b6f038cfd6809","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply(discrete_map: DiscreteMap, tile_layer: TileLayer, seed: int = 0) -> None"},"grid_size":{"doc_sha":"570f4c81acb781d8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"group_count":{"doc_sha":"892fc283939b3e0c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"4f5ca90860649b64","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"resolve":{"doc_sha":"f8fff4e6e6488e3f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resolve(discrete_map: DiscreteMap, seed: int = 0) -> list[int]"},"rule_count":{"doc_sha":"9b9d5a7c1475dcfa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"terrain_enum":{"doc_sha":"eb365bf99bbcca37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"terrain_enum() -> IntEnum"},"value_count":{"doc_sha":"3467d158dd5af073","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"values":{"doc_sha":"b3199e059fd1ca2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"BSP":{"doc_sha":"7e971e0542cf4006","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"adjacency":{"doc_sha":"9373aa85408486ba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"bounds":{"doc_sha":"9c41e7403f2a0b2f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"clear":{"doc_sha":"2e4ffd3360ac858e","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear() -> BSP"},"find":{"doc_sha":"fccfac484a2b889c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"find(pos: tuple[int, int] | list | Vector) -> BSPNode | None"},"get_leaf":{"doc_sha":"d8ba680ec2ad4fd1","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_leaf(index: int) -> BSPNode"},"leaves":{"doc_sha":"439ec78ec02e6df8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"leaves() -> Iterator[BSPNode]"},"pos":{"doc_sha":"b8b27f4ad76e2870","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"root":{"doc_sha":"d1e3d9741dab383d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"size":{"doc_sha":"621f11f9a37dd89d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":"Dimensions (width, height). Read-only."},"split_once":{"doc_sha":"0d7c0c33156bc4e5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"split_once(horizontal: bool, position: int) -> BSP"},"split_recursive":{"doc_sha":"fa516b79833e5094","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"split_recursive(depth: int, min_size: tuple[int, int], max_ratio: float = 1.5, seed: int | None = None) -> BSP"},"to_heightmap":{"doc_sha":"a0f03cab7a0f2d1b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_heightmap(size: tuple[int, int] | None = None, select: str = 'leaves', shrink: int = 0, value: float = 1.0) -> HeightMap"},"traverse":{"doc_sha":"57da83e0f37686aa","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"traverse(order: Traversal = Traversal.LEVEL_ORDER) -> Iterator[BSPNode]"}}},"Behavior":{"doc_sha":"09206365e6c37ecc","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Billboard":{"doc_sha":"38614d1d19942bab","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"facing":{"doc_sha":"f82e2d7d8087804a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"dc5ed39915ab896c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"phi":{"doc_sha":"1450c89fb5b47929","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"0d5fec7fd4701ea6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"scale":{"doc_sha":"c9d55c4579681854","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_index":{"doc_sha":"170c20c841b586fc","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"texture":{"doc_sha":"b6d846566b6ccf93","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"theta":{"doc_sha":"c214ecbcb099228b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"adf8070be9a09eba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"CallableBinding":{"doc_sha":"711bf0f149ccae7a","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"callable":{"doc_sha":"96d3d31a6b7c56d9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_valid":{"doc_sha":"bc69c90e13475ae6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"value":{"doc_sha":"8f7d9eb4f520c017","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Caption":{"doc_sha":"8cd46324baa46a0d","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill_color":{"doc_sha":"af7ba90df95e4b79","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"font":{"doc_sha":"fbdafdb33921aa13","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"font_size":{"doc_sha":"7894149ec4efec6e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"79a7d48503e657d1","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"25b029c86a618fee","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"h":{"doc_sha":"ca1a98d700ff1888","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"90a2ab0ec07c00eb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"b3b8de4e294d71b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"outline":{"doc_sha":"6580b31092048bcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"outline_color":{"doc_sha":"388919803d270fd3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"44e4967e15212959","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"shader":{"doc_sha":"418952064319ffb5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"size":{"doc_sha":"85abb564299b703d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"text":{"doc_sha":"41628142b287defe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"uniforms":{"doc_sha":"b1f2699da618d002","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"w":{"doc_sha":"8472810bca891509","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"528487f8deaaf789","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"114ecec940477107","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"328d87ae44d9fb71","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Circle":{"doc_sha":"077981a1fbdfb6e3","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center":{"doc_sha":"d1e80ccd6bf706b9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill_color":{"doc_sha":"46be64336e296c50","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"20bebfa7432ed339","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"b43e33c2d49a3565","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"0cc0684f26d8a660","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"3a340282000297e0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"outline":{"doc_sha":"20e9fd42a7ba4bb8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"outline_color":{"doc_sha":"3fbed883fee308fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"5f9d88ff075d2cfc","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"radius":{"doc_sha":"00a41207192c55a8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"0cb3df5278d2658b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Color":{"doc_sha":"f1f664405900332f","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"a":{"doc_sha":"ef61630ad34f8e2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"b":{"doc_sha":"2e2e91e93833fdd0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_hex":{"doc_sha":"24d1ff553133bb7e","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"from_hex(hex_string: str) -> Color"},"g":{"doc_sha":"716ced374bcc2dc4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"lerp":{"doc_sha":"290e204f3538e406","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"lerp(other: Color, t: float) -> Color"},"r":{"doc_sha":"ef64cae6296f68cb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_hex":{"doc_sha":"d0cf65b284158877","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_hex() -> str"}}},"ColorLayer":{"doc_sha":"f8a87b6184c9a9b6","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"apply_gradient":{"doc_sha":"20390111f0652ae0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_gradient(source: HeightMap, range: tuple, color_low: Color, color_high: Color) -> ColorLayer"},"apply_perspective":{"doc_sha":"a909e1b1c0373bc0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_perspective(entity: Entity, visible: Color | None = None, discovered: Color | None = None, unknown: Color | None = None) -> None"},"apply_ranges":{"doc_sha":"37fc5a26fda9cc0c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_ranges(source: HeightMap, ranges: list) -> ColorLayer"},"apply_threshold":{"doc_sha":"59cc9b72322cc677","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_threshold(source: HeightMap, range: tuple, color: Color) -> ColorLayer"},"at":{"doc_sha":"fef47313dcef9247","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"at(pos: tuple | Vector) or (x: int, y: int) -> Color"},"clear_perspective":{"doc_sha":"fec237fe4cbda340","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear_perspective() -> None"},"draw_fov":{"doc_sha":"ff965b12c888d092","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"draw_fov(source: tuple, radius: int | None = None, fov: FOV | None = None, visible: Color | None = None, discovered: Color | None = None, unknown: Color | None = None) -> None"},"edit":{"doc_sha":"b0edb9c8f4c1fe76","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"edit() -> context manager"},"fill":{"doc_sha":"f6ff376fd71ae90b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill(color: Color) -> None"},"fill_rect":{"doc_sha":"bc8b20da214aa37d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_rect(pos: tuple, size: tuple, color: Color) -> None"},"grid":{"doc_sha":"b965c55d57de78fa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"eac88eb0f7b16cbf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"dd282cc9273e2e36","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"set":{"doc_sha":"36801cc04606ee0b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set(pos, color: Color) -> None"},"update_perspective":{"doc_sha":"c9caac507fbc4921","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"update_perspective() -> None"},"visible":{"doc_sha":"ecea81ec16e31c19","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"eb13c1b4de11ce63","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"DijkstraMap":{"doc_sha":"822ccf5b086d37ec","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"descent_step":{"doc_sha":"fd7b649f1f3eb586","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"descent_step(pos: Vector | tuple) -> Vector | None"},"distance":{"doc_sha":"92b40108bb47bf88","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"distance(pos: Vector | tuple) -> float | None"},"invert":{"doc_sha":"3e5ae145dafc2c1d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"invert() -> DijkstraMap"},"path_from":{"doc_sha":"3dcf638bff837f2d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"path_from(pos: Vector | tuple) -> AStarPath"},"root":{"doc_sha":"95824bac9c46ad83","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"step_from":{"doc_sha":"ac9bc93f671d3936","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"step_from(pos: Vector | tuple) -> Vector | None"},"to_heightmap":{"doc_sha":"0ba542e6509b510b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_heightmap(size=None, unreachable=-1.0) -> HeightMap"}}},"DiscreteMap":{"doc_sha":"4d6d00ffa3ac62a9","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"add":{"doc_sha":"1e5a5b83f555fa87","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add(other: DiscreteMap | int, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"bitwise_and":{"doc_sha":"1644af83b8699792","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"bitwise_and(other: DiscreteMap, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"bitwise_or":{"doc_sha":"c8262af2fdccdeeb","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"bitwise_or(other: DiscreteMap, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"bitwise_xor":{"doc_sha":"01809471595bf8e7","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"bitwise_xor(other: DiscreteMap, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"bool":{"doc_sha":"a999f0f09edf7bf3","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"bool(condition: int | set | callable) -> DiscreteMap"},"clear":{"doc_sha":"b04d176e9c7bf9d2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear() -> DiscreteMap"},"copy_from":{"doc_sha":"efea5a0aa9a8d9c9","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"copy_from(other: DiscreteMap, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"count":{"doc_sha":"5e3303ddc3a9e3ae","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"count(value: int) -> int"},"count_range":{"doc_sha":"ac4e0298919fd16e","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"count_range(min_val: int, max_val: int) -> int"},"enum_type":{"doc_sha":"f27f1ad46e2d5afe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill":{"doc_sha":"7f358bdcc5c2c9f0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill(value: int, *, pos=None, size=None) -> DiscreteMap"},"from_bytes":{"doc_sha":"b1c09c737d43ffa9","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"from_bytes(data: bytes, size: tuple[int, int], *, enum: type = None) -> DiscreteMap"},"from_heightmap":{"doc_sha":"0e89bb4262b19ea3","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"from_heightmap(hmap: HeightMap, mapping: list[tuple[tuple[float,float], int]], *, enum=None) -> DiscreteMap"},"get":{"doc_sha":"a1097b27b43d6a27","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get(x, y) or (pos) -> int | Enum"},"histogram":{"doc_sha":"b2d9df4f14aedd51","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"histogram() -> dict[int, int]"},"invert":{"doc_sha":"0f52aecfe57ff499","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"invert() -> DiscreteMap"},"mask":{"doc_sha":"0d9628616f4592f4","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"mask() -> memoryview"},"max":{"doc_sha":"144265dd0da983a8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"max(other: DiscreteMap, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"min":{"doc_sha":"ff90ceef60a45959","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"min(other: DiscreteMap, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"min_max":{"doc_sha":"22018caaf1bdb60e","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"min_max() -> tuple[int, int]"},"multiply":{"doc_sha":"430abcb2b647132f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"multiply(factor: float, *, pos=None, size=None) -> DiscreteMap"},"set":{"doc_sha":"8439c14e5785f7e4","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set(x: int, y: int, value: int) -> None"},"size":{"doc_sha":"fc6c37c9d3916c5d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":"Dimensions (width, height) of the map. Read-only."},"subtract":{"doc_sha":"aeae8042663b9973","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"subtract(other: DiscreteMap | int, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"to_bytes":{"doc_sha":"4d7c4b5939a546bd","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_bytes() -> bytes"},"to_heightmap":{"doc_sha":"b0744db8f889b5d9","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_heightmap(mapping: dict[int, float] = None) -> HeightMap"}}},"Drawable":{"doc_sha":"bb28a8d677f24b33","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"move":{"doc_sha":"4a8f9ca3692c6b58","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"on_click":{"doc_sha":"b3b8de4e294d71b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"resize":{"doc_sha":"980bdc9065fc077b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"328d87ae44d9fb71","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Easing":{"doc_sha":"e3b0c44298fc1c14","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Entity":{"doc_sha":"7231aaf2e3b107d0","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"add_label":{"doc_sha":"be06d30bbd5a41ca","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_label(label: str) -> None"},"animate":{"doc_sha":"a06820cecef57a9a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"at":{"doc_sha":"b5775513388a1464","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"at(x: int, y: int) -> GridPoint | None"},"behavior_type":{"doc_sha":"745936b7029480fd","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"cell_pos":{"doc_sha":"f8feaba9f3652ca0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"cell_x":{"doc_sha":"8bdc1199bfb15967","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"cell_y":{"doc_sha":"8fd78a55ede4b259","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"default_behavior":{"doc_sha":"f0a1ea99426408dd","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"die":{"doc_sha":"1369fecbc5a1862a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"die() -> None"},"draw_pos":{"doc_sha":"2769bf67eec13406","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"find_path":{"doc_sha":"1a672b91a00eb597","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"find_path(target, diagonal_cost: float = 1.41, collide: str = None) -> AStarPath | None"},"grid":{"doc_sha":"d02c7b8c3beb5662","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"d2e9f06a9d9f0a3c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_x":{"doc_sha":"4108b9ec31aff2c0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_y":{"doc_sha":"26f7190f34a208b2","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"has_label":{"doc_sha":"0e65dc586b3c8d18","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"has_label(label: str) -> bool"},"index":{"doc_sha":"74e24820bb380594","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"index() -> int"},"labels":{"doc_sha":"4e16ef3312d5b4e7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"move_speed":{"doc_sha":"a3b3867a6d3b830a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"708f75f696069d69","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"6caae59e941bebf1","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"path_to":{"doc_sha":"5b11e33c92caac2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"path_to(x: int, y: int) -> list"},"perspective_map":{"doc_sha":"f61894673d8c27a7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"172ff9a95e621eaf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"remove_label":{"doc_sha":"a4a541d7e9cf7275","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"remove_label(label: str) -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"set_behavior":{"doc_sha":"328826510c72f049","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set_behavior(type, waypoints=None, turns: int = 0, path=None, pathfinder=None) -> None"},"shader":{"doc_sha":"04503c544358f827","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sight_radius":{"doc_sha":"4a9ec6c3788b093a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_grid":{"doc_sha":"a5ff2c3e5190bc41","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_index":{"doc_sha":"ca285ed1c6f460df","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_offset":{"doc_sha":"a92dae4a2555fa7b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_offset_x":{"doc_sha":"7ba6504a9bbbf681","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_offset_y":{"doc_sha":"24d4546e182bb2c8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"step":{"doc_sha":"8877861183e50020","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"target_label":{"doc_sha":"85acb11a7e713a41","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"texture":{"doc_sha":"1588a0d4779fd069","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_height":{"doc_sha":"7f2ef7cb6d425730","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_size":{"doc_sha":"1a647ababfde2daa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_width":{"doc_sha":"5d72ddf874e9db54","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"turn_order":{"doc_sha":"eba665bc9c7e75ee","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"uniforms":{"doc_sha":"d302457c5aaa495e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"update_visibility":{"doc_sha":"d096cd998ed99b49","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"update_visibility() -> None"},"visible":{"doc_sha":"2bca3a265b44b270","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible_entities":{"doc_sha":"2482fbbecbfac7ea","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"visible_entities(fov=None, radius: int | None = None) -> list[Entity]"},"x":{"doc_sha":"4ba6a677ea35e7ba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"52b85f7dc8a7cb27","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Entity3D":{"doc_sha":"0daee46cf6343e9c","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"anim_clip":{"doc_sha":"f69294fc08fc1d6c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"anim_frame":{"doc_sha":"41bdd9b6f4407d16","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"anim_loop":{"doc_sha":"b267a372c1aef2cd","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"anim_paused":{"doc_sha":"e100f0be03f09b09","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"anim_speed":{"doc_sha":"33c581c9533b5169","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"anim_time":{"doc_sha":"6b811c83dd2a2184","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"fcf44af080ce16a7","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property, target, duration, easing=None, delta=False, callback=None, conflict_mode=None)"},"at":{"doc_sha":"69d6101c79794f90","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"at(x, z) -> dict"},"auto_animate":{"doc_sha":"867ca7a9c2b5a4ab","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"clear_path":{"doc_sha":"989bb0a431b58e17","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear_path()"},"color":{"doc_sha":"ea9ab21659b6e392","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"follow_path":{"doc_sha":"f514b7092f561550","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"follow_path(path)"},"grid_pos":{"doc_sha":"f20411521f420193","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"idle_clip":{"doc_sha":"855c97611053652c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_moving":{"doc_sha":"b31c1090228993e4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"model":{"doc_sha":"26ae36cf867d07e9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"acea3a6577d65fbc","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_anim_complete":{"doc_sha":"5cc47894576d983d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":"Callback(entity, clip_name) when non-looping animation ends."},"path_to":{"doc_sha":"d6fe3936cc8e2d84","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"path_to(x, z) or path_to(pos=(x, z)) -> list"},"pos":{"doc_sha":"2488492030e9df40","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"5b603e8c652baf50","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"scale":{"doc_sha":"b06782214d92e3f7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"teleport":{"doc_sha":"d53364830cdc737a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"teleport(x, z) or teleport(pos=(x, z))"},"update_visibility":{"doc_sha":"61886fb70daedf6b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"update_visibility()"},"viewport":{"doc_sha":"e9f9154f00b47f9a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"bc1ae0f4c6b5cb11","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"walk_clip":{"doc_sha":"c95d11b4e1901f28","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"world_pos":{"doc_sha":"bcc6673be9243dd5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"EntityCollection3D":{"doc_sha":"55864ac691527ca9","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"append":{"doc_sha":"43922f93aff7d723","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"append(entity)"},"clear":{"doc_sha":"f44ea077b10186d7","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear()"},"extend":{"doc_sha":"4fd2e7e83437c7ae","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"extend(iterable)"},"find":{"doc_sha":"e4182a3a3317aaae","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"find(name) -> Entity3D or None"},"pop":{"doc_sha":"cbcc90e2a433f277","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"pop(index=-1) -> Entity3D"},"remove":{"doc_sha":"b2f8fb276b91ec1e","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"remove(entity)"}}},"EntityCollection3DIter":{"doc_sha":"d71ec48b224bfacc","kind":"class","lifecycle":{"since":"0.2.8"},"members":{}},"FOV":{"doc_sha":"e3b0c44298fc1c14","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Font":{"doc_sha":"245b4e9b0ca66fc9","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"family":{"doc_sha":"0cf26d3038432764","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"source":{"doc_sha":"efc970576a584cde","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Frame":{"doc_sha":"4d53c3cb9e9e4611","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"cache_subtree":{"doc_sha":"0b8d1175192c1ce2","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"children":{"doc_sha":"0039bc0488cad1dd","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"clip_children":{"doc_sha":"d12b2c4d1d2bb6cb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill_color":{"doc_sha":"8cfbe5aa6dd6da27","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"2f5b05882c4ad39f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"9c8707ad589e5d8a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"h":{"doc_sha":"ced8010da828cc93","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"90a2ab0ec07c00eb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"b3b8de4e294d71b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"outline":{"doc_sha":"c07b6dec9da5b9ea","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"outline_color":{"doc_sha":"cd98fcaf39f0bc56","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"55a118e7889fd555","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"shader":{"doc_sha":"418952064319ffb5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"uniforms":{"doc_sha":"b1f2699da618d002","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"w":{"doc_sha":"bd51299002a099c5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"4ed17c625f2289e3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"fabaa45fd789c7fd","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"328d87ae44d9fb71","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Grid":{"doc_sha":"f88e43e992d43a86","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"camera_rotation":{"doc_sha":"bc2cd502f52817e9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center":{"doc_sha":"913ef5c36eaf9635","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center_x":{"doc_sha":"fbb0ff08116f3c80","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center_y":{"doc_sha":"1bda27633025fb12","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill_color":{"doc_sha":"f26fb5da3de1789a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_data":{"doc_sha":"fdf0084b8456fd45","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"h":{"doc_sha":"bd5a06618a50efad","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"90a2ab0ec07c00eb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"4e33bd16b2dee20a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"7f556820c51df2c4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"shader":{"doc_sha":"418952064319ffb5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"texture":{"doc_sha":"b9bfb54e5571bfc9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"uniforms":{"doc_sha":"b1f2699da618d002","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"w":{"doc_sha":"ec55a5a578c4d993","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"2449b0f04153753c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"7958c0625706f2d2","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"0cb3df5278d2658b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"zoom":{"doc_sha":"e56c4b61e0303f09","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"GridView":{"doc_sha":"f88e43e992d43a86","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"camera_rotation":{"doc_sha":"bc2cd502f52817e9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center":{"doc_sha":"913ef5c36eaf9635","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center_x":{"doc_sha":"fbb0ff08116f3c80","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center_y":{"doc_sha":"1bda27633025fb12","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill_color":{"doc_sha":"f26fb5da3de1789a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_data":{"doc_sha":"fdf0084b8456fd45","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"h":{"doc_sha":"bd5a06618a50efad","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"90a2ab0ec07c00eb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"4e33bd16b2dee20a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"7f556820c51df2c4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"shader":{"doc_sha":"418952064319ffb5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"texture":{"doc_sha":"b9bfb54e5571bfc9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"uniforms":{"doc_sha":"b1f2699da618d002","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"w":{"doc_sha":"ec55a5a578c4d993","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"2449b0f04153753c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"7958c0625706f2d2","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"0cb3df5278d2658b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"zoom":{"doc_sha":"e56c4b61e0303f09","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"HeightMap":{"doc_sha":"e5f86ba9c89f2a5a","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"add":{"doc_sha":"d420dd760d7228af","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add(other: HeightMap, *, pos=None, source_pos=None, size=None) -> HeightMap"},"add_bsp":{"doc_sha":"b70f06e432c91a7a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_bsp(bsp: BSP, *, pos=None, select: str = 'leaves', nodes: list = None, shrink: int = 0, value: float = 1.0) -> HeightMap"},"add_constant":{"doc_sha":"f382eb3f3e667cb4","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_constant(value: float, *, pos=None, size=None) -> HeightMap"},"add_hill":{"doc_sha":"1ad2406960701682","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_hill(center, radius: float, height: float) -> HeightMap"},"add_noise":{"doc_sha":"3c3c15026ff43959","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_noise(source: NoiseSource, world_origin: tuple = (0.0, 0.0), world_size: tuple = None, mode: str = 'fbm', octaves: int = 4, scale: float = 1.0) -> HeightMap"},"add_voronoi":{"doc_sha":"b689af51f6867b78","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_voronoi(num_points: int, coefficients: tuple = (1.0, -0.5), seed: int = None) -> HeightMap"},"clamp":{"doc_sha":"60c08680fb281402","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clamp(min: float = 0.0, max: float = 1.0, *, pos=None, size=None) -> HeightMap"},"clear":{"doc_sha":"2297d98f231b6b7b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear() -> HeightMap"},"copy_from":{"doc_sha":"80d64f3f6e76f8a7","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"copy_from(other: HeightMap, *, pos=None, source_pos=None, size=None) -> HeightMap"},"count_in_range":{"doc_sha":"7af3d60f28d614b6","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"count_in_range(range: tuple[float, float]) -> int"},"dig_bezier":{"doc_sha":"f3327d6ddc165496","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"dig_bezier(points: tuple, start_radius: float, end_radius: float, start_height: float, end_height: float) -> HeightMap"},"dig_hill":{"doc_sha":"be55e494c4e50c3a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"dig_hill(center, radius: float, target_height: float) -> HeightMap"},"fill":{"doc_sha":"4e998a0b1d85c4f2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill(value: float, *, pos=None, size=None) -> HeightMap"},"get":{"doc_sha":"f55fcc655d43dc50","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get(x, y) or (pos) -> float"},"get_interpolated":{"doc_sha":"5c3e0267d9cbeda2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_interpolated(x, y) or (pos) -> float"},"get_normal":{"doc_sha":"6d4212add4e533f2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_normal(x, y, water_level=0.0) or (pos, water_level=0.0) -> tuple[float, float, float]"},"get_slope":{"doc_sha":"4876967f738c7d67","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_slope(x, y) or (pos) -> float"},"inverse":{"doc_sha":"f6c4de6cd6a9ca0f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"inverse() -> HeightMap"},"lerp":{"doc_sha":"967cacc180df98bc","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"lerp(other: HeightMap, t: float, *, pos=None, source_pos=None, size=None) -> HeightMap"},"max":{"doc_sha":"141515f8b1f23390","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"max(other: HeightMap, *, pos=None, source_pos=None, size=None) -> HeightMap"},"mid_point_displacement":{"doc_sha":"bfcbfe796d73410f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"mid_point_displacement(roughness: float = 0.5, seed: int = None) -> HeightMap"},"min":{"doc_sha":"c51e934ea5047d91","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"min(other: HeightMap, *, pos=None, source_pos=None, size=None) -> HeightMap"},"min_max":{"doc_sha":"4e0b3cb7472a7cfe","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"min_max() -> tuple[float, float]"},"multiply":{"doc_sha":"83d2fcea22463d18","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"multiply(other: HeightMap, *, pos=None, source_pos=None, size=None) -> HeightMap"},"multiply_bsp":{"doc_sha":"21f401c651344592","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"multiply_bsp(bsp: BSP, *, pos=None, select: str = 'leaves', nodes: list = None, shrink: int = 0, value: float = 1.0) -> HeightMap"},"multiply_noise":{"doc_sha":"177d1d06a401af54","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"multiply_noise(source: NoiseSource, world_origin: tuple = (0.0, 0.0), world_size: tuple = None, mode: str = 'fbm', octaves: int = 4, scale: float = 1.0) -> HeightMap"},"normalize":{"doc_sha":"93ce05bf80d158ed","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"normalize(min: float = 0.0, max: float = 1.0, *, pos=None, size=None) -> HeightMap"},"rain_erosion":{"doc_sha":"4dbe6bd42d9f6e5b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"rain_erosion(drops: int, erosion: float = 0.1, sedimentation: float = 0.05, seed: int = None) -> HeightMap"},"scale":{"doc_sha":"c85d9324b84c43ff","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"scale(factor: float, *, pos=None, size=None) -> HeightMap"},"size":{"doc_sha":"31846e24f4028b35","kind":"property","lifecycle":{"since":"0.2.8"},"signature":"Dimensions (width, height) of the heightmap. Read-only."},"smooth":{"doc_sha":"243be30aa73da43b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"smooth(iterations: int = 1) -> HeightMap"},"sparse_kernel":{"doc_sha":"e3b28d2c3913ac74","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"sparse_kernel(weights: dict[tuple[int, int], float]) -> HeightMap"},"sparse_kernel_from":{"doc_sha":"ebeed84050ee0b2f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"sparse_kernel_from(source: HeightMap, weights: dict[tuple[int, int], float]) -> None"},"subtract":{"doc_sha":"8e209f74aaad794d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"subtract(other: HeightMap, *, pos=None, source_pos=None, size=None) -> HeightMap"},"threshold":{"doc_sha":"946f6a1fb850decb","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"threshold(range: tuple[float, float]) -> HeightMap"},"threshold_binary":{"doc_sha":"6ebe7bd7cbc112c2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"threshold_binary(range: tuple[float, float], value: float = 1.0) -> HeightMap"}}},"Heuristic":{"doc_sha":"7582db951ab67fc5","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"InputState":{"doc_sha":"c7b7558edda29fea","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Key":{"doc_sha":"bc4feb60367e4be7","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Keyboard":{"doc_sha":"afbde6bcf7bfe1c6","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"alt":{"doc_sha":"051cb7dbc470d328","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"ctrl":{"doc_sha":"c062912b0b816bd2","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"shift":{"doc_sha":"614beb0d432c2ec0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"system":{"doc_sha":"2292efb47472f5e7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"LdtkProject":{"doc_sha":"d80a5fdda811cb33","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"enums":{"doc_sha":"5697f9e75980e2be","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"level":{"doc_sha":"33b80035be788d03","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"level(name: str) -> dict"},"level_names":{"doc_sha":"9479f6c2bd85608d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"ruleset":{"doc_sha":"ce72d154e5dd391c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"ruleset(name: str) -> AutoRuleSet"},"ruleset_names":{"doc_sha":"28983e9702e0dc81","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tileset":{"doc_sha":"30eabe3003acb244","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"tileset(name: str) -> TileSetFile"},"tileset_names":{"doc_sha":"77a45b51f49743ef","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"version":{"doc_sha":"e6d3d49ad9edfad8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Line":{"doc_sha":"8d778faa93b5d0d5","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"color":{"doc_sha":"f7aca0b82eaae97e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"end":{"doc_sha":"cc14ff1baa1b61fa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"9df77e9a996208ba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"e32208817299dfe9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"feeb7cb507a4692d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"49cecfb458b010a1","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"733a48ea3a730e60","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"start":{"doc_sha":"817049419558ea17","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"thickness":{"doc_sha":"b6c7f3e979028709","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"cecb3704206d35f7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Model3D":{"doc_sha":"be7fb5003ed48d84","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"animation_clips":{"doc_sha":"0d15ad9839919fe5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"bone_count":{"doc_sha":"6e389fb2496946bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"bounds":{"doc_sha":"4ddfb8f6ae5a8928","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"cube":{"doc_sha":"b49160efa8b0f71e","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"cube(size=1.0) -> Model3D"},"has_skeleton":{"doc_sha":"4e9ac073dac101b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"mesh_count":{"doc_sha":"49f8fe0ece668d77","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"b577d22f9a18de0c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"plane":{"doc_sha":"5e31b94e295b4429","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"plane(width=1.0, depth=1.0, segments=1) -> Model3D"},"sphere":{"doc_sha":"b385d8aaf0efd485","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"sphere(radius=0.5, segments=16, rings=12) -> Model3D"},"triangle_count":{"doc_sha":"b67c98fac8ffc8dd","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vertex_count":{"doc_sha":"8b76e70b26a820df","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Mouse":{"doc_sha":"e64f561c8a08bdec","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"grabbed":{"doc_sha":"3da420bb9cac434f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"left":{"doc_sha":"a4c7b98babc093cb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"middle":{"doc_sha":"1306b1240c6f64e3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"2ecba0a68d64976a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"right":{"doc_sha":"08d5534c1c034b39","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"834527eb5579f3e3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"c142f98ee94bf3f7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"5095db9e9e163e92","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"MouseButton":{"doc_sha":"a5a7584949d18f01","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Music":{"doc_sha":"e13e6ad378ec0e91","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"duration":{"doc_sha":"25607c5fa852d501","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"loop":{"doc_sha":"a165a91f8ff771f5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pause":{"doc_sha":"4eb6d242151147dc","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"pause() -> None"},"play":{"doc_sha":"f724039e0cdb2847","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"play() -> None"},"playing":{"doc_sha":"4451d007747fa3b1","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"position":{"doc_sha":"608a5f6d4ed927bc","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"source":{"doc_sha":"ee5d7818bae0a255","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"stop":{"doc_sha":"f3289bbb98a4da1f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"stop() -> None"},"volume":{"doc_sha":"749fc9d89252cb0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"NoiseSource":{"doc_sha":"3bfa3b53984c85cb","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"algorithm":{"doc_sha":"ba813d6c022f15f0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"dimensions":{"doc_sha":"f534d20928d8d67a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fbm":{"doc_sha":"d13c8670fc68b9df","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fbm(pos: tuple[float, ...], octaves: int = 4) -> float"},"get":{"doc_sha":"3d7776fffd7a0a39","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get(pos: tuple[float, ...]) -> float"},"hurst":{"doc_sha":"11682e6dc42f2417","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"lacunarity":{"doc_sha":"4d07f7079f3938de","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sample":{"doc_sha":"63fd0e680000d0f0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"sample(size: tuple[int, int], world_origin: tuple[float, float] = (0.0, 0.0), world_size: tuple[float, float] = None, mode: str = 'fbm', octaves: int = 4) -> HeightMap"},"seed":{"doc_sha":"17bc1e90a8ce6b23","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"turbulence":{"doc_sha":"800c841f913b3780","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"turbulence(pos: tuple[float, ...], octaves: int = 4) -> float"}}},"Perspective":{"doc_sha":"e1c8553ea2a32a40","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"PropertyBinding":{"doc_sha":"a23eb43edd46bb66","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"is_valid":{"doc_sha":"40ada14485c362a7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"property":{"doc_sha":"0dad06f4e661db2d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"target":{"doc_sha":"3b15e1922fd910c9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"value":{"doc_sha":"80d28b4e329837d8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Scene":{"doc_sha":"a156c42d77b20a3e","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"activate":{"doc_sha":"54ae3cd3cf652660","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"activate(transition: Transition = None, duration: float = None) -> None"},"active":{"doc_sha":"a59f70d3c12a7cfe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"children":{"doc_sha":"f21fb480dac856b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"7feed093cdf9334a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_key":{"doc_sha":"40ece618402a45f3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"9e60a4ae9bdb493b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"50e29b0dd34a76d5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"eef1e2dce9ee8894","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"register":{"doc_sha":"7603337801a7a498","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"register() -> None"},"registered":{"doc_sha":"d9ff54f488ed5b87","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"unregister":{"doc_sha":"fda6be9891d1f502","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"unregister() -> None"},"visible":{"doc_sha":"a7f321f4013dfb9b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Shader":{"doc_sha":"aded56cb37cba9d8","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"dynamic":{"doc_sha":"43d8bc587c3997e3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_valid":{"doc_sha":"fcdf95eedfa8479e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"set_uniform":{"doc_sha":"bdaf877e5bc28f21","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set_uniform(name: str, value: float|tuple) -> None"},"source":{"doc_sha":"dbd462698aadf450","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Sound":{"doc_sha":"8f31cca1781580d5","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"buffer":{"doc_sha":"c79f4e433d4300ac","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"duration":{"doc_sha":"48daac900b6eaf36","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"loop":{"doc_sha":"a624dff0e72a5337","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pause":{"doc_sha":"005627aca21692d3","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"pause() -> None"},"pitch":{"doc_sha":"80b38bfc202b4291","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"play":{"doc_sha":"ae090ee8c0320797","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"play() -> None"},"play_varied":{"doc_sha":"fd9b5cd6db3cb1cf","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"play_varied(pitch_range: float = 0.1, volume_range: float = 3.0) -> None"},"playing":{"doc_sha":"8a0c491fa38061d5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"source":{"doc_sha":"1736ca7393d96c48","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"stop":{"doc_sha":"f3289bbb98a4da1f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"stop() -> None"},"volume":{"doc_sha":"749fc9d89252cb0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"SoundBuffer":{"doc_sha":"426618cde68541be","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"bit_crush":{"doc_sha":"66ae55272fd9d182","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"bit_crush(bits: int, rate_divisor: int) -> SoundBuffer"},"channels":{"doc_sha":"f3948c1ceb5d7aec","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"concat":{"doc_sha":"7ee10bfe76aae5e2","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"concat(buffers: list[SoundBuffer], overlap: float = 0.0) -> SoundBuffer"},"distortion":{"doc_sha":"a36442ca725e5cc6","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"distortion(drive: float) -> SoundBuffer"},"duration":{"doc_sha":"bc1c03f781e0372b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"echo":{"doc_sha":"1b93f79c671068ab","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"echo(delay_ms: float, feedback: float, wet: float) -> SoundBuffer"},"from_samples":{"doc_sha":"556326f1f2cda4a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"from_samples(data: bytes, channels: int, sample_rate: int) -> SoundBuffer"},"gain":{"doc_sha":"22fc3aad26b084a5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"gain(factor: float) -> SoundBuffer"},"high_pass":{"doc_sha":"7d8af12720a4bbae","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"high_pass(cutoff_hz: float) -> SoundBuffer"},"low_pass":{"doc_sha":"82cdc215e7da9310","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"low_pass(cutoff_hz: float) -> SoundBuffer"},"mix":{"doc_sha":"4df14cf741427da9","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"mix(buffers: list[SoundBuffer]) -> SoundBuffer"},"normalize":{"doc_sha":"5476b16208b1ac7b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"normalize() -> SoundBuffer"},"pitch_shift":{"doc_sha":"ee9373f2d71fdaa8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"pitch_shift(factor: float) -> SoundBuffer"},"reverb":{"doc_sha":"b6d0dcf1e5f75a42","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"reverb(room_size: float, damping: float, wet: float) -> SoundBuffer"},"reverse":{"doc_sha":"eb70bfa5da4c860d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"reverse() -> SoundBuffer"},"sample_count":{"doc_sha":"5e96b7263eade6af","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sample_rate":{"doc_sha":"a41417a71e10a2d6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sfxr":{"doc_sha":"5f45a4b7afc74066","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"sfxr(preset: str = None, seed: int = None, **params) -> SoundBuffer"},"sfxr_mutate":{"doc_sha":"68b5b653de4f55dc","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"sfxr_mutate(amount: float = 0.05, seed: int = None) -> SoundBuffer"},"sfxr_params":{"doc_sha":"7fd7a2356600014a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"slice":{"doc_sha":"84099d0f46e6b7ad","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"slice(start: float, end: float) -> SoundBuffer"},"tone":{"doc_sha":"eaec1748a9089774","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"tone(frequency: float, duration: float, waveform: str = 'sine', ...) -> SoundBuffer"}}},"Sprite":{"doc_sha":"a687c4f393725428","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"9df77e9a996208ba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"e32208817299dfe9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"90a2ab0ec07c00eb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"b3b8de4e294d71b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"55a118e7889fd555","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"scale":{"doc_sha":"f91a66d322ee1a75","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"scale_x":{"doc_sha":"95f47a809a8ac927","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"scale_y":{"doc_sha":"8567691c22a9b5f8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"shader":{"doc_sha":"418952064319ffb5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_index":{"doc_sha":"826af9fc52ae5cef","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"texture":{"doc_sha":"df3e7671926aa0a3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"uniforms":{"doc_sha":"b1f2699da618d002","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"528487f8deaaf789","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"114ecec940477107","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"328d87ae44d9fb71","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Texture":{"doc_sha":"da368b536d9f844e","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"composite":{"doc_sha":"0bf406582f618af3","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"composite(layers: list[Texture], sprite_width: int, sprite_height: int, name: str = '') -> Texture"},"display_height":{"doc_sha":"0dc1ccea45ff4e40","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"display_offset_x":{"doc_sha":"0ca738fa6559aabb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"display_offset_y":{"doc_sha":"83b5bfadd26f4e79","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"display_width":{"doc_sha":"cfc6525a8a0b5bb7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"979f5a384770d87f","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"from_bytes(data: bytes, width: int, height: int, sprite_width: int, sprite_height: int, name: str = '') -> Texture"},"hsl_shift":{"doc_sha":"95f19de7a67646e3","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"hsl_shift(hue_shift: float, sat_shift: float = 0.0, lit_shift: float = 0.0) -> Texture"},"sheet_height":{"doc_sha":"59d4fb71cae72fba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sheet_width":{"doc_sha":"54ef54eb9c39a907","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"source":{"doc_sha":"51bee1cdb17257ba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_count":{"doc_sha":"d1ed79d8b59eca99","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_height":{"doc_sha":"19b6a36f45f965e8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_width":{"doc_sha":"6f9276522c3b2512","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"TileLayer":{"doc_sha":"5551e3bf9e668d89","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"apply_ranges":{"doc_sha":"e443e268532fdd2f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_ranges(source: HeightMap, ranges: list) -> TileLayer"},"apply_threshold":{"doc_sha":"2253f4367656d073","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_threshold(source: HeightMap, range: tuple, tile: int) -> TileLayer"},"at":{"doc_sha":"19975fea19b3fadb","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"at(pos: tuple | Vector) or (x: int, y: int) -> int"},"edit":{"doc_sha":"47c32fda0e88780a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"edit() -> context manager"},"fill":{"doc_sha":"5c8eca820794a605","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill(index: int) -> None"},"fill_rect":{"doc_sha":"adfc5ff6d6e91cc8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_rect(pos: tuple, size: tuple, index: int) -> None"},"grid":{"doc_sha":"b965c55d57de78fa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"eac88eb0f7b16cbf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"dd282cc9273e2e36","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"set":{"doc_sha":"2b242556ce84080f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set(pos, index: int) -> None"},"texture":{"doc_sha":"1d211a219f88c72c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"ecea81ec16e31c19","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"eb13c1b4de11ce63","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"TileMapFile":{"doc_sha":"b26cb3870e41a2c9","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"apply_to_tile_layer":{"doc_sha":"436e4fa972bd79d0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_to_tile_layer(tile_layer: TileLayer, layer_name: str, tileset_index: int = 0) -> None"},"height":{"doc_sha":"72aa81aefdab3ddb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"object_layer":{"doc_sha":"e658613bcbbe9b3a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"object_layer(name: str) -> list[dict]"},"object_layer_names":{"doc_sha":"7af1cc1454cd97f9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"orientation":{"doc_sha":"2ee759a156b5c903","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"properties":{"doc_sha":"f2cb52eb132891d8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"resolve_gid":{"doc_sha":"4a72f1c9f61cec27","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resolve_gid(gid: int) -> tuple[int, int]"},"tile_height":{"doc_sha":"cc47760c48b8c9be","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_layer_data":{"doc_sha":"399fd655e6402442","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"tile_layer_data(name: str) -> list[int]"},"tile_layer_names":{"doc_sha":"e225e2d4b71155e7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_width":{"doc_sha":"c109808c1e2d3ca1","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tileset":{"doc_sha":"a3e35f368c3cc89d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"tileset(index: int) -> tuple[int, TileSetFile]"},"tileset_count":{"doc_sha":"e7347387a4bcfeae","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"width":{"doc_sha":"acef1b7138a85569","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"TileSetFile":{"doc_sha":"ec83598f02a06258","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"columns":{"doc_sha":"5ba187696ce9596e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"image_source":{"doc_sha":"f21faacc0392eec3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"6e1b3cfd5b59af6a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"5e0a76b40f4db151","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"properties":{"doc_sha":"e0382abd62d297a6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"spacing":{"doc_sha":"950416fc0b8f1837","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_count":{"doc_sha":"df5ccd0141400827","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_height":{"doc_sha":"71a327fd061c1cf2","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_info":{"doc_sha":"b33077f44c79e050","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"tile_info(tile_id: int) -> dict | None"},"tile_width":{"doc_sha":"888787b1ef69f5d9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_texture":{"doc_sha":"610adac758051370","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_texture() -> Texture"},"wang_set":{"doc_sha":"c3b15db4611c250a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"wang_set(name: str) -> WangSet"},"wang_sets":{"doc_sha":"71541a1c5777b29f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Timer":{"doc_sha":"646feff7bdb817f5","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"active":{"doc_sha":"0ac0f4a607819264","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"callback":{"doc_sha":"a943e7e99b75fa22","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"interval":{"doc_sha":"e32658ee97f94823","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"98a62482b59640f6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"once":{"doc_sha":"7d5a7d20bae3793e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pause":{"doc_sha":"bfe544cc3c9f1cda","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"pause() -> None"},"paused":{"doc_sha":"060df10cbfc34662","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"remaining":{"doc_sha":"e223a64ed6a1ec63","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"restart":{"doc_sha":"a8c305ae5017cce0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"restart() -> None"},"resume":{"doc_sha":"66ab0cd39f579ef9","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resume() -> None"},"start":{"doc_sha":"0b2b51d812995d34","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"start() -> None"},"stop":{"doc_sha":"9f69f5e68512116c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"stop() -> None"},"stopped":{"doc_sha":"bffdb8aa4589c28b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Transition":{"doc_sha":"e3b0c44298fc1c14","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Traversal":{"doc_sha":"e3b0c44298fc1c14","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Trigger":{"doc_sha":"3f698ad8b187be9f","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Vector":{"doc_sha":"0c8ae9e2ef387065","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"angle":{"doc_sha":"a0ca5f1f4a89d780","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"angle() -> float"},"copy":{"doc_sha":"120e723fd513e072","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"copy() -> Vector"},"distance_to":{"doc_sha":"4f5d26bbe8434f65","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"distance_to(other: Vector) -> float"},"dot":{"doc_sha":"d69442ea289adfb8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"dot(other: Vector) -> float"},"floor":{"doc_sha":"c7e81a90c5420968","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"floor() -> Vector"},"int":{"doc_sha":"3d97cae0ad8a963c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"magnitude":{"doc_sha":"75f61a474afe3121","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"magnitude() -> float"},"magnitude_squared":{"doc_sha":"c976db5b540f827b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"magnitude_squared() -> float"},"normalize":{"doc_sha":"04b468da3fc60858","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"normalize() -> Vector"},"x":{"doc_sha":"0e322bdd857e652b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"bbac84f15b6740d9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Viewport3D":{"doc_sha":"c41e58effff86261","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"add_billboard":{"doc_sha":"ae2357f78a17a437","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_billboard(billboard)"},"add_layer":{"doc_sha":"b4c0274f9217aaa1","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_layer(name, z_index=0) -> dict"},"add_mesh":{"doc_sha":"588dbdf9a48f17e5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_mesh(layer_name, model, pos, rotation=0, scale=1.0) -> int"},"add_voxel_layer":{"doc_sha":"47f17324425647e1","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_voxel_layer(voxel_grid, z_index=0)"},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"apply_heightmap":{"doc_sha":"be8e92a25726238d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_heightmap(heightmap, y_scale=1.0)"},"apply_terrain_colors":{"doc_sha":"cf0e47c185484e70","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_terrain_colors(layer_name, r_map, g_map, b_map)"},"apply_threshold":{"doc_sha":"3adda69e435613d7","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_threshold(heightmap, min_height, max_height, walkable=True)"},"at":{"doc_sha":"7ec76d7602627cb9","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"at(x, z) -> VoxelPoint"},"bg_color":{"doc_sha":"c7e7141bd1cadaea","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"billboard_count":{"doc_sha":"4b432c5c560ee44f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"billboard_count() -> int"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"build_terrain":{"doc_sha":"5be2a61f78907326","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"build_terrain(layer_name, heightmap, y_scale=1.0, cell_size=1.0) -> int"},"camera_pos":{"doc_sha":"7bfead8afc2b8312","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"camera_target":{"doc_sha":"3ecf7bb4dbdf27e4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"cell_size":{"doc_sha":"8c3fa657c8fdc2aa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"clear_billboards":{"doc_sha":"63d6d64c39b46264","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear_billboards()"},"clear_meshes":{"doc_sha":"1d6eb71f274020cf","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear_meshes(layer_name)"},"clear_voxel_nav_region":{"doc_sha":"56901862e4dc595a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear_voxel_nav_region(voxel_grid)"},"compute_fov":{"doc_sha":"93c68ed57619564e","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"compute_fov(origin, radius=10) -> list"},"enable_affine":{"doc_sha":"96ba76ed43593940","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"enable_dither":{"doc_sha":"da6733dd08751b72","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"enable_fog":{"doc_sha":"ca6c5ffcef454868","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"enable_vertex_snap":{"doc_sha":"7401ad5dcd82024c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"entities":{"doc_sha":"c2b185a3b718cc6b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"find_path":{"doc_sha":"ebd174d40557cc19","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"find_path(start, end) -> list"},"fog_color":{"doc_sha":"3eb0cdbd75c5a94c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fog_far":{"doc_sha":"90406f8cae40bb58","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fog_near":{"doc_sha":"e49f6dc79b22a794","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"follow":{"doc_sha":"975d2b945069be26","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"follow(entity, distance=10, height=5, smoothing=1.0)"},"fov":{"doc_sha":"7f5d69a1c423f69d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"get_billboard":{"doc_sha":"38b0410480ab7d4d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_billboard(index) -> Billboard"},"get_layer":{"doc_sha":"92223f274b5312c3","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_layer(name) -> dict or None"},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"7b4dbfa47f259f02","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"h":{"doc_sha":"d7308cd01fffb4be","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_in_fov":{"doc_sha":"81d50fbbe2df4c8e","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"is_in_fov(x, z) -> bool"},"layer_count":{"doc_sha":"8bfbb28860b18d51","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"layer_count() -> int"},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"on_click":{"doc_sha":"b3b8de4e294d71b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"orbit_camera":{"doc_sha":"29e02de46a996495","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"orbit_camera(angle=0, distance=10, height=5)"},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"place_blocking":{"doc_sha":"9252fd1d594a3867","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"place_blocking(grid_pos, footprint, walkable=False, transparent=False)"},"pos":{"doc_sha":"c1693d7dd0fe875d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"project_all_voxels_to_nav":{"doc_sha":"ac9e0ca27b557d65","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"project_all_voxels_to_nav(headroom=2)"},"project_voxel_to_nav":{"doc_sha":"1fdf58bc686f7511","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"project_voxel_to_nav(voxel_grid, headroom=2)"},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"remove_billboard":{"doc_sha":"bf68668896f86bb0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"remove_billboard(billboard)"},"remove_layer":{"doc_sha":"f5fafdfe3d153aab","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"remove_layer(name) -> bool"},"remove_voxel_layer":{"doc_sha":"b88a956cacc361cb","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"remove_voxel_layer(voxel_grid) -> bool"},"render_resolution":{"doc_sha":"4b141c5648005f04","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"screen_to_world":{"doc_sha":"ba31510737afd516","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"screen_to_world(x, y, y_plane=0.0) -> tuple or None"},"set_grid_size":{"doc_sha":"ee7d1626547614c8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set_grid_size(width, depth)"},"set_slope_cost":{"doc_sha":"dac6d3cd319f1016","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set_slope_cost(max_slope=0.5, cost_multiplier=1.0)"},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"voxel_layer_count":{"doc_sha":"c1ca5c90881bbaae","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"voxel_layer_count() -> int"},"w":{"doc_sha":"4c5bcc34301022a0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"cd81d9dc457285aa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"406570900a1cf520","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"328d87ae44d9fb71","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"VoxelGrid":{"doc_sha":"6706e3f5276ce104","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"add_material":{"doc_sha":"27dec1c992cf7b99","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_material(name, color=Color(255,255,255), sprite_index=-1, transparent=False, path_cost=1.0) -> int"},"cell_size":{"doc_sha":"81b167d608b2cec5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"clear":{"doc_sha":"8ebe20948a33a84d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear() -> None"},"copy_region":{"doc_sha":"e56c5d28d7fd4e86","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"copy_region(min_coord, max_coord) -> VoxelRegion"},"count_material":{"doc_sha":"c9ef38e1f2f29ab8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"count_material(material) -> int"},"count_non_air":{"doc_sha":"275d512b30f5134a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"count_non_air() -> int"},"depth":{"doc_sha":"21671acfc312aeeb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill":{"doc_sha":"fff2fcdddba5ee8c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill(material) -> None"},"fill_box":{"doc_sha":"7c3d982a275f095d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_box(min_coord, max_coord, material) -> None"},"fill_box_hollow":{"doc_sha":"432e8b518feee0a5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_box_hollow(min_coord, max_coord, material, thickness=1) -> None"},"fill_cylinder":{"doc_sha":"0b2b0b0826381df0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_cylinder(base_pos, radius, height, material) -> None"},"fill_noise":{"doc_sha":"567355400611d920","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_noise(min_coord, max_coord, material, threshold=0.5, scale=0.1, seed=0) -> None"},"fill_sphere":{"doc_sha":"e6a85d9c72e2ea44","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_sphere(center, radius, material) -> None"},"from_bytes":{"doc_sha":"faefede0aa8ae636","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"from_bytes(data) -> bool"},"get":{"doc_sha":"52cea4645f0ea3d0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get(x, y, z) -> int"},"get_material":{"doc_sha":"2a61f6d54086df97","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_material(id) -> dict"},"greedy_meshing":{"doc_sha":"17fffa950c043917","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"height":{"doc_sha":"f271e989afe69da3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"load":{"doc_sha":"5dcaf71057f836a2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"load(path) -> bool"},"material_count":{"doc_sha":"0ef72bd68ef0c2d0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"offset":{"doc_sha":"75230579ca06d8f5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"paste_region":{"doc_sha":"1f44bacefd614cca","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"paste_region(region, position, skip_air=True) -> None"},"project_column":{"doc_sha":"9bacd59e3a7c5758","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"project_column(x, z, headroom=2) -> dict"},"rebuild_mesh":{"doc_sha":"fa60051037c3328c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"rebuild_mesh() -> None"},"rotation":{"doc_sha":"5b603e8c652baf50","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"save":{"doc_sha":"bb7090694292f8e3","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"save(path) -> bool"},"set":{"doc_sha":"e9223501162aa9c6","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set(x, y, z, material) -> None"},"size":{"doc_sha":"2d283d0584913b16","kind":"property","lifecycle":{"since":"0.2.8"},"signature":"Dimensions (width, height, depth) of the grid. Read-only."},"to_bytes":{"doc_sha":"f9a751e75bfc0478","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_bytes() -> bytes"},"vertex_count":{"doc_sha":"4df863704c32ecb7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"7ff1afdbd4bf86a3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"width":{"doc_sha":"0977aff160584918","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"VoxelRegion":{"doc_sha":"0cda0630ba7cafef","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"depth":{"doc_sha":"05b3223f7df8ab65","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"height":{"doc_sha":"04834a15ca591472","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"size":{"doc_sha":"75c252385afbc498","kind":"property","lifecycle":{"since":"0.2.8"},"signature":"Dimensions (width, height, depth) of the region. Read-only."},"width":{"doc_sha":"d10d49e58037417d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"WangSet":{"doc_sha":"320e161ef3d08a5d","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"apply":{"doc_sha":"2aa8c0ba2d6549d2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply(discrete_map: DiscreteMap, tile_layer: TileLayer) -> None"},"color_count":{"doc_sha":"13b244a538aec70f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"colors":{"doc_sha":"6d84b3c2dd048b1a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"8b4560b705e5724f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"resolve":{"doc_sha":"fe2fa09430c4bda6","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resolve(discrete_map: DiscreteMap) -> list[int]"},"terrain_enum":{"doc_sha":"b8c46ec1a2b03eb6","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"terrain_enum() -> IntEnum"},"type":{"doc_sha":"ea3706e2c65ba7d3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Window":{"doc_sha":"6021e9b58544c378","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"center":{"doc_sha":"91fe1b0d6ca2e4f1","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"center() -> None"},"framerate_limit":{"doc_sha":"de182ed271fbb4d3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fullscreen":{"doc_sha":"a517f5331026f2c4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"game_resolution":{"doc_sha":"3a0dba59fecf5a95","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"get":{"doc_sha":"544bdc10ab93d067","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"get() -> Window"},"resolution":{"doc_sha":"548abee10c4fbcaf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"scaling_mode":{"doc_sha":"57e03f9ffc9291ae","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"screenshot":{"doc_sha":"5102ab9c4c2c8358","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"screenshot(filename: str = None) -> bytes | None"},"title":{"doc_sha":"0d98279e5ec1b8b1","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"bad7f81ec2e48a31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vsync":{"doc_sha":"0335eb1fba386e37","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}}},"schema":1,"seeded":true,"version":"0.2.8-dev"} +{"commit":"4c0953c","dirty":true,"functions":{"bresenham":{"doc_sha":"ee2d0f7a54a664f5","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"bresenham(start, end, include_start=True, include_end=True) -> list[tuple[int, int]]"},"end_benchmark":{"doc_sha":"5d783c5dabb7a4e9","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"end_benchmark() -> str"},"exit":{"doc_sha":"7572d4d6b1a1c8a4","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"exit() -> None"},"find":{"doc_sha":"364b95807edcf8b4","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"find(name: str, scene: str = None) -> UIDrawable | None"},"find_all":{"doc_sha":"b4a278f16b172131","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"find_all(pattern: str, scene: str = None) -> list"},"get_metrics":{"doc_sha":"017f3b466a3911c8","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"get_metrics() -> dict"},"lock":{"doc_sha":"e42989cabc81d080","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"lock() -> _LockContext"},"log_benchmark":{"doc_sha":"4564bf7321366a0a","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"log_benchmark(message: str) -> None"},"set_dev_console":{"doc_sha":"940ed19ff4f5243f","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"set_dev_console(enabled: bool) -> None"},"set_scale":{"doc_sha":"b565b441a326af48","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"set_scale(multiplier: float) -> None"},"start_benchmark":{"doc_sha":"783957f3517518fe","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"start_benchmark() -> None"},"step":{"doc_sha":"90dec8ed10ee644f","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"step(dt: float = None) -> float"}},"objects":{"AStarPath":{"doc_sha":"60dd12bb4a54f3dd","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"destination":{"doc_sha":"62a81c7267ad9ed9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"c7dd130b8d4ef800","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"peek":{"doc_sha":"14054f10b4d9dda0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"peek() -> Vector"},"remaining":{"doc_sha":"c193adc4bbfa3564","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"walk":{"doc_sha":"3fb64b239109d301","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"walk() -> Vector"}}},"Alignment":{"doc_sha":"77d93d03c8994f84","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Arc":{"doc_sha":"8323f4b7101509e9","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center":{"doc_sha":"abf1643dda106bf8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"color":{"doc_sha":"bdf932405b56c319","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"end_angle":{"doc_sha":"74f9704909a3a23d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"9df77e9a996208ba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"e32208817299dfe9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"0cc0684f26d8a660","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"f2ef657aaf8b6c68","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"6612fa35c43918e7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"radius":{"doc_sha":"f9c2310b775f1e5a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"start_angle":{"doc_sha":"6b91f175ebe5ecb4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"thickness":{"doc_sha":"f8eba89682554e6d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"67dd517aa153c158","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"AutoRuleSet":{"doc_sha":"49ab716632a44f06","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"apply":{"doc_sha":"701b6f038cfd6809","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply(discrete_map: DiscreteMap, tile_layer: TileLayer, seed: int = 0) -> None"},"grid_size":{"doc_sha":"570f4c81acb781d8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"group_count":{"doc_sha":"892fc283939b3e0c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"4f5ca90860649b64","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"resolve":{"doc_sha":"f8fff4e6e6488e3f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resolve(discrete_map: DiscreteMap, seed: int = 0) -> list[int]"},"rule_count":{"doc_sha":"9b9d5a7c1475dcfa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"terrain_enum":{"doc_sha":"eb365bf99bbcca37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"terrain_enum() -> IntEnum"},"value_count":{"doc_sha":"3467d158dd5af073","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"values":{"doc_sha":"b3199e059fd1ca2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"BSP":{"doc_sha":"7e971e0542cf4006","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"adjacency":{"doc_sha":"9373aa85408486ba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"bounds":{"doc_sha":"9c41e7403f2a0b2f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"clear":{"doc_sha":"2e4ffd3360ac858e","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear() -> BSP"},"find":{"doc_sha":"fccfac484a2b889c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"find(pos: tuple[int, int] | list | Vector) -> BSPNode | None"},"get_leaf":{"doc_sha":"d8ba680ec2ad4fd1","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_leaf(index: int) -> BSPNode"},"leaves":{"doc_sha":"439ec78ec02e6df8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"leaves() -> Iterator[BSPNode]"},"pos":{"doc_sha":"b8b27f4ad76e2870","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"root":{"doc_sha":"d1e3d9741dab383d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"size":{"doc_sha":"621f11f9a37dd89d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":"Dimensions (width, height). Read-only."},"split_once":{"doc_sha":"0d7c0c33156bc4e5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"split_once(horizontal: bool, position: int) -> BSP"},"split_recursive":{"doc_sha":"fa516b79833e5094","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"split_recursive(depth: int, min_size: tuple[int, int], max_ratio: float = 1.5, seed: int | None = None) -> BSP"},"to_heightmap":{"doc_sha":"a0f03cab7a0f2d1b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_heightmap(size: tuple[int, int] | None = None, select: str = 'leaves', shrink: int = 0, value: float = 1.0) -> HeightMap"},"traverse":{"doc_sha":"57da83e0f37686aa","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"traverse(order: Traversal = Traversal.LEVEL_ORDER) -> Iterator[BSPNode]"}}},"Behavior":{"doc_sha":"09206365e6c37ecc","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Billboard":{"doc_sha":"38614d1d19942bab","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"facing":{"doc_sha":"f82e2d7d8087804a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"dc5ed39915ab896c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"phi":{"doc_sha":"1450c89fb5b47929","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"0d5fec7fd4701ea6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"scale":{"doc_sha":"c9d55c4579681854","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_index":{"doc_sha":"170c20c841b586fc","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"texture":{"doc_sha":"b6d846566b6ccf93","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"theta":{"doc_sha":"c214ecbcb099228b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"adf8070be9a09eba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"CallableBinding":{"doc_sha":"711bf0f149ccae7a","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"callable":{"doc_sha":"96d3d31a6b7c56d9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_valid":{"doc_sha":"bc69c90e13475ae6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"value":{"doc_sha":"8f7d9eb4f520c017","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Caption":{"doc_sha":"8cd46324baa46a0d","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill_color":{"doc_sha":"af7ba90df95e4b79","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"font":{"doc_sha":"fbdafdb33921aa13","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"font_size":{"doc_sha":"7894149ec4efec6e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"79a7d48503e657d1","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"25b029c86a618fee","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"h":{"doc_sha":"ca1a98d700ff1888","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"90a2ab0ec07c00eb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"b3b8de4e294d71b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"outline":{"doc_sha":"6580b31092048bcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"outline_color":{"doc_sha":"388919803d270fd3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"44e4967e15212959","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"shader":{"doc_sha":"418952064319ffb5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"size":{"doc_sha":"85abb564299b703d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"text":{"doc_sha":"41628142b287defe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"uniforms":{"doc_sha":"b1f2699da618d002","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"w":{"doc_sha":"8472810bca891509","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"528487f8deaaf789","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"114ecec940477107","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"328d87ae44d9fb71","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Circle":{"doc_sha":"077981a1fbdfb6e3","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center":{"doc_sha":"d1e80ccd6bf706b9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill_color":{"doc_sha":"46be64336e296c50","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"20bebfa7432ed339","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"b43e33c2d49a3565","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"0cc0684f26d8a660","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"3a340282000297e0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"outline":{"doc_sha":"20e9fd42a7ba4bb8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"outline_color":{"doc_sha":"3fbed883fee308fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"5f9d88ff075d2cfc","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"radius":{"doc_sha":"00a41207192c55a8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"0cb3df5278d2658b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Color":{"doc_sha":"f1f664405900332f","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"a":{"doc_sha":"ef61630ad34f8e2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"b":{"doc_sha":"2e2e91e93833fdd0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_hex":{"doc_sha":"24d1ff553133bb7e","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"from_hex(hex_string: str) -> Color"},"g":{"doc_sha":"716ced374bcc2dc4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"lerp":{"doc_sha":"290e204f3538e406","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"lerp(other: Color, t: float) -> Color"},"r":{"doc_sha":"ef64cae6296f68cb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_hex":{"doc_sha":"d0cf65b284158877","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_hex() -> str"}}},"ColorLayer":{"doc_sha":"f8a87b6184c9a9b6","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"apply_gradient":{"doc_sha":"20390111f0652ae0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_gradient(source: HeightMap, range: tuple, color_low: Color, color_high: Color) -> ColorLayer"},"apply_perspective":{"doc_sha":"a909e1b1c0373bc0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_perspective(entity: Entity, visible: Color | None = None, discovered: Color | None = None, unknown: Color | None = None) -> None"},"apply_ranges":{"doc_sha":"37fc5a26fda9cc0c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_ranges(source: HeightMap, ranges: list) -> ColorLayer"},"apply_threshold":{"doc_sha":"59cc9b72322cc677","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_threshold(source: HeightMap, range: tuple, color: Color) -> ColorLayer"},"at":{"doc_sha":"fef47313dcef9247","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"at(pos: tuple | Vector) or (x: int, y: int) -> Color"},"clear_perspective":{"doc_sha":"fec237fe4cbda340","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear_perspective() -> None"},"draw_fov":{"doc_sha":"ff965b12c888d092","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"draw_fov(source: tuple, radius: int | None = None, fov: FOV | None = None, visible: Color | None = None, discovered: Color | None = None, unknown: Color | None = None) -> None"},"edit":{"doc_sha":"b0edb9c8f4c1fe76","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"edit() -> context manager"},"fill":{"doc_sha":"f6ff376fd71ae90b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill(color: Color) -> None"},"fill_rect":{"doc_sha":"bc8b20da214aa37d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_rect(pos: tuple, size: tuple, color: Color) -> None"},"grid":{"doc_sha":"b965c55d57de78fa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"eac88eb0f7b16cbf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"dd282cc9273e2e36","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"set":{"doc_sha":"36801cc04606ee0b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set(pos, color: Color) -> None"},"update_perspective":{"doc_sha":"c9caac507fbc4921","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"update_perspective() -> None"},"visible":{"doc_sha":"ecea81ec16e31c19","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"eb13c1b4de11ce63","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"DijkstraMap":{"doc_sha":"822ccf5b086d37ec","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"descent_step":{"doc_sha":"fd7b649f1f3eb586","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"descent_step(pos: Vector | tuple) -> Vector | None"},"distance":{"doc_sha":"92b40108bb47bf88","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"distance(pos: Vector | tuple) -> float | None"},"invert":{"doc_sha":"3e5ae145dafc2c1d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"invert() -> DijkstraMap"},"path_from":{"doc_sha":"3dcf638bff837f2d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"path_from(pos: Vector | tuple) -> AStarPath"},"root":{"doc_sha":"95824bac9c46ad83","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"step_from":{"doc_sha":"ac9bc93f671d3936","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"step_from(pos: Vector | tuple) -> Vector | None"},"to_heightmap":{"doc_sha":"0ba542e6509b510b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_heightmap(size=None, unreachable=-1.0) -> HeightMap"}}},"DiscreteMap":{"doc_sha":"4d6d00ffa3ac62a9","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"add":{"doc_sha":"1e5a5b83f555fa87","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add(other: DiscreteMap | int, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"bitwise_and":{"doc_sha":"1644af83b8699792","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"bitwise_and(other: DiscreteMap, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"bitwise_or":{"doc_sha":"c8262af2fdccdeeb","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"bitwise_or(other: DiscreteMap, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"bitwise_xor":{"doc_sha":"01809471595bf8e7","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"bitwise_xor(other: DiscreteMap, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"bool":{"doc_sha":"a999f0f09edf7bf3","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"bool(condition: int | set | callable) -> DiscreteMap"},"clear":{"doc_sha":"b04d176e9c7bf9d2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear() -> DiscreteMap"},"copy_from":{"doc_sha":"efea5a0aa9a8d9c9","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"copy_from(other: DiscreteMap, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"count":{"doc_sha":"5e3303ddc3a9e3ae","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"count(value: int) -> int"},"count_range":{"doc_sha":"ac4e0298919fd16e","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"count_range(min_val: int, max_val: int) -> int"},"enum_type":{"doc_sha":"f27f1ad46e2d5afe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill":{"doc_sha":"7f358bdcc5c2c9f0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill(value: int, *, pos=None, size=None) -> DiscreteMap"},"from_bytes":{"doc_sha":"b1c09c737d43ffa9","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"from_bytes(data: bytes, size: tuple[int, int], *, enum: type = None) -> DiscreteMap"},"from_heightmap":{"doc_sha":"0e89bb4262b19ea3","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"from_heightmap(hmap: HeightMap, mapping: list[tuple[tuple[float,float], int]], *, enum=None) -> DiscreteMap"},"get":{"doc_sha":"a1097b27b43d6a27","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get(x, y) or (pos) -> int | Enum"},"histogram":{"doc_sha":"b2d9df4f14aedd51","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"histogram() -> dict[int, int]"},"invert":{"doc_sha":"0f52aecfe57ff499","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"invert() -> DiscreteMap"},"mask":{"doc_sha":"0d9628616f4592f4","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"mask() -> memoryview"},"max":{"doc_sha":"144265dd0da983a8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"max(other: DiscreteMap, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"min":{"doc_sha":"ff90ceef60a45959","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"min(other: DiscreteMap, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"min_max":{"doc_sha":"22018caaf1bdb60e","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"min_max() -> tuple[int, int]"},"multiply":{"doc_sha":"430abcb2b647132f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"multiply(factor: float, *, pos=None, size=None) -> DiscreteMap"},"set":{"doc_sha":"8439c14e5785f7e4","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set(x: int, y: int, value: int) -> None"},"size":{"doc_sha":"fc6c37c9d3916c5d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":"Dimensions (width, height) of the map. Read-only."},"subtract":{"doc_sha":"aeae8042663b9973","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"subtract(other: DiscreteMap | int, *, pos=None, source_pos=None, size=None) -> DiscreteMap"},"to_bytes":{"doc_sha":"4d7c4b5939a546bd","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_bytes() -> bytes"},"to_heightmap":{"doc_sha":"b0744db8f889b5d9","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_heightmap(mapping: dict[int, float] = None) -> HeightMap"}}},"Drawable":{"doc_sha":"bb28a8d677f24b33","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"move":{"doc_sha":"4a8f9ca3692c6b58","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"on_click":{"doc_sha":"b3b8de4e294d71b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"resize":{"doc_sha":"980bdc9065fc077b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"328d87ae44d9fb71","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Easing":{"doc_sha":"e3b0c44298fc1c14","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Entity":{"doc_sha":"7231aaf2e3b107d0","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"add_label":{"doc_sha":"be06d30bbd5a41ca","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_label(label: str) -> None"},"animate":{"doc_sha":"a06820cecef57a9a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"at":{"doc_sha":"b5775513388a1464","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"at(x: int, y: int) -> GridPoint | None"},"behavior_type":{"doc_sha":"745936b7029480fd","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"cell_pos":{"doc_sha":"f8feaba9f3652ca0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"cell_x":{"doc_sha":"8bdc1199bfb15967","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"cell_y":{"doc_sha":"8fd78a55ede4b259","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"default_behavior":{"doc_sha":"f0a1ea99426408dd","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"die":{"doc_sha":"1369fecbc5a1862a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"die() -> None"},"draw_pos":{"doc_sha":"2769bf67eec13406","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"find_path":{"doc_sha":"1a672b91a00eb597","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"find_path(target, diagonal_cost: float = 1.41, collide: str = None) -> AStarPath | None"},"grid":{"doc_sha":"d02c7b8c3beb5662","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"d2e9f06a9d9f0a3c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_x":{"doc_sha":"4108b9ec31aff2c0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_y":{"doc_sha":"26f7190f34a208b2","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"has_label":{"doc_sha":"0e65dc586b3c8d18","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"has_label(label: str) -> bool"},"index":{"doc_sha":"74e24820bb380594","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"index() -> int"},"labels":{"doc_sha":"4e16ef3312d5b4e7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"move_speed":{"doc_sha":"a3b3867a6d3b830a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"708f75f696069d69","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"6caae59e941bebf1","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"path_to":{"doc_sha":"5b11e33c92caac2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"path_to(x: int, y: int) -> list"},"perspective_map":{"doc_sha":"f61894673d8c27a7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"172ff9a95e621eaf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"remove_label":{"doc_sha":"a4a541d7e9cf7275","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"remove_label(label: str) -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"set_behavior":{"doc_sha":"328826510c72f049","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set_behavior(type, waypoints=None, turns: int = 0, path=None, pathfinder=None) -> None"},"shader":{"doc_sha":"04503c544358f827","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sight_radius":{"doc_sha":"4a9ec6c3788b093a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_grid":{"doc_sha":"a5ff2c3e5190bc41","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_index":{"doc_sha":"ca285ed1c6f460df","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_offset":{"doc_sha":"a92dae4a2555fa7b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_offset_x":{"doc_sha":"7ba6504a9bbbf681","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_offset_y":{"doc_sha":"24d4546e182bb2c8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"step":{"doc_sha":"8877861183e50020","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"target_label":{"doc_sha":"85acb11a7e713a41","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"texture":{"doc_sha":"1588a0d4779fd069","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_height":{"doc_sha":"7f2ef7cb6d425730","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_size":{"doc_sha":"1a647ababfde2daa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_width":{"doc_sha":"5d72ddf874e9db54","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"turn_order":{"doc_sha":"eba665bc9c7e75ee","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"uniforms":{"doc_sha":"d302457c5aaa495e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"update_visibility":{"doc_sha":"d096cd998ed99b49","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"update_visibility() -> None"},"visible":{"doc_sha":"2bca3a265b44b270","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible_entities":{"doc_sha":"2482fbbecbfac7ea","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"visible_entities(fov=None, radius: int | None = None) -> list[Entity]"},"x":{"doc_sha":"4ba6a677ea35e7ba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"52b85f7dc8a7cb27","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Entity3D":{"doc_sha":"0daee46cf6343e9c","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"anim_clip":{"doc_sha":"f69294fc08fc1d6c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"anim_frame":{"doc_sha":"41bdd9b6f4407d16","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"anim_loop":{"doc_sha":"b267a372c1aef2cd","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"anim_paused":{"doc_sha":"e100f0be03f09b09","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"anim_speed":{"doc_sha":"33c581c9533b5169","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"anim_time":{"doc_sha":"6b811c83dd2a2184","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"fcf44af080ce16a7","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property, target, duration, easing=None, delta=False, callback=None, conflict_mode=None)"},"at":{"doc_sha":"69d6101c79794f90","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"at(x, z) -> dict"},"auto_animate":{"doc_sha":"867ca7a9c2b5a4ab","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"clear_path":{"doc_sha":"989bb0a431b58e17","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear_path()"},"color":{"doc_sha":"ea9ab21659b6e392","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"follow_path":{"doc_sha":"f514b7092f561550","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"follow_path(path)"},"grid_pos":{"doc_sha":"f20411521f420193","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"idle_clip":{"doc_sha":"855c97611053652c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_moving":{"doc_sha":"b31c1090228993e4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"model":{"doc_sha":"26ae36cf867d07e9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"acea3a6577d65fbc","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_anim_complete":{"doc_sha":"5cc47894576d983d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":"Callback(entity, clip_name) when non-looping animation ends."},"path_to":{"doc_sha":"d6fe3936cc8e2d84","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"path_to(x, z) or path_to(pos=(x, z)) -> list"},"pos":{"doc_sha":"2488492030e9df40","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"5b603e8c652baf50","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"scale":{"doc_sha":"b06782214d92e3f7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"teleport":{"doc_sha":"d53364830cdc737a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"teleport(x, z) or teleport(pos=(x, z))"},"update_visibility":{"doc_sha":"61886fb70daedf6b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"update_visibility()"},"viewport":{"doc_sha":"e9f9154f00b47f9a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"bc1ae0f4c6b5cb11","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"walk_clip":{"doc_sha":"c95d11b4e1901f28","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"world_pos":{"doc_sha":"bcc6673be9243dd5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"EntityCollection3D":{"doc_sha":"55864ac691527ca9","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"append":{"doc_sha":"43922f93aff7d723","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"append(entity)"},"clear":{"doc_sha":"f44ea077b10186d7","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear()"},"extend":{"doc_sha":"4fd2e7e83437c7ae","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"extend(iterable)"},"find":{"doc_sha":"e4182a3a3317aaae","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"find(name) -> Entity3D or None"},"pop":{"doc_sha":"cbcc90e2a433f277","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"pop(index=-1) -> Entity3D"},"remove":{"doc_sha":"b2f8fb276b91ec1e","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"remove(entity)"}}},"EntityCollection3DIter":{"doc_sha":"d71ec48b224bfacc","kind":"class","lifecycle":{"since":"0.2.8"},"members":{}},"FOV":{"doc_sha":"e3b0c44298fc1c14","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Font":{"doc_sha":"245b4e9b0ca66fc9","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"family":{"doc_sha":"0cf26d3038432764","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"source":{"doc_sha":"efc970576a584cde","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Frame":{"doc_sha":"4d53c3cb9e9e4611","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"cache_subtree":{"doc_sha":"0b8d1175192c1ce2","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"children":{"doc_sha":"b2cf42011b86727c","kind":"property","lifecycle":{"modified":{"commit":"4c0953c","version":"0.2.8-dev"},"since":"0.2.8"},"signature":""},"clip_children":{"doc_sha":"d12b2c4d1d2bb6cb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill_color":{"doc_sha":"8cfbe5aa6dd6da27","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"2f5b05882c4ad39f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"9c8707ad589e5d8a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"h":{"doc_sha":"ced8010da828cc93","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"90a2ab0ec07c00eb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"b3b8de4e294d71b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"outline":{"doc_sha":"c07b6dec9da5b9ea","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"outline_color":{"doc_sha":"cd98fcaf39f0bc56","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"55a118e7889fd555","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"shader":{"doc_sha":"418952064319ffb5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"uniforms":{"doc_sha":"b1f2699da618d002","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"w":{"doc_sha":"bd51299002a099c5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"4ed17c625f2289e3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"fabaa45fd789c7fd","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"328d87ae44d9fb71","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Grid":{"doc_sha":"f88e43e992d43a86","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"camera_rotation":{"doc_sha":"bc2cd502f52817e9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center":{"doc_sha":"913ef5c36eaf9635","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center_x":{"doc_sha":"fbb0ff08116f3c80","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center_y":{"doc_sha":"1bda27633025fb12","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill_color":{"doc_sha":"f26fb5da3de1789a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_data":{"doc_sha":"fdf0084b8456fd45","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"h":{"doc_sha":"bd5a06618a50efad","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered_cell":{"doc_sha":"85c87c8aa013d0c4","kind":"property","lifecycle":{"since":"0.2.8-dev"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"90a2ab0ec07c00eb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_cell_click":{"doc_sha":"ada11ea920c71f29","kind":"property","lifecycle":{"since":"0.2.8-dev"},"signature":""},"on_cell_enter":{"doc_sha":"6ae7882d4f14f183","kind":"property","lifecycle":{"since":"0.2.8-dev"},"signature":""},"on_cell_exit":{"doc_sha":"729303b3a70b2a36","kind":"property","lifecycle":{"since":"0.2.8-dev"},"signature":""},"on_click":{"doc_sha":"4e33bd16b2dee20a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"perspective":{"doc_sha":"8854eef3677c4423","kind":"property","lifecycle":{"since":"0.2.8-dev"},"signature":""},"perspective_enabled":{"doc_sha":"abd2223cd551e1ca","kind":"property","lifecycle":{"since":"0.2.8-dev"},"signature":""},"pos":{"doc_sha":"7f556820c51df2c4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"shader":{"doc_sha":"418952064319ffb5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"texture":{"doc_sha":"b9bfb54e5571bfc9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"uniforms":{"doc_sha":"b1f2699da618d002","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"w":{"doc_sha":"ec55a5a578c4d993","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"2449b0f04153753c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"7958c0625706f2d2","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"0cb3df5278d2658b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"zoom":{"doc_sha":"e56c4b61e0303f09","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"GridView":{"doc_sha":"f88e43e992d43a86","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"camera_rotation":{"doc_sha":"bc2cd502f52817e9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center":{"doc_sha":"913ef5c36eaf9635","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center_x":{"doc_sha":"fbb0ff08116f3c80","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"center_y":{"doc_sha":"1bda27633025fb12","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill_color":{"doc_sha":"f26fb5da3de1789a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_data":{"doc_sha":"fdf0084b8456fd45","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"h":{"doc_sha":"bd5a06618a50efad","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered_cell":{"doc_sha":"85c87c8aa013d0c4","kind":"property","lifecycle":{"since":"0.2.8-dev"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"90a2ab0ec07c00eb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_cell_click":{"doc_sha":"ada11ea920c71f29","kind":"property","lifecycle":{"since":"0.2.8-dev"},"signature":""},"on_cell_enter":{"doc_sha":"6ae7882d4f14f183","kind":"property","lifecycle":{"since":"0.2.8-dev"},"signature":""},"on_cell_exit":{"doc_sha":"729303b3a70b2a36","kind":"property","lifecycle":{"since":"0.2.8-dev"},"signature":""},"on_click":{"doc_sha":"4e33bd16b2dee20a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"perspective":{"doc_sha":"8854eef3677c4423","kind":"property","lifecycle":{"since":"0.2.8-dev"},"signature":""},"perspective_enabled":{"doc_sha":"abd2223cd551e1ca","kind":"property","lifecycle":{"since":"0.2.8-dev"},"signature":""},"pos":{"doc_sha":"7f556820c51df2c4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"shader":{"doc_sha":"418952064319ffb5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"texture":{"doc_sha":"b9bfb54e5571bfc9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"uniforms":{"doc_sha":"b1f2699da618d002","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"w":{"doc_sha":"ec55a5a578c4d993","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"2449b0f04153753c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"7958c0625706f2d2","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"0cb3df5278d2658b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"zoom":{"doc_sha":"e56c4b61e0303f09","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"HeightMap":{"doc_sha":"e5f86ba9c89f2a5a","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"add":{"doc_sha":"d420dd760d7228af","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add(other: HeightMap, *, pos=None, source_pos=None, size=None) -> HeightMap"},"add_bsp":{"doc_sha":"b70f06e432c91a7a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_bsp(bsp: BSP, *, pos=None, select: str = 'leaves', nodes: list = None, shrink: int = 0, value: float = 1.0) -> HeightMap"},"add_constant":{"doc_sha":"f382eb3f3e667cb4","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_constant(value: float, *, pos=None, size=None) -> HeightMap"},"add_hill":{"doc_sha":"1ad2406960701682","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_hill(center, radius: float, height: float) -> HeightMap"},"add_noise":{"doc_sha":"3c3c15026ff43959","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_noise(source: NoiseSource, world_origin: tuple = (0.0, 0.0), world_size: tuple = None, mode: str = 'fbm', octaves: int = 4, scale: float = 1.0) -> HeightMap"},"add_voronoi":{"doc_sha":"b689af51f6867b78","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_voronoi(num_points: int, coefficients: tuple = (1.0, -0.5), seed: int = None) -> HeightMap"},"clamp":{"doc_sha":"60c08680fb281402","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clamp(min: float = 0.0, max: float = 1.0, *, pos=None, size=None) -> HeightMap"},"clear":{"doc_sha":"2297d98f231b6b7b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear() -> HeightMap"},"copy_from":{"doc_sha":"80d64f3f6e76f8a7","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"copy_from(other: HeightMap, *, pos=None, source_pos=None, size=None) -> HeightMap"},"count_in_range":{"doc_sha":"7af3d60f28d614b6","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"count_in_range(range: tuple[float, float]) -> int"},"dig_bezier":{"doc_sha":"f3327d6ddc165496","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"dig_bezier(points: tuple, start_radius: float, end_radius: float, start_height: float, end_height: float) -> HeightMap"},"dig_hill":{"doc_sha":"be55e494c4e50c3a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"dig_hill(center, radius: float, target_height: float) -> HeightMap"},"fill":{"doc_sha":"4e998a0b1d85c4f2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill(value: float, *, pos=None, size=None) -> HeightMap"},"get":{"doc_sha":"f55fcc655d43dc50","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get(x, y) or (pos) -> float"},"get_interpolated":{"doc_sha":"5c3e0267d9cbeda2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_interpolated(x, y) or (pos) -> float"},"get_normal":{"doc_sha":"6d4212add4e533f2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_normal(x, y, water_level=0.0) or (pos, water_level=0.0) -> tuple[float, float, float]"},"get_slope":{"doc_sha":"4876967f738c7d67","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_slope(x, y) or (pos) -> float"},"inverse":{"doc_sha":"f6c4de6cd6a9ca0f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"inverse() -> HeightMap"},"lerp":{"doc_sha":"967cacc180df98bc","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"lerp(other: HeightMap, t: float, *, pos=None, source_pos=None, size=None) -> HeightMap"},"max":{"doc_sha":"141515f8b1f23390","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"max(other: HeightMap, *, pos=None, source_pos=None, size=None) -> HeightMap"},"mid_point_displacement":{"doc_sha":"bfcbfe796d73410f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"mid_point_displacement(roughness: float = 0.5, seed: int = None) -> HeightMap"},"min":{"doc_sha":"c51e934ea5047d91","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"min(other: HeightMap, *, pos=None, source_pos=None, size=None) -> HeightMap"},"min_max":{"doc_sha":"4e0b3cb7472a7cfe","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"min_max() -> tuple[float, float]"},"multiply":{"doc_sha":"83d2fcea22463d18","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"multiply(other: HeightMap, *, pos=None, source_pos=None, size=None) -> HeightMap"},"multiply_bsp":{"doc_sha":"21f401c651344592","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"multiply_bsp(bsp: BSP, *, pos=None, select: str = 'leaves', nodes: list = None, shrink: int = 0, value: float = 1.0) -> HeightMap"},"multiply_noise":{"doc_sha":"177d1d06a401af54","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"multiply_noise(source: NoiseSource, world_origin: tuple = (0.0, 0.0), world_size: tuple = None, mode: str = 'fbm', octaves: int = 4, scale: float = 1.0) -> HeightMap"},"normalize":{"doc_sha":"93ce05bf80d158ed","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"normalize(min: float = 0.0, max: float = 1.0, *, pos=None, size=None) -> HeightMap"},"rain_erosion":{"doc_sha":"4dbe6bd42d9f6e5b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"rain_erosion(drops: int, erosion: float = 0.1, sedimentation: float = 0.05, seed: int = None) -> HeightMap"},"scale":{"doc_sha":"c85d9324b84c43ff","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"scale(factor: float, *, pos=None, size=None) -> HeightMap"},"size":{"doc_sha":"31846e24f4028b35","kind":"property","lifecycle":{"since":"0.2.8"},"signature":"Dimensions (width, height) of the heightmap. Read-only."},"smooth":{"doc_sha":"243be30aa73da43b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"smooth(iterations: int = 1) -> HeightMap"},"sparse_kernel":{"doc_sha":"e3b28d2c3913ac74","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"sparse_kernel(weights: dict[tuple[int, int], float]) -> HeightMap"},"sparse_kernel_from":{"doc_sha":"ebeed84050ee0b2f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"sparse_kernel_from(source: HeightMap, weights: dict[tuple[int, int], float]) -> None"},"subtract":{"doc_sha":"8e209f74aaad794d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"subtract(other: HeightMap, *, pos=None, source_pos=None, size=None) -> HeightMap"},"threshold":{"doc_sha":"946f6a1fb850decb","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"threshold(range: tuple[float, float]) -> HeightMap"},"threshold_binary":{"doc_sha":"6ebe7bd7cbc112c2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"threshold_binary(range: tuple[float, float], value: float = 1.0) -> HeightMap"}}},"Heuristic":{"doc_sha":"7582db951ab67fc5","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"InputState":{"doc_sha":"c7b7558edda29fea","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Key":{"doc_sha":"bc4feb60367e4be7","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Keyboard":{"doc_sha":"afbde6bcf7bfe1c6","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"alt":{"doc_sha":"051cb7dbc470d328","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"ctrl":{"doc_sha":"c062912b0b816bd2","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"shift":{"doc_sha":"614beb0d432c2ec0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"system":{"doc_sha":"2292efb47472f5e7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"LdtkProject":{"doc_sha":"d80a5fdda811cb33","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"enums":{"doc_sha":"5697f9e75980e2be","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"level":{"doc_sha":"33b80035be788d03","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"level(name: str) -> dict"},"level_names":{"doc_sha":"9479f6c2bd85608d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"ruleset":{"doc_sha":"ce72d154e5dd391c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"ruleset(name: str) -> AutoRuleSet"},"ruleset_names":{"doc_sha":"28983e9702e0dc81","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tileset":{"doc_sha":"30eabe3003acb244","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"tileset(name: str) -> TileSetFile"},"tileset_names":{"doc_sha":"77a45b51f49743ef","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"version":{"doc_sha":"e6d3d49ad9edfad8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Line":{"doc_sha":"8d778faa93b5d0d5","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"color":{"doc_sha":"f7aca0b82eaae97e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"end":{"doc_sha":"cc14ff1baa1b61fa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"9df77e9a996208ba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"e32208817299dfe9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"feeb7cb507a4692d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"49cecfb458b010a1","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"733a48ea3a730e60","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"start":{"doc_sha":"817049419558ea17","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"thickness":{"doc_sha":"b6c7f3e979028709","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"cecb3704206d35f7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Model3D":{"doc_sha":"be7fb5003ed48d84","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"animation_clips":{"doc_sha":"0d15ad9839919fe5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"bone_count":{"doc_sha":"6e389fb2496946bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"bounds":{"doc_sha":"4ddfb8f6ae5a8928","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"cube":{"doc_sha":"b49160efa8b0f71e","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"cube(size=1.0) -> Model3D"},"has_skeleton":{"doc_sha":"4e9ac073dac101b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"mesh_count":{"doc_sha":"49f8fe0ece668d77","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"b577d22f9a18de0c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"plane":{"doc_sha":"5e31b94e295b4429","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"plane(width=1.0, depth=1.0, segments=1) -> Model3D"},"sphere":{"doc_sha":"b385d8aaf0efd485","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"sphere(radius=0.5, segments=16, rings=12) -> Model3D"},"triangle_count":{"doc_sha":"b67c98fac8ffc8dd","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vertex_count":{"doc_sha":"8b76e70b26a820df","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Mouse":{"doc_sha":"e64f561c8a08bdec","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"grabbed":{"doc_sha":"3da420bb9cac434f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"left":{"doc_sha":"a4c7b98babc093cb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"middle":{"doc_sha":"1306b1240c6f64e3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"2ecba0a68d64976a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"right":{"doc_sha":"08d5534c1c034b39","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"834527eb5579f3e3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"c142f98ee94bf3f7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"5095db9e9e163e92","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"MouseButton":{"doc_sha":"a5a7584949d18f01","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Music":{"doc_sha":"e13e6ad378ec0e91","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"duration":{"doc_sha":"25607c5fa852d501","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"loop":{"doc_sha":"a165a91f8ff771f5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pause":{"doc_sha":"4eb6d242151147dc","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"pause() -> None"},"play":{"doc_sha":"f724039e0cdb2847","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"play() -> None"},"playing":{"doc_sha":"4451d007747fa3b1","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"position":{"doc_sha":"608a5f6d4ed927bc","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"source":{"doc_sha":"ee5d7818bae0a255","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"stop":{"doc_sha":"f3289bbb98a4da1f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"stop() -> None"},"volume":{"doc_sha":"749fc9d89252cb0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"NoiseSource":{"doc_sha":"3bfa3b53984c85cb","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"algorithm":{"doc_sha":"ba813d6c022f15f0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"dimensions":{"doc_sha":"f534d20928d8d67a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fbm":{"doc_sha":"d13c8670fc68b9df","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fbm(pos: tuple[float, ...], octaves: int = 4) -> float"},"get":{"doc_sha":"3d7776fffd7a0a39","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get(pos: tuple[float, ...]) -> float"},"hurst":{"doc_sha":"11682e6dc42f2417","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"lacunarity":{"doc_sha":"4d07f7079f3938de","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sample":{"doc_sha":"63fd0e680000d0f0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"sample(size: tuple[int, int], world_origin: tuple[float, float] = (0.0, 0.0), world_size: tuple[float, float] = None, mode: str = 'fbm', octaves: int = 4) -> HeightMap"},"seed":{"doc_sha":"17bc1e90a8ce6b23","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"turbulence":{"doc_sha":"800c841f913b3780","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"turbulence(pos: tuple[float, ...], octaves: int = 4) -> float"}}},"Perspective":{"doc_sha":"e1c8553ea2a32a40","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"PropertyBinding":{"doc_sha":"a23eb43edd46bb66","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"is_valid":{"doc_sha":"40ada14485c362a7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"property":{"doc_sha":"0dad06f4e661db2d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"target":{"doc_sha":"3b15e1922fd910c9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"value":{"doc_sha":"80d28b4e329837d8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Scene":{"doc_sha":"a156c42d77b20a3e","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"activate":{"doc_sha":"54ae3cd3cf652660","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"activate(transition: Transition = None, duration: float = None) -> None"},"active":{"doc_sha":"a59f70d3c12a7cfe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"children":{"doc_sha":"f21fb480dac856b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"7feed093cdf9334a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_key":{"doc_sha":"40ece618402a45f3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"9e60a4ae9bdb493b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"50e29b0dd34a76d5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"eef1e2dce9ee8894","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"register":{"doc_sha":"7603337801a7a498","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"register() -> None"},"registered":{"doc_sha":"d9ff54f488ed5b87","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"unregister":{"doc_sha":"fda6be9891d1f502","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"unregister() -> None"},"visible":{"doc_sha":"a7f321f4013dfb9b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Shader":{"doc_sha":"aded56cb37cba9d8","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"dynamic":{"doc_sha":"43d8bc587c3997e3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_valid":{"doc_sha":"fcdf95eedfa8479e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"set_uniform":{"doc_sha":"bdaf877e5bc28f21","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set_uniform(name: str, value: float|tuple) -> None"},"source":{"doc_sha":"dbd462698aadf450","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Sound":{"doc_sha":"8f31cca1781580d5","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"buffer":{"doc_sha":"c79f4e433d4300ac","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"duration":{"doc_sha":"48daac900b6eaf36","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"loop":{"doc_sha":"a624dff0e72a5337","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pause":{"doc_sha":"005627aca21692d3","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"pause() -> None"},"pitch":{"doc_sha":"80b38bfc202b4291","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"play":{"doc_sha":"ae090ee8c0320797","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"play() -> None"},"play_varied":{"doc_sha":"fd9b5cd6db3cb1cf","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"play_varied(pitch_range: float = 0.1, volume_range: float = 3.0) -> None"},"playing":{"doc_sha":"8a0c491fa38061d5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"source":{"doc_sha":"1736ca7393d96c48","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"stop":{"doc_sha":"f3289bbb98a4da1f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"stop() -> None"},"volume":{"doc_sha":"749fc9d89252cb0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"SoundBuffer":{"doc_sha":"426618cde68541be","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"bit_crush":{"doc_sha":"66ae55272fd9d182","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"bit_crush(bits: int, rate_divisor: int) -> SoundBuffer"},"channels":{"doc_sha":"f3948c1ceb5d7aec","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"concat":{"doc_sha":"7ee10bfe76aae5e2","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"concat(buffers: list[SoundBuffer], overlap: float = 0.0) -> SoundBuffer"},"distortion":{"doc_sha":"a36442ca725e5cc6","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"distortion(drive: float) -> SoundBuffer"},"duration":{"doc_sha":"bc1c03f781e0372b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"echo":{"doc_sha":"1b93f79c671068ab","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"echo(delay_ms: float, feedback: float, wet: float) -> SoundBuffer"},"from_samples":{"doc_sha":"556326f1f2cda4a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"from_samples(data: bytes, channels: int, sample_rate: int) -> SoundBuffer"},"gain":{"doc_sha":"22fc3aad26b084a5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"gain(factor: float) -> SoundBuffer"},"high_pass":{"doc_sha":"7d8af12720a4bbae","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"high_pass(cutoff_hz: float) -> SoundBuffer"},"low_pass":{"doc_sha":"82cdc215e7da9310","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"low_pass(cutoff_hz: float) -> SoundBuffer"},"mix":{"doc_sha":"4df14cf741427da9","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"mix(buffers: list[SoundBuffer]) -> SoundBuffer"},"normalize":{"doc_sha":"5476b16208b1ac7b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"normalize() -> SoundBuffer"},"pitch_shift":{"doc_sha":"ee9373f2d71fdaa8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"pitch_shift(factor: float) -> SoundBuffer"},"reverb":{"doc_sha":"b6d0dcf1e5f75a42","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"reverb(room_size: float, damping: float, wet: float) -> SoundBuffer"},"reverse":{"doc_sha":"eb70bfa5da4c860d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"reverse() -> SoundBuffer"},"sample_count":{"doc_sha":"5e96b7263eade6af","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sample_rate":{"doc_sha":"a41417a71e10a2d6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sfxr":{"doc_sha":"5f45a4b7afc74066","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"sfxr(preset: str = None, seed: int = None, **params) -> SoundBuffer"},"sfxr_mutate":{"doc_sha":"68b5b653de4f55dc","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"sfxr_mutate(amount: float = 0.05, seed: int = None) -> SoundBuffer"},"sfxr_params":{"doc_sha":"7fd7a2356600014a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"slice":{"doc_sha":"84099d0f46e6b7ad","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"slice(start: float, end: float) -> SoundBuffer"},"tone":{"doc_sha":"eaec1748a9089774","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"tone(frequency: float, duration: float, waveform: str = 'sine', ...) -> SoundBuffer"}}},"Sprite":{"doc_sha":"a687c4f393725428","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"align":{"doc_sha":"58657c3cfa010f31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_pos":{"doc_sha":"9df77e9a996208ba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"e32208817299dfe9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"horiz_margin":{"doc_sha":"0ef227a4cae6e675","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"ab774a7da8cfe9bf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"name":{"doc_sha":"90a2ab0ec07c00eb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_click":{"doc_sha":"b3b8de4e294d71b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"270bdf366c74bb1d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pos":{"doc_sha":"55a118e7889fd555","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"rotate_with_camera":{"doc_sha":"cf6919d67b9e275f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"rotation":{"doc_sha":"61ba3e66a0841a08","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"scale":{"doc_sha":"f91a66d322ee1a75","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"scale_x":{"doc_sha":"95f47a809a8ac927","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"scale_y":{"doc_sha":"8567691c22a9b5f8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"shader":{"doc_sha":"418952064319ffb5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_index":{"doc_sha":"826af9fc52ae5cef","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"texture":{"doc_sha":"df3e7671926aa0a3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"uniforms":{"doc_sha":"b1f2699da618d002","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vert_margin":{"doc_sha":"e2042be923bc6fcb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"528487f8deaaf789","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"114ecec940477107","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"328d87ae44d9fb71","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Texture":{"doc_sha":"da368b536d9f844e","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"composite":{"doc_sha":"0bf406582f618af3","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"composite(layers: list[Texture], sprite_width: int, sprite_height: int, name: str = '') -> Texture"},"display_height":{"doc_sha":"0dc1ccea45ff4e40","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"display_offset_x":{"doc_sha":"0ca738fa6559aabb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"display_offset_y":{"doc_sha":"83b5bfadd26f4e79","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"display_width":{"doc_sha":"cfc6525a8a0b5bb7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"979f5a384770d87f","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"from_bytes(data: bytes, width: int, height: int, sprite_width: int, sprite_height: int, name: str = '') -> Texture"},"hsl_shift":{"doc_sha":"95f19de7a67646e3","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"hsl_shift(hue_shift: float, sat_shift: float = 0.0, lit_shift: float = 0.0) -> Texture"},"sheet_height":{"doc_sha":"59d4fb71cae72fba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sheet_width":{"doc_sha":"54ef54eb9c39a907","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"source":{"doc_sha":"51bee1cdb17257ba","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_count":{"doc_sha":"d1ed79d8b59eca99","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_height":{"doc_sha":"19b6a36f45f965e8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"sprite_width":{"doc_sha":"6f9276522c3b2512","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"TileLayer":{"doc_sha":"5551e3bf9e668d89","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"apply_ranges":{"doc_sha":"e443e268532fdd2f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_ranges(source: HeightMap, ranges: list) -> TileLayer"},"apply_threshold":{"doc_sha":"2253f4367656d073","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_threshold(source: HeightMap, range: tuple, tile: int) -> TileLayer"},"at":{"doc_sha":"19975fea19b3fadb","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"at(pos: tuple | Vector) or (x: int, y: int) -> int"},"edit":{"doc_sha":"47c32fda0e88780a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"edit() -> context manager"},"fill":{"doc_sha":"5c8eca820794a605","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill(index: int) -> None"},"fill_rect":{"doc_sha":"adfc5ff6d6e91cc8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_rect(pos: tuple, size: tuple, index: int) -> None"},"grid":{"doc_sha":"b965c55d57de78fa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"eac88eb0f7b16cbf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"dd282cc9273e2e36","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"set":{"doc_sha":"2b242556ce84080f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set(pos, index: int) -> None"},"texture":{"doc_sha":"1d211a219f88c72c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"ecea81ec16e31c19","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"eb13c1b4de11ce63","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"TileMapFile":{"doc_sha":"b26cb3870e41a2c9","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"apply_to_tile_layer":{"doc_sha":"436e4fa972bd79d0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_to_tile_layer(tile_layer: TileLayer, layer_name: str, tileset_index: int = 0) -> None"},"height":{"doc_sha":"72aa81aefdab3ddb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"object_layer":{"doc_sha":"e658613bcbbe9b3a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"object_layer(name: str) -> list[dict]"},"object_layer_names":{"doc_sha":"7af1cc1454cd97f9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"orientation":{"doc_sha":"2ee759a156b5c903","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"properties":{"doc_sha":"f2cb52eb132891d8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"resolve_gid":{"doc_sha":"4a72f1c9f61cec27","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resolve_gid(gid: int) -> tuple[int, int]"},"tile_height":{"doc_sha":"cc47760c48b8c9be","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_layer_data":{"doc_sha":"399fd655e6402442","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"tile_layer_data(name: str) -> list[int]"},"tile_layer_names":{"doc_sha":"e225e2d4b71155e7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_width":{"doc_sha":"c109808c1e2d3ca1","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tileset":{"doc_sha":"a3e35f368c3cc89d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"tileset(index: int) -> tuple[int, TileSetFile]"},"tileset_count":{"doc_sha":"e7347387a4bcfeae","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"width":{"doc_sha":"acef1b7138a85569","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"TileSetFile":{"doc_sha":"ec83598f02a06258","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"columns":{"doc_sha":"5ba187696ce9596e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"image_source":{"doc_sha":"f21faacc0392eec3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"margin":{"doc_sha":"6e1b3cfd5b59af6a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"5e0a76b40f4db151","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"properties":{"doc_sha":"e0382abd62d297a6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"spacing":{"doc_sha":"950416fc0b8f1837","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_count":{"doc_sha":"df5ccd0141400827","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_height":{"doc_sha":"71a327fd061c1cf2","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"tile_info":{"doc_sha":"b33077f44c79e050","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"tile_info(tile_id: int) -> dict | None"},"tile_width":{"doc_sha":"888787b1ef69f5d9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_texture":{"doc_sha":"610adac758051370","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_texture() -> Texture"},"wang_set":{"doc_sha":"c3b15db4611c250a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"wang_set(name: str) -> WangSet"},"wang_sets":{"doc_sha":"71541a1c5777b29f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Timer":{"doc_sha":"646feff7bdb817f5","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"active":{"doc_sha":"0ac0f4a607819264","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"callback":{"doc_sha":"a943e7e99b75fa22","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"interval":{"doc_sha":"e32658ee97f94823","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"98a62482b59640f6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"once":{"doc_sha":"7d5a7d20bae3793e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"pause":{"doc_sha":"bfe544cc3c9f1cda","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"pause() -> None"},"paused":{"doc_sha":"060df10cbfc34662","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"remaining":{"doc_sha":"e223a64ed6a1ec63","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"restart":{"doc_sha":"a8c305ae5017cce0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"restart() -> None"},"resume":{"doc_sha":"66ab0cd39f579ef9","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resume() -> None"},"start":{"doc_sha":"0b2b51d812995d34","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"start() -> None"},"stop":{"doc_sha":"9f69f5e68512116c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"stop() -> None"},"stopped":{"doc_sha":"bffdb8aa4589c28b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Transition":{"doc_sha":"e3b0c44298fc1c14","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Traversal":{"doc_sha":"e3b0c44298fc1c14","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Trigger":{"doc_sha":"3f698ad8b187be9f","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"($type, /, bytes, byteorder='big', *, signed=False)"},"imag":{"doc_sha":"ef78ea410df39b26","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_integer":{"doc_sha":"6176763fbac2fd22","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"numerator":{"doc_sha":"ed255748ce2eda7c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"real":{"doc_sha":"d44497f1990af6fe","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"to_bytes":{"doc_sha":"b452319e48e64764","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /, length=1, byteorder='big', *, signed=False)"}}},"Vector":{"doc_sha":"0c8ae9e2ef387065","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"angle":{"doc_sha":"a0ca5f1f4a89d780","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"angle() -> float"},"copy":{"doc_sha":"120e723fd513e072","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"copy() -> Vector"},"distance_to":{"doc_sha":"4f5d26bbe8434f65","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"distance_to(other: Vector) -> float"},"dot":{"doc_sha":"d69442ea289adfb8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"dot(other: Vector) -> float"},"floor":{"doc_sha":"c7e81a90c5420968","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"floor() -> Vector"},"int":{"doc_sha":"3d97cae0ad8a963c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"magnitude":{"doc_sha":"75f61a474afe3121","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"magnitude() -> float"},"magnitude_squared":{"doc_sha":"c976db5b540f827b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"magnitude_squared() -> float"},"normalize":{"doc_sha":"04b468da3fc60858","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"normalize() -> Vector"},"x":{"doc_sha":"0e322bdd857e652b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"bbac84f15b6740d9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Viewport3D":{"doc_sha":"c41e58effff86261","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"add_billboard":{"doc_sha":"ae2357f78a17a437","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_billboard(billboard)"},"add_layer":{"doc_sha":"b4c0274f9217aaa1","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_layer(name, z_index=0) -> dict"},"add_mesh":{"doc_sha":"588dbdf9a48f17e5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_mesh(layer_name, model, pos, rotation=0, scale=1.0) -> int"},"add_voxel_layer":{"doc_sha":"47f17324425647e1","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_voxel_layer(voxel_grid, z_index=0)"},"animate":{"doc_sha":"400df4f5893261c5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"animate(property: str, target: Any, duration: float, easing=None, delta=False, loop=False, callback=None, conflict_mode='replace') -> Animation"},"apply_heightmap":{"doc_sha":"be8e92a25726238d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_heightmap(heightmap, y_scale=1.0)"},"apply_terrain_colors":{"doc_sha":"cf0e47c185484e70","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_terrain_colors(layer_name, r_map, g_map, b_map)"},"apply_threshold":{"doc_sha":"3adda69e435613d7","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply_threshold(heightmap, min_height, max_height, walkable=True)"},"at":{"doc_sha":"7ec76d7602627cb9","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"at(x, z) -> VoxelPoint"},"bg_color":{"doc_sha":"c7e7141bd1cadaea","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"billboard_count":{"doc_sha":"4b432c5c560ee44f","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"billboard_count() -> int"},"bounds":{"doc_sha":"d3186ac3b3ff8bed","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"build_terrain":{"doc_sha":"5be2a61f78907326","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"build_terrain(layer_name, heightmap, y_scale=1.0, cell_size=1.0) -> int"},"camera_pos":{"doc_sha":"7bfead8afc2b8312","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"camera_target":{"doc_sha":"3ecf7bb4dbdf27e4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"cell_size":{"doc_sha":"8c3fa657c8fdc2aa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"clear_billboards":{"doc_sha":"63d6d64c39b46264","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear_billboards()"},"clear_meshes":{"doc_sha":"1d6eb71f274020cf","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear_meshes(layer_name)"},"clear_voxel_nav_region":{"doc_sha":"56901862e4dc595a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear_voxel_nav_region(voxel_grid)"},"compute_fov":{"doc_sha":"93c68ed57619564e","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"compute_fov(origin, radius=10) -> list"},"enable_affine":{"doc_sha":"96ba76ed43593940","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"enable_dither":{"doc_sha":"da6733dd08751b72","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"enable_fog":{"doc_sha":"ca6c5ffcef454868","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"enable_vertex_snap":{"doc_sha":"7401ad5dcd82024c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"entities":{"doc_sha":"c2b185a3b718cc6b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"find_path":{"doc_sha":"ebd174d40557cc19","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"find_path(start, end) -> list"},"fog_color":{"doc_sha":"3eb0cdbd75c5a94c","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fog_far":{"doc_sha":"90406f8cae40bb58","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fog_near":{"doc_sha":"e49f6dc79b22a794","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"follow":{"doc_sha":"975d2b945069be26","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"follow(entity, distance=10, height=5, smoothing=1.0)"},"fov":{"doc_sha":"7f5d69a1c423f69d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"get_billboard":{"doc_sha":"38b0410480ab7d4d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_billboard(index) -> Billboard"},"get_layer":{"doc_sha":"92223f274b5312c3","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_layer(name) -> dict or None"},"global_bounds":{"doc_sha":"aa4de9a20df55c2b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"global_position":{"doc_sha":"b8dabbecc9fccd2a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"grid_size":{"doc_sha":"7b4dbfa47f259f02","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"h":{"doc_sha":"d7308cd01fffb4be","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"hovered":{"doc_sha":"af0d353ce08f7be0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"is_in_fov":{"doc_sha":"81d50fbbe2df4c8e","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"is_in_fov(x, z) -> bool"},"layer_count":{"doc_sha":"8bfbb28860b18d51","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"layer_count() -> int"},"move":{"doc_sha":"5c74f429970a2d2b","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"move(dx, dy) or (delta) -> None"},"on_click":{"doc_sha":"b3b8de4e294d71b6","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_enter":{"doc_sha":"48c996802e262396","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_exit":{"doc_sha":"c14ef0d6d6d40b0e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"on_move":{"doc_sha":"9c3e26818b5b25b0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"opacity":{"doc_sha":"c1a7ef41e074519e","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"orbit_camera":{"doc_sha":"29e02de46a996495","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"orbit_camera(angle=0, distance=10, height=5)"},"parent":{"doc_sha":"171b0de4e295c55b","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"place_blocking":{"doc_sha":"9252fd1d594a3867","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"place_blocking(grid_pos, footprint, walkable=False, transparent=False)"},"pos":{"doc_sha":"c1693d7dd0fe875d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"project_all_voxels_to_nav":{"doc_sha":"ac9e0ca27b557d65","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"project_all_voxels_to_nav(headroom=2)"},"project_voxel_to_nav":{"doc_sha":"1fdf58bc686f7511","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"project_voxel_to_nav(voxel_grid, headroom=2)"},"realign":{"doc_sha":"8dfa7333a49aa697","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"realign() -> None"},"remove_billboard":{"doc_sha":"bf68668896f86bb0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"remove_billboard(billboard)"},"remove_layer":{"doc_sha":"f5fafdfe3d153aab","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"remove_layer(name) -> bool"},"remove_voxel_layer":{"doc_sha":"b88a956cacc361cb","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"remove_voxel_layer(voxel_grid) -> bool"},"render_resolution":{"doc_sha":"4b141c5648005f04","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"resize":{"doc_sha":"005a04f1d129ebe5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resize(width, height) or (size) -> None"},"screen_to_world":{"doc_sha":"ba31510737afd516","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"screen_to_world(x, y, y_plane=0.0) -> tuple or None"},"set_grid_size":{"doc_sha":"ee7d1626547614c8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set_grid_size(width, depth)"},"set_slope_cost":{"doc_sha":"dac6d3cd319f1016","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set_slope_cost(max_slope=0.5, cost_multiplier=1.0)"},"visible":{"doc_sha":"49221a4ae830f3b8","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"voxel_layer_count":{"doc_sha":"c1ca5c90881bbaae","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"voxel_layer_count() -> int"},"w":{"doc_sha":"4c5bcc34301022a0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"x":{"doc_sha":"cd81d9dc457285aa","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"y":{"doc_sha":"406570900a1cf520","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"z_index":{"doc_sha":"328d87ae44d9fb71","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"VoxelGrid":{"doc_sha":"6706e3f5276ce104","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"add_material":{"doc_sha":"27dec1c992cf7b99","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"add_material(name, color=Color(255,255,255), sprite_index=-1, transparent=False, path_cost=1.0) -> int"},"cell_size":{"doc_sha":"81b167d608b2cec5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"clear":{"doc_sha":"8ebe20948a33a84d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"clear() -> None"},"copy_region":{"doc_sha":"e56c5d28d7fd4e86","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"copy_region(min_coord, max_coord) -> VoxelRegion"},"count_material":{"doc_sha":"c9ef38e1f2f29ab8","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"count_material(material) -> int"},"count_non_air":{"doc_sha":"275d512b30f5134a","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"count_non_air() -> int"},"depth":{"doc_sha":"21671acfc312aeeb","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fill":{"doc_sha":"fff2fcdddba5ee8c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill(material) -> None"},"fill_box":{"doc_sha":"7c3d982a275f095d","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_box(min_coord, max_coord, material) -> None"},"fill_box_hollow":{"doc_sha":"432e8b518feee0a5","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_box_hollow(min_coord, max_coord, material, thickness=1) -> None"},"fill_cylinder":{"doc_sha":"0b2b0b0826381df0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_cylinder(base_pos, radius, height, material) -> None"},"fill_noise":{"doc_sha":"567355400611d920","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_noise(min_coord, max_coord, material, threshold=0.5, scale=0.1, seed=0) -> None"},"fill_sphere":{"doc_sha":"e6a85d9c72e2ea44","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"fill_sphere(center, radius, material) -> None"},"from_bytes":{"doc_sha":"faefede0aa8ae636","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"from_bytes(data) -> bool"},"get":{"doc_sha":"52cea4645f0ea3d0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get(x, y, z) -> int"},"get_material":{"doc_sha":"2a61f6d54086df97","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"get_material(id) -> dict"},"greedy_meshing":{"doc_sha":"17fffa950c043917","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"height":{"doc_sha":"f271e989afe69da3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"load":{"doc_sha":"5dcaf71057f836a2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"load(path) -> bool"},"material_count":{"doc_sha":"0ef72bd68ef0c2d0","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"offset":{"doc_sha":"75230579ca06d8f5","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"paste_region":{"doc_sha":"1f44bacefd614cca","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"paste_region(region, position, skip_air=True) -> None"},"project_column":{"doc_sha":"9bacd59e3a7c5758","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"project_column(x, z, headroom=2) -> dict"},"rebuild_mesh":{"doc_sha":"fa60051037c3328c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"rebuild_mesh() -> None"},"rotation":{"doc_sha":"5b603e8c652baf50","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"save":{"doc_sha":"bb7090694292f8e3","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"save(path) -> bool"},"set":{"doc_sha":"e9223501162aa9c6","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"set(x, y, z, material) -> None"},"size":{"doc_sha":"2d283d0584913b16","kind":"property","lifecycle":{"since":"0.2.8"},"signature":"Dimensions (width, height, depth) of the grid. Read-only."},"to_bytes":{"doc_sha":"f9a751e75bfc0478","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"to_bytes() -> bytes"},"vertex_count":{"doc_sha":"4df863704c32ecb7","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"7ff1afdbd4bf86a3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"width":{"doc_sha":"0977aff160584918","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"VoxelRegion":{"doc_sha":"0cda0630ba7cafef","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"depth":{"doc_sha":"05b3223f7df8ab65","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"height":{"doc_sha":"04834a15ca591472","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"size":{"doc_sha":"75c252385afbc498","kind":"property","lifecycle":{"since":"0.2.8"},"signature":"Dimensions (width, height, depth) of the region. Read-only."},"width":{"doc_sha":"d10d49e58037417d","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"WangSet":{"doc_sha":"320e161ef3d08a5d","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"apply":{"doc_sha":"2aa8c0ba2d6549d2","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"apply(discrete_map: DiscreteMap, tile_layer: TileLayer) -> None"},"color_count":{"doc_sha":"13b244a538aec70f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"colors":{"doc_sha":"6d84b3c2dd048b1a","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"name":{"doc_sha":"8b4560b705e5724f","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"resolve":{"doc_sha":"fe2fa09430c4bda6","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"resolve(discrete_map: DiscreteMap) -> list[int]"},"terrain_enum":{"doc_sha":"b8c46ec1a2b03eb6","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"terrain_enum() -> IntEnum"},"type":{"doc_sha":"ea3706e2c65ba7d3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}},"Window":{"doc_sha":"6021e9b58544c378","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"center":{"doc_sha":"91fe1b0d6ca2e4f1","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"center() -> None"},"framerate_limit":{"doc_sha":"de182ed271fbb4d3","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"fullscreen":{"doc_sha":"a517f5331026f2c4","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"game_resolution":{"doc_sha":"3a0dba59fecf5a95","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"get":{"doc_sha":"544bdc10ab93d067","kind":"classmethod","lifecycle":{"since":"0.2.8"},"signature":"get() -> Window"},"resolution":{"doc_sha":"548abee10c4fbcaf","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"scaling_mode":{"doc_sha":"57e03f9ffc9291ae","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"screenshot":{"doc_sha":"5102ab9c4c2c8358","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"screenshot(filename: str = None) -> bytes | None"},"title":{"doc_sha":"0d98279e5ec1b8b1","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"visible":{"doc_sha":"bad7f81ec2e48a31","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"vsync":{"doc_sha":"0335eb1fba386e37","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""}}}},"schema":1,"seeded":false,"version":"0.2.8-dev"} diff --git a/src/GridData.cpp b/src/GridData.cpp index 4f91215..48077b2 100644 --- a/src/GridData.cpp +++ b/src/GridData.cpp @@ -3,7 +3,7 @@ #include "UIEntity.h" #include "PyTexture.h" #include "UIGrid.h" // #313 - markDirty forwards to the UIGrid subobject -#include "UIGridView.h" // #313 - and notifies owning_view +#include "UIGridView.h" // #313/#359 - and notifies registered views #include // #313 - Render invalidation from the data layer (see GridData.h). @@ -12,19 +12,46 @@ void GridData::markDirty() { content_generation++; // #351 - content changed; invalidate view early-out static_cast(this)->UIDrawable::markDirty(); - if (auto view = owning_view.lock()) { - view->markDirty(); + for (auto& weak_view : views) { + if (auto view = weak_view.lock()) view->markDirty(); } } void GridData::markCompositeDirty() { content_generation++; // #351 - content changed; invalidate view early-out static_cast(this)->UIDrawable::markCompositeDirty(); - if (auto view = owning_view.lock()) { - view->markCompositeDirty(); + for (auto& weak_view : views) { + if (auto view = weak_view.lock()) view->markCompositeDirty(); } } +// #359 - View registry (see GridData.h). Kept small (typically 1-2 entries: +// split-screen / minimap use cases), so linear scan is fine. +void GridData::registerView(const std::shared_ptr& view) { + if (!view) return; + for (auto& weak_view : views) { + if (weak_view.lock() == view) return; // already registered + } + views.push_back(view); +} + +void GridData::unregisterView(UIGridView* view) { + views.erase( + std::remove_if(views.begin(), views.end(), + [view](const std::weak_ptr& weak_view) { + auto locked = weak_view.lock(); + return !locked || locked.get() == view; // prune expired too + }), + views.end()); +} + +std::shared_ptr GridData::primaryView() const { + for (auto& weak_view : views) { + if (auto view = weak_view.lock()) return view; + } + return nullptr; +} + GridData::GridData() { entities = std::make_shared>>(); // #329 diff --git a/src/GridData.h b/src/GridData.h index c56fd68..dc8ffc9 100644 --- a/src/GridData.h +++ b/src/GridData.h @@ -119,26 +119,10 @@ public: std::shared_ptr getLayerByName(const std::string& name); static bool isProtectedLayerName(const std::string& name); - // ========================================================================= - // Cell callbacks (#142, #230) - // ========================================================================= - std::unique_ptr on_cell_enter_callable; - std::unique_ptr on_cell_exit_callable; - std::unique_ptr on_cell_click_callable; - std::optional hovered_cell; - std::optional last_clicked_cell; - - struct CellCallbackCache { - uint32_t generation = 0; - bool valid = false; - bool has_on_cell_click = false; - bool has_on_cell_enter = false; - bool has_on_cell_exit = false; - }; - CellCallbackCache cell_callback_cache; - - // fireCellClick/Enter/Exit and refreshCellCallbackCache are on UIGrid - // because they need access to UIDrawable::serial_number/is_python_subclass + // #355 - Cell input (callbacks, hovered/last-clicked cell, subclass-dispatch + // cache) moved to UIGridView: input is a property of the VIEW (camera), not of + // the data. Two views over one GridData must track hover independently, and + // the subclassable Python type (mcrfpy.Grid) IS UIGridView. // ========================================================================= // UIDrawable children (speech bubbles, effects, overlays) @@ -147,9 +131,27 @@ public: bool children_need_sort = true; // ========================================================================= - // #252 - Owning GridView back-reference (for Entity.grid → GridView lookup) + // #252/#359 - GridView back-references. Multiple GridViews can share one + // GridData (split-screen, minimap, multiple cameras); a single weak_ptr + // cannot represent that, so this is a vector. A fresh GridData is only + // ever produced by UIGridView::init_with_data (the Grid() factory path -- + // UIGridView::init_explicit_view / set_grid can only ATTACH to an + // EXISTING GridData, never create one), so views.front() is always the + // view that created this data: that ordering guarantee is what lets + // primaryView() give UIEntity::get_grid a deterministic (not arbitrary) + // answer for API identity, even once secondary views are registered. // ========================================================================= - std::weak_ptr owning_view; + std::vector> views; + + // Append view (idempotent -- a view already present is not duplicated). + void registerView(const std::shared_ptr& view); + // Remove view by identity (prunes expired entries too). Safe to call even + // if view was never registered. + void unregisterView(UIGridView* view); + // The view that created this GridData (views.front()), or the first + // still-alive view if the creator has since been destroyed while + // secondary views live on. nullptr if no view is alive. + std::shared_ptr primaryView() const; // #351 - Monotonic counter bumped whenever grid content drawn into a view's // RenderTexture changes (entities added/removed/moved, sprite changes, layer @@ -158,14 +160,21 @@ public: // live on the view and are compared there directly, not counted here. uint64_t content_generation = 0; - // #313 - Render invalidation from the data layer. Entities hold + // #313/#359 - Render invalidation from the data layer. Entities hold // shared_ptr but still need to invalidate rendering when their // visual state changes. These set the dirty flags on the UIGrid subobject // (GridData is never independently heap-allocated -- always a UIGrid base) - // AND notify owning_view, covering both render paths (a bare _GridData - // rendered directly, and the normal GridView). Within UIGrid itself the - // UIDrawable versions win via using-declarations (see UIGrid.h). - // Multi-view broadcast (secondary views) is deferred to #252. + // AND notify every registered view (see `views` above), covering both + // render paths (a bare _GridData rendered directly, and every GridView + // sharing this data) and every view's own ancestor chain (e.g. a + // Frame(use_render_texture=True) wrapping ANY of the N views needs its + // own cache invalidated, not just the creator's). Note the #351 render + // early-out itself does NOT depend on this notification -- it polls + // content_generation directly in UIGridView::render() -- this push is only + // for propagating markContentDirty/markCompositeDirty up a view's parent + // chain, which is a bottom-up push, not something pollable from a + // top-down render traversal. Within UIGrid itself the UIDrawable versions + // win via using-declarations (see UIGrid.h). void markDirty(); void markCompositeDirty(); diff --git a/src/PyScene.cpp b/src/PyScene.cpp index 8771bb2..48d60ed 100644 --- a/src/PyScene.cpp +++ b/src/PyScene.cpp @@ -257,41 +257,19 @@ void PyScene::do_mouse_input(std::string button, std::string type) // #184: Try property-assigned callable first (fast path) if (target->click_callable && !target->click_callable->isNone()) { target->click_callable->call(mousepos, button, type); - - // Also fire grid cell click if applicable - if (target->derived_type() == PyObjectsEnum::UIGRID) { - auto grid = static_cast(target); - if (grid->last_clicked_cell.has_value()) { - grid->fireCellClick(grid->last_clicked_cell.value(), button, type); - grid->last_clicked_cell = std::nullopt; - } - } + target->dispatchCellClick(button, type); // #355 (no-op unless grid view) return; // Stop after first handler } // #184: Try Python subclass method if (tryCallPythonMethod(target, "on_click", mousepos, button.c_str(), type.c_str())) { - // Also fire grid cell click if applicable - if (target->derived_type() == PyObjectsEnum::UIGRID) { - auto grid = static_cast(target); - if (grid->last_clicked_cell.has_value()) { - grid->fireCellClick(grid->last_clicked_cell.value(), button, type); - grid->last_clicked_cell = std::nullopt; - } - } + target->dispatchCellClick(button, type); // #355 return; // Stop after first handler } - // Fire grid cell click even if no on_click handler (but has cell click handler) - if (target->derived_type() == PyObjectsEnum::UIGRID) { - auto grid = static_cast(target); - if (grid->last_clicked_cell.has_value()) { - bool handled = grid->fireCellClick(grid->last_clicked_cell.value(), button, type); - grid->last_clicked_cell = std::nullopt; - if (handled) { - return; // Stop after handling cell click - } - } + // #355: cell click fires even without a whole-grid on_click handler + if (target->dispatchCellClick(button, type)) { + return; // Stop after handling cell click } // Element claimed the click but had no handler - still stop propagation @@ -326,11 +304,28 @@ void PyScene::do_mouse_hover(int x, int y) mousepos = game->windowToGameCoords(sf::Vector2f(static_cast(x), static_cast(y))); } - // Helper function to process hover for a single drawable and its children - std::function processHover = [&](UIDrawable* drawable) { + // Helper function to process hover for a single drawable and its children. + // + // `point` is in the drawable's PARENT-local coordinate space -- the same + // convention click_at() uses. At the top level that is the global/scene space + // (identical to the old contains_point() behavior, since global position is + // just the sum of ancestor positions). Descending into a Frame subtracts the + // frame's position; descending into a Grid applies the view's camera + // (localToGridWorld), which is what makes grid children hoverable at all (#355). + // + // `hit_allowed` is false while walking the children of a grid the mouse is NOT + // over: the camera transform is affine, so an outside point still maps to some + // grid-world coordinate, which could land on an off-screen child. Those subtrees + // must only ever fire exits, never enters. + std::function processHover = + [&](UIDrawable* drawable, sf::Vector2f point, bool hit_allowed) { if (!drawable || !drawable->visible) return; - bool is_inside = drawable->contains_point(mousepos.x, mousepos.y); + // Same rect get_global_bounds() builds (position + bounds SIZE), just + // expressed in parent-local space instead of accumulated global space. + sf::FloatRect b = drawable->get_bounds(); + bool is_inside = hit_allowed && + sf::FloatRect(drawable->position.x, drawable->position.y, b.width, b.height).contains(point); bool was_hovered = drawable->hovered; if (is_inside && !was_hovered) { @@ -367,26 +362,33 @@ void PyScene::do_mouse_hover(int x, int y) } } - // Process children for Frame elements + // #355 - cell enter/exit (no-op for non-grid drawables) + drawable->updateHover(point, hit_allowed); + + // Process children for Frame elements (children are positioned relative + // to the frame's own position). if (drawable->derived_type() == PyObjectsEnum::UIFRAME) { auto frame = static_cast(drawable); if (frame->children) { + sf::Vector2f child_point = point - frame->position; for (auto& child : *frame->children) { - processHover(child.get()); + processHover(child.get(), child_point, hit_allowed); } } } - // Process children for Grid elements - else if (drawable->derived_type() == PyObjectsEnum::UIGRID) { - auto grid = static_cast(drawable); - - // #142 - Update cell hover tracking for grid - // Pass "none" for button and "move" for action during hover - grid->updateCellHover(mousepos, "none", "move"); - - if (grid->children) { - for (auto& child : *grid->children) { - processHover(child.get()); + // #355 - Grid overlay children live in GRID-WORLD PIXEL coordinates, so the + // mouse point must go through the view's camera exactly as UIGridView::click_at + // does. Children are always visited (even when the mouse is outside the view) + // so a child that was hovered still receives its on_exit. + else if (drawable->derived_type() == PyObjectsEnum::UIGRIDVIEW) { + auto view = static_cast(drawable); + if (view->grid_data && view->grid_data->children) { + sf::Vector2f local = point - view->box.getPosition(); + sf::Vector2f grid_world = view->localToGridWorld(local); + bool inside_view = hit_allowed && + sf::FloatRect(sf::Vector2f(0.f, 0.f), view->box.getSize()).contains(local); + for (auto& child : *view->grid_data->children) { + processHover(child.get(), grid_world, inside_view); } } } @@ -394,7 +396,7 @@ void PyScene::do_mouse_hover(int x, int y) // Process all top-level UI elements for (auto& element : *ui_elements) { - processHover(element.get()); + processHover(element.get(), mousepos, true); } } diff --git a/src/UIBase.h b/src/UIBase.h index 3742883..a9377de 100644 --- a/src/UIBase.h +++ b/src/UIBase.h @@ -31,7 +31,6 @@ class UIGridView; typedef struct { PyObject_HEAD std::shared_ptr data; - std::shared_ptr view; // #252: auto-created rendering view (shim) PyObject* weakreflist; // Weak reference support } PyUIGridObject; diff --git a/src/UIDrawable.h b/src/UIDrawable.h index 64a8ef4..96bfd09 100644 --- a/src/UIDrawable.h +++ b/src/UIDrawable.h @@ -22,7 +22,7 @@ class UniformCollection; // PyShaderObject is a typedef, forward declare as a struct with explicit typedef typedef struct PyShaderObjectStruct PyShaderObject; -class UIFrame; class UICaption; class UISprite; class UIEntity; class UIGrid; +class UIFrame; class UICaption; class UISprite; class UIEntity; class UIGrid; class GridData; enum PyObjectsEnum : int { @@ -55,6 +55,27 @@ public: void click_register(PyObject*); void click_unregister(); + // #355 - Grid cell input. Defaults are inert: no caller may switch on grid-ness. + // + // dispatchCellClick: called by PyScene after click_at() resolved this drawable as + // the click target. Takes no point: click_at() already resolved the cell in the + // coordinate space of the hit (parent-local), which PyScene does not have. + // Returns true if a cell callback consumed the click. + virtual bool dispatchCellClick(const std::string& button, const std::string& action) + { (void)button; (void)action; return false; } + + // updateHover: called by PyScene::do_mouse_hover for every drawable, with the + // mouse position in this drawable's PARENT-local coordinate space (the same + // convention click_at() uses; at the top level that is global space). + // hit_allowed is false when an ancestor already determined the mouse cannot be + // over this subtree -- such a call may only clear hover state, never set it. + virtual void updateHover(sf::Vector2f point, bool hit_allowed) + { (void)point; (void)hit_allowed; } + + // asGridData: non-null only for drawables that own or view grid data. + // (#357 find/findAll and #358 ImGuiSceneExplorer will use this same primitive.) + virtual GridData* asGridData() { return nullptr; } + // #140 - Mouse enter/exit callbacks void on_enter_register(PyObject*); void on_enter_unregister(); diff --git a/src/UIEntity.cpp b/src/UIEntity.cpp index 7833ae3..1a7f15f 100644 --- a/src/UIEntity.cpp +++ b/src/UIEntity.cpp @@ -821,10 +821,14 @@ PyObject* UIEntity::get_grid(PyUIEntityObject* self, void* closure) auto& grid = self->data->grid; - // #252: If the grid has an owning GridView, return that instead. + // #252/#359: If the grid has a registered GridView, return that instead. // This preserves the unified Grid API where entity.grid returns the same - // object the user created via mcrfpy.Grid(...). - auto owning_view = grid->owning_view.lock(); + // object the user created via mcrfpy.Grid(...). primaryView() is + // deterministic even with multiple views sharing this GridData: it's + // views.front(), the view that actually created the data (a fresh + // GridData is only ever produced by the Grid() factory path), or the + // first still-alive secondary view if that original view has since died. + auto owning_view = grid->primaryView(); if (owning_view) { // Check cache for the GridView if (owning_view->serial_number != 0) { diff --git a/src/UIGrid.cpp b/src/UIGrid.cpp index e6233d0..0f1dd5a 100644 --- a/src/UIGrid.cpp +++ b/src/UIGrid.cpp @@ -25,8 +25,7 @@ UIGrid::UIGrid() : GridData(), // Initialize data layer (entities, children, FOV defaults) zoom(1.0f), center_x(0.0f), center_y(0.0f), ptex(nullptr), - fill_color(8, 8, 8, 255), - perspective_enabled(false) + fill_color(8, 8, 8, 255) { // Initialize box with safe defaults box.setSize(sf::Vector2f(0, 0)); @@ -51,8 +50,7 @@ UIGrid::UIGrid(int gx, int gy, std::shared_ptr _ptex, sf::Vector2f _x : GridData(), // Initialize data layer zoom(1.0f), ptex(_ptex), - fill_color(8, 8, 8, 255), - perspective_enabled(false) + fill_color(8, 8, 8, 255) { // Use texture dimensions if available, otherwise use defaults int cell_width = _ptex ? _ptex->sprite_width : DEFAULT_CELL_WIDTH; @@ -286,76 +284,8 @@ void UIGrid::render(sf::Vector2f offset, sf::RenderTarget& target) } } - // top layer - opacity for discovered / visible status based on perspective - // Only render visibility overlay if perspective is enabled - if (perspective_enabled) { - ScopedTimer fovTimer(Resources::game->metrics.fovOverlayTime); - auto entity = perspective_entity.lock(); - - // Create rectangle for overlays - sf::RectangleShape overlay; - overlay.setSize(sf::Vector2f(cell_width * zoom, cell_height * zoom)); - - if (entity && entity->perspective_map) { - // #294: perspective_map values -- 0=unknown, 1=discovered, 2=visible. - const uint8_t* pm = entity->perspective_map->data(); - const int pm_w = entity->perspective_map->width(); - const int pm_h = entity->perspective_map->height(); - for (int x = (left_edge - 1 >= 0 ? left_edge - 1 : 0); - x < x_limit; - x+=1) - { - for (int y = (top_edge - 1 >= 0 ? top_edge - 1 : 0); - y < y_limit; - y+=1) - { - // Skip out-of-bounds cells - if (x < 0 || x >= grid_w || y < 0 || y >= grid_h) continue; - if (x >= pm_w || y >= pm_h) continue; - - auto pixel_pos = sf::Vector2f( - (x*cell_width - left_spritepixels) * zoom, - (y*cell_height - top_spritepixels) * zoom ); - - uint8_t state = pm[y * pm_w + x]; - overlay.setPosition(pixel_pos); - - if (state == 0) { - overlay.setFillColor(sf::Color(0, 0, 0, 255)); - activeTexture->draw(overlay); - } else if (state == 1) { - overlay.setFillColor(sf::Color(32, 32, 40, 192)); - activeTexture->draw(overlay); - } - // state == 2: visible -- no overlay - } - } - } else { - // Invalid/destroyed entity with perspective_enabled = true - // Show all cells as undiscovered (black) - for (int x = (left_edge - 1 >= 0 ? left_edge - 1 : 0); - x < x_limit; - x+=1) - { - for (int y = (top_edge - 1 >= 0 ? top_edge - 1 : 0); - y < y_limit; - y+=1) - { - // Skip out-of-bounds cells - if (x < 0 || x >= grid_w || y < 0 || y >= grid_h) continue; - - auto pixel_pos = sf::Vector2f( - (x*cell_width - left_spritepixels) * zoom, - (y*cell_height - top_spritepixels) * zoom ); - - overlay.setPosition(pixel_pos); - overlay.setFillColor(sf::Color(0, 0, 0, 255)); - activeTexture->draw(overlay); - } - } - } - } - // else: omniscient view (no overlays) + // #355: the perspective/FOV overlay is drawn by UIGridView::render, which owns + // the perspective state. UIGrid (the internal _GridData) no longer duplicates it. // grid lines for testing & validation /* @@ -522,101 +452,14 @@ std::shared_ptr UIGrid::getTexture() return ptex; } -UIDrawable* UIGrid::click_at(sf::Vector2f point) +UIDrawable* UIGrid::click_at(sf::Vector2f) { - // Check grid bounds first - if (!box.getGlobalBounds().contains(point)) { - return nullptr; - } - - // Transform to local coordinates - sf::Vector2f localPoint = point - box.getPosition(); - - // Get cell dimensions - int cell_width = ptex ? ptex->sprite_width : DEFAULT_CELL_WIDTH; - int cell_height = ptex ? ptex->sprite_height : DEFAULT_CELL_HEIGHT; - - // Calculate visible area parameters (from render function) - float center_x_sq = center_x / cell_width; - float center_y_sq = center_y / cell_height; - float width_sq = box.getSize().x / (cell_width * zoom); - float height_sq = box.getSize().y / (cell_height * zoom); - - int left_spritepixels = center_x - (box.getSize().x / 2.0 / zoom); - int top_spritepixels = center_y - (box.getSize().y / 2.0 / zoom); - - // Convert click position to grid-world pixel coordinates - float grid_world_x = localPoint.x / zoom + left_spritepixels; - float grid_world_y = localPoint.y / zoom + top_spritepixels; - - // Convert to grid cell coordinates - float grid_x = grid_world_x / cell_width; - float grid_y = grid_world_y / cell_height; - - // Check children first (they render on top, so they get priority) - // Children are positioned in grid-world pixel coordinates - if (children && !children->empty()) { - // Check in reverse z-order (highest z_index first, rendered last = on top) - for (auto it = children->rbegin(); it != children->rend(); ++it) { - auto& child = *it; - if (!child->visible) continue; - - // Transform click to child's local coordinate space - // Children's position is in grid-world pixels - sf::Vector2f childLocalPoint = sf::Vector2f(grid_world_x, grid_world_y); - - if (auto target = child->click_at(childLocalPoint)) { - return target; - } - } - } - - // Check entities in reverse order (assuming they should be checked top to bottom) - // Note: entities list is not sorted by z-index currently, but we iterate in reverse - // to match the render order assumption - if (entities) { - for (auto it = entities->rbegin(); it != entities->rend(); ++it) { - auto& entity = *it; - if (!entity || !entity->sprite.visible) continue; - - // Check if click is within entity's grid cell - // Entities occupy a 1x1 grid cell centered on their position - float dx = grid_x - entity->position.x; - float dy = grid_y - entity->position.y; - - if (dx >= -0.5f && dx < 0.5f && dy >= -0.5f && dy < 0.5f) { - // Click is within the entity's cell - // Check if entity sprite has a click handler - // For now, we return the entity's sprite as the click target - // Note: UIEntity doesn't derive from UIDrawable, so we check its sprite - if (entity->sprite.click_callable) { - return &entity->sprite; - } - } - } - } - - // No entity handled it, check if grid itself has handler - // #184: Also check for Python subclass (might have on_click or on_cell_click method) - - // Store clicked cell for later callback firing (with button/action from PyScene) - int cell_x = static_cast(std::floor(grid_x)); - int cell_y = static_cast(std::floor(grid_y)); - if (cell_x >= 0 && cell_x < this->grid_w && cell_y >= 0 && cell_y < this->grid_h) { - last_clicked_cell = sf::Vector2i(cell_x, cell_y); - } else { - last_clicked_cell = std::nullopt; - } - - // Return this if we have any handler (property callback, subclass method, or cell callback) - if (click_callable || is_python_subclass || on_cell_click_callable) { - return this; - } - + // #355: a bare _GridData is never an input target -- the scene graph holds + // UIGridView, which owns the camera and all cell/child/entity hit testing. + // #361 removes UIDrawable from GridData entirely, which deletes this override. return nullptr; } - int UIGrid::init(PyUIGridObject* self, PyObject* args, PyObject* kwds) { // Define all parameters with defaults PyObject* pos_obj = nullptr; @@ -782,8 +625,7 @@ int UIGrid::init(PyUIGridObject* self, PyObject* args, PyObject* kwds) { } self->data->center_x = center_x; self->data->center_y = center_y; - // perspective is now handled by perspective_entity and perspective_enabled - // self->data->perspective = perspective; + // #355: perspective lives on UIGridView (the object that renders the overlay). self->data->visible = visible; self->data->opacity = opacity; self->data->z_index = z_index; @@ -984,32 +826,15 @@ int UIGrid::init(PyUIGridObject* self, PyObject* args, PyObject* kwds) { // #184: Check if this is a Python subclass (for callback method support) self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != (PyObject*)&mcrfpydef::PyUIGridType; - // #252 shim: auto-create a GridView for rendering - // The GridView shares GridData (via aliasing shared_ptr) and copies rendering state - { - auto view = std::make_shared(); - // Share grid data (aliasing shared_ptr: shares UIGrid ownership, points to GridData base) - view->grid_data = std::shared_ptr( - self->data, static_cast(self->data.get())); - // Copy rendering state from UIGrid to GridView - view->ptex = texture_ptr; - view->box.setPosition(self->data->box.getPosition()); - view->box.setSize(self->data->box.getSize()); - view->position = self->data->position; - view->center_x = self->data->center_x; - view->center_y = self->data->center_y; - view->zoom = self->data->zoom; - view->fill_color = self->data->fill_color; - view->camera_rotation = self->data->camera_rotation; - view->perspective_entity = self->data->perspective_entity; - view->perspective_enabled = self->data->perspective_enabled; - view->visible = self->data->visible; - view->opacity = self->data->opacity; - view->z_index = self->data->z_index; - view->name = self->data->name; - view->ensureRenderTextureSize(); - self->view = view; - } + // #359: previously constructed an extra "shim" GridView here (self->view) + // that copied rendering state and allocated its own RenderTexture, but was + // NEVER used -- UIGridView::init_with_data (the only caller of UIGrid::init, + // see UIGridView.cpp) discards this PyUIGridObject wrapper immediately after + // stealing its GridData via an aliasing shared_ptr, and builds the REAL, + // user-visible view directly on itself. The shim was dead weight (a wasted + // RenderTexture allocation on every Grid() construction) backing a field + // (PyUIGridObject::view / `_GridData.view`) nothing ever read. Removed along + // with the field itself. return 0; // Success } @@ -1017,45 +842,6 @@ int UIGrid::init(PyUIGridObject* self, PyObject* args, PyObject* kwds) { // Python property getters/setters moved to UIGridPyProperties.cpp // Python method implementations moved to UIGridPyMethods.cpp -// #142 - Convert screen coordinates to cell coordinates -std::optional UIGrid::screenToCell(sf::Vector2f screen_pos) const { - // Get grid's global position - sf::Vector2f global_pos = get_global_position(); - sf::Vector2f local_pos = screen_pos - global_pos; - - // Check if within grid bounds - sf::FloatRect bounds = box.getGlobalBounds(); - if (local_pos.x < 0 || local_pos.y < 0 || - local_pos.x >= bounds.width || local_pos.y >= bounds.height) { - return std::nullopt; - } - - // Get cell size from texture or default - float cell_width = ptex ? ptex->sprite_width : DEFAULT_CELL_WIDTH; - float cell_height = ptex ? ptex->sprite_height : DEFAULT_CELL_HEIGHT; - - // Apply zoom - cell_width *= zoom; - cell_height *= zoom; - - // Calculate grid space position (account for center/pan) - float half_width = bounds.width / 2.0f; - float half_height = bounds.height / 2.0f; - float grid_space_x = (local_pos.x - half_width) / zoom + center_x; - float grid_space_y = (local_pos.y - half_height) / zoom + center_y; - - // Convert to cell coordinates - int cell_x = static_cast(std::floor(grid_space_x / (ptex ? ptex->sprite_width : DEFAULT_CELL_WIDTH))); - int cell_y = static_cast(std::floor(grid_space_y / (ptex ? ptex->sprite_height : DEFAULT_CELL_HEIGHT))); - - // Check if within valid cell range - if (cell_x < 0 || cell_x >= grid_w || cell_y < 0 || cell_y >= grid_h) { - return std::nullopt; - } - - return sf::Vector2i(cell_x, cell_y); -} - // #221 - Get effective cell size (texture size * zoom) sf::Vector2f UIGrid::getEffectiveCellSize() const { float cell_w = ptex ? static_cast(ptex->sprite_width) : static_cast(DEFAULT_CELL_WIDTH); @@ -1063,287 +849,6 @@ sf::Vector2f UIGrid::getEffectiveCellSize() const { return sf::Vector2f(cell_w * zoom, cell_h * zoom); } -// Helper function to convert button string to MouseButton enum value -static int buttonStringToEnum(const std::string& button) { - if (button == "left") return 0; // MouseButton.LEFT - if (button == "right") return 1; // MouseButton.RIGHT - if (button == "middle") return 2; // MouseButton.MIDDLE - if (button == "wheel_up") return 3; // MouseButton.WHEEL_UP - if (button == "wheel_down") return 4; // MouseButton.WHEEL_DOWN - return 0; // Default to LEFT -} - -// Helper function to convert action string to InputState enum value -static int actionStringToEnum(const std::string& action) { - if (action == "start" || action == "pressed") return 0; // InputState.PRESSED - if (action == "end" || action == "released") return 1; // InputState.RELEASED - return 0; // Default to PRESSED -} - -// #142 - Refresh cell callback cache for Python subclass method support -void UIGrid::refreshCellCallbackCache(PyObject* pyObj) { - if (!pyObj || !is_python_subclass) { - cell_callback_cache.valid = false; - return; - } - - // Get the class's callback generation counter - PyObject* cls = (PyObject*)Py_TYPE(pyObj); - uint32_t current_gen = 0; - PyObject* gen_obj = PyObject_GetAttrString(cls, "_mcrf_callback_gen"); - if (gen_obj) { - current_gen = static_cast(PyLong_AsUnsignedLong(gen_obj)); - Py_DECREF(gen_obj); - } else { - PyErr_Clear(); - } - - // Check if cache is still valid - if (cell_callback_cache.valid && cell_callback_cache.generation == current_gen) { - return; // Cache is fresh - } - - // Refresh cache - check for each cell callback method - cell_callback_cache.has_on_cell_click = false; - cell_callback_cache.has_on_cell_enter = false; - cell_callback_cache.has_on_cell_exit = false; - - // Check class hierarchy for each method - PyTypeObject* type = Py_TYPE(pyObj); - while (type && type != &mcrfpydef::PyUIGridType && type != &PyBaseObject_Type) { - if (type->tp_dict) { - if (!cell_callback_cache.has_on_cell_click) { - PyObject* method = PyDict_GetItemString(type->tp_dict, "on_cell_click"); - if (method && PyCallable_Check(method)) { - cell_callback_cache.has_on_cell_click = true; - } - } - if (!cell_callback_cache.has_on_cell_enter) { - PyObject* method = PyDict_GetItemString(type->tp_dict, "on_cell_enter"); - if (method && PyCallable_Check(method)) { - cell_callback_cache.has_on_cell_enter = true; - } - } - if (!cell_callback_cache.has_on_cell_exit) { - PyObject* method = PyDict_GetItemString(type->tp_dict, "on_cell_exit"); - if (method && PyCallable_Check(method)) { - cell_callback_cache.has_on_cell_exit = true; - } - } - } - type = type->tp_base; - } - - cell_callback_cache.generation = current_gen; - cell_callback_cache.valid = true; -} - -// Helper to create typed cell callback arguments: (Vector, MouseButton, InputState) -static PyObject* createCellCallbackArgs(sf::Vector2i cell, const std::string& button, const std::string& action) { - // Create Vector object for cell position - PyObject* cell_pos = PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ff", (float)cell.x, (float)cell.y); - if (!cell_pos) { - PyErr_Print(); - return nullptr; - } - - // Create MouseButton enum - int button_val = buttonStringToEnum(button); - PyObject* button_enum = PyObject_CallFunction(PyMouseButton::mouse_button_enum_class, "i", button_val); - if (!button_enum) { - Py_DECREF(cell_pos); - PyErr_Print(); - return nullptr; - } - - // Create InputState enum - int action_val = actionStringToEnum(action); - PyObject* action_enum = PyObject_CallFunction(PyInputState::input_state_enum_class, "i", action_val); - if (!action_enum) { - Py_DECREF(cell_pos); - Py_DECREF(button_enum); - PyErr_Print(); - return nullptr; - } - - PyObject* args = Py_BuildValue("(OOO)", cell_pos, button_enum, action_enum); - Py_DECREF(cell_pos); - Py_DECREF(button_enum); - Py_DECREF(action_enum); - return args; -} - -// #230 - Helper to create cell hover callback arguments: (Vector) only -static PyObject* createCellHoverArgs(sf::Vector2i cell) { - // Create Vector object for cell position - PyObject* cell_pos = PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ii", cell.x, cell.y); - if (!cell_pos) { - PyErr_Print(); - return nullptr; - } - - PyObject* args = Py_BuildValue("(O)", cell_pos); - Py_DECREF(cell_pos); - return args; -} - -// Fire cell click callback with full signature (cell_pos, button, action) -bool UIGrid::fireCellClick(sf::Vector2i cell, const std::string& button, const std::string& action) { - // Try property-assigned callback first - if (on_cell_click_callable && !on_cell_click_callable->isNone()) { - PyObject* args = createCellCallbackArgs(cell, button, action); - if (args) { - PyObject* result = PyObject_CallObject(on_cell_click_callable->borrow(), args); - Py_DECREF(args); - if (!result) { - std::cerr << "Cell click callback raised an exception:" << std::endl; - PyErr_Print(); - PyErr_Clear(); - } else { - Py_DECREF(result); - } - return true; - } - } - - // Try Python subclass method - if (is_python_subclass) { - PyObject* pyObj = PythonObjectCache::getInstance().lookup(this->serial_number); - if (pyObj) { - refreshCellCallbackCache(pyObj); - if (cell_callback_cache.has_on_cell_click) { - PyObject* method = PyObject_GetAttrString(pyObj, "on_cell_click"); - if (method && PyCallable_Check(method)) { - PyObject* args = createCellCallbackArgs(cell, button, action); - if (args) { - PyObject* result = PyObject_CallObject(method, args); - Py_DECREF(args); - Py_DECREF(method); - Py_DECREF(pyObj); - if (!result) { - std::cerr << "Cell click method raised an exception:" << std::endl; - PyErr_Print(); - PyErr_Clear(); - } else { - Py_DECREF(result); - } - return true; - } - } - Py_XDECREF(method); - } - Py_DECREF(pyObj); - } - } - return false; -} - -// #230 - Fire cell enter callback with position-only signature (cell_pos) -bool UIGrid::fireCellEnter(sf::Vector2i cell) { - // Try property-assigned callback first (now PyCellHoverCallable) - if (on_cell_enter_callable && !on_cell_enter_callable->isNone()) { - on_cell_enter_callable->call(cell); - return true; - } - - // Try Python subclass method - if (is_python_subclass) { - PyObject* pyObj = PythonObjectCache::getInstance().lookup(this->serial_number); - if (pyObj) { - refreshCellCallbackCache(pyObj); - if (cell_callback_cache.has_on_cell_enter) { - PyObject* method = PyObject_GetAttrString(pyObj, "on_cell_enter"); - if (method && PyCallable_Check(method)) { - // #230: Cell hover takes only (cell_pos) - PyObject* args = createCellHoverArgs(cell); - if (args) { - PyObject* result = PyObject_CallObject(method, args); - Py_DECREF(args); - Py_DECREF(method); - Py_DECREF(pyObj); - if (!result) { - std::cerr << "Cell enter method raised an exception:" << std::endl; - PyErr_Print(); - PyErr_Clear(); - } else { - Py_DECREF(result); - } - return true; - } - } - Py_XDECREF(method); - } - Py_DECREF(pyObj); - } - } - return false; -} - -// #230 - Fire cell exit callback with position-only signature (cell_pos) -bool UIGrid::fireCellExit(sf::Vector2i cell) { - // Try property-assigned callback first (now PyCellHoverCallable) - if (on_cell_exit_callable && !on_cell_exit_callable->isNone()) { - on_cell_exit_callable->call(cell); - return true; - } - - // Try Python subclass method - if (is_python_subclass) { - PyObject* pyObj = PythonObjectCache::getInstance().lookup(this->serial_number); - if (pyObj) { - refreshCellCallbackCache(pyObj); - if (cell_callback_cache.has_on_cell_exit) { - PyObject* method = PyObject_GetAttrString(pyObj, "on_cell_exit"); - if (method && PyCallable_Check(method)) { - // #230: Cell hover takes only (cell_pos) - PyObject* args = createCellHoverArgs(cell); - if (args) { - PyObject* result = PyObject_CallObject(method, args); - Py_DECREF(args); - Py_DECREF(method); - Py_DECREF(pyObj); - if (!result) { - std::cerr << "Cell exit method raised an exception:" << std::endl; - PyErr_Print(); - PyErr_Clear(); - } else { - Py_DECREF(result); - } - return true; - } - } - Py_XDECREF(method); - } - Py_DECREF(pyObj); - } - } - return false; -} - -// #142 - Update cell hover state and fire callbacks -// #230 - Cell hover callbacks now take only (cell_pos), no button/action -void UIGrid::updateCellHover(sf::Vector2f mousepos, const std::string& button, const std::string& action) { - (void)button; // #230 - No longer used for hover callbacks - (void)action; // #230 - No longer used for hover callbacks - - auto new_cell = screenToCell(mousepos); - - // Check if cell changed - if (new_cell != hovered_cell) { - // Fire exit callback for old cell - if (hovered_cell.has_value()) { - fireCellExit(hovered_cell.value()); - } - - // Fire enter callback for new cell - if (new_cell.has_value()) { - fireCellEnter(new_cell.value()); - } - - hovered_cell = new_cell; - } -} - // UIEntityCollection code has been moved to UIEntityCollection.cpp // Property system implementation for animations diff --git a/src/UIGrid.h b/src/UIGrid.h index 78ff351..bb8e95c 100644 --- a/src/UIGrid.h +++ b/src/UIGrid.h @@ -56,6 +56,7 @@ public: void render(sf::Vector2f, sf::RenderTarget&) override final; PyObjectsEnum derived_type() override final; virtual UIDrawable* click_at(sf::Vector2f point) override final; + GridData* asGridData() override { return static_cast(this); } // #355 // Phase 1 virtual method implementations sf::FloatRect get_bounds() const override; @@ -80,20 +81,12 @@ public: // Background rendering sf::Color fill_color; - // Perspective system - std::weak_ptr perspective_entity; - bool perspective_enabled; + // #355: the perspective system (entity + enabled flag) lives on UIGridView, + // which renders the FOV overlay. Keeping a copy here was a dead duplicate. - // Cell callback firing (needs UIDrawable::is_python_subclass, serial_number) - bool fireCellClick(sf::Vector2i cell, const std::string& button, const std::string& action); - bool fireCellEnter(sf::Vector2i cell); - bool fireCellExit(sf::Vector2i cell); - void refreshCellCallbackCache(PyObject* pyObj); - - // #142 - Cell coordinate conversion (needs texture for cell size) - std::optional screenToCell(sf::Vector2f screen_pos) const; + // #355 - cell callback firing, screenToCell and cell hover moved to UIGridView. + // getEffectiveCellSize stays: UIDrawable uses it for grid_pos <-> pixel math. sf::Vector2f getEffectiveCellSize() const; - void updateCellHover(sf::Vector2f mousepos, const std::string& button, const std::string& action); // Property system for animations bool setProperty(const std::string& name, float value) override; @@ -122,10 +115,6 @@ public: static PyObject* get_texture(PyUIGridObject* self, void* closure); static PyObject* get_fill_color(PyUIGridObject* self, void* closure); static int set_fill_color(PyUIGridObject* self, PyObject* value, void* closure); - static PyObject* get_perspective(PyUIGridObject* self, void* closure); - static int set_perspective(PyUIGridObject* self, PyObject* value, void* closure); - static PyObject* get_perspective_enabled(PyUIGridObject* self, void* closure); - static int set_perspective_enabled(PyUIGridObject* self, PyObject* value, void* closure); static PyObject* get_fov(PyUIGridObject* self, void* closure); static int set_fov(PyUIGridObject* self, PyObject* value, void* closure); static PyObject* get_fov_radius(PyUIGridObject* self, void* closure); @@ -149,15 +138,6 @@ public: static PyObject* get_children(PyUIGridObject* self, void* closure); static PyObject* repr(PyUIGridObject* self); - static PyObject* get_on_cell_enter(PyUIGridObject* self, void* closure); - static int set_on_cell_enter(PyUIGridObject* self, PyObject* value, void* closure); - static PyObject* get_on_cell_exit(PyUIGridObject* self, void* closure); - static int set_on_cell_exit(PyUIGridObject* self, PyObject* value, void* closure); - static PyObject* get_on_cell_click(PyUIGridObject* self, void* closure); - static int set_on_cell_click(PyUIGridObject* self, PyObject* value, void* closure); - static PyObject* get_hovered_cell(PyUIGridObject* self, void* closure); - - static PyObject* get_view(PyUIGridObject* self, void* closure); // #252 shim static PyObject* py_add_layer(PyUIGridObject* self, PyObject* args); static PyObject* py_remove_layer(PyUIGridObject* self, PyObject* args); static PyObject* get_layers(PyUIGridObject* self, void* closure); @@ -190,12 +170,8 @@ namespace mcrfpydef { obj->data->on_enter_unregister(); obj->data->on_exit_unregister(); obj->data->on_move_unregister(); - // Grid-specific cell callbacks (now on GridData base) - obj->data->on_cell_enter_callable.reset(); - obj->data->on_cell_exit_callable.reset(); - obj->data->on_cell_click_callable.reset(); + // #355: cell callbacks now live on UIGridView, not GridData. } - obj->view.reset(); // #252: release GridView shim obj->data.reset(); Py_TYPE(self)->tp_free(self); }, @@ -215,7 +191,6 @@ namespace mcrfpydef { " center_x (float): X coordinate of center point. Default: 0\n" " center_y (float): Y coordinate of center point. Default: 0\n" " zoom (float): Zoom level for rendering. Default: 1.0\n" - " perspective (int): Entity perspective index (-1 for omniscient). Default: -1\n" " visible (bool): Visibility state. Default: True\n" " opacity (float): Opacity (0.0-1.0). Default: 1.0\n" " z_index (int): Rendering order. Default: 0\n" @@ -243,7 +218,12 @@ namespace mcrfpydef { " texture (Texture): Tile texture atlas\n" " fill_color (Color): Background color\n" " entities (EntityCollection): Collection of entities in the grid\n" - " perspective (int): Entity perspective index\n" + " children (UICollection): UIDrawable children (speech bubbles, markers, " + "range indicators) anchored to grid content -- positioned in the grid's " + "pixel-world coordinates, same origin as entities, and pan/zoom with the " + "camera. NOT the same coordinate space as Frame.children. For screen-space " + "UI that floats over the grid, use a sibling Frame instead; see " + "docs/grid-coordinate-spaces.md\n" " click (callable): Click event handler\n" " visible (bool): Visibility state\n" " opacity (float): Opacity value\n" @@ -272,18 +252,6 @@ namespace mcrfpydef { PyObject* callback = obj->data->on_move_callable->borrow(); if (callback && callback != Py_None) Py_VISIT(callback); } - if (obj->data->on_cell_enter_callable) { - PyObject* callback = obj->data->on_cell_enter_callable->borrow(); - if (callback && callback != Py_None) Py_VISIT(callback); - } - if (obj->data->on_cell_exit_callable) { - PyObject* callback = obj->data->on_cell_exit_callable->borrow(); - if (callback && callback != Py_None) Py_VISIT(callback); - } - if (obj->data->on_cell_click_callable) { - PyObject* callback = obj->data->on_cell_click_callable->borrow(); - if (callback && callback != Py_None) Py_VISIT(callback); - } } return 0; }, @@ -294,9 +262,6 @@ namespace mcrfpydef { obj->data->on_enter_unregister(); obj->data->on_exit_unregister(); obj->data->on_move_unregister(); - obj->data->on_cell_enter_callable.reset(); - obj->data->on_cell_exit_callable.reset(); - obj->data->on_cell_click_callable.reset(); } return 0; }, @@ -309,8 +274,6 @@ namespace mcrfpydef { PyUIGridObject* self = (PyUIGridObject*)type->tp_alloc(type, 0); if (self) { self->data = std::make_shared(); - // Placement-new the shared_ptr (tp_alloc zero-fills, not construct) - new (&self->view) std::shared_ptr(); } return (PyObject*)self; } diff --git a/src/UIGridPyMethods.cpp b/src/UIGridPyMethods.cpp index 45273a5..b77ec2f 100644 --- a/src/UIGridPyMethods.cpp +++ b/src/UIGridPyMethods.cpp @@ -829,7 +829,7 @@ PyObject* UIGrid::py_step(PyUIGridObject* self, PyObject* args, PyObject* kwds) // #351 - invalidate the view's render early-out once if anything moved. // Must call the GridData override explicitly: UIGrid's `using // UIDrawable::markCompositeDirty` would otherwise shadow it and skip the - // content_generation bump + owning_view notification. + // content_generation bump + registered-views notification. if (content_changed) grid->GridData::markCompositeDirty(); Py_RETURN_NONE; diff --git a/src/UIGridPyProperties.cpp b/src/UIGridPyProperties.cpp index a9d0904..296057c 100644 --- a/src/UIGridPyProperties.cpp +++ b/src/UIGridPyProperties.cpp @@ -156,22 +156,6 @@ int UIGrid::set_float_member(PyUIGridObject* self, PyObject* value, void* closur else if (member_ptr == 7) self->data->camera_rotation = val; - if (self->view) { - if (member_ptr == 0) - self->view->box.setPosition(val, self->view->box.getPosition().y); - else if (member_ptr == 1) - self->view->box.setPosition(self->view->box.getPosition().x, val); - else if (member_ptr == 2) - self->view->box.setSize(sf::Vector2f(val, self->view->box.getSize().y)); - else if (member_ptr == 3) - self->view->box.setSize(sf::Vector2f(self->view->box.getSize().x, val)); - else if (member_ptr == 4) self->view->center_x = val; - else if (member_ptr == 5) self->view->center_y = val; - else if (member_ptr == 6) self->view->zoom = val; - else if (member_ptr == 7) self->view->camera_rotation = val; - self->view->position = self->view->box.getPosition(); - } - if (member_ptr == 0 || member_ptr == 1) { self->data->markCompositeDirty(); } else { @@ -224,72 +208,6 @@ int UIGrid::set_fill_color(PyUIGridObject* self, PyObject* value, void* closure) return 0; } -// ========================================================================= -// Perspective properties -// ========================================================================= - -PyObject* UIGrid::get_perspective(PyUIGridObject* self, void* closure) -{ - auto locked = self->data->perspective_entity.lock(); - if (locked) { - if (locked->serial_number != 0) { - PyObject* cached = PythonObjectCache::getInstance().lookup(locked->serial_number); - if (cached) { - return cached; - } - } - - auto type = &mcrfpydef::PyUIEntityType; - auto o = (PyUIEntityObject*)type->tp_alloc(type, 0); - if (o) { - o->data = locked; - o->weakreflist = NULL; - return (PyObject*)o; - } - } - Py_RETURN_NONE; -} - -int UIGrid::set_perspective(PyUIGridObject* self, PyObject* value, void* closure) -{ - if (value == Py_None) { - self->data->perspective_entity.reset(); - self->data->markDirty(); - return 0; - } - - if (!PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PyUIEntityType)) { - PyErr_SetString(PyExc_TypeError, "perspective must be a UIEntity or None"); - return -1; - } - - PyUIEntityObject* entity_obj = (PyUIEntityObject*)value; - self->data->perspective_entity = entity_obj->data; - self->data->perspective_enabled = true; - self->data->markDirty(); - return 0; -} - -PyObject* UIGrid::get_perspective_enabled(PyUIGridObject* self, void* closure) -{ - return PyBool_FromLong(self->data->perspective_enabled); -} - -int UIGrid::set_perspective_enabled(PyUIGridObject* self, PyObject* value, void* closure) -{ - int enabled = PyObject_IsTrue(value); - if (enabled == -1) { - return -1; - } - self->data->perspective_enabled = enabled; - self->data->markDirty(); - return 0; -} - -// ========================================================================= -// FOV properties -// ========================================================================= - PyObject* UIGrid::get_fov(PyUIGridObject* self, void* closure) { if (PyFOV::fov_enum_class) { @@ -368,17 +286,6 @@ PyObject* UIGrid::get_children(PyUIGridObject* self, void* closure) return (PyObject*)o; } -PyObject* UIGrid::get_view(PyUIGridObject* self, void* closure) -{ - if (!self->view) Py_RETURN_NONE; - auto type = &mcrfpydef::PyUIGridViewType; - auto obj = (PyUIGridViewObject*)type->tp_alloc(type, 0); - if (!obj) return PyErr_NoMemory(); - obj->data = self->view; - obj->weakreflist = NULL; - return (PyObject*)obj; -} - PyObject* UIGrid::get_layers(PyUIGridObject* self, void* closure) { self->data->sortLayers(); @@ -438,70 +345,7 @@ PyObject* UIGrid::repr(PyUIGridObject* self) return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace"); } -// ========================================================================= -// Cell callback properties -// ========================================================================= - -PyObject* UIGrid::get_on_cell_enter(PyUIGridObject* self, void* closure) { - if (self->data->on_cell_enter_callable) { - PyObject* cb = self->data->on_cell_enter_callable->borrow(); - Py_INCREF(cb); - return cb; - } - Py_RETURN_NONE; -} - -int UIGrid::set_on_cell_enter(PyUIGridObject* self, PyObject* value, void* closure) { - if (value == Py_None) { - self->data->on_cell_enter_callable.reset(); - } else { - self->data->on_cell_enter_callable = std::make_unique(value); - } - return 0; -} - -PyObject* UIGrid::get_on_cell_exit(PyUIGridObject* self, void* closure) { - if (self->data->on_cell_exit_callable) { - PyObject* cb = self->data->on_cell_exit_callable->borrow(); - Py_INCREF(cb); - return cb; - } - Py_RETURN_NONE; -} - -int UIGrid::set_on_cell_exit(PyUIGridObject* self, PyObject* value, void* closure) { - if (value == Py_None) { - self->data->on_cell_exit_callable.reset(); - } else { - self->data->on_cell_exit_callable = std::make_unique(value); - } - return 0; -} - -PyObject* UIGrid::get_on_cell_click(PyUIGridObject* self, void* closure) { - if (self->data->on_cell_click_callable) { - PyObject* cb = self->data->on_cell_click_callable->borrow(); - Py_INCREF(cb); - return cb; - } - Py_RETURN_NONE; -} - -int UIGrid::set_on_cell_click(PyUIGridObject* self, PyObject* value, void* closure) { - if (value == Py_None) { - self->data->on_cell_click_callable.reset(); - } else { - self->data->on_cell_click_callable = std::make_unique(value); - } - return 0; -} - -PyObject* UIGrid::get_hovered_cell(PyUIGridObject* self, void* closure) { - if (self->data->hovered_cell.has_value()) { - return Py_BuildValue("(ii)", self->data->hovered_cell->x, self->data->hovered_cell->y); - } - Py_RETURN_NONE; -} +// #355 - cell callback properties moved to UIGridView (src/UIGridView.cpp) // ========================================================================= // getsetters[] table @@ -564,17 +408,6 @@ PyGetSetDef UIGrid::getsetters[] = { "Returns a copy; modifying components requires reassignment. " "For animation, use 'fill_color.r', 'fill_color.g', etc." ), NULL}, - {"perspective", (getter)UIGrid::get_perspective, (setter)UIGrid::set_perspective, - MCRF_PROPERTY(perspective, - "Entity whose perspective to use for FOV rendering (Entity | None). " - "Setting an entity automatically enables perspective mode. " - "Set to None for omniscient view." - ), NULL}, - {"perspective_enabled", (getter)UIGrid::get_perspective_enabled, (setter)UIGrid::set_perspective_enabled, - MCRF_PROPERTY(perspective_enabled, - "Whether to use perspective-based FOV rendering (bool). " - "When True with no valid entity, all cells appear undiscovered." - ), NULL}, {"fov", (getter)UIGrid::get_fov, (setter)UIGrid::set_fov, MCRF_PROPERTY(fov, "FOV algorithm for this grid (FOV enum). " @@ -593,19 +426,6 @@ PyGetSetDef UIGrid::getsetters[] = { UIDRAWABLE_PARENT_GETSETTERS(PyObjectsEnum::UIGRID), UIDRAWABLE_ALIGNMENT_GETSETTERS(PyObjectsEnum::UIGRID), UIDRAWABLE_ROTATION_GETSETTERS(PyObjectsEnum::UIGRID), - {"on_cell_enter", (getter)UIGrid::get_on_cell_enter, (setter)UIGrid::set_on_cell_enter, - MCRF_PROPERTY(on_cell_enter, "Callback when mouse enters a grid cell (Callable | None). Called with (cell_pos: Vector)."), NULL}, - {"on_cell_exit", (getter)UIGrid::get_on_cell_exit, (setter)UIGrid::set_on_cell_exit, - MCRF_PROPERTY(on_cell_exit, "Callback when mouse exits a grid cell (Callable | None). Called with (cell_pos: Vector)."), NULL}, - {"on_cell_click", (getter)UIGrid::get_on_cell_click, (setter)UIGrid::set_on_cell_click, - MCRF_PROPERTY(on_cell_click, "Callback when a grid cell is clicked (Callable | None). Called with (cell_pos: Vector, button: MouseButton, action: InputState)."), NULL}, - {"hovered_cell", (getter)UIGrid::get_hovered_cell, NULL, - MCRF_PROPERTY(hovered_cell, "Currently hovered cell as (x, y) tuple, or None if not hovering (tuple | None, read-only)."), NULL}, UIDRAWABLE_SHADER_GETSETTERS(PyObjectsEnum::UIGRID), - {"view", (getter)UIGrid::get_view, NULL, - MCRF_PROPERTY(view, - "Auto-created GridView for rendering (GridView | None, read-only). " - "When Grid is appended to a scene, this view is what actually renders." - ), NULL}, {NULL} }; diff --git a/src/UIGridView.cpp b/src/UIGridView.cpp index de8a33d..12f6f60 100644 --- a/src/UIGridView.cpp +++ b/src/UIGridView.cpp @@ -15,6 +15,8 @@ #include "PythonObjectCache.h" #include "PySceneObject.h" // parent= kwarg: Scene is a valid parent type #include "McRFPy_Doc.h" +#include "PyMouseButton.h" // #355 - MouseButton enum for cell click args +#include "PyInputState.h" // #355 - InputState enum for cell click args #include #include @@ -78,6 +80,14 @@ void UIGridView::resize(float w, float h) box.setSize(sf::Vector2f(w, h)); } +void UIGridView::onPositionChanged() +{ + // #355: UIDrawable::set_pos/set_float_member write `position` and call this; + // without it the rendered box (and every hit test derived from it) stayed at + // the construction-time origin. + box.setPosition(position); +} + sf::Vector2f UIGridView::getEffectiveCellSize() const { int cw = ptex ? ptex->sprite_width : DEFAULT_CELL_WIDTH; @@ -85,24 +95,53 @@ sf::Vector2f UIGridView::getEffectiveCellSize() const return sf::Vector2f(cw * zoom, ch * zoom); } -std::optional UIGridView::screenToCell(sf::Vector2f screen_pos) const +sf::Vector2f UIGridView::localToGridWorld(sf::Vector2f local) const +{ + // Exact inverse of render()'s rasterize-then-composite transform (including + // the int truncation of left/top_spritepixels), so hit testing matches what + // is drawn -- rotated camera included. + // + // render(): grid-world -> texture pixel + // T = (gw - spritepixels) * zoom [texture is aabb_w x aabb_h] + // then the texture is blitted rotated by camera_rotation about its center, + // landing on the widget center: + // L - box_center = R(camera_rotation) * (T - tex_center) + // Inverting: T = R(-camera_rotation) * (L - box_center) + tex_center, + // gw = T / zoom + spritepixels. + const float grid_w_px = box.getSize().x; + const float grid_h_px = box.getSize().y; + + const float rad = camera_rotation * (float)(M_PI / 180.0); + const float cos_r = std::cos(rad); + const float sin_r = std::sin(rad); + // Same AABB the renderer rasterizes into (equals the box when unrotated). + const float aabb_w = grid_w_px * std::abs(cos_r) + grid_h_px * std::abs(sin_r); + const float aabb_h = grid_w_px * std::abs(sin_r) + grid_h_px * std::abs(cos_r); + + const float dx = local.x - grid_w_px / 2.0f; + const float dy = local.y - grid_h_px / 2.0f; + // R(-camera_rotation) applied to (dx, dy), then re-centered on the AABB. + const float tx = dx * cos_r + dy * sin_r + aabb_w / 2.0f; + const float ty = -dx * sin_r + dy * cos_r + aabb_h / 2.0f; + + int left_spritepixels = center_x - (aabb_w / 2.0 / zoom); + int top_spritepixels = center_y - (aabb_h / 2.0 / zoom); + return sf::Vector2f(tx / zoom + left_spritepixels, + ty / zoom + top_spritepixels); +} + +std::optional UIGridView::cellAtLocal(sf::Vector2f local) const { if (!grid_data) return std::nullopt; - if (!box.getGlobalBounds().contains(screen_pos)) return std::nullopt; - - int cw = ptex ? ptex->sprite_width : DEFAULT_CELL_WIDTH; + if (local.x < 0 || local.y < 0 || + local.x >= box.getSize().x || local.y >= box.getSize().y) { + return std::nullopt; + } + int cw = ptex ? ptex->sprite_width : DEFAULT_CELL_WIDTH; int ch = ptex ? ptex->sprite_height : DEFAULT_CELL_HEIGHT; - - sf::Vector2f local = screen_pos - box.getPosition(); - int left_sp = center_x - (box.getSize().x / 2.0 / zoom); - int top_sp = center_y - (box.getSize().y / 2.0 / zoom); - - float gx = (local.x / zoom + left_sp) / cw; - float gy = (local.y / zoom + top_sp) / ch; - - int cx = static_cast(std::floor(gx)); - int cy = static_cast(std::floor(gy)); - + sf::Vector2f gw = localToGridWorld(local); + int cx = static_cast(std::floor(gw.x / cw)); + int cy = static_cast(std::floor(gw.y / ch)); if (cx < 0 || cx >= grid_data->grid_w || cy < 0 || cy >= grid_data->grid_h) return std::nullopt; return sf::Vector2i(cx, cy); @@ -137,14 +176,16 @@ void UIGridView::render(sf::Vector2f offset, sf::RenderTarget& target) // #351 - clean-state early-out: re-blit the cached RenderTexture when nothing // affecting the raster changed since last frame. Camera params are compared // directly (view-local); grid content changes bump content_generation. The - // perspective overlay (checked authoritatively on the UIGrid, since the view's - // copy is not resynced at runtime) and any grid children are conservative + // perspective overlay (single source of truth: this view's own + // perspective_enabled, see #355 fix) and any grid children are conservative // always-render carve-outs until tracked precisely (#352). - UIGrid* ugrid = static_cast(grid_data.get()); - bool perspective_active = perspective_enabled || (ugrid && ugrid->perspective_enabled); + // last_perspective_enabled: the cached raster HAS an overlay baked into it, so + // the frame that turns perspective off must re-rasterize even though every + // other input is unchanged (otherwise the fog stays on screen forever). bool can_skip = has_rendered_once - && !perspective_active + && !perspective_enabled + && !last_perspective_enabled && (!grid_data->children || grid_data->children->empty()) && grid_data->content_generation == last_content_gen && center_x == last_center_x && center_y == last_center_y @@ -273,8 +314,9 @@ void UIGridView::render(sf::Vector2f offset, sf::RenderTarget& target) } } - // Perspective overlay + // Perspective overlay (#355: state owned by the view -- see get/set_perspective) if (perspective_enabled) { + ScopedTimer fovTimer(Resources::game->metrics.fovOverlayTime); auto entity = perspective_entity.lock(); sf::RectangleShape overlay; overlay.setSize(sf::Vector2f(cell_width * zoom, cell_height * zoom)); @@ -355,6 +397,7 @@ void UIGridView::render(sf::Vector2f offset, sf::RenderTarget& target) last_box_size = box.getSize(); last_fill_color = fill_color; last_render_tex_size = renderTextureSize; + last_perspective_enabled = perspective_enabled; if (shader && shader->shader) { sf::Vector2f resolution(box.getSize().x, box.getSize().y); @@ -368,8 +411,59 @@ void UIGridView::render(sf::Vector2f offset, sf::RenderTarget& target) UIDrawable* UIGridView::click_at(sf::Vector2f point) { + // point is in PARENT-LOCAL space (UIFrame::click_at passes point - position down). if (!box.getGlobalBounds().contains(point)) return nullptr; - return this; // GridView consumes clicks within its bounds + if (!grid_data) { + return (click_callable || is_python_subclass) ? this : nullptr; + } + + sf::Vector2f local = point - box.getPosition(); + sf::Vector2f gw = localToGridWorld(local); + + int cw = ptex ? ptex->sprite_width : DEFAULT_CELL_WIDTH; + int ch = ptex ? ptex->sprite_height : DEFAULT_CELL_HEIGHT; + float grid_x = gw.x / cw; + float grid_y = gw.y / ch; + + // 1. Children first (drawn on top). Children of a grid live in GRID-WORLD PIXEL + // coordinates -- NOT view-local, NOT screen (#360, by design: moving the + // camera must not move a child's logical position). Do not "fix" this. + if (grid_data->children && !grid_data->children->empty()) { + if (grid_data->children_need_sort) { + std::sort(grid_data->children->begin(), grid_data->children->end(), + [](const auto& a, const auto& b) { return a->z_index < b->z_index; }); + grid_data->children_need_sort = false; + } + for (auto it = grid_data->children->rbegin(); it != grid_data->children->rend(); ++it) { + auto& child = *it; + if (!child->visible) continue; + if (auto target = child->click_at(gw)) return target; + } + } + + // 2. Entities: 1x1 cell hit box matching the renderer, which draws the sprite at + // position.x * cell_width -- i.e. cell [pos, pos+1). + // NOTE: unreachable from Python today -- Entity exposes no on_click/sprite + // binding, so entity->sprite.click_callable can never be set, and this branch + // cannot fire. Implemented per #355; dead until an Entity.on_click binding + // exists (needs its own issue). + if (grid_data->entities) { + for (auto it = grid_data->entities->rbegin(); it != grid_data->entities->rend(); ++it) { + auto& entity = *it; + if (!entity || !entity->sprite.visible) continue; + float dx = grid_x - entity->position.x; + float dy = grid_y - entity->position.y; + if (dx >= 0.0f && dx < 1.0f && dy >= 0.0f && dy < 1.0f) { + if (entity->sprite.click_callable) return &entity->sprite; + } + } + } + + // 3. The cell itself. Stash for dispatchCellClick (PyScene has only global coords). + last_clicked_cell = cellAtLocal(local); + + if (click_callable || is_python_subclass || on_cell_click_callable) return this; + return nullptr; } // Property system @@ -532,6 +626,14 @@ int UIGridView::init_explicit_view(PyUIGridViewObject* self, PyObject* args, PyO if (self->data->grid_data) { self->data->center_camera(); self->data->ensureRenderTextureSize(); + // #359 - Register this view so it receives markDirty/markCompositeDirty + // notifications (its own ancestor chain -- e.g. a Frame(use_render_texture= + // True) wrapping this view -- needs invalidating too, not just the + // creating view's). Does NOT disturb identity: primaryView() (used by + // UIEntity::get_grid) is views.front(), which is always the view that + // created this GridData via init_with_data, since init_explicit_view can + // only attach to grid_data that already exists. + self->data->grid_data->registerView(self->data); } self->weakreflist = NULL; @@ -605,8 +707,8 @@ int UIGridView::init_with_data(PyUIGridViewObject* self, PyObject* args, PyObjec } } - // Set owning_view back-reference on the GridData - self->data->grid_data->owning_view = self->data; + // #359 - Register this view on the GridData (dirty-notification + identity) + self->data->grid_data->registerView(self->data); self->data->ensureRenderTextureSize(); @@ -776,35 +878,35 @@ int UIGridView::set_grid(PyUIGridViewObject* self, PyObject* value, void* closur // #348: the persistent wrapper tracks the *current* grid_data; any reassign // (including to None) invalidates it so get_grid rebuilds for the new data. Py_CLEAR(self->data->cached_grid_wrapper); + // #359 - Unregister self from whatever grid_data it was viewing before + // reassignment. unregisterView matches by identity (self->data.get()), so + // this is safe even when other views also share the old grid_data. + if (self->data->grid_data) { + self->data->grid_data->unregisterView(self->data.get()); + } if (value == Py_None) { - if (self->data->grid_data) { - self->data->grid_data->owning_view.reset(); - } self->data->grid_data = nullptr; return 0; } // Accept internal _GridData (UIGrid) objects if (PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PyUIGridType)) { PyUIGridObject* pygrid = (PyUIGridObject*)value; - if (self->data->grid_data) { - self->data->grid_data->owning_view.reset(); - } self->data->grid_data = std::shared_ptr( pygrid->data, static_cast(pygrid->data.get())); self->data->ptex = pygrid->data->getTexture(); - self->data->grid_data->owning_view = self->data; + self->data->grid_data->registerView(self->data); return 0; } // Accept GridView (unified Grid) objects - share their grid_data if (PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PyUIGridViewType)) { PyUIGridViewObject* pyview = (PyUIGridViewObject*)value; if (pyview->data->grid_data) { - if (self->data->grid_data) { - self->data->grid_data->owning_view.reset(); - } self->data->grid_data = pyview->data->grid_data; self->data->ptex = pyview->data->ptex; - // Don't override owning_view - original owner keeps it + // #359: register self alongside the original owner (and any other + // secondary views) -- does not disturb primaryView() identity, + // which stays views.front() (the original creator). + self->data->grid_data->registerView(self->data); return 0; } self->data->grid_data = nullptr; @@ -856,6 +958,68 @@ int UIGridView::set_fill_color(PyUIGridViewObject* self, PyObject* value, void* return 0; } +// ========================================================================= +// Perspective (#355 fix): OWNED BY THE VIEW. The FOV overlay is drawn by +// UIGridView::render, so the state it gates on must live here -- previously +// `grid.perspective` fell through getattro to the internal _GridData and wrote +// UIGrid::perspective_enabled, which render() never read: the overlay was dead. +// Per-view ownership is also the correct semantics for shared GridData (#359): +// two views of one map can follow two different entities' FOV. +// ========================================================================= +PyObject* UIGridView::get_perspective(PyUIGridViewObject* self, void* closure) +{ + auto locked = self->data->perspective_entity.lock(); + if (!locked) Py_RETURN_NONE; + + // Honor the cache so Entity subclass identity survives (#266). + if (locked->serial_number != 0) { + PyObject* cached = PythonObjectCache::getInstance().lookup(locked->serial_number); + if (cached) return cached; // new ref + } + + auto type = &mcrfpydef::PyUIEntityType; + auto o = (PyUIEntityObject*)type->tp_alloc(type, 0); + if (!o) return PyErr_NoMemory(); + o->data = locked; + o->weakreflist = NULL; + return (PyObject*)o; +} + +int UIGridView::set_perspective(PyUIGridViewObject* self, PyObject* value, void* closure) +{ + if (value == Py_None) { + self->data->perspective_entity.reset(); + self->data->perspective_enabled = false; + self->data->markDirty(); + return 0; + } + + if (!PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PyUIEntityType)) { + PyErr_SetString(PyExc_TypeError, "perspective must be an Entity or None"); + return -1; + } + + PyUIEntityObject* entity_obj = (PyUIEntityObject*)value; + self->data->perspective_entity = entity_obj->data; + self->data->perspective_enabled = true; + self->data->markDirty(); + return 0; +} + +PyObject* UIGridView::get_perspective_enabled(PyUIGridViewObject* self, void* closure) +{ + return PyBool_FromLong(self->data->perspective_enabled); +} + +int UIGridView::set_perspective_enabled(PyUIGridViewObject* self, PyObject* value, void* closure) +{ + int enabled = PyObject_IsTrue(value); + if (enabled == -1) return -1; + self->data->perspective_enabled = enabled; + self->data->markDirty(); + return 0; +} + PyObject* UIGridView::get_texture(PyUIGridViewObject* self, void* closure) { // #318: return a Texture wrapper sharing the underlying shared_ptr, @@ -904,6 +1068,342 @@ int UIGridView::set_float_member_gv(PyUIGridViewObject* self, PyObject* value, v return 0; } +// ========================================================================= +// #355 - Cell input machinery (moved verbatim from UIGrid, retargeted to the view) +// ========================================================================= + +// Helper function to convert button string to MouseButton enum value +static int buttonStringToEnum(const std::string& button) { + if (button == "left") return 0; // MouseButton.LEFT + if (button == "right") return 1; // MouseButton.RIGHT + if (button == "middle") return 2; // MouseButton.MIDDLE + if (button == "wheel_up") return 3; // MouseButton.WHEEL_UP + if (button == "wheel_down") return 4; // MouseButton.WHEEL_DOWN + return 0; // Default to LEFT +} + +// Helper function to convert action string to InputState enum value +static int actionStringToEnum(const std::string& action) { + if (action == "start" || action == "pressed") return 0; // InputState.PRESSED + if (action == "end" || action == "released") return 1; // InputState.RELEASED + return 0; // Default to PRESSED +} + +// Helper to create typed cell callback arguments: (Vector, MouseButton, InputState) +static PyObject* createCellCallbackArgs(sf::Vector2i cell, const std::string& button, const std::string& action) { + PyObject* cell_pos = PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ff", (float)cell.x, (float)cell.y); + if (!cell_pos) { + PyErr_Print(); + return nullptr; + } + + int button_val = buttonStringToEnum(button); + PyObject* button_enum = PyObject_CallFunction(PyMouseButton::mouse_button_enum_class, "i", button_val); + if (!button_enum) { + Py_DECREF(cell_pos); + PyErr_Print(); + return nullptr; + } + + int action_val = actionStringToEnum(action); + PyObject* action_enum = PyObject_CallFunction(PyInputState::input_state_enum_class, "i", action_val); + if (!action_enum) { + Py_DECREF(cell_pos); + Py_DECREF(button_enum); + PyErr_Print(); + return nullptr; + } + + PyObject* args = Py_BuildValue("(OOO)", cell_pos, button_enum, action_enum); + Py_DECREF(cell_pos); + Py_DECREF(button_enum); + Py_DECREF(action_enum); + return args; +} + +// #230 - Helper to create cell hover callback arguments: (Vector) only +static PyObject* createCellHoverArgs(sf::Vector2i cell) { + PyObject* cell_pos = PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ii", cell.x, cell.y); + if (!cell_pos) { + PyErr_Print(); + return nullptr; + } + + PyObject* args = Py_BuildValue("(O)", cell_pos); + Py_DECREF(cell_pos); + return args; +} + +// #142 - Refresh cell callback cache for Python subclass method support +void UIGridView::refreshCellCallbackCache(PyObject* pyObj) { + if (!pyObj || !is_python_subclass) { + cell_callback_cache.valid = false; + return; + } + + // Get the class's callback generation counter + PyObject* cls = (PyObject*)Py_TYPE(pyObj); + uint32_t current_gen = 0; + PyObject* gen_obj = PyObject_GetAttrString(cls, "_mcrf_callback_gen"); + if (gen_obj) { + current_gen = static_cast(PyLong_AsUnsignedLong(gen_obj)); + Py_DECREF(gen_obj); + } else { + PyErr_Clear(); + } + + if (cell_callback_cache.valid && cell_callback_cache.generation == current_gen) { + return; // Cache is fresh + } + + cell_callback_cache.has_on_cell_click = false; + cell_callback_cache.has_on_cell_enter = false; + cell_callback_cache.has_on_cell_exit = false; + + // Walk the class hierarchy down to (but not including) the base Grid type. + // #355: sentinel is PyUIGridViewType -- mcrfpy.Grid IS UIGridView. + PyTypeObject* type = Py_TYPE(pyObj); + while (type && type != &mcrfpydef::PyUIGridViewType && type != &PyBaseObject_Type) { + if (type->tp_dict) { + if (!cell_callback_cache.has_on_cell_click) { + PyObject* method = PyDict_GetItemString(type->tp_dict, "on_cell_click"); + if (method && PyCallable_Check(method)) { + cell_callback_cache.has_on_cell_click = true; + } + } + if (!cell_callback_cache.has_on_cell_enter) { + PyObject* method = PyDict_GetItemString(type->tp_dict, "on_cell_enter"); + if (method && PyCallable_Check(method)) { + cell_callback_cache.has_on_cell_enter = true; + } + } + if (!cell_callback_cache.has_on_cell_exit) { + PyObject* method = PyDict_GetItemString(type->tp_dict, "on_cell_exit"); + if (method && PyCallable_Check(method)) { + cell_callback_cache.has_on_cell_exit = true; + } + } + } + type = type->tp_base; + } + + cell_callback_cache.generation = current_gen; + cell_callback_cache.valid = true; +} + +// Fire cell click callback with full signature (cell_pos, button, action) +bool UIGridView::fireCellClick(sf::Vector2i cell, const std::string& button, const std::string& action) { + // Try property-assigned callback first + if (on_cell_click_callable && !on_cell_click_callable->isNone()) { + PyObject* args = createCellCallbackArgs(cell, button, action); + if (args) { + PyObject* result = PyObject_CallObject(on_cell_click_callable->borrow(), args); + Py_DECREF(args); + if (!result) { + std::cerr << "Cell click callback raised an exception:" << std::endl; + PyErr_Print(); + PyErr_Clear(); + } else { + Py_DECREF(result); + } + return true; + } + } + + // Try Python subclass method + if (is_python_subclass) { + PyObject* pyObj = PythonObjectCache::getInstance().lookup(this->serial_number); + if (pyObj) { + refreshCellCallbackCache(pyObj); + if (cell_callback_cache.has_on_cell_click) { + PyObject* method = PyObject_GetAttrString(pyObj, "on_cell_click"); + if (method && PyCallable_Check(method)) { + PyObject* args = createCellCallbackArgs(cell, button, action); + if (args) { + PyObject* result = PyObject_CallObject(method, args); + Py_DECREF(args); + Py_DECREF(method); + Py_DECREF(pyObj); + if (!result) { + std::cerr << "Cell click method raised an exception:" << std::endl; + PyErr_Print(); + PyErr_Clear(); + } else { + Py_DECREF(result); + } + return true; + } + } + Py_XDECREF(method); + } + Py_DECREF(pyObj); + } + } + return false; +} + +// #230 - Fire cell enter callback with position-only signature (cell_pos) +bool UIGridView::fireCellEnter(sf::Vector2i cell) { + if (on_cell_enter_callable && !on_cell_enter_callable->isNone()) { + on_cell_enter_callable->call(cell); + return true; + } + + if (is_python_subclass) { + PyObject* pyObj = PythonObjectCache::getInstance().lookup(this->serial_number); + if (pyObj) { + refreshCellCallbackCache(pyObj); + if (cell_callback_cache.has_on_cell_enter) { + PyObject* method = PyObject_GetAttrString(pyObj, "on_cell_enter"); + if (method && PyCallable_Check(method)) { + PyObject* args = createCellHoverArgs(cell); + if (args) { + PyObject* result = PyObject_CallObject(method, args); + Py_DECREF(args); + Py_DECREF(method); + Py_DECREF(pyObj); + if (!result) { + std::cerr << "Cell enter method raised an exception:" << std::endl; + PyErr_Print(); + PyErr_Clear(); + } else { + Py_DECREF(result); + } + return true; + } + } + Py_XDECREF(method); + } + Py_DECREF(pyObj); + } + } + return false; +} + +// #230 - Fire cell exit callback with position-only signature (cell_pos) +bool UIGridView::fireCellExit(sf::Vector2i cell) { + if (on_cell_exit_callable && !on_cell_exit_callable->isNone()) { + on_cell_exit_callable->call(cell); + return true; + } + + if (is_python_subclass) { + PyObject* pyObj = PythonObjectCache::getInstance().lookup(this->serial_number); + if (pyObj) { + refreshCellCallbackCache(pyObj); + if (cell_callback_cache.has_on_cell_exit) { + PyObject* method = PyObject_GetAttrString(pyObj, "on_cell_exit"); + if (method && PyCallable_Check(method)) { + PyObject* args = createCellHoverArgs(cell); + if (args) { + PyObject* result = PyObject_CallObject(method, args); + Py_DECREF(args); + Py_DECREF(method); + Py_DECREF(pyObj); + if (!result) { + std::cerr << "Cell exit method raised an exception:" << std::endl; + PyErr_Print(); + PyErr_Clear(); + } else { + Py_DECREF(result); + } + return true; + } + } + Py_XDECREF(method); + } + Py_DECREF(pyObj); + } + } + return false; +} + +// #355 - UIDrawable input virtuals +bool UIGridView::dispatchCellClick(const std::string& button, const std::string& action) +{ + if (!last_clicked_cell.has_value()) return false; + sf::Vector2i cell = last_clicked_cell.value(); + last_clicked_cell = std::nullopt; + return fireCellClick(cell, button, action); +} + +void UIGridView::updateHover(sf::Vector2f point, bool hit_allowed) +{ + // point is PARENT-local (same space as click_at); the view's own box position + // takes it to widget-local, and cellAtLocal applies this view's camera. + std::optional new_cell = std::nullopt; + if (hit_allowed) new_cell = cellAtLocal(point - box.getPosition()); + if (new_cell != hovered_cell) { + if (hovered_cell.has_value()) fireCellExit(hovered_cell.value()); + if (new_cell.has_value()) fireCellEnter(new_cell.value()); + hovered_cell = new_cell; + } +} + +// ========================================================================= +// #355 - Cell callback properties (moved from UIGrid) +// ========================================================================= +PyObject* UIGridView::get_on_cell_enter(PyUIGridViewObject* self, void* closure) { + if (self->data->on_cell_enter_callable) { + PyObject* cb = self->data->on_cell_enter_callable->borrow(); + Py_INCREF(cb); + return cb; + } + Py_RETURN_NONE; +} + +int UIGridView::set_on_cell_enter(PyUIGridViewObject* self, PyObject* value, void* closure) { + if (value == Py_None) { + self->data->on_cell_enter_callable.reset(); + } else { + self->data->on_cell_enter_callable = std::make_unique(value); + } + return 0; +} + +PyObject* UIGridView::get_on_cell_exit(PyUIGridViewObject* self, void* closure) { + if (self->data->on_cell_exit_callable) { + PyObject* cb = self->data->on_cell_exit_callable->borrow(); + Py_INCREF(cb); + return cb; + } + Py_RETURN_NONE; +} + +int UIGridView::set_on_cell_exit(PyUIGridViewObject* self, PyObject* value, void* closure) { + if (value == Py_None) { + self->data->on_cell_exit_callable.reset(); + } else { + self->data->on_cell_exit_callable = std::make_unique(value); + } + return 0; +} + +PyObject* UIGridView::get_on_cell_click(PyUIGridViewObject* self, void* closure) { + if (self->data->on_cell_click_callable) { + PyObject* cb = self->data->on_cell_click_callable->borrow(); + Py_INCREF(cb); + return cb; + } + Py_RETURN_NONE; +} + +int UIGridView::set_on_cell_click(PyUIGridViewObject* self, PyObject* value, void* closure) { + if (value == Py_None) { + self->data->on_cell_click_callable.reset(); + } else { + self->data->on_cell_click_callable = std::make_unique(value); + } + return 0; +} + +PyObject* UIGridView::get_hovered_cell(PyUIGridViewObject* self, void* closure) { + if (self->data->hovered_cell.has_value()) { + return Py_BuildValue("(ii)", self->data->hovered_cell->x, self->data->hovered_cell->y); + } + Py_RETURN_NONE; +} + // ========================================================================= // Subscript protocol: grid[x, y] -> GridPoint (delegates to GridData). // Setitem raises TypeError (GridPoints are views, not assignable). @@ -1019,5 +1519,26 @@ PyGetSetDef UIGridView::getsetters[] = { UIDRAWABLE_ALIGNMENT_GETSETTERS(PyObjectsEnum::UIGRIDVIEW), UIDRAWABLE_ROTATION_GETSETTERS(PyObjectsEnum::UIGRIDVIEW), UIDRAWABLE_SHADER_GETSETTERS(PyObjectsEnum::UIGRIDVIEW), + // #355 - cell input properties (moved from _GridData to the view) + {"on_cell_enter", (getter)UIGridView::get_on_cell_enter, (setter)UIGridView::set_on_cell_enter, + MCRF_PROPERTY(on_cell_enter, "Callback when mouse enters a grid cell (Callable | None). Called with (cell_pos: Vector)."), NULL}, + {"on_cell_exit", (getter)UIGridView::get_on_cell_exit, (setter)UIGridView::set_on_cell_exit, + MCRF_PROPERTY(on_cell_exit, "Callback when mouse exits a grid cell (Callable | None). Called with (cell_pos: Vector)."), NULL}, + {"on_cell_click", (getter)UIGridView::get_on_cell_click, (setter)UIGridView::set_on_cell_click, + MCRF_PROPERTY(on_cell_click, "Callback when a grid cell is clicked (Callable | None). Called with (cell_pos: Vector, button: MouseButton, action: InputState)."), NULL}, + {"hovered_cell", (getter)UIGridView::get_hovered_cell, NULL, + MCRF_PROPERTY(hovered_cell, "Currently hovered cell as (x, y) tuple, or None if not hovering (tuple | None, read-only)."), NULL}, + // #355 - perspective moved from _GridData to the view: render() draws the FOV + // overlay, so the view must own the state it gates on. Per-view, so two views + // of one grid can follow different entities. + {"perspective", (getter)UIGridView::get_perspective, (setter)UIGridView::set_perspective, + MCRF_PROPERTY(perspective, + "Entity whose perspective_map drives fog-of-war rendering in this view (Entity | None). " + "Setting an entity enables perspective mode; setting None disables it. " + "Cells the entity has never seen are drawn black, discovered-but-not-visible cells dimmed."), NULL}, + {"perspective_enabled", (getter)UIGridView::get_perspective_enabled, (setter)UIGridView::set_perspective_enabled, + MCRF_PROPERTY(perspective_enabled, + "Whether this view renders the perspective/FOV overlay (bool). " + "Set automatically when assigning perspective; set False to show the whole map without clearing the entity."), NULL}, {NULL} }; diff --git a/src/UIGridView.h b/src/UIGridView.h index 1871cdb..61be536 100644 --- a/src/UIGridView.h +++ b/src/UIGridView.h @@ -41,6 +41,7 @@ public: sf::FloatRect get_bounds() const override; void move(float dx, float dy) override; void resize(float w, float h) override; + void onPositionChanged() override; // #355: keep box in sync with position // The grid data this view renders std::shared_ptr grid_data; @@ -64,6 +65,42 @@ public: std::weak_ptr perspective_entity; bool perspective_enabled = false; + // ===================================================================== + // #355 - Cell input. Owned by the VIEW, not GridData: two views over one + // GridData must each track their own hover cell (a shared hovered_cell + // would ping-pong exit/enter between views), and the subclass-dispatch + // path must resolve against the VIEW's serial_number, because the public + // subclassable type (mcrfpy.Grid) IS UIGridView. + // ===================================================================== + std::unique_ptr on_cell_enter_callable; + std::unique_ptr on_cell_exit_callable; + std::unique_ptr on_cell_click_callable; + std::optional hovered_cell; // Python-visible (read-only) + std::optional last_clicked_cell; // C++ only: click_at -> dispatchCellClick + + struct CellCallbackCache { + uint32_t generation = 0; + bool valid = false; + bool has_on_cell_click = false; + bool has_on_cell_enter = false; + bool has_on_cell_exit = false; + }; + CellCallbackCache cell_callback_cache; + + bool fireCellClick(sf::Vector2i cell, const std::string& button, const std::string& action); + bool fireCellEnter(sf::Vector2i cell); + bool fireCellExit(sf::Vector2i cell); + void refreshCellCallbackCache(PyObject* pyObj); + + // UIDrawable input virtuals (#355) + bool dispatchCellClick(const std::string& button, const std::string& action) override; + void updateHover(sf::Vector2f point, bool hit_allowed) override; + GridData* asGridData() override { return grid_data.get(); } + + // Cell math. local_point is relative to the widget's top-left. + sf::Vector2f localToGridWorld(sf::Vector2f local_point) const; + std::optional cellAtLocal(sf::Vector2f local_point) const; + // #351 - clean-state render early-out cache. These record the inputs the // current RenderTexture was rasterized from; render() re-blits the cached // texture instead of clear+redraw when none changed. Camera params are @@ -76,6 +113,7 @@ public: sf::Vector2f last_box_size{-1.f, -1.f}; sf::Color last_fill_color{0, 0, 0, 0}; sf::Vector2u last_render_tex_size{0, 0}; + bool last_perspective_enabled = false; // #355: fog baked into the cached raster // Render textures sf::Sprite sprite_proto, output; @@ -96,8 +134,9 @@ public: void center_camera(); void center_camera(float tile_x, float tile_y); - // Cell coordinate conversion - std::optional screenToCell(sf::Vector2f screen_pos) const; + // #355: no screenToCell() -- hover/click both arrive in parent-local space and + // go through cellAtLocal(). A global-coords helper would be a second, wrong + // coordinate path for grids nested inside frames/grids. sf::Vector2f getEffectiveCellSize() const; static constexpr int DEFAULT_CELL_WIDTH = 16; @@ -130,6 +169,21 @@ public: static PyObject* get_float_member_gv(PyUIGridViewObject* self, void* closure); static int set_float_member_gv(PyUIGridViewObject* self, PyObject* value, void* closure); + // #355 - cell callback properties (moved from UIGrid) + static PyObject* get_on_cell_enter(PyUIGridViewObject* self, void* closure); + static int set_on_cell_enter(PyUIGridViewObject* self, PyObject* value, void* closure); + static PyObject* get_on_cell_exit(PyUIGridViewObject* self, void* closure); + static int set_on_cell_exit(PyUIGridViewObject* self, PyObject* value, void* closure); + static PyObject* get_on_cell_click(PyUIGridViewObject* self, void* closure); + static int set_on_cell_click(PyUIGridViewObject* self, PyObject* value, void* closure); + static PyObject* get_hovered_cell(PyUIGridViewObject* self, void* closure); + + // #355 - perspective properties (moved from UIGrid: the view renders the overlay) + static PyObject* get_perspective(PyUIGridViewObject* self, void* closure); + static int set_perspective(PyUIGridViewObject* self, PyObject* value, void* closure); + static PyObject* get_perspective_enabled(PyUIGridViewObject* self, void* closure); + static int set_perspective_enabled(PyUIGridViewObject* self, PyObject* value, void* closure); + static PyMethodDef methods[]; static PyGetSetDef getsetters[]; @@ -159,17 +213,16 @@ namespace mcrfpydef { if (obj->weakreflist != NULL) { PyObject_ClearWeakRefs(self); } - // Clear owning_view back-reference before releasing grid_data -- - // but only when this wrapper is the LAST owner of the view (#251 - // pattern, mirrors PyUIGridType) AND the dying view is actually - // the one owning_view points at. The previous ungated reset - // severed the back-reference whenever ANY Python wrapper was + // #359: Unregister from the GridData's view list before releasing + // grid_data -- but only when this wrapper is the LAST owner of the + // view (#251 pattern, mirrors PyUIGridType). An ungated unregister + // would sever the back-reference whenever ANY Python wrapper was // GC'd while the C++ view lived on (e.g. held by scene.children), // breaking entity.grid -> Grid identity and the #313 data-layer - // dirty notifications. - if (obj->data && obj->data->grid_data && obj->data.use_count() <= 1 && - obj->data->grid_data->owning_view.lock() == obj->data) { - obj->data->grid_data->owning_view.reset(); + // dirty notifications. unregisterView matches by identity, so it's + // harmless (a no-op) if this view was never registered. + if (obj->data && obj->data->grid_data && obj->data.use_count() <= 1) { + obj->data->grid_data->unregisterView(obj->data.get()); } obj->data.reset(); Py_TYPE(self)->tp_free(self); @@ -212,6 +265,21 @@ namespace mcrfpydef { if (obj->data && obj->data->cached_grid_wrapper) { Py_VISIT(obj->data->cached_grid_wrapper); } + // #355: cell callbacks now live on the view. + if (obj->data) { + if (obj->data->on_cell_enter_callable) { + PyObject* cb = obj->data->on_cell_enter_callable->borrow(); + if (cb && cb != Py_None) Py_VISIT(cb); + } + if (obj->data->on_cell_exit_callable) { + PyObject* cb = obj->data->on_cell_exit_callable->borrow(); + if (cb && cb != Py_None) Py_VISIT(cb); + } + if (obj->data->on_cell_click_callable) { + PyObject* cb = obj->data->on_cell_click_callable->borrow(); + if (cb && cb != Py_None) Py_VISIT(cb); + } + } return 0; }, .tp_clear = [](PyObject* self) -> int { @@ -220,6 +288,10 @@ namespace mcrfpydef { obj->data->click_unregister(); // #348: drop the persistent wrapper; get_grid rebuilds on demand. Py_CLEAR(obj->data->cached_grid_wrapper); + // #355: release cell callbacks (breaks closure->grid cycles). + obj->data->on_cell_enter_callable.reset(); + obj->data->on_cell_exit_callable.reset(); + obj->data->on_cell_click_callable.reset(); } return 0; }, diff --git a/tests/regression/issue_355_camera_rotation_hit_test.py b/tests/regression/issue_355_camera_rotation_hit_test.py new file mode 100644 index 0000000..66b3b53 --- /dev/null +++ b/tests/regression/issue_355_camera_rotation_hit_test.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python3 +"""Regression test for #355 - cell hit testing under camera_rotation. + +UIGridView::localToGridWorld() rasterizes-then-rotates in render(), but the hit +test used to skip the rotation entirely (and used the widget size instead of the +rotated AABB). With camera_rotation != 0 every cell handed to on_cell_click / +on_cell_enter / on_cell_exit / hovered_cell was the cell that WOULD be under the +mouse if the camera were unrotated -- plausible-looking, silently wrong data. +Before #355 all grid input was dead, so this ships as new behavior; it has to be +right. + +GROUND TRUTH IS THE RENDERED IMAGE, not a re-derivation of the camera math: one +cell is painted pure red by a ColorLayer, the frame is screenshotted, the red +pixels are located by decoding the PNG, and the click is aimed at their centroid. +The cell reported back by on_cell_click must be the red cell. +""" +import sys +import os +import zlib +import struct +import tempfile + +import mcrfpy +from mcrfpy import automation + +CELL = 16 +TMPDIR = tempfile.mkdtemp(prefix="mcrf355rot_") +FAILURES = [] + + +def check(cond, msg): + if not cond: + print("FAIL: %s" % msg, file=sys.stderr) + FAILURES.append(msg) + + +# --------------------------------------------------------------------------- # +# Minimal PNG reader (stdlib only): 8-bit RGB/RGBA, non-interlaced -- what the +# engine's screenshot encoder emits. +# --------------------------------------------------------------------------- # +def read_png(path): + with open(path, "rb") as f: + data = f.read() + assert data[:8] == b"\x89PNG\r\n\x1a\n", "not a PNG" + pos = 8 + idat = b"" + width = height = depth = color = None + while pos < len(data): + (length,) = struct.unpack(">I", data[pos:pos + 4]) + ctype = data[pos + 4:pos + 8] + chunk = data[pos + 8:pos + 8 + length] + pos += 12 + length + if ctype == b"IHDR": + width, height, depth, color, _, _, interlace = struct.unpack(">IIBBBBB", chunk) + assert depth == 8, "unexpected bit depth %d" % depth + assert color in (2, 6), "unexpected color type %d" % color + assert interlace == 0, "interlaced PNG not supported" + elif ctype == b"IDAT": + idat += chunk + elif ctype == b"IEND": + break + + raw = zlib.decompress(idat) + channels = 3 if color == 2 else 4 + stride = width * channels + out = bytearray(height * stride) + prev = bytearray(stride) + p = 0 + for y in range(height): + filt = raw[p] + p += 1 + line = bytearray(raw[p:p + stride]) + p += stride + if filt == 1: # Sub + for i in range(channels, stride): + line[i] = (line[i] + line[i - channels]) & 0xFF + elif filt == 2: # Up + for i in range(stride): + line[i] = (line[i] + prev[i]) & 0xFF + elif filt == 3: # Average + for i in range(stride): + a = line[i - channels] if i >= channels else 0 + line[i] = (line[i] + ((a + prev[i]) >> 1)) & 0xFF + elif filt == 4: # Paeth + for i in range(stride): + a = line[i - channels] if i >= channels else 0 + b = prev[i] + c = prev[i - channels] if i >= channels else 0 + pa, pb, pc = abs(b - c), abs(a - c), abs(a + b - 2 * c) + pr = a if (pa <= pb and pa <= pc) else (b if pb <= pc else c) + line[i] = (line[i] + pr) & 0xFF + elif filt != 0: + raise AssertionError("bad PNG filter %d" % filt) + out[y * stride:(y + 1) * stride] = line + prev = line + return width, height, channels, bytes(out) + + +def red_centroid(path): + """Centroid of pure-red pixels in the screenshot, or None.""" + w, h, ch, px = read_png(path) + sx = sy = n = 0 + for y in range(h): + row = y * w * ch + for x in range(w): + i = row + x * ch + if px[i] > 200 and px[i + 1] < 60 and px[i + 2] < 60: + sx += x + sy += y + n += 1 + if n == 0: + return None + return (sx / n, sy / n, n) + + +def build_scene(rotation): + scene = mcrfpy.Scene("rot%d" % int(rotation)) + scene.activate() + # 5x5 cells of 16px = 80x80 of content; widget is 80x80 and the camera is + # centered, so content exactly fills the widget at zoom 1. + grid = mcrfpy.Grid(grid_size=(5, 5), pos=(100, 100), size=(80, 80)) + scene.children.append(grid) + grid.center = (40, 40) + grid.zoom = 1.0 + + layer = mcrfpy.ColorLayer(z_index=-1, grid_size=(5, 5)) + grid.add_layer(layer) + for x in range(5): + for y in range(5): + layer.set((x, y), mcrfpy.Color(20, 20, 20)) + layer.set(RED_CELL, mcrfpy.Color(255, 0, 0)) + + grid.camera_rotation = rotation + return scene, grid + + +RED_CELL = (0, 1) # off-center and off-diagonal: distinguishable under any rotation + + +def run_case(rotation): + scene, grid = build_scene(rotation) + + clicks = [] + grid.on_cell_click = lambda pos, button, action: clicks.append((int(pos.x), int(pos.y))) + + path = os.path.join(TMPDIR, "rot%d.png" % int(rotation)) + automation.screenshot(path) # headless screenshot is synchronous (#153) + + c = red_centroid(path) + check(c is not None, "[rot=%s] red marker cell was not rendered at all" % rotation) + if c is None: + return + cx, cy, n = c + check(n > 100, "[rot=%s] red marker too small (%d px) to aim at" % (rotation, n)) + + automation.click((int(round(cx)), int(round(cy)))) + check(len(clicks) >= 1, + "[rot=%s] clicking the visible red cell fired no on_cell_click" % rotation) + if clicks: + check(clicks[0] == RED_CELL, + "[rot=%s] clicked the pixel where cell %s is DRAWN (%.1f,%.1f); " + "on_cell_click reported %s" % (rotation, RED_CELL, cx, cy, clicks[0])) + + automation.moveTo((int(round(cx)), int(round(cy)))) + check(grid.hovered_cell is not None and tuple(grid.hovered_cell) == RED_CELL, + "[rot=%s] hovered_cell over the drawn red cell should be %s, got %s" + % (rotation, RED_CELL, grid.hovered_cell)) + + +def main(): + for rotation in (0.0, 90.0, 180.0, 270.0, 45.0): + run_case(rotation) + + if FAILURES: + print("\n%d FAILURE(S)" % len(FAILURES), file=sys.stderr) + sys.exit(1) + print("PASS") + sys.exit(0) + + +if __name__ == "__main__": + try: + main() + except SystemExit: + raise + except Exception as e: + print("\nTEST CRASHED: %s" % e, file=sys.stderr) + import traceback + traceback.print_exc() + sys.exit(1) diff --git a/tests/regression/issue_355_grid_cell_dispatch_test.py b/tests/regression/issue_355_grid_cell_dispatch_test.py new file mode 100644 index 0000000..b5882a2 --- /dev/null +++ b/tests/regression/issue_355_grid_cell_dispatch_test.py @@ -0,0 +1,300 @@ +#!/usr/bin/env python3 +"""Regression test for #355: grid cell input dispatch (click + hover). + +Before #355, cell input was owned by GridData/UIGrid and PyScene gated it on +derived_type() == UIGRID. But mcrfpy.Grid IS a UIGridView (UIGRIDVIEW), so every +one of those gates was dead: on_cell_click / on_cell_enter / on_cell_exit / +hovered_cell never fired for any user-reachable Grid. + +Input now lives on UIGridView (the object that owns the camera), dispatched via +the UIDrawable::dispatchCellClick / updateHover virtuals. + +automation.click()/moveTo() reach PyScene::do_mouse_input / do_mouse_hover +synchronously in headless mode, so no mcrfpy.step() is needed for dispatch. + +NOT covered (deliberately): entity clicks. UIEntity exposes no on_click/sprite +binding, so entity->sprite.click_callable is unreachable from Python. The entity +branch of UIGridView::click_at is implemented but dead until that binding exists. +""" +import sys +import mcrfpy +from mcrfpy import automation + +CELL = 16 # default texture cell size (px) +FAILURES = [] + + +def check(cond, msg): + if not cond: + print(f"FAIL: {msg}", file=sys.stderr) + FAILURES.append(msg) + + +def cell_tuple(hovered): + """hovered_cell as a comparable tuple; None stays None (never raises).""" + return None if hovered is None else tuple(hovered) + + +def screen_of_cell(grid, cx, cy, zoom=1.0): + """Screen coords of the center of cell (cx, cy), using the view's own camera + formula: left_spritepixels = center_x - w/(2*zoom); screen = pos + (gw - lsp)*zoom + """ + ox, oy = grid.x, grid.y + w, h = grid.w, grid.h + left_sp = int(grid.center_x - (w / 2.0 / zoom)) + top_sp = int(grid.center_y - (h / 2.0 / zoom)) + gwx = (cx + 0.5) * CELL + gwy = (cy + 0.5) * CELL + return (ox + (gwx - left_sp) * zoom, oy + (gwy - top_sp) * zoom) + + +def case_a_property_click(): + scene = mcrfpy.Scene("a_click") + scene.activate() + grid = mcrfpy.Grid(grid_size=(5, 5), pos=(100, 100), size=(200, 200)) + scene.children.append(grid) + grid.center_camera((2.5, 2.5)) + + events = [] + grid.on_cell_click = lambda pos, button, action: events.append((pos.x, pos.y, button, action)) + + for cell in [(0, 0), (2, 3), (4, 4)]: + events.clear() + automation.click(screen_of_cell(grid, *cell)) + check(len(events) >= 1, f"[a] on_cell_click did not fire for cell {cell}") + if not events: + continue + cx, cy, button, action = events[0] + check((cx, cy) == (float(cell[0]), float(cell[1])), + f"[a] expected cell {cell}, got ({cx},{cy})") + check(button == mcrfpy.MouseButton.LEFT, f"[a] expected LEFT, got {button}") + check(action == mcrfpy.InputState.PRESSED, f"[a] expected PRESSED first, got {action}") + + +def case_b_panned_zoomed(): + scene = mcrfpy.Scene("b_zoom") + scene.activate() + grid = mcrfpy.Grid(grid_size=(10, 10), pos=(100, 100), size=(200, 200)) + scene.children.append(grid) + grid.zoom = 2.0 + grid.center = (7 * CELL, 5 * CELL) # pan the camera off the default + + events = [] + grid.on_cell_click = lambda pos, button, action: events.append((pos.x, pos.y)) + + for cell in [(6, 4), (7, 5), (8, 6)]: + events.clear() + automation.click(screen_of_cell(grid, *cell, zoom=2.0)) + check(len(events) >= 1, f"[b] on_cell_click did not fire for panned+zoomed cell {cell}") + if events: + check(events[0] == (float(cell[0]), float(cell[1])), + f"[b] panned+zoomed: expected cell {cell}, got {events[0]}") + + +def case_c_hover(): + scene = mcrfpy.Scene("c_hover") + scene.activate() + grid = mcrfpy.Grid(grid_size=(5, 5), pos=(100, 100), size=(200, 200)) + scene.children.append(grid) + + entered, exited = [], [] + grid.on_cell_enter = lambda pos: entered.append((pos.x, pos.y)) + grid.on_cell_exit = lambda pos: exited.append((pos.x, pos.y)) + + A, B = (1, 1), (3, 2) + + automation.moveTo(screen_of_cell(grid, *A)) + check(entered == [(1.0, 1.0)], f"[c] expected one enter for {A}, got {entered}") + check(cell_tuple(grid.hovered_cell) == A, f"[c] hovered_cell should be {A}, got {grid.hovered_cell}") + + entered.clear() + automation.moveTo(screen_of_cell(grid, *B)) + check(exited == [(1.0, 1.0)], f"[c] expected exit for {A}, got {exited}") + check(entered == [(3.0, 2.0)], f"[c] expected enter for {B}, got {entered}") + check(cell_tuple(grid.hovered_cell) == B, f"[c] hovered_cell should be {B}, got {grid.hovered_cell}") + + entered.clear() + exited.clear() + automation.moveTo((10, 10)) # outside the grid + check(exited == [(3.0, 2.0)], f"[c] expected exit for {B} on leaving grid, got {exited}") + check(entered == [], f"[c] no enter expected outside the grid, got {entered}") + check(grid.hovered_cell is None, f"[c] hovered_cell should be None outside, got {grid.hovered_cell}") + + +def case_d_subclass(): + calls = [] + + class MyGrid(mcrfpy.Grid): + def on_cell_click(self, pos, button, action): + calls.append(("click", pos.x, pos.y)) + + def on_cell_enter(self, pos): + calls.append(("enter", pos.x, pos.y)) + + def on_cell_exit(self, pos): + calls.append(("exit", pos.x, pos.y)) + + scene = mcrfpy.Scene("d_subclass") + scene.activate() + grid = MyGrid(grid_size=(5, 5), pos=(100, 100), size=(200, 200)) + scene.children.append(grid) + + automation.moveTo(screen_of_cell(grid, 1, 1)) + automation.moveTo(screen_of_cell(grid, 2, 2)) + automation.click(screen_of_cell(grid, 2, 2)) + + check(("enter", 1.0, 1.0) in calls, f"[d] subclass on_cell_enter(1,1) did not fire: {calls}") + check(("exit", 1.0, 1.0) in calls, f"[d] subclass on_cell_exit(1,1) did not fire: {calls}") + check(("enter", 2.0, 2.0) in calls, f"[d] subclass on_cell_enter(2,2) did not fire: {calls}") + check(("click", 2.0, 2.0) in calls, f"[d] subclass on_cell_click(2,2) did not fire: {calls}") + + +def case_e_child_consumes_click(): + scene = mcrfpy.Scene("e_child") + scene.activate() + grid = mcrfpy.Grid(grid_size=(5, 5), pos=(100, 100), size=(200, 200)) + scene.children.append(grid) + + cell_clicks, frame_clicks = [], [] + grid.on_cell_click = lambda pos, button, action: cell_clicks.append((pos.x, pos.y)) + + # #360: grid children are positioned in GRID-WORLD PIXEL coordinates. + gx, gy = 3, 1 + frame = mcrfpy.Frame(pos=(gx * CELL, gy * CELL), size=(CELL, CELL)) + frame.on_click = lambda pos, button, action: frame_clicks.append((pos.x, pos.y)) + grid.children.append(frame) + + automation.click(screen_of_cell(grid, gx, gy)) + check(len(frame_clicks) >= 1, + f"[e] grid child's on_click did not fire (grid-world child coords broken?): {frame_clicks}") + check(cell_clicks == [], + f"[e] child consumed the click, so on_cell_click must NOT fire; got {cell_clicks}") + + # And a click on a cell NOT covered by the child still reaches on_cell_click. + automation.click(screen_of_cell(grid, 0, 4)) + check(cell_clicks and cell_clicks[0] == (0.0, 4.0), + f"[e] cell outside the child should still fire on_cell_click; got {cell_clicks}") + + +def case_f_two_views_one_griddata(): + scene = mcrfpy.Scene("f_views") + scene.activate() + g = mcrfpy.Grid(grid_size=(5, 5), pos=(100, 100), size=(200, 200)) + scene.children.append(g) + + v2 = mcrfpy.GridView(grid=g.grid_data, pos=(400, 100), size=(200, 200)) + scene.children.append(v2) + + g_events, v_events = [], [] + g.on_cell_enter = lambda pos: g_events.append(("enter", pos.x, pos.y)) + g.on_cell_exit = lambda pos: g_events.append(("exit", pos.x, pos.y)) + v2.on_cell_enter = lambda pos: v_events.append(("enter", pos.x, pos.y)) + v2.on_cell_exit = lambda pos: v_events.append(("exit", pos.x, pos.y)) + + # Hover over v2 only. + automation.moveTo(screen_of_cell(v2, 2, 2)) + check(v_events == [("enter", 2.0, 2.0)], f"[f] v2 should have entered (2,2); got {v_events}") + check(g_events == [], f"[f] hovering v2 must not fire events on g; got {g_events}") + check(g.hovered_cell is None, f"[f] g.hovered_cell must stay None; got {g.hovered_cell}") + check(cell_tuple(v2.hovered_cell) == (2, 2), f"[f] v2.hovered_cell should be (2,2); got {v2.hovered_cell}") + + # Move to g: v2 exits, g enters. No spurious cross-talk. + v_events.clear() + g_events.clear() + automation.moveTo(screen_of_cell(g, 1, 3)) + check(v_events == [("exit", 2.0, 2.0)], f"[f] v2 should have exited (2,2); got {v_events}") + check(g_events == [("enter", 1.0, 3.0)], f"[f] g should have entered (1,3); got {g_events}") + check(v2.hovered_cell is None, f"[f] v2.hovered_cell should be None now; got {v2.hovered_cell}") + check(cell_tuple(g.hovered_cell) == (1, 3), f"[f] g.hovered_cell should be (1,3); got {g.hovered_cell}") + + # Back to v2: each view tracks its own hover, no ping-pong on the other. + v_events.clear() + g_events.clear() + automation.moveTo(screen_of_cell(v2, 2, 2)) + check(v_events == [("enter", 2.0, 2.0)], f"[f] v2 re-enter (2,2) expected; got {v_events}") + check(g_events == [("exit", 1.0, 3.0)], f"[f] g exit (1,3) expected; got {g_events}") + + +def case_g_child_hover(): + """Hover must reach grid children, exactly as click already does. + + do_mouse_hover used to recurse only into UIFRAME children, so a drawable in + grid.children could receive on_click but never on_enter/on_exit/on_move, and + its .hovered flag was stuck False -- callbacks that exist on the API surface + but can never fire. The hover walk now descends through the view's camera + (grid-world pixel coords), the same transform click_at uses. + """ + scene = mcrfpy.Scene("g_child_hover") + scene.activate() + grid = mcrfpy.Grid(grid_size=(5, 5), pos=(100, 100), size=(200, 200)) + scene.children.append(grid) + + entered, exited, moved = [], [], [] + gx, gy = 3, 1 + frame = mcrfpy.Frame(pos=(gx * CELL, gy * CELL), size=(CELL, CELL)) # grid-world coords + frame.on_enter = lambda pos: entered.append((pos.x, pos.y)) + frame.on_exit = lambda pos: exited.append((pos.x, pos.y)) + frame.on_move = lambda pos: moved.append((pos.x, pos.y)) + grid.children.append(frame) + + # Mouse onto the cell the child covers. + automation.moveTo(screen_of_cell(grid, gx, gy)) + check(len(entered) == 1, f"[g] grid child's on_enter did not fire: {entered}") + check(frame.hovered is True, f"[g] grid child's .hovered should be True, got {frame.hovered}") + check(len(moved) == 1, f"[g] grid child's on_move did not fire while inside: {moved}") + + # Mouse to a different cell inside the grid but outside the child. + automation.moveTo(screen_of_cell(grid, 0, 4)) + check(len(exited) == 1, f"[g] grid child's on_exit did not fire on leaving it: {exited}") + check(frame.hovered is False, f"[g] grid child's .hovered should be False, got {frame.hovered}") + + # Re-enter, then leave the grid widget entirely: the child must still exit, + # and must NOT be re-entered by a point outside the view that happens to map + # into grid-world space over the child. + entered.clear() + exited.clear() + automation.moveTo(screen_of_cell(grid, gx, gy)) + check(len(entered) == 1, f"[g] grid child re-enter expected, got {entered}") + automation.moveTo((10, 10)) # far outside the grid widget + check(len(exited) == 1, f"[g] leaving the grid must exit the hovered child: {exited}") + check(frame.hovered is False, "[g] child still hovered after mouse left the grid") + + # Panning the camera moves the child under a DIFFERENT screen pixel; hover + # must follow the camera (the whole point of routing through localToGridWorld). + entered.clear() + grid.zoom = 2.0 + grid.center = (gx * CELL, gy * CELL) # child centered in the widget + automation.moveTo((int(grid.x + grid.w / 2), int(grid.y + grid.h / 2))) + check(len(entered) == 1, + f"[g] after pan+zoom, hover did not track the child through the camera: {entered}") + check(frame.hovered is True, "[g] child not hovered at its new on-screen position") + + +def main(): + case_a_property_click() + case_b_panned_zoomed() + case_c_hover() + case_d_subclass() + case_e_child_consumes_click() + case_f_two_views_one_griddata() + case_g_child_hover() + + if FAILURES: + print(f"\n{len(FAILURES)} FAILURE(S)", file=sys.stderr) + sys.exit(1) + print("PASS") + sys.exit(0) + + +if __name__ == "__main__": + # --exec does NOT turn an unhandled exception into a non-zero exit code, so a + # crashing test would otherwise report success. Translate explicitly. + try: + main() + except SystemExit: + raise + except Exception as e: + print(f"\nTEST CRASHED: {e}", file=sys.stderr) + import traceback + traceback.print_exc() + sys.exit(1) diff --git a/tests/regression/issue_355_grid_input_test.py b/tests/regression/issue_355_grid_input_test.py new file mode 100644 index 0000000..39d68b4 --- /dev/null +++ b/tests/regression/issue_355_grid_input_test.py @@ -0,0 +1,223 @@ +#!/usr/bin/env python3 +"""Regression test for #355 - mcrfpy.Grid input is entirely dead. + +Since the #252 Grid/GridView split, mcrfpy.Grid(...) constructs a +UIGridView (PyObjectsEnum::UIGRIDVIEW). Every input dispatch site that +matters for grid cell/child/entity interactivity (PyScene::do_mouse_input, +PyScene::do_mouse_hover's processHover, and the subclass-method lookup in +UIGrid::fireCellClick) still gates on derived_type() == UIGRID -- the +*internal* _GridData type nothing user-visible is ever an instance of. As a +result: + - on_cell_click / on_cell_enter / on_cell_exit never fire on a real Grid. + - Child drawables appended to grid.children never receive their own + on_click. + - A Python subclass of mcrfpy.Grid that overrides on_cell_click as a + *method* (rather than assigning the on_cell_click property) is doubly + broken: is_python_subclass/serial_number tracking for that lookup is + keyed off the internal _GridData wrapper, not the public Grid/GridView + instance a subclass is actually built from. + +Each check below is a hard assertion (sys.exit via unhandled AssertionError +on failure) -- no "PARTIAL" outs. + +Coordinate math: with an unmodified camera and an explicit `size=`, +UIGridView's default center is size/(2*zoom) == the viewport's own +half-width/half-height, which cancels the half-width term in the +screen->cell formula, so grid_space == local screen-relative offset +whenever zoom==1. cell = floor(grid_space / cell_pixel_size), with the +16x16 default texture. Case (b) explicitly overrides grid.center/grid.zoom +to non-default values and uses the full formula +(grid_space = (local - half_width) / zoom + center_x) so it is a genuine +discriminator against a fix that reads the wrong (stale, internal +_GridData-owned) camera copy instead of the public Grid/GridView's own +center_x/center_y/zoom. +""" +import sys +import mcrfpy +from mcrfpy import automation + + +def test_a_plain_cell_click(): + """(a) on_cell_click fires with the correct cell for a click on a plain Grid.""" + print("(a) plain grid cell click...") + scene = mcrfpy.Scene("issue355_a") + ui = scene.children + mcrfpy.current_scene = scene + + grid = mcrfpy.Grid(grid_size=(5, 5), pos=(100, 100), size=(200, 200)) + ui.append(grid) + + clicks = [] + def on_cell_click(cell_pos, button, action): + clicks.append((cell_pos.x, cell_pos.y, button, action)) + grid.on_cell_click = on_cell_click + + # local=(36,52) -> cell (2,3), see module docstring for the math. + automation.click((136, 152)) + mcrfpy.step(0.05) + + assert len(clicks) >= 1, f"on_cell_click never fired; clicks={clicks}" + cx, cy, button, action = clicks[0] + assert (cx, cy) == (2, 3), f"expected cell (2,3), got ({cx},{cy})" + assert button == mcrfpy.MouseButton.LEFT + assert action == mcrfpy.InputState.PRESSED + print(" OK") + + +def test_b_panned_zoomed_cell_click(): + """(b) on_cell_click reports the CORRECT cell after grid.center/grid.zoom + are set to non-default values -- discriminates against a fix that reads + a stale internal camera copy instead of the public Grid's own.""" + print("(b) panned+zoomed grid cell click...") + scene = mcrfpy.Scene("issue355_b") + ui = scene.children + mcrfpy.current_scene = scene + + grid = mcrfpy.Grid(grid_size=(10, 10), pos=(50, 50), size=(200, 200)) + ui.append(grid) + + grid.zoom = 2.0 + grid.center = (88, 88) # pixel-space camera center (== tile (5.5,5.5) at 16px cells) + assert grid.zoom == 2.0 + assert (grid.center.x, grid.center.y) == (88, 88), \ + f"grid.center did not take the assigned value: {grid.center}" + + clicks = [] + def on_cell_click(cell_pos, button, action): + clicks.append((cell_pos.x, cell_pos.y)) + grid.on_cell_click = on_cell_click + + # local=(60,60); grid_space = (60-100)/2.0 + 88 = 68; cell = floor(68/16) = 4 + automation.click((110, 110)) + mcrfpy.step(0.05) + + assert len(clicks) >= 1, f"on_cell_click never fired under pan/zoom; clicks={clicks}" + assert clicks[0] == (4, 4), ( + f"expected cell (4,4) under grid.center=(88,88)/grid.zoom=2.0, got {clicks[0]} " + "(a stale-camera fix would report (3,3) instead)" + ) + print(" OK") + + +def test_c_hover_boundary(): + """(c) on_cell_enter / on_cell_exit fire on hover across a cell boundary.""" + print("(c) cell hover enter/exit across a boundary...") + scene = mcrfpy.Scene("issue355_c") + ui = scene.children + mcrfpy.current_scene = scene + + grid = mcrfpy.Grid(grid_size=(5, 5), pos=(100, 100), size=(200, 200)) + ui.append(grid) + + enters = [] + exits = [] + grid.on_cell_enter = lambda pos: enters.append((pos.x, pos.y)) + grid.on_cell_exit = lambda pos: exits.append((pos.x, pos.y)) + + # local=(40,40) -> cell (2,2); local=(56,40) -> cell (3,2) + automation.moveTo((140, 140)) + mcrfpy.step(0.05) + automation.moveTo((156, 140)) + mcrfpy.step(0.05) + + assert (2, 2) in enters, f"on_cell_enter never fired for (2,2); enters={enters}" + assert (2, 2) in exits, f"on_cell_exit never fired for (2,2); exits={exits}" + assert (3, 2) in enters, f"on_cell_enter never fired for (3,2); enters={enters}" + print(" OK") + + +def test_d_child_drawable_click(): + """(d) A Frame child of grid.children receives its own on_click when + clicked, at the screen pixel derived from the grid's camera transform + (children live in grid-world pixel coordinates, not screen pixels).""" + print("(d) child drawable click (grid-world pixel coords via camera)...") + scene = mcrfpy.Scene("issue355_d") + ui = scene.children + mcrfpy.current_scene = scene + + grid = mcrfpy.Grid(grid_size=(10, 10), pos=(50, 50), size=(200, 200)) + ui.append(grid) + + # Grid-world pixel box [90,110]x[90,110]. Default camera (center=(100,100), + # zoom=1) makes grid_space == local, so: + # screen (150,150) -> local (100,100) -> world (100,100): INSIDE the frame + # screen (120,120) -> local (70,70) -> world (70,70): OUTSIDE the frame + frame = mcrfpy.Frame(pos=(90, 90), size=(20, 20)) + grid.children.append(frame) + + frame_clicks = [] + def on_frame_click(pos, button, action): + frame_clicks.append((pos.x, pos.y)) + frame.on_click = on_frame_click + + # Miss first: proves the screen point isn't just always hitting the frame. + automation.click((120, 120)) + mcrfpy.step(0.05) + assert len(frame_clicks) == 0, ( + f"frame.on_click fired for a screen point outside its grid-world bounds: {frame_clicks}" + ) + + automation.click((150, 150)) + mcrfpy.step(0.05) + assert len(frame_clicks) >= 1, ( + "frame.on_click never fired for a click on a Frame in grid.children " + "at the correctly camera-transformed screen pixel" + ) + print(" OK") + + +def test_e_subclass_method_override(): + """(e) A Python subclass of mcrfpy.Grid overriding on_cell_click as a + METHOD (not the property) has that method invoked.""" + print("(e) Grid subclass on_cell_click method override...") + + class ClickCountingGrid(mcrfpy.Grid): + def __init__(self, *a, **kw): + super().__init__(*a, **kw) + self.clicked_cells = [] + + def on_cell_click(self, cell_pos, button, action): + self.clicked_cells.append((cell_pos.x, cell_pos.y)) + + scene = mcrfpy.Scene("issue355_e") + ui = scene.children + mcrfpy.current_scene = scene + + mg = ClickCountingGrid(grid_size=(5, 5), pos=(100, 100), size=(200, 200)) + ui.append(mg) + + # local=(36,52) -> cell (2,3), same math as (a). + automation.click((136, 152)) + mcrfpy.step(0.05) + + assert len(mg.clicked_cells) >= 1, ( + "ClickCountingGrid.on_cell_click (method override) never fired" + ) + assert mg.clicked_cells[0] == (2, 3), \ + f"expected cell (2,3), got {mg.clicked_cells[0]}" + print(" OK") + + +def main(): + test_a_plain_cell_click() + test_b_panned_zoomed_cell_click() + test_c_hover_boundary() + test_d_child_drawable_click() + test_e_subclass_method_override() + print("PASS") + + +if __name__ == "__main__": + # NOTE: --exec does not turn an unhandled Python exception into a + # non-zero process exit code (verified empirically), so failures MUST + # be caught and translated to sys.exit(1) explicitly here -- letting a + # bare AssertionError propagate would silently "pass" the suite, which + # is exactly the masking anti-pattern #355 shipped behind. + try: + main() + sys.exit(0) + except Exception as e: + print(f"\nTEST FAILED: {e}") + import traceback + traceback.print_exc() + sys.exit(1) diff --git a/tests/regression/issue_355_gridview_position_sync_test.py b/tests/regression/issue_355_gridview_position_sync_test.py new file mode 100644 index 0000000..42984c9 --- /dev/null +++ b/tests/regression/issue_355_gridview_position_sync_test.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +"""Regression test for #355 (prerequisite): UIGridView box/position desync. + +UIGridView overrode move()/resize() but NOT onPositionChanged(), so assigning +grid.pos / grid.x / grid.y updated UIDrawable::position while the sf::RectangleShape +`box` -- which render() and get_bounds() and every hit test read -- stayed at the +construction-time origin. A repositioned Grid rendered at the stale spot and its +cell hit testing was meaningless. +""" +import sys +import mcrfpy +from mcrfpy import automation + +CELL = 16 # default texture cell size + + +def fail(msg): + print(f"FAIL: {msg}", file=sys.stderr) + sys.exit(1) + + +def main(): + scene = mcrfpy.Scene("pos_sync") + scene.activate() + grid = mcrfpy.Grid(grid_size=(5, 5), pos=(100, 100), size=(200, 200)) + scene.children.append(grid) + + # 1. box follows position + grid.pos = (300, 50) + origin, size = grid.bounds # bounds == (pos: Vector, size: Vector), read from `box` + if (origin.x, origin.y) != (300, 50): + fail(f"grid.bounds should follow grid.pos; expected origin (300,50), got ({origin.x},{origin.y})") + if (size.x, size.y) != (200, 200): + fail(f"grid.bounds size changed unexpectedly: ({size.x},{size.y})") + + clicks = [] + grid.on_cell_click = lambda pos, button, action: clicks.append((pos.x, pos.y)) + + # 2. a click at the NEW location resolves the correct cell. + # center defaults to size/2 => left_spritepixels == 0 => grid-world == local. + # local (40, 40) -> cell (2, 2) + automation.click((340, 90)) + if not clicks: + fail("on_cell_click did not fire for a click inside the repositioned grid") + if clicks[0] != (2.0, 2.0): + fail(f"expected cell (2,2) at the new position, got {clicks[0]}") + + # 3. a click at the OLD location resolves nothing. + clicks.clear() + automation.click((140, 140)) + if clicks: + fail(f"click at the old (vacated) position should not hit the grid; got {clicks}") + + print("PASS") + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/tests/regression/issue_355_perspective_overlay_test.py b/tests/regression/issue_355_perspective_overlay_test.py new file mode 100644 index 0000000..03d4741 --- /dev/null +++ b/tests/regression/issue_355_perspective_overlay_test.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +"""Regression test for #355 - grid.perspective actually renders fog-of-war. + +After the #252 Grid/GridView split, mcrfpy.Grid IS a UIGridView and the FOV +overlay is drawn by UIGridView::render(). But `grid.perspective = entity` fell +through getattro delegation to the internal _GridData and wrote UIGrid's copy of +the perspective state, which render() never reads -- the view gated the overlay +on its OWN perspective_enabled member, which nothing ever set. Result: +perspective_map computed correctly, grid.perspective_enabled read True, and not +a single fog pixel was drawn. + +The state now lives on the view (single owner). This test asserts on PIXELS, not +on the property round-trip -- the property round-trip is exactly what lied. +""" +import sys +import os +import tempfile + +import mcrfpy +from mcrfpy import automation + +TMPDIR = tempfile.mkdtemp(prefix="mcrf355persp_") +_counter = 0 + + +def shot(): + """Headless screenshot is synchronous (#153): render + capture inline.""" + global _counter + path = os.path.join(TMPDIR, "p%d.png" % _counter) + _counter += 1 + automation.screenshot(path) + with open(path, "rb") as f: + return f.read() + + +def main(): + texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16) + + scene = mcrfpy.Scene("persp355") + scene.activate() + + grid = mcrfpy.Grid(grid_size=(10, 10), pos=(0, 0), size=(160, 160), texture=texture) + scene.children.append(grid) + + tiles = mcrfpy.TileLayer(name="terrain", z_index=-2, texture=texture) + grid.add_layer(tiles) + tiles.fill(5) + + # Opaque everywhere except the entity's own cell -> FOV is a tiny island, so + # the vast majority of the map must be covered by the unknown/black overlay. + for x in range(10): + for y in range(10): + grid.at(x, y).transparent = False + + e = mcrfpy.Entity((1, 1), grid=grid) + e.sprite_index = 5 + + omniscient = shot() + + grid.perspective = e + e.update_visibility() + + assert grid.perspective is e, "grid.perspective did not round-trip the entity" + assert grid.perspective_enabled is True, "assigning perspective must enable it" + + visible = sum(1 for x in range(10) for y in range(10) + if e.perspective_map[x, y] == mcrfpy.Perspective.VISIBLE) + assert 0 < visible < 100, "test setup: expected a partial FOV, got %d visible" % visible + + fogged = shot() + assert fogged != omniscient, ( + "grid.perspective is set and perspective_map has %d/100 visible cells, but the " + "rendered frame is byte-identical to the omniscient one -- the FOV overlay is " + "not being drawn (view's perspective state never set)" % visible + ) + + # Turning perspective back off must restore the omniscient image exactly. + grid.perspective = None + assert grid.perspective_enabled is False, "perspective=None must disable the overlay" + cleared = shot() + assert cleared == omniscient, ( + "clearing grid.perspective did not restore the un-fogged render" + ) + + # perspective_enabled toggles the overlay without clearing the entity. + grid.perspective = e + assert shot() != omniscient, "re-enabling perspective did not re-draw the overlay" + grid.perspective_enabled = False + assert grid.perspective is e, "perspective_enabled=False must not clear the entity" + assert shot() == omniscient, "perspective_enabled=False did not remove the overlay" + + print("PASS") + + +if __name__ == "__main__": + try: + main() + sys.exit(0) + except Exception as e: + print("\nTEST FAILED: %s" % e) + import traceback + traceback.print_exc() + sys.exit(1) diff --git a/tests/regression/issue_359_shared_griddata_test.py b/tests/regression/issue_359_shared_griddata_test.py new file mode 100644 index 0000000..47ccce2 --- /dev/null +++ b/tests/regression/issue_359_shared_griddata_test.py @@ -0,0 +1,191 @@ +"""Regression test for #359 - the shared-data grid path is unwired. + +Two concrete defects, both in the `Grid(grid=other)` shared-GridData path +(the whole point of the #252 split -- split-screen, minimap, multiple +cameras over one dataset): + + (a) UIGridView::init_explicit_view never registered the new view with the + GridData it attaches to, so GridData::markDirty()/markCompositeDirty() + (which push markContentDirty/markCompositeDirty up a view's OWN + ancestor chain -- e.g. a Frame(cache_subtree=True) wrapping that view) + never reached a secondary view's ancestors. Note this is NOT the same + thing as the #351 render early-out itself: UIGridView::render() polls + GridData::content_generation directly every time it actually runs, so + a bare secondary view (no cached ancestor) already re-rasters + correctly regardless of this bug. The bug only surfaces when a + secondary view sits under a render-texture-caching ancestor, because + that ancestor decides whether to invoke the child's render() AT ALL -- + a push notification, not a poll, is required to reach it. Test 3 below + is the discriminator: it fails (stale cache) on the pre-fix code and + passes once init_explicit_view registers the view. + + (b) PyUIGridObject::view (the internal `_GridData.view` shim, meant to + point back at "the" GridView) was placement-new'd but never assigned + anywhere reachable from Python -- `_GridData.view` was always None. + Given `_GridData` is internal (never exported to the mcrfpy module + namespace), the fix deletes the field/getter outright rather than + wiring it up (a single view back-pointer is structurally wrong once N + views can share one GridData; see GridData::views / primaryView() for + the replacement, exercised implicitly by test 2). Test 4 confirms the + dead property is gone, not silently still None. + +Design note carried over from the fix: GridData::views is a *list*, not a +single pointer, specifically because N views can share one GridData. Index 0 +is guaranteed (by construction: a fresh GridData is only ever produced by +Grid()'s factory path, `init_with_data`; `init_explicit_view` can only ATTACH +to an already-existing GridData) to be the view that created the data, so +UIEntity.grid identity (test 2) stays deterministic even with secondary +views registered -- not an arbitrary pick from an unordered set. +""" +import sys +import os +import tempfile +import mcrfpy +from mcrfpy import automation + +TMPDIR = tempfile.mkdtemp(prefix="mcrf359_") +_counter = 0 + + +def shot(): + """Render the active scene to PNG and return its bytes (headless + screenshot is synchronous -- see #351's test for the same pattern).""" + global _counter + path = os.path.join(TMPDIR, "s%d.png" % _counter) + _counter += 1 + automation.screenshot(path) + with open(path, "rb") as f: + return f.read() + + +def test_1_two_views_render_shared_mutations(): + """Two Grid views over one GridData, with different camera params, both + reflect a mutation made through a third path (this is the exact scenario + the #359 issue's own test description asks for).""" + print("(1) two views over one GridData both render mutations...") + texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16) + + scene_a = mcrfpy.Scene("issue359_1a") + grid_a = mcrfpy.Grid(grid_size=(10, 10), pos=(0, 0), size=(160, 160), texture=texture) + scene_a.children.append(grid_a) + + scene_b = mcrfpy.Scene("issue359_1b") + grid_b = mcrfpy.Grid(grid=grid_a, pos=(0, 0), size=(160, 160)) + grid_b.zoom = 1.5 + grid_b.center = (64, 64) + scene_b.children.append(grid_b) + + mcrfpy.current_scene = scene_a + a1 = shot() + mcrfpy.current_scene = scene_b + b1 = shot() + + # Mutate through the shared data (add a visible entity at cell (3,3)). + e = mcrfpy.Entity((3, 3), grid=grid_a) + e.sprite_index = 5 + + mcrfpy.current_scene = scene_a + a2 = shot() + assert a2 != a1, "primary view (grid_a) did not reflect the mutation" + + mcrfpy.current_scene = scene_b + b2 = shot() + assert b2 != b1, "secondary view (grid_b) did not reflect the mutation" + print(" OK") + + +def test_2_entity_grid_identity(): + """entity.grid returns the SAME object as the Grid() that actually + created the data (GridData::views.front()), not the secondary view, not + None, and not a fresh throwaway wrapper -- even once a secondary view is + registered on the same GridData.""" + print("(2) entity.grid identity with a secondary view registered...") + grid_a = mcrfpy.Grid(grid_size=(5, 5)) + grid_b = mcrfpy.Grid(grid=grid_a, pos=(0, 0), size=(80, 80)) # noqa: F841 (keep alive) + + e = mcrfpy.Entity((1, 1), grid=grid_a) + + assert e.grid is grid_a, f"entity.grid identity broken: {e.grid!r} is not grid_a ({grid_a!r})" + assert e.grid is not grid_b, "entity.grid returned the secondary view instead of the creator" + print(" OK") + + +def test_3_ancestor_cache_invalidation_through_secondary_view(): + """The discriminating regression: a SECONDARY view nested inside a + Frame(cache_subtree=True) must have its ancestor's cached subtree + invalidated when the shared GridData mutates, even though the mutation + happens through a DIFFERENT (primary) view/handle. This requires + init_explicit_view to register the secondary view with GridData -- pure + content_generation polling (#351) is not enough, because the caching + Frame decides whether to call the child's render() at all.""" + print("(3) ancestor render-texture cache invalidated via secondary view...") + texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16) + + scene = mcrfpy.Scene("issue359_3") + grid_a = mcrfpy.Grid(grid_size=(6, 6), pos=(200, 200), size=(96, 96), texture=texture) + # grid_a deliberately NOT added to this scene -- it exists only to own + # the data and be the mutation path; only the secondary view is visible. + + grid_b = mcrfpy.Grid(grid=grid_a, pos=(0, 0), size=(96, 96)) + + frame = mcrfpy.Frame(pos=(0, 0), size=(96, 96)) + frame.cache_subtree = True + frame.children.append(grid_b) + scene.children.append(frame) + mcrfpy.current_scene = scene + + # First render bakes the Frame's cached subtree (render_dirty starts True). + shot1 = shot() + # Idle render: cache should be stable (sanity check the test methodology). + shot2 = shot() + assert shot1 == shot2, "cache_subtree Frame was not stable across an idle frame (test setup problem)" + + # Mutate the shared GridData through the PRIMARY handle grid_a, NOT the + # secondary view. If grid_b is registered on the GridData, this reaches + # grid_b's own ancestor chain (the cache_subtree Frame) and invalidates it. + e = mcrfpy.Entity((3, 3), grid=grid_a) + e.sprite_index = 5 + + shot3 = shot() + assert shot3 != shot2, ( + "Frame(cache_subtree=True) wrapping the SECONDARY view did not invalidate " + "when the shared GridData mutated through the primary handle -- " + "init_explicit_view is not registering the view with GridData (#359 defect a)" + ) + print(" OK") + + +def test_4_griddata_view_property_removed(): + """_GridData.view (PyUIGridObject::view) is dead: nothing in the + codebase ever assigned it, and _GridData is internal/not exported. The + fix deletes the field and getter outright rather than wiring a + structurally-wrong single back-pointer; confirm it's actually gone, not + silently still None.""" + print("(4) _GridData.view property deleted (not left dangling)...") + grid_a = mcrfpy.Grid(grid_size=(3, 3)) + gd = grid_a.grid_data + assert not hasattr(gd, "view"), ( + "_GridData.view still exists -- #359 defect (b) says delete it " + "(internal type, never wired, N-view sharing makes a single " + "back-pointer wrong) rather than leave it dangling" + ) + print(" OK") + + +def main(): + test_1_two_views_render_shared_mutations() + test_2_entity_grid_identity() + test_3_ancestor_cache_invalidation_through_secondary_view() + test_4_griddata_view_property_removed() + print("PASS") + + +if __name__ == "__main__": + try: + main() + sys.exit(0) + except Exception as e: + print(f"\nTEST FAILED: {e}") + import traceback + traceback.print_exc() + sys.exit(1) diff --git a/tests/snapshots/api_surface.golden.txt b/tests/snapshots/api_surface.golden.txt index e88a497..ec2edd5 100644 --- a/tests/snapshots/api_surface.golden.txt +++ b/tests/snapshots/api_surface.golden.txt @@ -547,8 +547,12 @@ submodule automation prop h: float (rw) prop horiz_margin: float (rw) prop hovered: Any (ro) + prop hovered_cell: tuple | None (ro) prop margin: float (rw) prop name: str (rw) + prop on_cell_click: Callable | None (rw) + prop on_cell_enter: Callable | None (rw) + prop on_cell_exit: Callable | None (rw) prop on_click: Callable | None (rw) prop on_enter: Any (rw) prop on_exit: Any (rw) @@ -556,6 +560,8 @@ submodule automation prop opacity: Any (rw) prop origin: Any (rw) prop parent: Any (rw) + prop perspective: Entity | None (rw) + prop perspective_enabled: bool (rw) prop pos: Vector (rw) prop rotate_with_camera: bool (rw) prop rotation: Any (rw) @@ -587,8 +593,12 @@ submodule automation prop h: float (rw) prop horiz_margin: float (rw) prop hovered: Any (ro) + prop hovered_cell: tuple | None (ro) prop margin: float (rw) prop name: str (rw) + prop on_cell_click: Callable | None (rw) + prop on_cell_enter: Callable | None (rw) + prop on_cell_exit: Callable | None (rw) prop on_click: Callable | None (rw) prop on_enter: Any (rw) prop on_exit: Any (rw) @@ -596,6 +606,8 @@ submodule automation prop opacity: Any (rw) prop origin: Any (rw) prop parent: Any (rw) + prop perspective: Entity | None (rw) + prop perspective_enabled: bool (rw) prop pos: Vector (rw) prop rotate_with_camera: bool (rw) prop rotation: Any (rw) @@ -1127,13 +1139,9 @@ submodule automation prop h: float (rw) prop horiz_margin: float (rw) prop hovered: Any (ro) - prop hovered_cell: tuple | None (ro) prop layers: tuple (ro) prop margin: float (rw) prop name: str (rw) - prop on_cell_click: Callable | None (rw) - prop on_cell_enter: Callable | None (rw) - prop on_cell_exit: Callable | None (rw) prop on_click: Any (rw) prop on_enter: Any (rw) prop on_exit: Any (rw) @@ -1141,8 +1149,6 @@ submodule automation prop opacity: Any (rw) prop origin: Any (rw) prop parent: Any (rw) - prop perspective: Entity | None (rw) - prop perspective_enabled: bool (rw) prop pos: Vector (rw) prop rotate_with_camera: bool (rw) prop rotation: Any (rw) @@ -1151,7 +1157,6 @@ submodule automation prop texture: Texture | None (ro) prop uniforms: Any (ro) prop vert_margin: float (rw) - prop view: GridView | None (ro) prop visible: bool (rw) prop w: float (rw) prop x: float (rw) @@ -1228,7 +1233,7 @@ func tripleClick :: tripleClick(pos: tuple | list | Vector | None = None) -> Non func typewrite :: typewrite(message: str, interval: float = 0.0) -> None === DELEGATION INTEGRITY (Grid instance -> _GridData) === - delegated-resolved: 69/69 + delegated-resolved: 62/62 === WRITABILITY PROBES (#313-touched properties) === Entity.grid: writable diff --git a/tests/unit/test_grid_cell_events.py b/tests/unit/test_grid_cell_events.py index 94902ab..79a3045 100644 --- a/tests/unit/test_grid_cell_events.py +++ b/tests/unit/test_grid_cell_events.py @@ -1,5 +1,22 @@ #!/usr/bin/env python3 -"""Test #142: Grid Cell Mouse Events""" +"""Test #142: Grid Cell Mouse Events + +#355 follow-up: this file used to treat "zero events fired" as a soft +"PARTIAL" print and still exit(0). That masked the #355 regression (grid +cell click/hover dispatch is entirely dead for mcrfpy.Grid, which is a +UIGridView under the hood) as a passing test suite. Every path below now +hard-asserts; a callback that fails to fire is a test failure, not a +"maybe interactive mode" shrug. + +Coordinate math: with an unmodified (default) camera and an explicit +`size=`, UIGridView's default center is exactly size/(2*zoom), which +equals the viewport's own half-width/half-height. That makes grid_space +== local screen-relative position when zoom==1 (the two halves cancel), +so cell = floor(local_offset / cell_pixel_size) with the default 16x16 +texture. All screen coordinates below are chosen with that arithmetic, +landing deliberately mid-cell (not on a boundary) to avoid float-edge +ambiguity. +""" import sys import mcrfpy from mcrfpy import automation @@ -47,7 +64,7 @@ def test_properties(): def test_cell_hover(): - """Test cell hover events""" + """Test cell hover events fire with the correct cells, across a boundary.""" print("Testing cell hover events...") test_hover = mcrfpy.Scene("test_hover") @@ -70,23 +87,31 @@ def test_cell_hover(): grid.on_cell_enter = on_enter grid.on_cell_exit = on_exit - # Move into grid and between cells - automation.moveTo((150, 150)) + # local=(40,40) -> cell (2,2); local=(56,40) -> cell (3,2) (adjacent, same row) + automation.moveTo((140, 140)) mcrfpy.step(0.05) - automation.moveTo((200, 200)) + automation.moveTo((156, 140)) mcrfpy.step(0.05) - print(f" Enter events: {len(enter_events)}, Exit events: {len(exit_events)}") + print(f" Enter events: {enter_events}, Exit events: {exit_events}") print(f" Hovered cell: {grid.hovered_cell}") - if len(enter_events) >= 1: - print(" - Hover: PASS") - else: - print(" - Hover: PARTIAL (events may require interactive mode)") + assert (2, 2) in enter_events, \ + f"expected on_cell_enter to fire for cell (2,2); got {enter_events}" + assert (3, 2) in enter_events, \ + f"expected on_cell_enter to fire for cell (3,2) after crossing the boundary; got {enter_events}" + assert (2, 2) in exit_events, \ + f"expected on_cell_exit to fire for cell (2,2) when leaving it; got {exit_events}" + assert grid.hovered_cell is not None, "grid.hovered_cell should be set after hovering" + # hovered_cell is an (x, y) tuple (see its docstring / api_surface golden). + assert tuple(grid.hovered_cell) == (3, 2), \ + f"expected grid.hovered_cell == (3,2), got {grid.hovered_cell}" + + print(" - Hover: PASS") def test_cell_click(): - """Test cell click events""" + """Test cell click events fire with the correct cell.""" print("Testing cell click events...") test_click = mcrfpy.Scene("test_click") @@ -100,19 +125,23 @@ def test_cell_click(): # #230 - cell click receives (cell_pos: Vector, button: MouseButton, action: InputState) def on_click(pos, button, action): - click_events.append((pos.x, pos.y)) + click_events.append((pos.x, pos.y, button, action)) grid.on_cell_click = on_click - automation.click((200, 200)) + # local=(36,52) -> cell (2,3) + automation.click((136, 152)) mcrfpy.step(0.05) - print(f" Click events: {len(click_events)}") + print(f" Click events: {click_events}") - if len(click_events) >= 1: - print(" - Click: PASS") - else: - print(" - Click: PARTIAL (events may require interactive mode)") + assert len(click_events) >= 1, \ + "expected on_cell_click to fire at least once for a click inside the grid" + cx, cy, button, action = click_events[0] + assert (cx, cy) == (2, 3), f"expected cell (2,3), got ({cx},{cy})" + assert button == mcrfpy.MouseButton.LEFT, f"expected LEFT button, got {button}" + + print(" - Click: PASS") if __name__ == "__main__":