__init__.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. """
  2. Export to godot's escn file format - a format that Godot can work with
  3. without significant importing (it's the same as Godot's tscn format).
  4. """
  5. # ##### BEGIN GPL LICENSE BLOCK #####
  6. #
  7. # This program is free software; you can redistribute it and/or
  8. # modify it under the terms of the GNU General Public License
  9. # as published by the Free Software Foundation; either version 2
  10. # of the License, or (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. #
  20. # ##### END GPL LICENSE BLOCK #####
  21. import bpy
  22. from bpy.props import StringProperty, BoolProperty, FloatProperty, EnumProperty
  23. from bpy_extras.io_utils import ExportHelper
  24. from .structures import ValidationError
  25. bl_info = { # pylint: disable=invalid-name
  26. "name": "Godot Engine Exporter",
  27. "author": "Juan Linietsky",
  28. "blender": (2, 5, 8),
  29. "api": 38691,
  30. "location": "File > Import-Export",
  31. "description": ("Export Godot Scenes to a format that can be efficiently "
  32. "imported. "),
  33. "warning": "",
  34. "wiki_url": ("https://godotengine.org"),
  35. "tracker_url": "https://github.com/godotengine/blender-exporter",
  36. "support": "OFFICIAL",
  37. "category": "Import-Export"
  38. }
  39. class ExportGodot(bpy.types.Operator, ExportHelper):
  40. """Selection to Godot"""
  41. bl_idname = "export_godot.escn"
  42. bl_label = "Export to Godot"
  43. bl_options = {"PRESET"}
  44. filename_ext = ".escn"
  45. filter_glob = StringProperty(default="*.escn", options={"HIDDEN"})
  46. # List of operator properties, the attributes will be assigned
  47. # to the class instance from the operator settings before calling
  48. object_types = EnumProperty(
  49. name="Object Types",
  50. options={"ENUM_FLAG"},
  51. items=(
  52. ("EMPTY", "Empty", ""),
  53. ("CAMERA", "Camera", ""),
  54. ("LAMP", "Lamp", ""),
  55. ("ARMATURE", "Armature", ""),
  56. ("MESH", "Mesh", ""),
  57. # ("CURVE", "Curve", ""),
  58. ),
  59. default={
  60. "EMPTY",
  61. "CAMERA",
  62. "LAMP",
  63. "ARMATURE",
  64. "MESH",
  65. # "CURVE"
  66. },
  67. )
  68. use_export_shape_key = BoolProperty(
  69. name="Export Shape Key",
  70. description="Export all the shape keys in mesh objects",
  71. default=True,
  72. )
  73. use_export_selected = BoolProperty(
  74. name="Selected Objects",
  75. description="Export only selected objects (and visible in active "
  76. "layers if that applies).",
  77. default=False,
  78. )
  79. use_exclude_ctrl_bone = BoolProperty(
  80. name="Exclude Control Bones",
  81. description="Do not export control bones (bone.use_deform = false)",
  82. default=True,
  83. )
  84. use_export_animation = BoolProperty(
  85. name="Export Animation",
  86. description="Export all the animation actions (include actions "
  87. "in nla_tracks), note that by default blender animation "
  88. "is exported as actions, so every node would have their "
  89. "own AnimationPlayer hold their actions",
  90. default=True,
  91. )
  92. use_mesh_modifiers = BoolProperty(
  93. name="Apply Modifiers",
  94. description="Apply modifiers to mesh objects (on a copy!).",
  95. default=True,
  96. )
  97. use_active_layers = BoolProperty(
  98. name="Active Layers",
  99. description="Export only objects on the active layers.",
  100. default=True,
  101. )
  102. animation_modes = EnumProperty(
  103. name="Animation Modes",
  104. description="Configuration of how blender animation data being "
  105. "exported to godot AnimationPlayer as well as the "
  106. "placement of AnimationPlayers in the node tree.",
  107. default="ACTIONS",
  108. items=(
  109. (
  110. "ACTIONS", "Animation as Actions",
  111. "Each animated node would have their own AnimationPlayer"
  112. ),
  113. (
  114. "SCENE_ANIMATION", "Scene Animation",
  115. "All the animations of the whole scene would be placed "
  116. "into one AnimationPlayer at scene root"
  117. ),
  118. (
  119. "SQUASHED_ACTIONS", "Animation as Actions with Squash",
  120. "Animation is exported as actions of nodes, but instead "
  121. "of having an individual AnimationPlayer for each node, "
  122. "this configuration would squash children nodes' actions "
  123. "to their parents"
  124. )
  125. )
  126. )
  127. material_search_paths = EnumProperty(
  128. name="Material Search Paths",
  129. description="Search for existing godot materials with names that match"
  130. "the blender material names (ie the file <matname>.tres"
  131. "containing a material resource)",
  132. default="PROJECT_DIR",
  133. items=(
  134. (
  135. "NONE", "None",
  136. "Don't search for materials"
  137. ),
  138. (
  139. "EXPORT_DIR", "Export Directory",
  140. "Search the folder where the escn is exported to"
  141. ),
  142. (
  143. "PROJECT_DIR", "Project Directory",
  144. "Search for materials in the godot project directory"
  145. ),
  146. )
  147. )
  148. @property
  149. def check_extension(self):
  150. """Checks if the file extension is valid. It appears we don't
  151. really care.... """
  152. return True
  153. def execute(self, context):
  154. """Begin the export"""
  155. try:
  156. if not self.filepath:
  157. raise Exception("filepath not set")
  158. keywords = self.as_keywords(ignore=(
  159. "axis_forward",
  160. "axis_up",
  161. "global_scale",
  162. "check_existing",
  163. "filter_glob",
  164. "xna_validate",
  165. ))
  166. from . import export_godot
  167. return export_godot.save(self, context, **keywords)
  168. except ValidationError as error:
  169. self.report({'ERROR'}, str(error))
  170. return {'CANCELLED'}
  171. def menu_func(self, context):
  172. """Add to the menu"""
  173. self.layout.operator(ExportGodot.bl_idname, text="Godot Engine (.escn)")
  174. def register():
  175. """Add addon to blender"""
  176. bpy.utils.register_module(__name__)
  177. bpy.types.INFO_MT_file_export.append(menu_func)
  178. def unregister():
  179. """Remove addon from blender"""
  180. bpy.utils.unregister_module(__name__)
  181. bpy.types.INFO_MT_file_export.remove(menu_func)
  182. def export(filename, overrides=None):
  183. """A function to allow build systems to invoke this script more easily
  184. with a call to io_scene_godot.export(filename).
  185. The overrides property allows the config of the exporter to be controlled
  186. keys should be the various properties defined in the ExportGodot class.
  187. Eg:
  188. io_scene_godot.export(
  189. filename,
  190. {
  191. 'material_search_path':'EXPORT_DIR',
  192. 'use_mesh_modifiers':True,
  193. }
  194. )
  195. Anything not overridden will use the default properties
  196. """
  197. default_settings = dict()
  198. for attr_name in ExportGodot.__dict__:
  199. attr = ExportGodot.__dict__[attr_name]
  200. # This introspection is not very robust and may break in future blende
  201. # versions. This is becase for some reason you can't compare against
  202. # bpy.types.Property because. well, they end up not being subclasses
  203. # of that!!!
  204. if issubclass(type(attr), tuple):
  205. default_settings[attr_name] = attr[1]['default']
  206. if overrides is not None:
  207. default_settings.update(overrides)
  208. class FakeOp:
  209. """Fake blender operator"""
  210. def __init__(self):
  211. self.report = print
  212. from . import export_godot
  213. export_godot.save(FakeOp(), bpy.context, filename, **default_settings)
  214. if __name__ == "__main__":
  215. register()