1 # SPDX-License-Identifier: GPL-2.0-or-later
4 "name": "Web3D X3D/VRML2 format",
5 "author": "Campbell Barton, Bart, Bastien Montagne, Seva Alekseyev",
8 "location": "File > Import-Export",
9 "description": "Import-Export X3D, Import VRML2",
11 "doc_url": "{BLENDER_MANUAL_URL}/addons/import_export/scene_x3d.html",
12 "category": "Import-Export",
17 if "import_x3d" in locals():
18 importlib
.reload(import_x3d
)
19 if "export_x3d" in locals():
20 importlib
.reload(export_x3d
)
23 from bpy
.props
import (
29 from bpy_extras
.io_utils
import (
38 @orientation_helper(axis_forward
='Z', axis_up
='Y')
39 class ImportX3D(bpy
.types
.Operator
, ImportHelper
):
40 """Import an X3D or VRML2 file"""
41 bl_idname
= "import_scene.x3d"
42 bl_label
= "Import X3D/VRML2"
43 bl_options
= {'PRESET', 'UNDO'}
46 filter_glob
: StringProperty(default
="*.x3d;*.wrl", options
={'HIDDEN'})
48 def execute(self
, context
):
49 from . import import_x3d
51 keywords
= self
.as_keywords(ignore
=("axis_forward",
55 global_matrix
= axis_conversion(from_forward
=self
.axis_forward
,
58 keywords
["global_matrix"] = global_matrix
60 return import_x3d
.load(context
, **keywords
)
62 def draw(self
, context
):
66 class X3D_PT_export_include(bpy
.types
.Panel
):
67 bl_space_type
= 'FILE_BROWSER'
68 bl_region_type
= 'TOOL_PROPS'
70 bl_parent_id
= "FILE_PT_operator"
73 def poll(cls
, context
):
74 sfile
= context
.space_data
75 operator
= sfile
.active_operator
77 return operator
.bl_idname
== "EXPORT_SCENE_OT_x3d"
79 def draw(self
, context
):
81 layout
.use_property_split
= True
82 layout
.use_property_decorate
= False # No animation.
84 sfile
= context
.space_data
85 operator
= sfile
.active_operator
87 layout
.prop(operator
, "use_selection")
88 layout
.prop(operator
, "use_hierarchy")
89 layout
.prop(operator
, "name_decorations")
90 layout
.prop(operator
, "use_h3d")
93 class X3D_PT_export_transform(bpy
.types
.Panel
):
94 bl_space_type
= 'FILE_BROWSER'
95 bl_region_type
= 'TOOL_PROPS'
96 bl_label
= "Transform"
97 bl_parent_id
= "FILE_PT_operator"
100 def poll(cls
, context
):
101 sfile
= context
.space_data
102 operator
= sfile
.active_operator
104 return operator
.bl_idname
== "EXPORT_SCENE_OT_x3d"
106 def draw(self
, context
):
108 layout
.use_property_split
= True
109 layout
.use_property_decorate
= False # No animation.
111 sfile
= context
.space_data
112 operator
= sfile
.active_operator
114 layout
.prop(operator
, "global_scale")
115 layout
.prop(operator
, "axis_forward")
116 layout
.prop(operator
, "axis_up")
119 class X3D_PT_export_geometry(bpy
.types
.Panel
):
120 bl_space_type
= 'FILE_BROWSER'
121 bl_region_type
= 'TOOL_PROPS'
122 bl_label
= "Geometry"
123 bl_parent_id
= "FILE_PT_operator"
126 def poll(cls
, context
):
127 sfile
= context
.space_data
128 operator
= sfile
.active_operator
130 return operator
.bl_idname
== "EXPORT_SCENE_OT_x3d"
132 def draw(self
, context
):
134 layout
.use_property_split
= True
135 layout
.use_property_decorate
= False # No animation.
137 sfile
= context
.space_data
138 operator
= sfile
.active_operator
140 layout
.prop(operator
, "use_mesh_modifiers")
141 layout
.prop(operator
, "use_triangulate")
142 layout
.prop(operator
, "use_normals")
143 layout
.prop(operator
, "use_compress")
146 @orientation_helper(axis_forward
='Z', axis_up
='Y')
147 class ExportX3D(bpy
.types
.Operator
, ExportHelper
):
148 """Export selection to Extensible 3D file (.x3d)"""
149 bl_idname
= "export_scene.x3d"
150 bl_label
= 'Export X3D'
151 bl_options
= {'PRESET'}
153 filename_ext
= ".x3d"
154 filter_glob
: StringProperty(default
="*.x3d", options
={'HIDDEN'})
156 use_selection
: BoolProperty(
157 name
="Selection Only",
158 description
="Export selected objects only",
161 use_mesh_modifiers
: BoolProperty(
162 name
="Apply Modifiers",
163 description
="Use transformed mesh data from each object",
166 use_triangulate
: BoolProperty(
168 description
="Write quads into 'IndexedTriangleSet'",
171 use_normals
: BoolProperty(
173 description
="Write normals with geometry",
176 use_compress
: BoolProperty(
178 description
="Compress the exported file",
181 use_hierarchy
: BoolProperty(
183 description
="Export parent child relationships",
186 name_decorations
: BoolProperty(
187 name
="Name decorations",
188 description
=("Add prefixes to the names of exported nodes to "
189 "indicate their type"),
192 use_h3d
: BoolProperty(
193 name
="H3D Extensions",
194 description
="Export shaders for H3D",
198 global_scale
: FloatProperty(
200 min=0.01, max=1000.0,
204 path_mode
: path_reference_mode
206 def execute(self
, context
):
207 from . import export_x3d
209 from mathutils
import Matrix
211 keywords
= self
.as_keywords(ignore
=("axis_forward",
217 global_matrix
= axis_conversion(to_forward
=self
.axis_forward
,
219 ).to_4x4() @ Matrix
.Scale(self
.global_scale
, 4)
220 keywords
["global_matrix"] = global_matrix
222 return export_x3d
.save(context
, **keywords
)
224 def draw(self
, context
):
228 class X3D_PT_import_transform(bpy
.types
.Panel
):
229 bl_space_type
= 'FILE_BROWSER'
230 bl_region_type
= 'TOOL_PROPS'
231 bl_label
= "Transform"
232 bl_parent_id
= "FILE_PT_operator"
235 def poll(cls
, context
):
236 sfile
= context
.space_data
237 operator
= sfile
.active_operator
239 return operator
.bl_idname
== "IMPORT_SCENE_OT_x3d"
241 def draw(self
, context
):
243 layout
.use_property_split
= True
244 layout
.use_property_decorate
= False # No animation.
246 sfile
= context
.space_data
247 operator
= sfile
.active_operator
249 layout
.prop(operator
, "axis_forward")
250 layout
.prop(operator
, "axis_up")
253 def menu_func_import(self
, context
):
254 self
.layout
.operator(ImportX3D
.bl_idname
,
255 text
="X3D Extensible 3D (.x3d/.wrl)")
258 def menu_func_export(self
, context
):
259 self
.layout
.operator(ExportX3D
.bl_idname
,
260 text
="X3D Extensible 3D (.x3d)")
265 X3D_PT_export_include
,
266 X3D_PT_export_transform
,
267 X3D_PT_export_geometry
,
269 X3D_PT_import_transform
,
275 bpy
.utils
.register_class(cls
)
277 bpy
.types
.TOPBAR_MT_file_import
.append(menu_func_import
)
278 bpy
.types
.TOPBAR_MT_file_export
.append(menu_func_export
)
282 bpy
.types
.TOPBAR_MT_file_import
.remove(menu_func_import
)
283 bpy
.types
.TOPBAR_MT_file_export
.remove(menu_func_export
)
286 bpy
.utils
.unregister_class(cls
)
289 if __name__
== "__main__":