1
$\begingroup$

in this little addon i try to make an asset management system. I'd like that the number of assets per row are adapting in real time to the size.x of the window or maybe the other way around: the size of the icon are adapting. how is it possible to do that with python ?

any solution that's keeping the preview ratio 1:1 is really good. but it may be trivial to do a more elaborated system.

enter image description here


import os
import bpy

bl_info = {
    "name" : "Test [BD3D]",
    "author" : "BD3D",   
    "description" : "Wow such manager",
    "blender" : (2, 80, 0),
    "location" : "Operator",
    "warning" : "",
    "category" : "Generic"
}


class SCATTER_TestAddonPref(bpy.types.AddonPreferences):
    bl_idname = __name__

    item_per_row : bpy.props.IntProperty(name="Items per rows",subtype='NONE',default=6,min=2,max=30)
    item_size    : bpy.props.FloatProperty(name="Items sizes",subtype='NONE',default=7,min=0,max=20)

    def draw(self, context):
        layout = self.layout

        winx = bpy.context.window.x #could start doing something if window x was reactive. but it stay static. 
        item_per_row = round((winx-170)/150)

        row = layout.row()
        row.label(text=str(winx))
        row.prop(self,"item_per_row") 
        row.prop(self,"item_size")       

        row = layout.row()
        row.alignment = 'LEFT'
        i=0
        for z in custom_icons:
            i+=1
            #row.separator(factor=1.0)
            row.box().template_icon(icon_value=custom_icons[z].icon_id,scale=self.item_size)
            row.separator(factor=1.0)
            if i == self.item_per_row:
                row = layout.row()
                row.alignment = 'LEFT'
                i=0
            #layout.label(text=str(i))


class Panel(bpy.types.Panel):
    bl_idname      = "TEST_PT_Panel" 
    bl_label       = "Scatter Icon test"
    bl_category    = "Scatter BETA"
    bl_space_type  = "VIEW_3D"
    bl_region_type = "UI"
    bl_context     = "objectmode"

    def draw(self, context):
        layout = self.layout

        global custom_icons

        layout.operator(SCATTER_OT_refresh_asset_manager.bl_idname, text="refresh", icon="FILE_REFRESH")

        # for z in custom_icons:
        #     layout.template_icon(icon_value=custom_icons[z].icon_id,scale=7)

#############################################################

class SCATTER_OT_size(bpy.types.Operator):
    bl_idname      = "scatter.size"
    bl_label       = ""
    bl_description = "refresh the asset manager"

    def execute(self, context):
        print()
        return {'FINISHED'}



class SCATTER_OT_refresh_asset_manager(bpy.types.Operator):
    bl_idname      = "scatter.refresh_asset_manager"
    bl_label       = ""
    bl_description = "refresh the asset manager"

    def execute(self, context):

        global custom_icons
        bpy.utils.previews.remove(custom_icons)
        custom_icons.clear()
        icon_set_up()

        return {'FINISHED'}

#############################################################


def icon_set_up():

    global custom_icons
    from os import listdir
    from os.path import isfile, join

    onlyfiles = [f for f in listdir(preset_directory) if isfile(join(preset_directory, f))]
    custom_icons = bpy.utils.previews.new()

    for f in onlyfiles:
        if f[-4:] == ".jpg":
            custom_icons.load(f, os.path.join(preset_directory, f), 'IMAGE')




#################### INSERT BELOW r'folder_path'
#preset_directory = r'C:\Myfolder\myset_of_images\'
preset_directory = os.path.join(bpy.utils.user_resource('SCRIPTS'), "presets", "scatter_presets_custom\\")
custom_icons     = None

#############################################################

def register():

    icon_set_up()

    bpy.utils.register_class(Panel)
    bpy.utils.register_class(SCATTER_OT_refresh_asset_manager)
    bpy.utils.register_class(SCATTER_TestAddonPref)


def unregister():

    global custom_icons                      #current removal method
    bpy.utils.previews.remove(custom_icons)  #corrent removal method
    custom_icons.clear()                     #corrent removal method

    bpy.utils.unregister_class(Panel)
    bpy.utils.unregister_class(SCATTER_OT_refresh_asset_manager)
    bpy.utils.unregister_class(SCATTER_TestAddonPref)

if __name__ == "__main__":
    register()


$\endgroup$
1
  • 1
    $\begingroup$ Think you should be using grid_flow $\endgroup$
    – Moog
    Oct 19, 2019 at 0:30

2 Answers 2

2
$\begingroup$

This should work:

def draw(self, context):
    grid = self.layout.grid_flow()

    for icon in custom_icons:
        grid.template_icon(icon_value=icons.icon_id,scale=self.item_size)
$\endgroup$
0
$\begingroup$

i just search in the api and it seems that there is multiples solution possible. in this case the best code i found is grid_flow (thanks merlin for confirming) https://docs.blender.org/api/current/bpy.types.UILayout.html?highlight=grid_flow#bpy.types.UILayout.grid_flow

it also seems that ui_units_x and y are good contestors but i didn't try them yet.

class SCATTER_TestAddonPref(bpy.types.AddonPreferences):
    bl_idname = __name__

    item_size    : bpy.props.FloatProperty(name="Items sizes",subtype='NONE',default=7,min=0,max=20)
    def draw(self, context):
        layout = self.layout

        row = layout.row()
        row.prop(self,"item_size")       

        row = layout.box().grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=False)
        row.alignment = 'LEFT'
        i=0
        for z in custom_icons:
            i+=1
            #row.separator(factor=1.0)
            prevbox= row.column(align=True)
            prevBOX=prevbox.box()
            prevBOX.template_icon(icon_value=custom_icons[z].icon_id,scale=self.item_size)
            prevBOX.label(text=z[:-4].replace("_"," ").title())
            prevbox.separator(factor=4)
$\endgroup$
1
  • $\begingroup$ There is no way to make these icons clickable? $\endgroup$ Jan 3 at 2:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .