def plugin_components(plugin_name, sub_category=None): """Get all of the components of a Ladybug Tools Plugin from the component server. Args: plugin_name: Text for the name of a particular plugin (aka. insect) to place components from (eg. "Ladybug", "Honeybee", "HB-Energy"). sub_category: Text for a specific plugin sub-category (aka. tab) to be exported (eg. "1 :: Analyze Data"). If None, all components in the plugin will be places on the canvas. (Default: None). Returns: A dictionary of the plugin components with the name of the component as the key and the component object as the value. """ # loop through the component server and find all the components in the plugin components = {} for proxy in ghi.ComponentServer.ObjectProxies: if proxy.Obsolete: continue category = proxy.Desc.Category subcategory = proxy.Desc.SubCategory # check to see if the component is in the plugin if category.strip() == plugin_name: # if so, see if it is in the sub category if sub_category is None or subcategory.strip() == sub_category: if str(proxy.Kind) == 'CompiledObject': # it's a .gha components[proxy.Desc.Name] = proxy.CreateInstance() elif str(proxy.Kind) == 'UserObject': # it's a .ghuser components[proxy.Desc.Name] = \ gh.GH_UserObject(proxy.Location).InstantiateObject() return components
def current_userobject_version(component): """Get the current installed version of a component. Args: component: A Grasshopper Python component with the same name as an installed user object. If no matching user object is found, this method returns None. """ # load component from the folder where it should be assert component.Category in FOLDER_MAP, \ 'Unknown category: %s. Add category to folder_dict.' % component.Category fp = os.path.join(UO_FOLDER, FOLDER_MAP[component.Category], 'user_objects', '%s.ghuser' % component.Name) if os.path.isfile(fp): # if the component was found, parse out the version uo = gh.GH_UserObject(fp).InstantiateObject() # uo.Message returns None so we have to find it the old school way! for lc, line in enumerate(uo.Code.split('\n')): if lc > 200: # this should never happen for valid userobjects raise ValueError( 'Failed to find version from UserObject for %s' % uo.Name) if line.strip().startswith("ghenv.Component.Message"): return line.split("=")[1].strip()[1:-1] else: # there is no currently installed version of this userobject return None
def create_userobject(component, move=True): """Create UserObject from a component. Args: component: A Grasshopper Python component. move: A Boolean to note whether the component should be moved to a subdirectory based on FOLDER_MAP. (Default: True). """ # initiate userobject uo = gh.GH_UserObject() # set attributes uo.Icon = component.Icon_24x24 try: exposure = int(component.AdditionalHelpFromDocStrings) except Exception: # no exposure category specified exposure = 1 uo.Exposure = EXPOSURE_MAP[exposure] uo.BaseGuid = component.ComponentGuid uo.Description.Name = component.Name uo.Description.Description = component.Description uo.Description.Category = component.Category uo.Description.SubCategory = component.SubCategory # save the userobject to a file uo.SetDataFromObject(component) uo.SaveToFile() # move the user object file to the assigned folder if move: ufd = os.path.join(UO_FOLDER, FOLDER_MAP[component.Category], 'user_objects') ufp = os.path.join(ufd, '%s.ghuser' % component.Name) if not os.path.isdir(ufd): # create folder if it is not already created os.mkdir(ufd) elif os.path.isfile(ufp): # remove current userobject try: os.remove(ufp) except Exception: pass # access is denied to the user object location uo.Path = ufp uo.SaveToFile() return uo
def create_userobject(component, move=True): """Create UserObject from a component. Args: component: A Grasshopper Python component. move: A Boolean to move the component a subdirectory based on folder_dict. """ # initiate userobject uo = gh.GH_UserObject() # set attributes uo.Icon = component.Icon_24x24 try: exposure = int(component.AdditionalHelpFromDocStrings) except: expousre = 1 uo.Exposure = exposure_dict.get(exposure, 1) uo.BaseGuid = component.ComponentGuid uo.Description.Name = component.Name uo.Description.Description = component.Description uo.Description.Category = component.Category uo.Description.SubCategory = component.SubCategory # save the userobject uo.SetDataFromObject(component) uo.SaveToFile() # move to the assigned folder if move: ufd = os.path.join(UOFOLDER, folder_dict[comp.Category], 'user_objects') ufp = os.path.join(ufd, '%s.ghuser' % comp.Name) if not os.path.isdir(ufd): # create folder if it is not already created os.mkdir(ufd) elif os.path.isfile(ufp): # remove current userobject os.remove(ufp) uo.Path = ufp uo.SaveToFile() return uo
def get_current_version(comp): """Find the current userobject with the same name and get its version.""" # load component from possible folder assert comp.Category in folder_dict, \ 'Unknown category: %s. Add category to folder_dict.' % comp.Category fp = os.path.join(UOFOLDER, folder_dict[comp.Category], 'user_objects', '%s.ghuser' % comp.Name) if os.path.isfile(fp): uo = gh.GH_UserObject(fp).InstantiateObject() # uo.Message returns None so we have to find it the old school way! for lc, line in enumerate(uo.Code.split('\n')): if lc > 200: # this should never happen for valid userobjects raise ValueError( 'Failed to find version from UserObject for %s' % uo.Name) if line.strip().startswith("ghenv.Component.Message"): return line.split("=")[1].strip()[1:-1] else: # this is no previous version of this userobject return None
def sync_component(component, syncing_component): """Sync a component on the canvas with its corresponding installed version. This includes identifying if the component by name in the user object folder, injecting the code from that user object into the component, and (if the component inputs or outputs have changed) circling the component in red + dropping the new user object next to the component. Args: component: A Grasshopper component object on the canvas to be circled. syncing_component: An object for the component that is doing the syncing. This will be used to give warnings and access the Grasshopper doc. Typically, this can be accessed through the ghenv.Component call. """ # identify the correct user object sub-folder to which the component belongs ghuser_file = '%s.ghuser' % component.Name if str(component.Name).startswith(('LB', 'HB', 'DF')): fp = os.path.join(UO_FOLDER, FOLDER_MAP[component.Category], 'user_objects', ghuser_file) elif str(component.Name).startswith( ('Ladybug', 'Honeybee', 'HoneybeePlus')): category = str(component.Name).split('_')[0] fp = os.path.join(UO_FOLDER, category, ghuser_file) else: # unidentified plugin; see if we can find it in the root fp = os.path.join(UO_FOLDER, ghuser_file) # check to see if the user object is installed if not os.path.isfile(fp): # see if there's a folder for the category if component.Category in FOLDER_MAP: fp = os.path.join(UO_FOLDER, FOLDER_MAP[component.Category], ghuser_file) if not os.path.isfile(fp): # see if the component is in the root fp = os.path.join(UO_FOLDER, ghuser_file) if not os.path.isfile( fp): # all hope is lost; component not installed warning = 'Failed to find the userobject for %s' % component.Name give_warning(syncing_component, warning) return False # the the instance of the user object from the file uo = gh.GH_UserObject(fp).InstantiateObject() # check to see if the version of the userobject has changed if not has_version_changed(uo, component): return False # the version has changed, let's update the code component.Code = uo.Code doc = syncing_component.OnPingDocument() # get the Grasshopper document # define the callback function and update the solution def call_back(document): component.ExpireSolution(False) doc.ScheduleSolution(2, gh.GH_Document.GH_ScheduleDelegate(call_back)) # check if the inputs or outputs have changed if input_output_changed(uo, component): insert_new_user_object(uo, component, doc) mark_component(doc, component) # mark component with a warning to the user return 'Cannot update %s. Replace manually.' % component.Name return 'Updated %s' % component.Name
def exportToUserObject(component, targetFolder, lb_preparation): targetFolder = os.path.join(targetFolder, "userObjects") if not os.path.isdir(targetFolder): os.mkdir(targetFolder) def isNewerVersion(currentUO, component): # check if the component has a newer version than the current userObjects # version of the connected component if component.Message == None: return True if len(component.Message.split("\n")) < 2: return True ghVersion, ghDate = component.Message.split("\n") ghCompVersion = map(int, ghVersion.split("VER ")[1].split(".")) month, day, ghYear = ghDate.split("_") # print version, date month = lb_preparation.monthList.index(month.upper()) + 1 ghCompDate = int(lb_preparation.getJD(month, day)) # in case there was no date for the userobject # the file will be considered older and will be overwrittern ghComponent = currentUO.InstantiateObject() # this is not the best way but works for now! # should be a better way to compute the component and get the message componentCode = ghComponent.Code.split("\n") UODate = ghCompDate - 1 # version of the file for lineCount, line in enumerate(componentCode): if lineCount > 200: break if line.strip().startswith("ghenv.Component.Message"): #print line # print line.split("=")[1].strip().split("\n") version, date = line.split("=")[1].strip().split("\\n") # in case the file doesn't have an standard Dragonfly message let it be updated try: UOVersion = map(int, version.split("VER ")[1].split(".")) except: return True month, day, UOYear = date.split("_") # should find the reason and fix it later if month == "SEPT": month = "SEP" month = lb_preparation.monthList.index(month.upper()) + 1 UODate = int(lb_preparation.getJD(month, day)) break # check if the version of the code is newer try: if int(ghYear.strip()) > int(UOYear[:-1].strip()): return True elif ghCompDate > UODate: return True elif ghCompDate == UODate: for ghVer, UOVer in zip(UOVersion, UOVersion): if ghVer < UOVer: return False return True else: print "\nThere is a newer userObject in Grasshopper folder that will be copied: " + currentUO.Path + "." + \ "\nUserObject version is: " + version + " " + date + \ "\nThe component version is: " + ghVersion + " " + ghDate + ".\n" return False except: return True # check if the userObject is already existed in the folder try: filePath = os.path.join(UOFolder, component.Name + ".ghuser") currentUO = gh.GH_UserObject(filePath) except: # the userobject is not there so just create it currentUO = None if currentUO != None: # if is newer remove if isNewerVersion(currentUO, component): # it has a newer version so let's remove the old one and creat a new userobject pass if not component.Category == "Maths": removeNicely = cs.RemoveCachedObject(filePath) if not removeNicely: os.remove(filePath) else: # there is already a newer version so just copy that to the folder instead # and return dstFullPath = os.path.join(targetFolder, component.Name + ".ghuser") shutil.copy2(filePath, dstFullPath) return # create the new userObject in Grasshopper folder uo = gh.GH_UserObject() uo.Icon = component.Icon_24x24 try: uo.Exposure = exposureDict[int(component.AdditionalHelpFromDocStrings)] except: try: compCode = component.Code # this is so dirty exposureNumber = compCode.split( "ghenv.Component.AdditionalHelpFromDocStrings")[1].split( "\n")[0].replace("=", "").replace('"', "").strip() uo.Exposure = exposureDict[int(exposureNumber)] except: uo.Exposure = exposureDict[int(1)] uo.BaseGuid = component.ComponentGuid uo.Description.Name = component.Name uo.Description.Description = component.Description # if user hasn't identified the category then put it into honeybee as an unknown! if component.Category == "Maths": uo.Description.Category = "Honeybee" else: uo.Description.Category = component.Category if component.SubCategory == "Script": uo.Description.SubCategory = "UnknownBees" else: uo.Description.SubCategory = component.SubCategory uo.CreateDefaultPath(True) uo.SetDataFromObject(component) uo.SaveToFile() # copy into Dragonfly filePathInit = os.path.join('\\'.join(filePath.split('\\')[:-2]), component.Name + ".ghuser") shutil.copy2(filePathInit, filePath) os.remove(filePathInit) # copy the component over dstFullPath = os.path.join(targetFolder, component.Name + ".ghuser") shutil.copy2(filePath, dstFullPath) gh.GH_ComponentServer.UpdateRibbonUI() print "UserObject successfully added to: "
ghenv.Component.SubCategory = "4 | Developers" #compatibleLBVersion = VER 0.0.59\nFEB_01_2015 try: ghenv.Component.AdditionalHelpFromDocStrings = "1" except: pass import Grasshopper.Folders as folders import Grasshopper.Kernel as gh import scriptcontext as sc import shutil import os import uuid UOFolder = folders.UserObjectFolders[0] + '\\Dragonfly' cs = gh.GH_ComponentServer() #gh.GH_ComponentServer exposureDict = { 0: ghenv.Component.Exposure.dropdown, 1: ghenv.Component.Exposure.primary, 2: ghenv.Component.Exposure.secondary, 3: ghenv.Component.Exposure.tertiary, 4: ghenv.Component.Exposure.quarternary, 5: ghenv.Component.Exposure.quinary, 6: ghenv.Component.Exposure.senary, 7: ghenv.Component.Exposure.septenary }
# check if the version of the code is newer if int(ghYear.strip()) < int(UOYear[:-1].strip()): return True, ghComponent.Code elif ghCompDate < UODate: return True, ghComponent.Code elif ghCompDate == UODate: for ghVer, UOVer in zip(UOVersion, UOVersion): if ghVer > UOVer: return False, " " return True, ghComponent.Code else: return False, " " # check if the userObject is already existed in the folder try: filePath = os.path.join(newUOFolder, component.Name + ".ghuser") newUO = gh.GH_UserObject(filePath) except: # there is no newer userobject with the same name so just return return # if is newer remove isNewer, newCode = isNewerVersion(newUO, component) # replace the code inside the component with userObject code if isNewer: if component.CodeInputParam == None: component.Code = newCode component.ExpireSolution(True) else: warning = "Failed to update %s. Remove code input from the component and try again!"%component.Name print warning ghenv.Component.AddRuntimeMessage(gh.GH_RuntimeMessageLevel.Warning, warning)
def update_component(component, uofolder): """Update a component using its version in the user object folder.""" # identify the correct user object sub-folder to which the component belongs if str(component.Name).startswith('LB'): # ladybug [+] fp = os.path.join(uofolder, 'ladybug_grasshopper', 'user_objects', '%s.ghuser' % component.Name) elif str(component.Name).startswith('HB'): # honeybee[+] if str(component.Category) == 'Honeybee': fp = os.path.join(uofolder, 'honeybee_grasshopper_core', 'user_objects', '%s.ghuser' % component.Name) elif str(component.Category) == 'HB-Energy': fp = os.path.join(uofolder, 'honeybee_grasshopper_energy', 'user_objects', '%s.ghuser' % component.Name) elif str(component.Category) == 'HB-Radiance': fp = os.path.join(uofolder, 'honeybee_grasshopper_radiance', 'user_objects', '%s.ghuser' % component.Name) elif str(component.Name).startswith('DF'): # dragonfly [+] fp = os.path.join(uofolder, 'dragonfly_grasshopper', 'user_objects', '%s.ghuser' % component.Name) elif str(component.Name).startswith('Ladybug'): # ladybug legacy fp = os.path.join(uofolder, 'Ladybug', '%s.ghuser' % component.Name) elif str(component.Name).startswith('Honeybee'): # honeybee legacy fp = os.path.join(uofolder, 'Honeybee', '%s.ghuser' % component.Name) elif str(component.Name).startswith('HoneybeePlus'): # old honeybee [+] fp = os.path.join(uofolder, 'HoneybeePlus', '%s.ghuser' % component.Name) else: # unidentified plugin; see if we can find it in the root fp = os.path.join(uofolder, '%s.ghuser' % component.Name) if not os.path.isfile(fp): category = str(component.Name).split('_')[0] fp = os.path.join(uofolder, category, '%s.ghuser' % component.Name) if not os.path.isfile(fp): warning = 'Failed to find the userobject for %s' % component.Name give_warning(ghenv.Component, warning) return False # the the instance of the user object uo = gh.GH_UserObject(fp).InstantiateObject() # check to see if the version of the userobject has changed if not has_version_changed(uo, component): return False # the version has changed component.Code = uo.Code # define the callback function def call_back(document): component.ExpireSolution(False) # update the solution doc.ScheduleSolution(2, gh.GH_Document.GH_ScheduleDelegate(call_back)) # check if the inputs or outputs have changed if input_output_changed(uo, component): insert_new_uo(uo, component, doc) mark_component(doc, component) # mark component with a warning to the user return 'Cannot update %s. Replace manually.' % component.Name return 'Updated %s' % component.Name
#compatibleLBVersion = VER 0.0.58\nAUG_20_2014 try: ghenv.Component.AdditionalHelpFromDocStrings = "5" except: pass import scriptcontext as sc import urllib import os import zipfile,os.path from clr import AddReference AddReference('Grasshopper') import Grasshopper.Kernel as gh import time doc = gh.GH_Document() def checkTheInputs(): # import the classes if sc.sticky.has_key('ladybug_release'): try: if not sc.sticky['ladybug_release'].isCompatible(ghenv.Component): return -1 except: warning = "You need a newer version of Ladybug to use this compoent." + \ "Use updateLadybug component to update userObjects.\n" + \ "If you have already updated userObjects drag Ladybug_Ladybug component " + \ "into canvas and try again." w = gh.GH_RuntimeMessageLevel.Warning ghenv.Component.AddRuntimeMessage(w, warning) return -1