1
$\begingroup$

I have a .x3d file containing several meshes. When I load them into Blender, they are loaded into separate objects; I'd like all of them to be loaded into one group so I can manipulate them (e.g., rotate them) together.

To emphasize, I know how to group objects once they are loaded, however there are a lot of them, so being able to load them directly to a group would be more convenient. Is there a way to do it?

$\endgroup$
  • $\begingroup$ it could be added easily as a feature to the addon. A completely reasonable request btw. $\endgroup$ – zeffii May 6 '15 at 11:43
  • $\begingroup$ the .x3d standard does specify an element tag called <Group> which goes directly inside a scene. but the blender .x3d importer doesn't handle it explicitly, at least I don't see it in the code. You could file a bug report to acknowledge it. $\endgroup$ – zeffii May 6 '15 at 12:18
2
$\begingroup$

While the .x3d specifies a Group tag, as of (May 2015) it doesn't appear that the blender .x3d importer does anything special with the tag It might not be possible to avoid a bit of scripting..

The .x3d importer currently prepends the name 'Shape' to all objects it generates. A simple way to select all objects with that prefix is

import bpy

D = bpy.data
for obj in D.objects:
    if obj.name.startswith("ShapeCylinder"):
        obj.select = True

or also generate the Empty and parent them all in one go.

import bpy

objects = bpy.data.objects

# makes the Empty, adds to scene
MT = objects.new('Empty_Grouper', None)
bpy.context.scene.objects.link(MT)

# parent every new object to MT
for obj in objects:
    if obj.name.startswith("ShapeCylinder"):
        obj.parent = MT

These scripts can be executed from inside Blender's Text Editor. An alternative is to write a thin wrapper around the .x3d importer, something like:

wrapped_importer_x3d.py

In essence what the code below does is:

  • it loads the existing x3d importer code.
  • Before triggering it, it stores the list of existing object names
  • after the import is complete it figures out the names of the objects that have been added
  • then parents those to an Empty.

You could save this, and stick it into /scripts/addons/wrapped_importer_x3d.py, enable it so:

enter image description here

Then it will be located in Import -> Import x3d parented

# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####

# <pep8-80 compliant>

bl_info = {
    "name": "x3d wrapped importer Parents",
    "author": "alias",
    "version": (0, 0, 1),
    "blender": (2, 7, 4),
    "category": "Import-Export",
    "wiki_url": "",
    "tracker_url": ""
}

import bpy
from bpy.types import Operator
from bpy.props import (
    BoolProperty,
    EnumProperty,
    FloatProperty,
    StringProperty)

from bpy_extras.io_utils import (
    ImportHelper,
    orientation_helper_factory,
    axis_conversion,
    path_reference_mode)

from io_scene_x3d import import_x3d


IOX3DOrientationHelper = orientation_helper_factory(
    "IOX3DOrientationHelper",
    axis_forward='Z',
    axis_up='Y')


class ImportX3DBETA(Operator, ImportHelper, IOX3DOrientationHelper):
    """Import an X3D or VRML2 file"""
    bl_idname = "import_scene.x3d_grouped"
    bl_label = "Import X3D/VRML2 Grouped"
    bl_options = {'PRESET', 'UNDO'}

    filename_ext = ".x3d"
    filter_glob = StringProperty(default="*.x3d;*.wrl", options={'HIDDEN'})

    def parent_new_objects(self, object_names):
        objects = bpy.data.objects
        MT = objects.new('Empty_Grouper', None)
        bpy.context.scene.objects.link(MT)

        # for every object in the scene which matches the start of the string
        # parent it to MT
        for obj in (o for o in objects if o.name in object_names):
            obj.parent = MT

    def execute(self, context):

        keywords = self.as_keywords(ignore=("axis_forward",
                                            "axis_up",
                                            "filter_glob",
                                            ))
        global_matrix = axis_conversion(from_forward=self.axis_forward,
                                        from_up=self.axis_up,
                                        ).to_4x4()
        keywords["global_matrix"] = global_matrix

        before = {obj.name for obj in bpy.data.objects}

        response = import_x3d.load(self, context, **keywords)
        if response == {'FINISHED'}:
            after = {obj.name for obj in bpy.data.objects}
            new_names = after ^ before
            self.parent_new_objects(new_names)

        return {'FINISHED'}


# Only needed if you want to add into a dynamic menu
def menu_func_import(self, context):
    self.layout.operator(ImportX3DBETA.bl_idname, text="Import x3d parented")


def register():
    bpy.utils.register_class(ImportX3DBETA)
    bpy.types.INFO_MT_file_import.append(menu_func_import)


def unregister():
    bpy.types.INFO_MT_file_import.remove(menu_func_import)
    bpy.utils.unregister_class(ImportX3DBETA)


if __name__ == "__main__":
    register()

    # test call
    # bpy.ops.import_scene.x3d_grouped('INVOKE_DEFAULT')
|improve this answer|||||
$\endgroup$
  • $\begingroup$ Thanks, but I think my question was a little unclear, please see the bold text in the revised question. $\endgroup$ – olamundo May 6 '15 at 11:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.