def getInertiaRelevantObjects(link, selected_only=False): """Returns a list of visual and collision objects of a link. If name-pairs of visual and collision objects are detected, the one with the latest change-date is used. If this is not clear, visual objects are omitted in favor of collision objects. If the selected_only parameter is used, only the selected objects are considered. Args: link(bpy_types.Object): The link you want to gather the inertia relevant objects for. selected_only(bool, optional): return only relevant objects which are selected (Default value = False) Returns: list """ objdict = { obj.name: obj for obj in sUtils.getImmediateChildren(link, ['visual', 'collision'], selected_only) } basenames = set() inertiaobjects = [] for objname in objdict.keys(): if 'mass' in objdict[objname]: if not objname.startswith('visual_') and not objname.startswith( 'collision_'): inertiaobjects.append(objdict[objname]) else: basename = objname.replace(objdict[objname].phobostype + '_', '') if basename not in basenames: basenames.add(basename) collision = 'collision_'+basename if 'collision_'+basename in objdict.keys()\ and 'mass' in objdict['collision_'+basename] else None visual = 'visual_'+basename if 'visual_'+basename in objdict.keys()\ and 'mass' in objdict['visual_'+basename] else None if visual and collision: try: tv = gUtils.datetimeFromIso( objdict[visual]['masschanged']) tc = gUtils.datetimeFromIso( objdict[collision]['masschanged']) # if collision information is older than visual information if tc < tv: inertiaobjects.append(objdict[visual]) else: inertiaobjects.append(objdict[collision]) # if masschanged not present in both except KeyError: inertiaobjects.append(objdict[collision]) else: inertiaobjects.append(objdict[collision] if collision else objdict[visual]) return inertiaobjects
def execute(self, context): sourcelist = [] targetlist = [] processed = set() links = [obj.name for obj in bpy.context.selected_objects if obj.phobostype == 'link'] t = datetime.now() objdict = {obj.name: obj for obj in bpy.data.objects if obj.phobostype in ['visual', 'collision'] and obj.parent.name in links} # gather all name bases of objects for which both visual and collision are present for obj in objdict.keys(): basename = obj.replace(objdict[obj].phobostype + '_', '') if 'visual_' + basename in objdict.keys() and 'collision_' + basename in objdict.keys(): processed.add(basename) # fill source and target lists for syncing for basename in processed: if self.synctype == "vtc": sourcelist.append('visual_' + basename) targetlist.append('collision_' + basename) elif self.synctype == "ctv": targetlist.append('visual_' + basename) sourcelist.append('collision_' + basename) else: # latest to oldest try: tv = generalUtils.datetimeFromIso(objdict['visual_' + basename]['masschanged']) tc = generalUtils.datetimeFromIso(objdict['collision_' + basename]['masschanged']) if tc < tv: # if collision information is older than visual information sourcelist.append('visual_' + basename) targetlist.append('collision_' + basename) else: targetlist.append('visual_' + basename) sourcelist.append('collision_' + basename) except KeyError: print(basename, "has insufficient data for time-based synchronisation of masses.") # sync the mass values for i in range(len(sourcelist)): try: objdict[targetlist[i]]['mass'] = objdict[sourcelist[i]]['mass'] except KeyError: print("No mass information in object", targetlist[i]) if self.synctype != "vtc" and self.synctype != "ctv": objdict[targetlist[i]]['masschanged'] = objdict[sourcelist[i]]['masschanged'] for linkname in links: masssum = 0.0 link = bpy.data.objects[linkname] viscols = inertia.getInertiaRelevantObjects(link) for obj in viscols: masssum += obj['mass'] link['mass'] = masssum link['masschanged'] = t.isoformat() if self.updateinertial: inertia.createInertials(link) return {'FINISHED'}
def getInertiaRelevantObjects(link): """Returns a list of visual and collision objects of a link. If name-pairs of visual and collision objects are detected, the one with the latest change-date is used. If this is not clear, visual objects are omitted in favor of collision objects. :param link: The link you want to gather the inertia relevant objects for. :type link: bpy_types.Object :return: list """ objdict = { obj.name: obj for obj in selectionUtils.getImmediateChildren(link, ['visual', 'collision']) } basenames = set() inertiaobjects = [] for objname in objdict.keys(): if 'mass' in objdict[objname]: if not objname.startswith('visual_') and not objname.startswith( 'collision_'): inertiaobjects.append(objdict[objname]) else: basename = objname.replace(objdict[objname].phobostype + '_', '') if not basename in basenames: basenames.add(basename) collision = 'collision_'+basename if 'collision_'+basename in objdict.keys()\ and 'mass' in objdict['collision_'+basename] else None visual = 'visual_'+basename if 'visual_'+basename in objdict.keys()\ and 'mass' in objdict['visual_'+basename] else None if visual and collision: try: tv = generalUtils.datetimeFromIso( objdict[visual]['masschanged']) tc = generalUtils.datetimeFromIso( objdict[collision]['masschanged']) if tc < tv: # if collision information is older than visual information inertiaobjects.append(objdict[visual]) else: inertiaobjects.append(objdict[collision]) except KeyError: # if masschanged not present in both inertiaobjects.append(objdict[collision]) else: inertiaobjects.append(objdict[collision] if collision else objdict[visual]) return inertiaobjects
def getInertiaRelevantObjects(link): """Returns a list of visual and collision objects of a link. If name-pairs of visual and collision objects are detected, the one with the latest change-date is used. If this is not clear, visual objects are omitted in favor of collision objects. :param link: The link you want to gather the inertia relevant objects for. :type link: Blender object. :return: list. """ objdict = {obj.name: obj for obj in selectionUtils.getImmediateChildren(link, ['visual', 'collision'])} basenames = set() inertiaobjects = [] for objname in objdict.keys(): if 'mass' in objdict[objname]: if not objname.startswith('visual_') and not objname.startswith('collision_'): inertiaobjects.append(objdict[objname]) else: basename = objname.replace(objdict[objname].phobostype + '_', '') if not basename in basenames: basenames.add(basename) collision = 'collision_'+basename if 'collision_'+basename in objdict.keys()\ and 'mass' in objdict['collision_'+basename] else None visual = 'visual_'+basename if 'visual_'+basename in objdict.keys()\ and 'mass' in objdict['visual_'+basename] else None if visual and collision: try: tv = generalUtils.datetimeFromIso(objdict[visual]['masschanged']) tc = generalUtils.datetimeFromIso(objdict[collision]['masschanged']) if tc < tv: # if collision information is older than visual information inertiaobjects.append(objdict[visual]) else: inertiaobjects.append(objdict[collision]) except KeyError: # if masschanged not present in both inertiaobjects.append(objdict[collision]) else: inertiaobjects.append(objdict[collision] if collision else objdict[visual]) return inertiaobjects
def execute(self, context): sourcelist = [] targetlist = [] processed = set() # FIXME NoneTypeError although objects are selected links = [ obj.name for obj in context.selected_objects if obj.phobostype == 'link' ] t = datetime.now() objdict = { obj.name: obj for obj in bpy.data.objects if obj.phobostype in ['visual', 'collision'] and obj.parent.name in links } # gather all name bases of objects for which both visual and collision are present for obj in objdict.keys(): basename = obj.replace(objdict[obj].phobostype + '_', '') if 'visual_' + basename in objdict.keys( ) and 'collision_' + basename in objdict.keys(): processed.add(basename) # fill source and target lists for syncing for basename in processed: if self.synctype == "vtc": sourcelist.append('visual_' + basename) targetlist.append('collision_' + basename) elif self.synctype == "ctv": targetlist.append('visual_' + basename) sourcelist.append('collision_' + basename) else: # latest to oldest try: tv = gUtils.datetimeFromIso( objdict['visual_' + basename]['masschanged']) tc = gUtils.datetimeFromIso( objdict['collision_' + basename]['masschanged']) if tc < tv: # if collision information is older than visual information sourcelist.append('visual_' + basename) targetlist.append('collision_' + basename) else: targetlist.append('visual_' + basename) sourcelist.append('collision_' + basename) except KeyError: log( basename + " has insufficient data for time-based" + "synchronisation of masses.", "WARNING") # sync the mass values for i in range(len(sourcelist)): try: objdict[targetlist[i]]['mass'] = objdict[sourcelist[i]]['mass'] except KeyError: log("No mass information in object " + targetlist[i], "WARNING") if self.synctype != "vtc" and self.synctype != "ctv": objdict[targetlist[i]]['masschanged'] = objdict[ sourcelist[i]]['masschanged'] # update inertials and sum masses for links for linkname in links: masssum = 0.0 link = bpy.data.objects[linkname] viscols = inertia.getInertiaRelevantObjects(link) for obj in viscols: masssum += obj['mass'] link['mass'] = masssum link['masschanged'] = t.isoformat() if self.updateinertial: inertia.createInertials(link) return {'FINISHED'}