gameobj.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. # Flexlay - A Generic 2D Game Editor
  2. # Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
  3. #
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. from typing import Any, List, Optional, TYPE_CHECKING
  17. import os
  18. from PyQt5.QtWidgets import QWidget
  19. from flexlay.color import Colorf
  20. from flexlay.gui.generic_dialog import GenericDialog
  21. from flexlay.math import Rectf, Pointf, Sizef
  22. from flexlay.objmap_object import ObjMapObject
  23. from flexlay.objmap_rect_object import ObjMapRectObject
  24. from flexlay.objmap_sprite_object import ObjMapSpriteObject
  25. from flexlay.property import Property
  26. from flexlay.util.config import Config
  27. from flexlay.util.sexpr_writer import SExprWriter
  28. from flexlay.workspace import Workspace
  29. from supertux.constraint import Constraint
  30. from supertux.sprite import SuperTuxSprite
  31. from supertux.gameobj_props_change_command import GameObjPropsChangeCommand
  32. if TYPE_CHECKING:
  33. from supertux.gui import SuperTuxGUI
  34. def make_sprite_object(metadata: Any, filename: str, pos: Optional[Pointf] = None) -> ObjMapSpriteObject:
  35. pos = Pointf(0, 0) if pos is None else pos
  36. assert Config.current is not None
  37. st_sprite = SuperTuxSprite.from_file(os.path.join(Config.current.datadir, filename))
  38. sprite = st_sprite.get_sprite()
  39. assert sprite is not None
  40. obj = ObjMapSpriteObject(sprite, pos, metadata)
  41. return obj
  42. def make_rect_object(metadata: Any, color: Optional[Colorf] = None) -> ObjMapRectObject:
  43. if color is None:
  44. color = Colorf(0, 0, 1, 0.5)
  45. pos = Pointf(0, 0)
  46. size = Sizef(64, 64)
  47. obj = ObjMapRectObject(Rectf.from_ps(pos, size), color.to_i(), metadata)
  48. return obj
  49. class GameObj:
  50. label: str
  51. identifier: str
  52. sprite: str
  53. properties: list[Property] = []
  54. constraints: List[Constraint] = []
  55. def __init__(self) -> None:
  56. self.objmap_object: Optional[ObjMapObject] = None
  57. def signal_connect(self) -> None:
  58. """Connect the objmap_object signals to the on_select and on_deselect
  59. Used, for example, to display properties in PropertiesWidget.
  60. """
  61. if not self.objmap_object:
  62. return
  63. self.objmap_object.sig_select.connect(self.on_select)
  64. self.objmap_object.sig_deselect.connect(self.on_deselect)
  65. def on_select(self, manager: 'SuperTuxGUI') -> None:
  66. if manager:
  67. manager.properties_widget.set_properties(self.properties)
  68. manager.properties_widget.add_callback(self.on_callback)
  69. def on_deselect(self, manager: 'SuperTuxGUI') -> None:
  70. if manager:
  71. manager.properties_widget.clear_properties()
  72. manager.properties_widget.call_signal.clear()
  73. def add_property(self, prop: Property) -> None:
  74. self.properties.append(prop)
  75. def read(self, sexpr: Any) -> None:
  76. for prop in self.properties:
  77. prop.read(sexpr, self.objmap_object)
  78. def write(self, writer: SExprWriter, obj: ObjMapObject) -> None:
  79. writer.begin_list(self.identifier)
  80. for prop in self.properties:
  81. prop.write(writer, obj)
  82. writer.end_list()
  83. def property_dialog(self, parent: QWidget) -> None:
  84. assert self.label is not None
  85. dialog = GenericDialog(self.label + " Property Dialog", parent)
  86. for prop in self.properties:
  87. prop.property_dialog(dialog)
  88. dialog.add_callback(self.on_callback)
  89. def find_property(self, identifier: str) -> Optional[Property]:
  90. for prop in self.properties:
  91. if prop.identifier == identifier:
  92. return prop
  93. return None
  94. def on_callback(self, *args: Any) -> None:
  95. """Called when "Apply" or "Okay" hit"""
  96. assert Workspace.current is not None
  97. print(args)
  98. prop_diff = []
  99. i = 0
  100. for property in self.properties:
  101. if property.editable:
  102. if args[i] == property.value:
  103. continue
  104. prop_diff.append((i, args[i], property.value))
  105. i += 1
  106. command = GameObjPropsChangeCommand(self, prop_diff)
  107. Workspace.current.get_map().execute(command)
  108. def update(self) -> None:
  109. """Called after properties read, and optionally at any other time"""
  110. pass
  111. # EOF #