示例#1
0
def __recalculate_connection_entry__(data_block, conn_key):
    """Recalculates connection entry data for given connection key.
    NOTE: if key doesn't exists error stack trace will be printed and script execution cancelled

    :param data_block: data block from where data should be read
    :type data_block: bpy_struct
    :param conn_key: connection key for connection which should be recalculated
    :type conn_key: str
    """
    conn_entries = data_block[MAIN_DICT][REFS][CONNECTIONS][ENTRIES]
    locators_refs = data_block[MAIN_DICT][REFS][LOCATORS]

    conn_ref = conn_entries[conn_key]

    loc0_obj = bpy.data.objects[conn_ref[OUT]]
    loc1_obj = bpy.data.objects[conn_ref[IN]]

    conn_type = locators_refs[conn_ref[IN]][TYPE]

    conn_ref[VALID] = _object_utils.get_scs_root(loc0_obj) == _object_utils.get_scs_root(loc1_obj)

    # recalculate curves depending on type
    if conn_type == "Navigation Point":
        conn_ref[DATA] = _collector.collect_nav_curve_data(loc0_obj, loc1_obj)
    elif conn_type == "Map Point":
        conn_ref[DATA] = _collector.collect_map_line_data(loc0_obj, loc1_obj)
    elif conn_type == "Trigger Point":
        (loc0_avaliable, loc0_conns_count) = __tp_locator_avaliable__(data_block, loc0_obj.name)
        (loc1_avaliable, loc1_conns_count) = __tp_locator_avaliable__(data_block, loc1_obj.name)
        conn_ref[DATA] = _collector.collect_trigger_line_data(loc0_obj, loc0_conns_count, loc1_obj, loc1_conns_count)
示例#2
0
    def locator_type_update(self, context):

        obj = context.object

        # PREVIEW MODELS LOADING
        if obj.scs_props.locator_type in ("Collision", "None"):
            _preview_models.unload(obj)
        elif not obj.scs_props.locator_preview_model_present:
            _preview_models.load(obj)

        # SCS_PART RESET
        if not _object_utils.has_part_property(obj):
            obj.scs_props.scs_part = ""
        else:

            scs_root_object = _object_utils.get_scs_root(obj)

            if scs_root_object:

                part_inventory = scs_root_object.scs_object_part_inventory

                # set part index to active or first
                # NOTE: direct access needed otherwise get function sets invalid index because
                # active object has still old part value
                part_index = scs_root_object.scs_props.active_scs_part_get_direct()
                if part_index >= len(part_inventory) or part_index < 0:
                    part_index = 0

                obj.scs_props.scs_part = part_inventory[part_index].name

            else:  # if no root assign default

                obj.scs_props.scs_part = _PART_consts.default_name
示例#3
0
def __objects_reparent__(parent, new_objs):
    """Hookup function for objects reparent operation.

    :param parent: parent object where all of the objects were parented
    :type parent: bpy.types.Object
    :param new_objs: list of object which were parented to object
    :type new_objs: list of bpy.types.Object
    """

    # fixing parts on newly parented object
    scs_root_object = _object_utils.get_scs_root(parent)
    if scs_root_object:

        part_inventory = scs_root_object.scs_object_part_inventory
        assign_part_index = scs_root_object.scs_props.active_scs_part

        # if active is out of range assign first one
        if assign_part_index >= len(part_inventory) or assign_part_index < 0:
            assign_part_index = 0

        new_mats = []
        for new_obj in new_objs:
            if _object_utils.has_part_property(new_obj):
                new_obj.scs_props.scs_part = part_inventory[assign_part_index].name

            for slot in new_obj.material_slots:
                if slot.material and slot.material not in new_mats:
                    new_mats.append(slot.material)

        _looks.add_materials(scs_root_object, new_mats)
示例#4
0
        def execute(self, context):

            scs_globals = _get_scs_globals()

            if self.type == "DefaultExportPath":
                obj = context.scene.scs_props
                prop = "default_export_filepath"
            elif self.type == "GameObjectExportPath":
                obj = context.active_object.scs_props
                prop = "scs_root_object_export_filepath"
            elif self.type == "GameObjectAnimExportPath":
                obj = _object_utils.get_scs_root(context.active_object).scs_props
                prop = "scs_root_object_anim_export_filepath"
            else:
                obj = context.active_object.scs_props
                prop = "scs_skeleton_custom_export_dirpath"

            if _path_utils.startswith(self.directory, scs_globals.scs_project_path):
                setattr(obj, prop, _path_utils.relative_path(scs_globals.scs_project_path, self.directory))
            else:
                setattr(obj, prop, "//")
                self.report({'ERROR'}, "Selected path is not within SCS Project Base Path,\npath will be reset to SCS Project Base Path instead.")
                return {'CANCELLED'}

            return {'FINISHED'}
示例#5
0
        def execute(self, context):
            lprint('D Decrease Animation Steps...')
            scene = context.scene
            scene.use_preview_range = True
            action = context.active_object.animation_data.action

            if action.scs_props.anim_export_step == 1:
                lprint('E Cannot set lower value for %r than %i!', ('Export Step', 1))
            else:
                active_object = context.active_object
                scs_root_object = _object_utils.get_scs_root(active_object)
                # active_scs_animation = scs_root_object.scs_props.active_scs_animation
                inventory = scs_root_object.scs_object_animation_inventory
                # animation = inventory[active_scs_animation]

                # MOVE FRAMES
                # print_fcurve = 13
                for fcurve_i, fcurve in enumerate(action.fcurves):
                    # if fcurve_i == print_fcurve: print('fcurve: %r - %s' % (str(fcurve.data_path), str(fcurve.range())))
                    for keyframe_i, keyframe in enumerate(fcurve.keyframe_points):
                        # if fcurve_i == print_fcurve: print('  %i keyframe: %s' % (keyframe_i, str(keyframe.co)))

                        # OLD WAY OF INCREASING ACTION LENGTH FROM THE FIRST KEYFRAME
                        # start_frame = fcurve.range()[0]
                        # actual_frame = keyframe.co.x
                        # keyframe.co.x = ((actual_frame - start_frame) / 2) + start_frame

                        # NEW WAY - SIMPLE DOUBLING THE VALUES
                        keyframe.co.x /= 2
                    fcurve.update()

                    # ## PRINTOUTS
                    # print('  group: %r' % str(fcurve.group.name))
                    # for channel_i, channel in enumerate(fcurve.group.channels):
                    # print('    %i channel: %s - %s' % (channel_i, str(channel.data_path), str(channel.range())))
                    # for keyframe_i, keyframe in enumerate(channel.keyframe_points):
                    # print('      %i keyframe: %s' % (keyframe_i, str(keyframe.co)))

                # INCREASE GLOBAL RANGE
                scene.frame_start /= 2
                scene.frame_end /= 2

                # INCREASE PREVIEW RANGE
                scene.frame_preview_start /= 2
                scene.frame_preview_end /= 2

                # INCREASE END FRAME NUMBER IN ALL ANIMATIONS THAT USES THE ACTUAL ACTION
                for anim in inventory:
                    if anim.action == action.name:
                        anim.anim_start /= 2
                        anim.anim_end /= 2

                # INCREASE EXPORT STEP
                # print('anim_export_step: %s' % str(action.scs_props.anim_export_step))
                action.scs_props.anim_export_step /= 2

                # INCREASE FPS
                scene.render.fps /= 2

            return {'FINISHED'}
示例#6
0
        def execute(self, context):
            lprint('D Import Animation Action...')

            '''
            print('  o directory: %r' % str(self.directory))
            print('  o files:')
            for file in self.files:
                print('  o   file: %r' % str(file.name))
            '''

            pia_files = [os.path.join(self.directory, file.name) for file in self.files]

            if context.active_object.type == 'ARMATURE':
                armature = context.active_object
            else:
                return {'CANCELLED'}

            skeleton = None
            bones = None

            '''
            for file in pia_files:
                print('  o   file: %r' % str(file))
            '''
            root_object = _object_utils.get_scs_root(armature)

            lprint('S armature: %s\nskeleton: %s\nbones: %s\n', (str(armature), str(skeleton), str(bones)))
            _import.pia.load(root_object, pia_files, armature)  # , skeleton, bones)
            return {'FINISHED'}
示例#7
0
def __objects_reparent__(parent, new_objs):
    """Hookup function for objects reparent operation.

    :param parent: parent object where all of the objects were parented
    :type parent: bpy.types.Object
    :param new_objs: list of object which were parented to object
    :type new_objs: list of bpy.types.Object
    """

    # fixing parts on newly parented object
    scs_root_object = _object_utils.get_scs_root(parent)
    if scs_root_object:

        part_inventory = scs_root_object.scs_object_part_inventory
        assign_part_index = scs_root_object.scs_props.active_scs_part

        # if active is out of range assign first one
        if assign_part_index >= len(part_inventory) or assign_part_index < 0:
            assign_part_index = 0

        new_mats = []
        for new_obj in new_objs:
            # NOTE: second condition prevents overwriting part on object which already have
            # valid part from before (This might happen when re-parenting from one SCS Root to another)
            if _object_utils.has_part_property(new_obj) and new_obj.scs_props.scs_part not in part_inventory:
                new_obj.scs_props.scs_part = part_inventory[assign_part_index].name

            for slot in new_obj.material_slots:
                if slot.material and slot.material not in new_mats:
                    new_mats.append(slot.material)

        _looks.add_materials(scs_root_object, new_mats)
示例#8
0
def __locator_changed__(data_block, loc_obj):
    """Checks if locator object is different from current state in cache.
    In case that is, it returns True and already updates cached locator to current state

    :param loc_obj: Blender object which is locator
    :type loc_obj: bpy.types.Object
    :return: True if object was changed and False if there is no change
    :rtype: bool
    """

    data = data_block[MAIN_DICT]

    loc_cached = data[CACHE][LOCATORS][loc_obj.name]

    changed = False

    # in case we will extend caching properties we have to make sure
    # that existing models saved in blend file won't fail because of
    # index out of bounds during access.
    while len(loc_cached) <= 7:
        loc_cached.append("")

    matrix_hash = hashlib.md5(str(loc_obj.matrix_world).encode("utf-8")).hexdigest()
    if matrix_hash != loc_cached[0]:
        loc_cached[0] = matrix_hash
        changed = True

    if loc_obj.scs_props.locator_prefab_np_blinker != loc_cached[1]:
        loc_cached[1] = loc_obj.scs_props.locator_prefab_np_blinker
        changed = True

    if loc_obj.scs_props.locator_prefab_np_allowed_veh != loc_cached[2]:
        loc_cached[2] = loc_obj.scs_props.locator_prefab_np_allowed_veh
        changed = True

    if loc_obj.scs_props.locator_prefab_np_priority_modifier != loc_cached[3]:
        loc_cached[3] = loc_obj.scs_props.locator_prefab_np_priority_modifier
        changed = True

    if loc_obj.scs_props.locator_prefab_mp_custom_color != loc_cached[4]:
        loc_cached[4] = loc_obj.scs_props.locator_prefab_mp_custom_color
        changed = True

    prefab_exit = str(loc_obj.scs_props.locator_prefab_mp_prefab_exit)
    if prefab_exit != loc_cached[5]:
        loc_cached[5] = prefab_exit
        changed = True

    road_size = str(loc_obj.scs_props.locator_prefab_mp_road_size)
    if road_size != loc_cached[6]:
        loc_cached[6] = road_size
        changed = True

    root_hash = hashlib.md5(str(_object_utils.get_scs_root(loc_obj)).encode("utf-8")).hexdigest()
    if root_hash != loc_cached[7]:
        loc_cached[7] = root_hash
        changed = True

    data[CACHE][LOCATORS][loc_obj.name] = loc_cached
    return changed
示例#9
0
    def execute(self, context):
        lprint('D Export From Menu...')

        from io_scs_tools import exp as _export
        from io_scs_tools.utils import object as _object_utils

        filepath = os.path.dirname(self.filepath)

        # convert it to None, so export will ignore given menu file path and try to export to other none menu set paths
        if self.filepath == "":
            filepath = None

        export_scope = _get_scs_globals().export_scope
        init_obj_list = {}
        if export_scope == "selection":
            for obj in bpy.context.selected_objects:
                root = _object_utils.get_scs_root(obj)
                if root:
                    if root != obj:  # add only selected children
                        init_obj_list[obj.name] = obj
                        init_obj_list[root.name] = root
                    else:  # add every children if all are unselected
                        children = _object_utils.get_children(obj)
                        local_reselected_objs = []
                        for child_obj in children:
                            local_reselected_objs.append(child_obj)
                            # if some child is selected this means we won't reselect nothing in this game object
                            if child_obj.select:
                                local_reselected_objs = []
                                break

                        for reselected_obj in local_reselected_objs:
                            init_obj_list[reselected_obj.name] = reselected_obj

            init_obj_list = tuple(init_obj_list.values())
        elif export_scope == "scene":
            init_obj_list = tuple(bpy.context.scene.objects)
        elif export_scope == 'scenes':
            init_obj_list = tuple(bpy.data.objects)

        try:
            result = _export.batch_export(self, init_obj_list, menu_filepath=filepath)
        except Exception as e:

            result = {"CANCELLED"}
            context.window.cursor_modal_restore()

            import traceback

            traceback.print_exc()
            lprint("E Unexpected %r accured during batch export, see stack trace above.",
                   (type(e).__name__,),
                   report_errors=1,
                   report_warnings=1)

        return result
示例#10
0
def __update_look__(self, context):
    """Hookup function for triggering update look from material in internal module of looks.
    It should be used on any property which should be saved in exported into looks.
    :param context: Blender context
    :type context: bpy.types.Context
    """

    if hasattr(context, "active_object") and hasattr(context.active_object, "active_material") and context.active_object.active_material:
        scs_root = _object_utils.get_scs_root(context.active_object)
        if scs_root:
            _looks.update_look_from_material(scs_root, context.active_object.active_material, "preset_change" in self)
示例#11
0
    def set_active_scs_look(self, value):

        if value != self.get_active_scs_look():

            self["active_scs_look"] = value

            if bpy.context.active_object:

                scs_root = _object_utils.get_scs_root(bpy.context.active_object)
                if scs_root:
                    _looks.apply_active_look(scs_root)
示例#12
0
def __create_locator_entries__(data_block, loc_obj):
    """Creates new entries in LOCATORS and CACHE for given SCS locator object
    If type of given SCS locator object is not right entry is not created

    :param data_block: data block from where data should be read
    :type data_block: bpy_struct
    :param loc_obj: SCS locator object
    :type loc_obj: bpy.types.Object
    :return: True if creation was successfull otherwise False
    :rtype: bool
    """

    data = data_block[MAIN_DICT]

    locators_refs = data[REFS][LOCATORS]
    locators_cache = data[CACHE][LOCATORS]

    loc_type = loc_obj.scs_props.locator_prefab_type
    if loc_type in ("Navigation Point", "Map Point", "Trigger Point"):

        # create LOCATORS and CACHE entry if necessary
        if loc_obj.name not in locators_refs:
            if loc_type == "Navigation Point":
                locators_refs[loc_obj.name] = {
                    TYPE: loc_type,
                    IN_CONNS: [],
                    OUT_CONNS: []
                }

            elif loc_type in ("Map Point", "Trigger Point"):
                locators_refs[loc_obj.name] = {
                    TYPE: loc_type,
                    CONNS: []
                }

        locators_cache[loc_obj.name] = [
            hashlib.md5(str(loc_obj.matrix_world).encode('utf-8')).hexdigest(),
            loc_obj.scs_props.locator_prefab_np_blinker,
            loc_obj.scs_props.locator_prefab_np_allowed_veh,
            loc_obj.scs_props.locator_prefab_np_priority_modifier,
            loc_obj.scs_props.locator_prefab_mp_custom_color,
            str(loc_obj.scs_props.locator_prefab_mp_prefab_exit),
            str(loc_obj.scs_props.locator_prefab_mp_road_size),
            hashlib.md5(str(_object_utils.get_scs_root(loc_obj)).encode('utf-8')).hexdigest()
        ]

        return True

    else:
        return False
示例#13
0
    def active_scs_animation_update(self, context):
        """Update function for Active SCS Animation record on Objects.

        :param context: Blender Context
        :type context: bpy.types.Context
        :rtype: None
        """
        active_object = context.active_object
        scs_root_object = _object_utils.get_scs_root(active_object)
        scene = context.scene

        # GET ARMATURE OBJECT
        armature = None
        if active_object.type == 'ARMATURE':
            armature = active_object
        else:
            children = _object_utils.get_children(scs_root_object)
            for child in children:
                if child.type == 'ARMATURE':
                    armature = child
                    break

        scs_object_anim_inventory = scs_root_object.scs_object_animation_inventory
        active_scs_anim_i = self.active_scs_animation
        if len(scs_object_anim_inventory) > active_scs_anim_i:
            active_scs_anim = scs_object_anim_inventory[active_scs_anim_i]
            start_frame = active_scs_anim.anim_start
            end_frame = active_scs_anim.anim_end
            length = active_scs_anim.length

            # set frame range properly
            _animation_utils.set_frame_range(scene, start_frame, end_frame)

            # set action to armature end properly set preview fps
            action = None
            if active_scs_anim.action in bpy.data.actions:
                action = bpy.data.actions[active_scs_anim.action]

                _animation_utils.set_fps_for_preview(scene, length, start_frame, end_frame)

            # ensure animation data block to be able to set action
            if armature.animation_data is None:
                armature.animation_data_create()

            armature.animation_data.action = action  # set/reset action of current animation

        else:
            print('Wrong Animation index %i/%i!' % (active_scs_anim_i, len(scs_object_anim_inventory)))
        return None
示例#14
0
    def draw(self, context):
        """UI draw function."""
        layout = self.layout
        scene = bpy.context.scene
        mat = context.material
        scs_globals = _get_scs_globals()

        if mat:
            # PROVISIONAL SHADER PRESET PANEL
            _draw_preset_shader_panel(layout.box(), mat, scene.scs_props, scs_globals)

            active_object = context.active_object
            scs_root_object = _object_utils.get_scs_root(active_object)
            if active_object and scs_root_object:
                _shared.draw_scs_looks_panel(layout, scene, active_object, scs_root_object)
示例#15
0
        def execute(self, context):
            lprint('D Import Animation Action...')

            pia_files = [os.path.join(self.directory, file.name) for file in self.files]

            armature = context.active_object
            root_object = _object_utils.get_scs_root(armature)

            imported_count = _import.pia.load(root_object, pia_files, armature)

            # report warnings and errors if actually imported count differs from number of pia files
            if imported_count != len(pia_files):
                lprint("", report_warnings=1, report_errors=1)

            return {'FINISHED'}
示例#16
0
    def name_update(self, context):

        lprint("D SCS Part inventory name update: %s", (self.name,))

        # convert name to game engine like name
        tokenized_name = _name_utils.tokenize_name(self.name, default_name=_PART_consts.default_name)
        if self.name != tokenized_name:
            self.name = tokenized_name

        # always get scs root because we allow editing of parts in any child
        scs_root_obj = _object_utils.get_scs_root(context.active_object)

        # if there is more of parts with same name, make postfixed name (this will cause another name update)
        if len(_inventory.get_indices(scs_root_obj.scs_object_part_inventory, self.name)) == 2:  # duplicate

            i = 1
            new_name = _name_utils.tokenize_name(self.name + "_" + str(i).zfill(2))
            while _inventory.get_index(scs_root_obj.scs_object_part_inventory, new_name) != -1:
                new_name = _name_utils.tokenize_name(self.name + "_" + str(i).zfill(2))
                i += 1

            if new_name != self.name:
                self.name = new_name

        if "scs_part_old_name" in self:

            if scs_root_obj:

                # fix part name in all children of current root
                children = _object_utils.get_children(scs_root_obj)
                for child in children:

                    # fix part name in child with existing old name
                    if child.scs_props.scs_part == self["scs_part_old_name"]:

                        child.scs_props.scs_part = self.name

                # rename parts in all variants also
                variant_inventory = scs_root_obj.scs_object_variant_inventory
                for variant in variant_inventory:
                    for part in variant.parts:

                        if part.name == self["scs_part_old_name"]:
                            part.name = self.name
                            break

        # backup current name for checking children on next renaming
        self["scs_part_old_name"] = self.name
示例#17
0
def _fix_ex_parent(obj):
    """Fixes ex parent settings which were caused by re/unparenting.
    NOTE: ex parent is readed from parent identity property

    :param obj: SCS Blender object from which ex parent object should be taken
    :type obj: bpy.types.Object
    """

    # fix children count for ex parent
    if obj.scs_props.parent_identity in bpy.data.objects:
        ex_parent_obj = bpy.data.objects[obj.scs_props.parent_identity]
        ex_parent_obj.scs_cached_num_children = len(ex_parent_obj.children)

        ex_parent_scs_root = _object_utils.get_scs_root(ex_parent_obj)
        if ex_parent_scs_root:
            _looks.clean_unused(ex_parent_scs_root)
示例#18
0
    def get_objects(context):
        if context.scene.scs_props.visibility_tools_scope == "Global":

            objects = context.scene.objects

        else:

            scs_root_object = _object_utils.get_scs_root(context.scene.objects.active)
            if scs_root_object:
                objects = _object_utils.get_children(scs_root_object)
                scs_root_object.hide = False
                scs_root_object.select = True
                bpy.context.scene.objects.active = scs_root_object
            else:  # fallback don't do anything
                objects = []

        return objects
示例#19
0
        def execute(self, context):
            material = context.active_object.active_material

            if material and hasattr(material.scs_props, self.property_str):

                scs_root = _object_utils.get_scs_root(context.active_object)

                if scs_root:
                    altered_looks = _looks.write_through(scs_root, material, self.property_str)
                    if altered_looks > 0:
                        message = "Write through successfully altered %s looks!" % altered_looks
                    else:
                        message = "Nothing to write through."

                    self.report({'INFO'}, message)

            return {'FINISHED'}
示例#20
0
def __locator_changed__(data_block, loc_obj):
    """Checks if locator object is different from current state in cache.
    In case that is, it returns True and already updates cached locator to current state

    :param loc_obj: Blender object which is locator
    :type loc_obj: bpy.types.Object
    :return: True if object was changed and False if there is no change
    :rtype: bool
    """

    data = data_block[MAIN_DICT]

    loc_cached = data[CACHE][LOCATORS][loc_obj.name]

    changed = False

    matrix_hash = hashlib.md5(str(loc_obj.matrix_world).encode("utf-8")).hexdigest()
    if matrix_hash != loc_cached[0]:
        loc_cached[0] = matrix_hash
        changed = True

    if loc_obj.scs_props.locator_prefab_np_blinker != loc_cached[1]:
        loc_cached[1] = loc_obj.scs_props.locator_prefab_np_blinker
        changed = True

    if loc_obj.scs_props.locator_prefab_np_allowed_veh != loc_cached[2]:
        loc_cached[2] = loc_obj.scs_props.locator_prefab_np_allowed_veh
        changed = True

    if loc_obj.scs_props.locator_prefab_mp_custom_color != loc_cached[3]:
        loc_cached[3] = loc_obj.scs_props.locator_prefab_mp_custom_color
        changed = True

    prefab_exit = str(loc_obj.scs_props.locator_prefab_mp_prefab_exit)
    if prefab_exit != loc_cached[4]:
        loc_cached[4] = prefab_exit
        changed = True

    root_hash = hashlib.md5(str(_object_utils.get_scs_root(loc_obj)).encode("utf-8")).hexdigest()
    if root_hash != loc_cached[5]:
        loc_cached[5] = root_hash
        changed = True

    data[CACHE][LOCATORS][loc_obj.name] = loc_cached
    return changed
示例#21
0
        def execute(self, context):
            lprint("D " + self.bl_idname, report_errors=-1, report_warnings=-1)

            if not _path_utils.startswith(self.directory, _get_scs_globals().scs_project_path):
                message = "E Selected path is not inside SCS Project Base Path! Animation can't be exported to this directory."
                lprint(message)
                self.report({'ERROR'}, message[2:])
                return {'CANCELLED'}

            armature = context.active_object
            scs_root_obj = _object_utils.get_scs_root(armature)
            anim_inventory = scs_root_obj.scs_object_animation_inventory

            skeleton_filepath = _path_utils.get_skeleton_relative_filepath(armature, self.directory, scs_root_obj.name)

            if 0 <= self.index < len(anim_inventory):

                anim = anim_inventory[self.index]
                _export.pia.export(scs_root_obj, armature, anim, self.directory, skeleton_filepath)

            lprint("", report_errors=1, report_warnings=1)
            return {'FINISHED'}
示例#22
0
        def __init__(self):
            """Shows all layer to be able to alter selection on the whole scene and
            alter Blender selection the way that:
            1. if only child within root is selected -> selects root too
            2. if only root is selected -> select all children
            3. if root and some children are selected -> don't change selection
            """
            self.layers_visibilities = _view3d_utils.switch_layers_visibility([], True)
            self.last_active_obj = bpy.context.active_object
            self.altered_objs = []
            self.altered_objs_visibilities = []
            self.not_root_objs = []

            for obj in bpy.context.selected_objects:
                root = _object_utils.get_scs_root(obj)
                if root:
                    if root != obj:
                        if not root.select:
                            root.select = True
                            self.altered_objs.append(root.name)
                    else:
                        children = _object_utils.get_children(obj)
                        local_reselected_objs = []
                        for child_obj in children:
                            local_reselected_objs.append(child_obj.name)
                            # if some child is selected this means we won't reselect nothing in this game objecdt
                            if child_obj.select:
                                local_reselected_objs = []
                                break
                        self.altered_objs.extend(local_reselected_objs)
                else:
                    obj.select = False
                    self.not_root_objs.append(obj.name)

            for obj_name in self.altered_objs:
                self.altered_objs_visibilities.append(bpy.data.objects[obj_name].hide)
                bpy.data.objects[obj_name].hide = False
                bpy.data.objects[obj_name].select = True
示例#23
0
    def name_update(self, context):

        lprint("D SCS Look inventory name update: %s", (self.name,))

        # convert name to game engine like name
        tokenized_name = _name_utils.tokenize_name(self.name)
        if self.name != tokenized_name:
            self.name = tokenized_name

        # always get scs root to have access to look inventory
        scs_root_obj = _object_utils.get_scs_root(context.active_object)

        # if there is more of variants with same name, make postfixed name (this will cause another name update)
        if len(_inventory.get_indices(scs_root_obj.scs_object_look_inventory, self.name)) == 2:  # duplicate

            i = 1
            new_name = _name_utils.tokenize_name(self.name + "_" + str(i).zfill(2))
            while _inventory.get_index(scs_root_obj.scs_object_look_inventory, new_name) != -1:
                new_name = _name_utils.tokenize_name(self.name + "_" + str(i).zfill(2))
                i += 1

            if new_name != self.name:
                self.name = new_name
示例#24
0
    def active_scs_part_get(self):
        """Getting active index in SCS Parts list. On active object change active index of the list is altered
        with the index of part belonging to new active object.

        """

        if not "active_scs_part_old_active" in self:
            self["active_scs_part_old_active"] = ""

        if not "active_scs_part_value" in self:
            self["active_scs_part_value"] = 0

        scs_root_object = _object_utils.get_scs_root(bpy.context.active_object)
        if scs_root_object and bpy.context.active_object != scs_root_object:

            # if old active object is different than current
            # set the value for active part index from it
            if self["active_scs_part_old_active"] != bpy.context.active_object.name:
                self["active_scs_part_value"] = _inventory.get_index(scs_root_object.scs_object_part_inventory,
                                                                     bpy.context.active_object.scs_props.scs_part)

        self["active_scs_part_old_active"] = bpy.context.active_object.name
        return self["active_scs_part_value"]
示例#25
0
def __material_assignement__(obj, new_mat_ids, removed_mat_ids):
    """Hookup function for material reassignement on object.

    :param obj: object on which material assignement happend
    :type obj: bpy.types.Object
    :param new_mat_ids: ID of newly added materials
    :type new_mat_ids: iter
    :param removed_mat_ids: ID of removed materials
    :type removed_mat_ids: iter
    """

    # create actual new materials list
    new_mats = []
    for mat in bpy.data.materials:
        curr_mat_id = str(mat.scs_props.id)
        if curr_mat_id in new_mat_ids:
            new_mats.append(mat)

    scs_root = _object_utils.get_scs_root(obj)
    if scs_root:
        _looks.add_materials(scs_root, new_mats)
        if len(removed_mat_ids) > 0:
            _looks.clean_unused(scs_root)
示例#26
0
    def length_update(self, context):
        """If the total time for animation is tweaked, FPS value is recalculated to keep the
        playback speed as close as possible to the resulting playback speed in the game engine.

        :param context: Blender Context
        :type context: bpy.types.Context
        """
        active_object = context.active_object
        if active_object:
            if active_object.animation_data:
                action = active_object.animation_data.action
                if action:
                    scs_root_object = _object_utils.get_scs_root(active_object)
                    if scs_root_object:
                        active_scs_animation = scs_root_object.scs_props.active_scs_animation
                        scs_object_animation_inventory = scs_root_object.scs_object_animation_inventory
                        animation = scs_object_animation_inventory[active_scs_animation]
                        _animation_utils.set_fps_for_preview(
                            context.scene,
                            animation.length,
                            action.scs_props.anim_export_step,
                            animation.anim_start,
                            animation.anim_end,
                        )
示例#27
0
        def execute(self, context):
            material = context.active_object.active_material

            if not material or not hasattr(material.scs_props, self.property_str):
                return {'CANCELLED'}

            scs_roots = []
            active_scs_root = _object_utils.get_scs_root(context.active_object)
            if active_scs_root:
                scs_roots.append(active_scs_root)

            if self.is_ctrl:
                scs_roots = _object_utils.gather_scs_roots(bpy.data.objects)

            if self.is_shift or not self.is_ctrl:  # WT either on active only or all SCS roots; (Shift + Ctrl) or none

                altered_looks = 0
                for scs_root in scs_roots:
                    altered_looks += _looks.write_through(scs_root, material, self.property_str)

                if altered_looks > 0:
                    message = "Write through successfully altered %s looks on %s SCS Root Objects!" % (altered_looks, len(scs_roots))
                else:
                    message = "Nothing to write through."

                self.report({'INFO'}, message)

            elif self.is_ctrl:  # special WT only into the same look of other SCS Roots

                # get current look id
                look_i = active_scs_root.scs_props.active_scs_look
                look_name = active_scs_root.scs_object_look_inventory[look_i].name if look_i >= 0 else None

                if look_name is None:
                    self.report({'WARNING'}, "Aborting as current object is not in any SCS Game Object, parent it to SCS Root first!")
                    return {'CANCELLED'}

                altered_looks = 0
                for scs_root in scs_roots:

                    # ignore active root
                    if scs_root == active_scs_root:
                        continue

                    look_id = -1

                    # search for same look by name on other scs root
                    for look in scs_root.scs_object_look_inventory:
                        if look.name == look_name:
                            look_id = look.id
                            break

                    if _looks.write_prop_to_look(scs_root, look_id, material, self.property_str):
                        altered_looks += 1

                if len(scs_roots) - 1 != altered_looks:
                    self.report({'WARNING'}, "WT partially done, same look was found on %s/%s other SCS Root Objects!" %
                                (altered_looks, len(scs_roots) - 1))
                else:
                    self.report({'INFO'}, "Write through altered property on %s other SCS Root Objects!" % altered_looks)

            return {'FINISHED'}
示例#28
0
    def draw(self, context):
        """UI draw function."""
        layout = self.layout
        scene = context.scene

        if scene:
            scs_root_is_reachable = _object_utils.get_scs_root(context.active_object) is not None

            box = layout.box()

            row = box.row()
            row.prop(scene.scs_props, "visibility_tools_scope", expand=True)

            col = box.column(align=True)
            col.enabled = scs_root_is_reachable or scene.scs_props.visibility_tools_scope == "Global"
            row1 = col.row(align=True)
            row1.alignment = 'CENTER'
            props = row1.operator('object.switch_model_objects_visibility', text='', icon_value=get_icon(_ICON_TYPES.mesh))
            props.view_type = _OP_consts.ViewType.viewonly
            props = row1.operator('object.switch_shadow_casters_visibility', text='', icon_value=get_icon(_ICON_TYPES.mesh_shadow_caster))
            props.view_type = _OP_consts.ViewType.viewonly
            props = row1.operator('object.switch_glass_objects_visibility', text='', icon_value=get_icon(_ICON_TYPES.mesh_glass))
            props.view_type = _OP_consts.ViewType.viewonly
            props = row1.operator('object.switch_substance_objects_visibility', text='', icon_value=get_icon(_ICON_TYPES.mesh_with_physics))
            props.view_type = _OP_consts.ViewType.viewonly
            row2 = col.row(align=True)
            row2.alignment = 'CENTER'
            props = row2.operator('object.switch_all_locators_visibility', text='', icon_value=get_icon(_ICON_TYPES.loc))
            props.view_type = _OP_consts.ViewType.viewonly
            props = row2.operator('object.switch_model_locators_visibility', text='', icon_value=get_icon(_ICON_TYPES.loc_model))
            props.view_type = _OP_consts.ViewType.viewonly
            props = row2.operator('object.switch_prefab_locators_visibility', text='', icon_value=get_icon(_ICON_TYPES.loc_prefab))
            props.view_type = _OP_consts.ViewType.viewonly
            props = row2.operator('object.switch_collision_locators_visibility', text='', icon_value=get_icon(_ICON_TYPES.loc_collider))
            props.view_type = _OP_consts.ViewType.viewonly

            col = box.column(align=True)
            col.enabled = scs_root_is_reachable or scene.scs_props.visibility_tools_scope == "Global"
            row2 = col.row(align=True)
            row2.alignment = 'CENTER'
            props = row2.operator('object.switch_prefab_nodes_visibility', text='', icon_value=get_icon(_ICON_TYPES.loc_prefab_node))
            props.view_type = _OP_consts.ViewType.viewonly
            props = row2.operator('object.switch_prefab_signs_visibility', text='', icon_value=get_icon(_ICON_TYPES.loc_prefab_sign))
            props.view_type = _OP_consts.ViewType.viewonly
            props = row2.operator('object.switch_prefab_spawns_visibility', text='', icon_value=get_icon(_ICON_TYPES.loc_prefab_spawn))
            props.view_type = _OP_consts.ViewType.viewonly
            props = row2.operator('object.switch_prefab_traffics_visibility', text='', icon_value=get_icon(_ICON_TYPES.loc_prefab_semaphore))
            props.view_type = _OP_consts.ViewType.viewonly
            row2 = col.row(align=True)
            row2.alignment = 'CENTER'
            props = row2.operator('object.switch_prefab_navigations_visibility', text='',
                                  icon_value=get_icon(_ICONS_consts.Types.loc_prefab_navigation))
            props.view_type = _OP_consts.ViewType.viewonly
            props = row2.operator('object.switch_prefab_maps_visibility', text='', icon_value=get_icon(_ICON_TYPES.loc_prefab_map))
            props.view_type = _OP_consts.ViewType.viewonly
            props = row2.operator('object.switch_prefab_triggers_visibility', text='', icon_value=get_icon(_ICON_TYPES.loc_prefab_trigger))
            props.view_type = _OP_consts.ViewType.viewonly
            row2.operator('object.blank_operator', text='', icon='BLANK1')

            col = layout.column(align=True)
            col.enabled = scs_root_is_reachable or scene.scs_props.visibility_tools_scope == "Global"
            col.label("Current SCS Root:", icon_value=get_icon(_ICONS_consts.Types.scs_root))
            col.operator('object.invert_visibility_within_root', text='Invert Visibility')
            col.operator('object.view_all_objects_within_root', text='View All')
            col.operator('object.isolate_objects_within_root', text='Isolate')
示例#29
0
def object_data_check(scene):

    # during rendering in Blender active_object doesn't exists so ignore this case
    if not hasattr(bpy.context, "active_object"):
        return

    active_obj = bpy.context.active_object
    selected_objs = bpy.context.selected_objects

    # skip persistent check if import is in the process
    if _get_scs_globals().import_in_progress:
        return

    # CHECK FOR DATA CHANGE UPON SELECTION
    if active_obj:

        if active_obj.is_updated_data:
            _Timer.data_updated += 1

        if active_obj.is_updated:
            _Timer.updated += 1

        elif len(selected_objs) > 0:
            # search for any updated object
            for sel_obj in selected_objs[:2]:
                if sel_obj.is_updated:
                    _Timer.updated += 1
                    break
    if _Timer.updated > 0:
        _connections_group_wrapper.switch_to_update()

    # BREAK EXECUTION IF TIMER SAYS SO
    if not _Timer.can_execute():
        return

    # GET UPDATE STATES
    updated = _Timer.updated > 0
    data_updated = _Timer.data_updated > 0
    _Timer.updated = _Timer.data_updated = 0

    if not updated:
        _connections_group_wrapper.switch_to_stall()

    # NEW/COPY
    if len(scene.objects) > scene.scs_cached_num_objects:

        scene.scs_cached_num_objects = len(scene.objects)

        if len(selected_objs) > 0:

            # create real selected list
            # (in case that one of selected objects is parent then children are not in this list)
            real_sel_objs = selected_objs.copy()
            for sel_obj in selected_objs:
                for child in sel_obj.children:
                    if child.select:
                        real_sel_objs.append(child)

            if real_sel_objs[0].scs_props.object_identity != "":

                old_objects = []
                for obj in real_sel_objs:
                    old_objects.append(bpy.data.objects[obj.scs_props.object_identity])
                    obj.scs_props.object_identity = obj.name

                __objects_copy__(old_objects, real_sel_objs)

                lprint("D ---> COPY of the objects: %s", (len(real_sel_objs),))
                return
            else:

                for obj in real_sel_objs:
                    obj.scs_props.object_identity = obj.name

                lprint("D ---> NEW objects: %s", (len(real_sel_objs),))
                return

    # DELETE
    if len(scene.objects) < scene.scs_cached_num_objects:

        scene.scs_cached_num_objects = len(scene.objects)

        unparented_objects = []
        for obj in scene.objects:

            if obj.scs_props.parent_identity != "" and not obj.scs_props.parent_identity in bpy.data.objects:
                obj.scs_props.parent_identity = ""
                unparented_objects.append(obj)

            obj.scs_cached_num_children = len(obj.children)

        __objects_delete__(unparented_objects)

        lprint("D ---> DELETE of the objects!")
        return

    # if there is no active object then all of rest actions can not be executed at all
    if active_obj:

        # RENAME
        active_obj_identity = active_obj.scs_props.object_identity
        if active_obj.name != active_obj_identity and active_obj_identity != "":

            old_name = active_obj_identity
            new_name = active_obj.name

            active_obj.scs_props.object_identity = active_obj.name
            _fix_children(active_obj)

            __object_rename__(old_name, new_name)

            if old_name in bpy.data.objects:

                lprint("D ---> NAME SWITCHING")
                bpy.data.objects[old_name].scs_props.object_identity = old_name
                _fix_children(bpy.data.objects[old_name])

                # switching names causes invalid connections data so recalculate curves for these objects
                _connections_group_wrapper.force_recalculate([bpy.data.objects[old_name], bpy.data.objects[new_name]])

            lprint("D ---> RENAME of the active object!")
            return

        # RE/PARENT
        active_obj_children_count = len(active_obj.children)
        if active_obj_children_count > active_obj.scs_cached_num_children:

            active_obj.scs_cached_num_children = active_obj_children_count

            for obj in selected_objs:
                if obj != active_obj:

                    _fix_ex_parent(obj)
                    obj.scs_props.parent_identity = active_obj.name
                    obj.scs_cached_num_children = len(obj.children)

            __objects_reparent__(active_obj, selected_objs)

            lprint("D ---> RE/PARENT selected objects to active object %s", (len(selected_objs),))
            return

        if active_obj.parent and active_obj.parent.name != active_obj.scs_props.parent_identity:

            _fix_ex_parent(active_obj)
            active_obj.scs_props.parent_identity = active_obj.parent.name

            __objects_reparent__(active_obj.parent, [active_obj])

            lprint("D ---> RE/PARENT active object to some other parent")
            return

        # UNPARENT
        if not active_obj.select and not active_obj.parent and active_obj.scs_props.parent_identity != "":

            _fix_ex_parent(active_obj)
            active_obj.scs_props.parent_identity = ""

            lprint("D ---> UNPARENT active object in panel")
            return

        if ((not active_obj.parent and active_obj.scs_props.parent_identity != "") or
                (len(selected_objs) > 0 and not selected_objs[0].parent and selected_objs[0].scs_props.parent_identity != "")):

            for obj in selected_objs:

                _fix_ex_parent(obj)
                obj.scs_props.parent_identity = ""

            lprint("D ---> UNPARENT selected objects in 3D view: %s", (len(selected_objs),))
            return

        # ACTIVE SCS ROOT CHANGED
        active_scs_root = _object_utils.get_scs_root(active_obj)
        if active_scs_root and scene.scs_cached_active_scs_root != active_scs_root.name:

            __active_scs_root_change__(active_scs_root)

            scene.scs_cached_active_scs_root = active_scs_root.name
            lprint("D ---> ACTIVE SCS ROOT CHANGE: %r", (active_scs_root.name,))
            return

        # MATERIAL ASSIGNEMENT ACTION
        if data_updated or updated:

            mats_ids = {}
            new_mats = {}
            removed_mats = dict(active_obj.scs_cached_materials_ids)
            for slot in active_obj.material_slots:
                if slot.material:
                    curr_id = str(slot.material.scs_props.id)
                    mats_ids[curr_id] = 1
                    if curr_id not in active_obj.scs_cached_materials_ids:  # if not in cached -> it's newly assigned
                        new_mats[curr_id] = 1
                    elif curr_id in removed_mats:  # if in cached remove it from dictionary which stores removed materials
                        del removed_mats[curr_id]

            if len(new_mats) > 0 or len(removed_mats) > 0:
                active_obj.scs_cached_materials_ids = mats_ids

                __material_assignement__(active_obj, new_mats.keys(), removed_mats.keys())

                lprint("D ---> MATERIAL ASSIGNEMENT CHANGED")
                return
示例#30
0
 def poll(cls, context):
     active_obj = context.active_object
     return active_obj and active_obj.type == "ARMATURE" and _object_utils.get_scs_root(active_obj)