Ordnerinhalt in template_list anzeigen

Blenders Funktionsumfang mit Python-Scripten erweitern.

Ordnerinhalt in template_list anzeigen

Beitragvon Tiles » 15.10.2016, 11:07

Ich hänge mal wieder an Basics fest. Ich würde gern den Inhalt eines Ordners in einer template_list anzeigen.

Das Auslesen des Ordners funktioniert bereits. Der Inhalt landet derzeit in einer List. Und wird auch brav in die Konsole geprintet. Aber wie bekomme ich das jetzt nun in meine template_list rein?

Mein Problem ist kurz formuliert folgendes. Ich habe meine Liste. Und ich habe mein Blender List Item. Aber keine Verbindung zwischen den Beiden:

Code: Alles auswählen
mylist = []
...
//Umwandlung in das was Blender braucht?
...
row.template_list(Was muss hier stehen?)


Einfach ist das wohl nicht. Auf Blender Stack Exchange schicken sie mich per Links in die Manual und die Python API. Und ich bin genauso schlau wie vorher. Deswegen hatte ich ja auf Stack Exchange nachgefragt, weil ich mit den Eklärungen da nicht zurechtkomme :(

Hier gibts zum Beispiel ein List Beispiel das mit Materialien arbeitet. Das steckt auch in den Scripting Beispielen: https://www.blender.org/api/blender_pyt ... IList.html
Und hier das Beispiel für eine Collection Property: https://www.blender.org/api/blender_pyt ... on-example
Und hier die Definition für template_list: https://www.blender.org/api/blender_pyt ... plate_list

Was ich verstanden habe ist dass ich wohl meine Liste in eine Collection Property umwandeln muss. Aber wie mache ich das? Und wie verknüpfe ich das dann mit der template_list? Was muss wo rein? Und vor allem warum?

Ich bin wie immer für alle sachdienlichen Hinweise dankbar :)

Liebe Grüsse

Tiles

Fast hätte ich das bisherige Script vergessen:

Code: Alles auswählen
import bpy
import os


 # -----------------------------------------------------------------------------------------------------
 # the panel is in the properties sidebar. 
 # -----------------------------------------------------------------------------------------------------
 
mylist = []

class VIEW3D_read_dir(bpy.types.Operator):
    """Blubb"""
    bl_idname = "view3d.read_dir"
    bl_label = "Read Dir"
   
    def execute(self, context):
       
        mylist = [] # empty the list

        start_path = 'C:/Users/x/Documents' # current directory. Change to your needs. Do NOT use backslashes here.
        for path,dirs,files in os.walk(start_path):
            for filename in files:
                if filename.endswith(".blend"):
                    mylist.append(os.path.join(filename))
        print (mylist) # debugging. The content in the console.
        return {'FINISHED'} 
 
class MyPanel(bpy.types.Panel):
    bl_label = "MyPanel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'

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

        layout.operator("view3d.read_dir", text="read directory") # Click me to read the directory. Content of blend files will be printed in the console.
       
        scene = context.scene
        row = layout.row()

        row.template_list("UI_UL_list", "keying_sets", scene, "keying_sets", scene.keying_sets, "active_index", rows=1) # Placeholder for my template_list
       

# ------------------------------ register unregister -------------------------------------------------------- 

def register():

    bpy.utils.register_module(__name__)
               
def unregister():

    bpy.utils.unregister_module(__name__)
       
if __name__ == "__main__":
    register()
   
   
Dateianhänge
listinlist.jpg
Free Game Graphics, Freeware Games http://www.reinerstilesets.de
Benutzeravatar
Tiles
 
Registriert:
20.11.2007, 12:19

Re: Ordnerinhalt in template_list anzeigen

Beitragvon HG1 » 16.10.2016, 09:31

Für listen gibt es zwei Draw-Aufrufe einer zeichnet die Liste der zweite zeichnet die Elemete in die Liste.
Code: Alles auswählen
# custom list
class UL_items(UIList):

    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
        layout.label(item.name)
 
    def invoke(self, context, event):
        pass   


Und du musst die Elemente zur Liste hinzufügen.
Code: Alles auswählen
       item = scn.keying_sets.add()
       item.name = os.path.join(filename)

Achtung: Ich habe den Code nicht mit deinem Beispiel getestet.
HG1
 
Registriert:
16.08.2010, 11:43

Re: Ordnerinhalt in template_list anzeigen

Beitragvon Tiles » 16.10.2016, 09:54

Danke Hg1, das hilft mir ein wenig weiter :)
Free Game Graphics, Freeware Games http://www.reinerstilesets.de
Benutzeravatar
Tiles
 
Registriert:
20.11.2007, 12:19

Re: Ordnerinhalt in template_list anzeigen

Beitragvon Eric » 17.10.2016, 23:28

... kannst Du die Lösung posten? War für mich leider noch nicht ausreichend 8)
Eric
 
Registriert:
05.08.2013, 14:46

Re: Ordnerinhalt in template_list anzeigen

Beitragvon Tiles » 18.10.2016, 08:46

Ich kaue immer noch dran rum. Imzwischen bin ich so weit das Ding an die Wand zu klatschen :D

Sobald ich eine Lösung habe werde ich die aber natürlich hier posten :)
Free Game Graphics, Freeware Games http://www.reinerstilesets.de
Benutzeravatar
Tiles
 
Registriert:
20.11.2007, 12:19

Re: Ordnerinhalt in template_list anzeigen

Beitragvon Tiles » 18.10.2016, 12:29

Also die custom List ist class UL_items(bpy.types.UIList):

Mit dem zweiten Teil mit dem man die Liste einliest kann ich allerdings auch nichts anfangen. Im Moment schmeisst mir das nur Not Defined Fehler.
Free Game Graphics, Freeware Games http://www.reinerstilesets.de
Benutzeravatar
Tiles
 
Registriert:
20.11.2007, 12:19

Re: Ordnerinhalt in template_list anzeigen

Beitragvon HG1 » 18.10.2016, 20:26

Hier zwei Beispiel (waren für einen anderen Zweck). Daher passen sie nicht zu dem was du machen möchtest aber sie funktionieren zumindest.
Code: Alles auswählen
import bpy
from bpy.props import IntProperty, CollectionProperty #, StringProperty
from bpy.types import Panel, UIList


# return name of selected object
def get_activeSceneObject():
    return bpy.context.scene.objects.active.name


# ui list item actions
class Uilist_actions(bpy.types.Operator):
    bl_idname = "custom.list_action"
    bl_label = "List Action"

    action = bpy.props.EnumProperty(
        items=(
            ('UP', "Up", ""),
            ('DOWN', "Down", ""),
            ('REMOVE', "Remove", ""),
            ('ADD', "Add", ""),
        )
    )

    def invoke(self, context, event):

        scn = context.scene
        idx = scn.custom_index

        try:
            item = scn.custom[idx]
        except IndexError:
            pass

        else:
            if self.action == 'DOWN' and idx < len(scn.custom) - 1:
                item_next = scn.custom[idx+1].name
                scn.custom_index += 1
                info = 'Item %d selected' % (scn.custom_index + 1)
                self.report({'INFO'}, info)

            elif self.action == 'UP' and idx >= 1:
                item_prev = scn.custom[idx-1].name
                scn.custom_index -= 1
                info = 'Item %d selected' % (scn.custom_index + 1)
                self.report({'INFO'}, info)

            elif self.action == 'REMOVE':
                info = 'Item %s removed from list' % (scn.custom[scn.custom_index].name)
                scn.custom_index -= 1
                self.report({'INFO'}, info)
                scn.custom.remove(idx)

        if self.action == 'ADD':
            item = scn.custom.add()
            item.id = len(scn.custom)
            item.name = get_activeSceneObject() # assign name of selected object
            scn.custom_index = (len(scn.custom)-1)
            info = '%s added to list' % (item.name)
            self.report({'INFO'}, info)

        return {"FINISHED"}

# -------------------------------------------------------------------
# draw
# -------------------------------------------------------------------

# custom list
class UL_items(UIList):

    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
        split = layout.split(0.3)
        split.label("Index: %d" % (index))
        split.prop(item, "name", text="", emboss=False, translate=False, icon='BORDER_RECT')

    def invoke(self, context, event):
        pass   

# draw the panel
class UIListPanelExample(Panel):
    """Creates a Panel in the Object properties window"""
    bl_idname = 'OBJECT_PT_my_panel'
    bl_space_type = "TEXT_EDITOR"
    bl_region_type = "UI"
    bl_label = "Custom Object List"

    def draw(self, context):
        layout = self.layout
        scn = bpy.context.scene

        rows = 2
        row = layout.row()
        row.template_list("UL_items", "", scn, "custom", scn, "custom_index", rows=rows)

        col = row.column(align=True)
        col.operator("custom.list_action", icon='ZOOMIN', text="").action = 'ADD'
        col.operator("custom.list_action", icon='ZOOMOUT', text="").action = 'REMOVE'
        col.separator()
        col.operator("custom.list_action", icon='TRIA_UP', text="").action = 'UP'
        col.operator("custom.list_action", icon='TRIA_DOWN', text="").action = 'DOWN'

        row = layout.row()
        col = row.column(align=True)
        col.operator("custom.print_list", icon="WORDWRAP_ON")
        col.operator("custom.select_item", icon="UV_SYNC_SELECT")
        col.operator("custom.clear_list", icon="X")


# print button
class Uilist_printAllItems(bpy.types.Operator):
    bl_idname = "custom.print_list"
    bl_label = "Print List"
    bl_description = "Print all items to the console"

    def execute(self, context):
        scn = context.scene
        for i in scn.custom:
            print (i.name, i.id)
        return{'FINISHED'}

# select button
class Uilist_selectAllItems(bpy.types.Operator):
    bl_idname = "custom.select_item"
    bl_label = "Select List Item"
    bl_description = "Select Item in scene"

    def execute(self, context):
        scn = context.scene
        bpy.ops.object.select_all(action='DESELECT')
        obj = bpy.data.objects[scn.custom[scn.custom_index].name]
        obj.select = True

        return{'FINISHED'}

# clear button
class Uilist_clearAllItems(bpy.types.Operator):
    bl_idname = "custom.clear_list"
    bl_label = "Clear List"
    bl_description = "Clear all items in the list"

    def execute(self, context):
        scn = context.scene
        lst = scn.custom
        current_index = scn.custom_index

        if len(lst) > 0:
             # reverse range to remove last item first
            for i in range(len(lst)-1,-1,-1):
                scn.custom.remove(i)
            self.report({'INFO'}, "All items removed")

        else:
            self.report({'INFO'}, "Nothing to remove")   

        return{'FINISHED'}

# Create custom property group
class CustomProp(bpy.types.PropertyGroup):
    #'''name = StringProperty() '''
    id = IntProperty()

# -------------------------------------------------------------------
# register
# -------------------------------------------------------------------

def register():
    bpy.utils.register_module(__name__)
    bpy.types.Scene.custom = CollectionProperty(type=CustomProp)
    bpy.types.Scene.custom_index = IntProperty()

def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.Scene.custom
    del bpy.types.Scene.custom_index

if __name__ == "__main__":
    register()

Code: Alles auswählen
import bpy

# ----------------------------------
event_type_items = [
        ("on_activate", "OnActivate", "", 0),
        ("on_deactivate", "OnDeactivate", "", 1),
        ("on_actor_collision_start", "OnActorCollisionStart", "", 2),
        ("on_actor_collision_end", "OnActorCollisionEnd", "", 3),
        ("on_collision_start", "OnCollisionStart", "", 4),
        ("on_collision_end", "OnCollisionEnd", "", 5),
        ]

class EventSettings(bpy.types.PropertyGroup):
    event_type = bpy.props.EnumProperty(items=event_type_items, default="on_activate" , options={'HIDDEN', 'ANIMATABLE'});
    event_body = bpy.props.StringProperty()

class EventSettingsAddOp(bpy.types.Operator):
    bl_label = "Add event"
    bl_idname = "collection.event_add"
   
    def invoke(self, context, event):
        obj = context.object
        collection = obj.event_settings
        collection.add()
        return {'FINISHED'}

class EventSettingsRemoveOp(bpy.types.Operator):
    bl_label = "Remove event"
    bl_idname = "collection.event_remove"
   
    def invoke(self, context, event):
        obj = context.object
        collection = obj.event_settings
        index = obj.event_settings_index
        collection.remove(index)
        return {'FINISHED'}

class EventSettingsItem(bpy.types.UIList):
        def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
                layout.prop(item, "event_type", "Type");
                layout.prop(item, "event_body", "Body");

# ----------------------------

class OwlObjectProperties(bpy.types.Panel):     
    bl_label = "Owl Engine Properties"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"
 
    def draw(self, context):
        obj = bpy.context.active_object;
        self.layout.prop(obj, "auto_activate", "Auto Activate");
        self.layout.label(text="Animation", icon='ANIM')
        anim_layout = self.layout.box();
        anim_layout.prop(obj, "anim_fps", "FPS");
        anim_layout.prop(obj, "anim_loop", "Loop");
       
        self.layout.label(text="Events", icon='PHYSICS')
        activation_layout = self.layout.box();
        row = activation_layout.row()
        row.template_list(listtype_name="EventSettingsItem", dataptr=obj, propname="event_settings", active_dataptr=obj, active_propname="event_settings_index")
        col = row.column(align=True)
        col.operator("collection.event_add", icon="ZOOMIN", text="")
        col.operator("collection.event_remove", icon="ZOOMOUT", text="")
       

def register():
    bpy.utils.register_class(EventSettings)
    bpy.utils.register_class(EventSettingsAddOp)
    bpy.utils.register_class(EventSettingsRemoveOp)
    bpy.utils.register_class(EventSettingsItem)
    bpy.utils.register_class(OwlObjectProperties)
   
    # anim
    bpy.types.Object.anim_loop = bpy.props.BoolProperty(default=False, options={'HIDDEN', 'ANIMATABLE'});
    bpy.types.Object.anim_fps = bpy.props.IntProperty(default=10, options={'HIDDEN', 'ANIMATABLE'});
   
    # events
    bpy.types.Object.event_settings_index = bpy.props.IntProperty(min= 0,default= 0)
    bpy.types.Object.event_settings = bpy.props.CollectionProperty(type=EventSettings)
   
    # other
    bpy.types.Object.auto_activate = bpy.props.BoolProperty(default=False, options={'HIDDEN', 'ANIMATABLE'});

 
def unregister():
    bpy.utils.unregister_class(EventSettings)
    bpy.utils.unregister_class(EventSettingsAddOp)
    bpy.utils.unregister_class(EventSettingsRemoveOp)
    bpy.utils.unregister_class(EventSettingsItem)
    bpy.utils.unregister_class(OwlObjectProperties) 
     
if __name__ == "__main__":
    register()
HG1
 
Registriert:
16.08.2010, 11:43

Re: Ordnerinhalt in template_list anzeigen

Beitragvon Tiles » 18.10.2016, 21:08

Vielen Dank für die Beispiele HG1. Die werde ich morgen sezieren :)
Free Game Graphics, Freeware Games http://www.reinerstilesets.de
Benutzeravatar
Tiles
 
Registriert:
20.11.2007, 12:19

Re: Ordnerinhalt in template_list anzeigen

Beitragvon Tiles » 19.10.2016, 18:07

Borr, ich geb auf XD

Mal eine andere Methode probieren. Muss ja kein template_list sein ^^
Free Game Graphics, Freeware Games http://www.reinerstilesets.de
Benutzeravatar
Tiles
 
Registriert:
20.11.2007, 12:19

Re: Ordnerinhalt in template_list anzeigen

Beitragvon alias_ludi » 19.10.2016, 21:22

Hier mal mein Versuch:

Code: Alles auswählen
import bpy
import os

 # -----------------------------------------------------------------------------------------------------
 # the panel is in the properties sidebar.
 # -----------------------------------------------------------------------------------------------------
 
mylist = []
my_listing = []

bpy.types.Scene.path = bpy.props.StringProperty(name="dir_path", description="", default="C:/Users")
bpy.context.scene.path = "C:/Users"

def read_dir(path = "C:/Users"):
        print("path :", path)
        mylist = [] # empty the list
        my_listing = []

        start_path = 'C:/Users/Ludwig/Documents' # current directory. Change to your needs. Do NOT use backslashes here.
        start_path = path
        print("startpath :", start_path)
        for path,dirs,files in os.walk(start_path):
            for filename in files:
                if filename.endswith(".blend"):
                    mylist.append(os.path.join(filename))
        #print (mylist) # debugging. The content in the console.
       
        for n, entry in enumerate(mylist):
            my_listing.append((str(n), entry, entry))
        print(my_listing)
        return my_listing

class VIEW3D_read_dir(bpy.types.Operator):
    """Blubb"""
    bl_idname = "view3d.read_dir"
    bl_label = "Read Dir"
   
    def execute(self, context):
       
        mylist = [] # empty the list
        start_path = bpy.context.scene.path # current directory. Change to your needs. Do NOT use backslashes here.   
        read_dir(start_path)
        return {'FINISHED'}

old_path = ""
old_dir = ""

def item_cb(self, context):
    global old_path, old_dir
    if bpy.context.scene.path == old_path:
        print("yes")
        return old_dir
    print("no")
    old_path = bpy.context.scene.path
    old_dir = read_dir(bpy.context.scene.path)
    return old_dir

bpy.types.Scene.enumprop = bpy.props.EnumProperty(items = item_cb)

class MyPanel(bpy.types.Panel):
    bl_label = "MyPanel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'

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

        layout.operator("view3d.read_dir", text="read directory") # Click me to read the directory. Content of blend files will be printed in the console.
       
        scene = context.scene
        row = layout.row()
        layout.prop(scene, 'enumprop', text='listing')
        row.prop(context.scene, "path", text="Dir_Path")
       
# ------------------------------ register unregister --------------------------------------------------------

def register():
    bpy.utils.register_module(__name__)
def unregister():
    bpy.utils.unregister_module(__name__)       
if __name__ == "__main__":
    register()


Hat ein bischen gedauert.
Der Grund war peinlicherweise, dass mir die Funktion von os.walk nicht so klar war, bzw. ich es einfach überlesen hatte. Ich dachte es liest nur ein directory ein (und nicht alle, wie der Name ja auch andeutet). Wenn ich dann das directory (nach oben :roll: ) geändert habe, hat sich nichts an den angezeigten Dateien geändert und ich habe mich nach dem Fehler blöd gesucht.
In item_cb hat es diese "old_path", "old_dir" Anteile, die noch aus einer früheren Version stammten, wo die Anzeige eingefroren ist und ich dachte es liegt am Versuch 30mal pro Sekunde das Verzeichnis einzulesen.
Kann man wohl entfernen, ebenso den read_dir Knopf und auch sonst kann man sicher noch aufräumen.
Zuletzt geändert von alias_ludi am 19.10.2016, 23:36, insgesamt 1-mal geändert.
alias_ludi
 
Registriert:
02.03.2011, 17:15

Re: Ordnerinhalt in template_list anzeigen

Beitragvon Tiles » 19.10.2016, 21:28

Hui, vielen Dank. Dann muss ich das doch noch mal zerpflücken gehen :)

Aber cool, du hast das auch ohne template_list gemacht ^^

Ich werde da sicher Teile davon verwenden. Im Moment habe ich mich entschieden das über ein Textfile zu regeln, also nicht direkt jedesmal die Dir auszulesen. Bei der Menügeschichte bin ich da allerdings noch nicht angekommen. Das werde ich mir wohl dann von dir hier mausen :)
Free Game Graphics, Freeware Games http://www.reinerstilesets.de
Benutzeravatar
Tiles
 
Registriert:
20.11.2007, 12:19

Re: Ordnerinhalt in template_list anzeigen

Beitragvon Tiles » 20.10.2016, 13:21

Hm, mit deiner Lösung brauche ich eigentlich das ganze Textgedöns gar nicht mehr fällt mir grade auf. Bin ja eigentlich schon da wo ich hin will. Plus minus ein paar kleinen Umbauten. Eigentlich fehlt nur noch der Append Code, den ich auch schon in der Schublade habe. Und fertig ist das Mini Library Addon. Und genau das wollte ich bauen. Deswegen doppelt Dank für deine Lösung :)

Sou, hab da mal ein wenig hinterhergewedelt. Die start_path Variable und zugehöriger Code ist komplett entsorgt. Und der Read Directory Button auch erst mal. Es liest ja nun automatisch aus. mylist = [] fürs leeren wurde zu mylist.clear(). Die Listen müssen ja nicht jedesmal neu erstellt werden. Ich habe den Items in der Liste die File Extension weggenommen. Es wird also nur noch der eigentliche Filename angezeigt. Macht die Dropdown Box übersichtlicher. Im Tooltip werden sie dann aber mit .blend angezeigt. Und ich habe einige Kommentare dazugemacht. Und die Debugging Prints ausgeknipst. Noch sind sie aber drin.

Mit was ich noch nicht so ganz klarkomme ist die Funktion item_cb. Das Ding is um zu checken ob die Listen gefüllt werden sollen, gell? Ich hoffe mal die Kommentare da stimmen. Und eigentlich wollte ich die zweite Liste auch rausoperieren. Müsste doch theoretisch auch mit einer Liste tun. Aber dafür war ich zu doof ^^

Fazit, eigentliches Problem zwar nicht behoben, ich wollte das ja eigentlich in einer template_List, aber trotzdem Problem gelöst :D

Wenn noch jemand was zum optimieren findet, immer her damit :)

Code: Alles auswählen
import bpy
import os

 # -----------------------------------------------------------------------------------------------------
 # the panel is in the properties sidebar.
 # -----------------------------------------------------------------------------------------------------
 
mylist = [] # the list to retreive the files in the target folder
my_listing = [] # the list to create the dropdown box.

bpy.types.Scene.path = bpy.props.StringProperty(name="dir_path", description="", default="")
bpy.context.scene.path = "C:/Users/x/Documents/muh" # the directory to check

def read_dir(path):
        mylist.clear() # clear the list. We don't want double, triple, etc. entries.
        my_listing.clear() # clear the list. We don't want double, triple, etc. entries.
        for path,dirs,files in os.walk(path):
            for filename in files:
                if filename.endswith(".blend"):
                    filename = os.path.splitext(filename)[0] # just filename, no extention name
                    mylist.append(os.path.join(filename)) # add the files to the mylist list.
       
        # fill the list my_listing
        for n, entry in enumerate(mylist):
            my_listing.append((str(n), entry, entry+".blend"))
        # print(my_listing) # debugging
        return my_listing

class VIEW3D_read_dir(bpy.types.Operator):
    """Blubb"""
    bl_idname = "view3d.read_dir"
    bl_label = "Read Dir"

    def execute(self, context):
        read_dir(path)
        return {'FINISHED'}
   
# Enumerate the dropdown list in the dropdown prop

old_path = ""
old_dir = ""

def item_cb(self, context):
    global old_path, old_dir
    # Check if path is the same
    if bpy.context.scene.path == old_path:
        #print("yes") # debugging.
        return old_dir
    #Path has changed or is not set. So read the dir again.
    #print("no") # debugging
    old_path = bpy.context.scene.path
    old_dir = read_dir(bpy.context.scene.path)
    return old_dir

#The dropdown prop enumeration
bpy.types.Scene.enumprop = bpy.props.EnumProperty(items = item_cb)

class MyPanel(bpy.types.Panel):
    bl_label = "Minilib"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'

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

        scene = context.scene
 
        layout.prop(scene, 'enumprop', text='Files')
        layout.prop(context.scene, "path", text="Dir_Path") # Of interest when you want to change the path.


# ------------------------------ register unregister --------------------------------------------------------

def register():
    bpy.utils.register_module(__name__)
def unregister():
    bpy.utils.unregister_module(__name__)       
if __name__ == "__main__":
    register()
Free Game Graphics, Freeware Games http://www.reinerstilesets.de
Benutzeravatar
Tiles
 
Registriert:
20.11.2007, 12:19

Re: Ordnerinhalt in template_list anzeigen

Beitragvon Tiles » 21.10.2016, 10:50

Ein klitzekleines Problem habe ich doch noch. Wie komme ich denn an die derzeitige Auswahl in der Dropdown box? Also an die erste Zahl, den Index? Ich muss ja irgendwie auswählen was ich laden will.
Free Game Graphics, Freeware Games http://www.reinerstilesets.de
Benutzeravatar
Tiles
 
Registriert:
20.11.2007, 12:19

Re: Ordnerinhalt in template_list anzeigen

Beitragvon HG1 » 21.10.2016, 15:17

Code: Alles auswählen
if scene.enumprop == "0": # Achtung: scene nicht Scene und "0" nicht 0
   .
   .
HG1
 
Registriert:
16.08.2010, 11:43

Re: Ordnerinhalt in template_list anzeigen

Beitragvon Tiles » 21.10.2016, 18:03

Ah, Danke. Gleich mal testen. Mit einer if komme ich hier aber nicht hin, der Ordner kann ja Hunderte Blendfiles beinhalten. Aber mit scene.enumprop müsste ich ja auch eine Variable setzen können :)

EDIT sagt, so einfach gehts denn wohl doch nicht. Ich ende immer wieder in einem Attribute Error. Einmal sagt er mir scene gibts net, einmal enumprob gibts net -.-
Free Game Graphics, Freeware Games http://www.reinerstilesets.de
Benutzeravatar
Tiles
 
Registriert:
20.11.2007, 12:19

Re: Ordnerinhalt in template_list anzeigen

Beitragvon HG1 » 21.10.2016, 19:04

Kein Ahnung was du machst aber bei mir funktioniert es. Ich habe es auch zur Sicherheit auch mit deinem Code getestet.

Ich weiß ja nicht was du mit deinem Code vor hast und wo du den Aufruf platzierst.
Ich habe die If Anweisung unter layout.prop(context.scene, "path", text="Dir_Path") platziert.
Wenn du die Abfrage wo anders machst dann musst du dir noch die scene mit scene = context.scene holen. Und der Aufruf muss natürlich nach dem du das Property "enumprop" mit bpy.types.Scene.enumprop = bpy.props.EnumProperty(items = item_cb) angelegt hast erfolgen.

Du msst auch kein If verwenden. Wenn du alle durchlaufen möchtest dann kannst du ja eine "for x in y" verwenden.

Wenn du nur den ausgewählten Dateinamen haben möchtest dann musst du nur den Index in einen Integer wandeln und dann den Dateinamen aus der Liste mit Hilfe des Index heraussuchen.
print(mylist[int(scene.enumprop)])
print(my_listing[int(scene.enumprop)][2])

Ich habe es getestet es funktioniert.
HG1
 
Registriert:
16.08.2010, 11:43

Re: Ordnerinhalt in template_list anzeigen

Beitragvon Tiles » 21.10.2016, 20:24

Ja, mir fehlen da wohl noch ein paar Basics, sorry :)

Das war bei mir einfach mal so getestet:

Code: Alles auswählen
meinevalue = 0

if scene.enumprop == "1":
    meinevalue = scene.enumprop


Das Ganze steht im Panelcode, unter den UI Elementen. Und da bekomme ich eben Mecker dass enumprop nicht existiert. Was ich nicht vestehe, denn im if selbst gibts kein Mecker. Den Mecker gibts erst wenn ich versuche meinevalue drauf einzustellen.

Ich weiß ja nicht was du mit deinem Code vor hast und wo du den Aufruf platzierst.


Eine Minilibrary. Knöpfchen drücken, und das ausgewählte Item in der Liste, ein blend file, appenden. Der Append Code geht. Ich muss nur irgendwie die Value setzen welches File von der Liste denn nun geladen werden soll.
Free Game Graphics, Freeware Games http://www.reinerstilesets.de
Benutzeravatar
Tiles
 
Registriert:
20.11.2007, 12:19

Re: Ordnerinhalt in template_list anzeigen

Beitragvon Tiles » 21.10.2016, 21:06

Ich habe das jetzt anders gelöst. So ne Prop hat doch auch ein update. Darüber komme ich endlich ran. Dazu musste ich allerdings die Prop ins register packen.

Jetzt wird meine index variable brav gesetzt. Und an die index Variable kann ich jetzt nun meinen Appendcode anhängen, und das richtige File laden :)

Mich würde trotzdem interesieren was ich da mit deiner Methode falsch mache. Hm.

Code: Alles auswählen
import bpy
import os

 # -----------------------------------------------------------------------------------------------------
 # the panel is in the properties sidebar.
 # -----------------------------------------------------------------------------------------------------
 
mylist = [] # the list to retreive the files in the target folder
my_listing = [] # the list to create the dropdown box.
index = 0

bpy.types.Scene.path = bpy.props.StringProperty(name="dir_path", description="", default="")
bpy.context.scene.path = "C:/Users/x/Documents/muh" # the directory to check

def read_dir(path):
        mylist.clear() # clear the list. We don't want double, triple, etc. entries.
        my_listing.clear() # clear the list. We don't want double, triple, etc. entries.
        for path,dirs,files in os.walk(path):
            for filename in files:
                if filename.endswith(".blend"):
                    filename = os.path.splitext(filename)[0] # just filename, no extention name
                    mylist.append(os.path.join(filename)) # add the files to the mylist list.
       
        # fill the list my_listing
        for n, entry in enumerate(mylist):
            my_listing.append((str(n), entry, entry+".blend"))
        print(my_listing)
        return my_listing

class VIEW3D_read_dir(bpy.types.Operator):
    """Blubb"""
    bl_idname = "view3d.read_dir"
    bl_label = "Read Dir"

    def execute(self, context):
        read_dir(path)
        return {'FINISHED'}
   
# Enumerate the dropdown list in the dropdown prop

old_path = ""
old_dir = ""

def item_cb(self, context):
    global old_path, old_dir
    # Check if path is the same
    if bpy.context.scene.path == old_path:
        #print("yes") # debugging.
        return old_dir
    #Path has changed or is not set. So read the dir again.
    print("no")
    old_path = bpy.context.scene.path
    old_dir = read_dir(bpy.context.scene.path)
    return old_dir

def myindex(self, context):
    print('called and changed to,', context.scene.MyEnum)
    index = context.scene.MyEnum
    print(index)


class MyPanel(bpy.types.Panel):
    bl_label = "Minilib"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'

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

        scene = context.scene
 
        layout.prop(scene, "MyEnum", text = "Item")
        layout.prop(context.scene, "path", text="Dir_Path") # Of interest when you want to change the path.

# ------------------------------ register unregister --------------------------------------------------------

def register():
   
    bpy.types.Scene.MyEnum = bpy.props.EnumProperty(items = item_cb, update = myindex)   
   
    bpy.utils.register_module(__name__)
def unregister():
    bpy.utils.unregister_module(__name__)       
if __name__ == "__main__":
    register()
Free Game Graphics, Freeware Games http://www.reinerstilesets.de
Benutzeravatar
Tiles
 
Registriert:
20.11.2007, 12:19

Re: Ordnerinhalt in template_list anzeigen

Beitragvon HG1 » 22.10.2016, 09:51

Ja ich lege die RNA Properties auch im register() an (damit sie vom Anfang an schon vorhanden sind). Auch die update Funktion verende ich meistens.

Kleiner Hinweis.
Mit del kannst du das Property wieder löschen, wenn du es nicht mehr benötigst. Z.B. im unregister() wenn das Addon wieder entladen wird. Ansonsten bleibt das Property erhalten. Es wird auch in der Datei gespeichert.
del bpy.types.Scene.MyEnum

Ich habe das gerammte Script hinzugefügt. Die Dateiname wird einmal in der Draw und einmal in der Update Funktion (wird bei einer Änderung ausgelöst) ausgegeben.
Draw wird bei Mouse over auf einem beliebigen Property Element im entsprechenden Fenster und bei einer Änderung ausgelöst.
Die Update Funktion wird nur bei einer Änderung ausgelöst.
Code: Alles auswählen
import bpy
import os

 # -----------------------------------------------------------------------------------------------------
 # the panel is in the properties sidebar.
 # -----------------------------------------------------------------------------------------------------
 
mylist = [] # the list to retreive the files in the target folder
my_listing = [] # the list to create the dropdown box.

bpy.types.Scene.path = bpy.props.StringProperty(name="dir_path", description="", default="")
bpy.context.scene.path = "C:/Users/x/Documents/muh" # the directory to check

def read_dir(path):
      mylist.clear() # clear the list. We don't want double, triple, etc. entries.
      my_listing.clear() # clear the list. We don't want double, triple, etc. entries.
      for path,dirs,files in os.walk(path):
         for filename in files:
            if filename.endswith(".blend"):
               filename = os.path.splitext(filename)[0] # just filename, no extention name
               mylist.append(os.path.join(filename)) # add the files to the mylist list.
      
      # fill the list my_listing
      for n, entry in enumerate(mylist):
         my_listing.append((str(n), entry, entry+".blend"))
      print(my_listing)
      return my_listing

class VIEW3D_read_dir(bpy.types.Operator):
   """Blubb"""
   bl_idname = "view3d.read_dir"
   bl_label = "Read Dir"

   def execute(self, context):
      read_dir(path)
      return {'FINISHED'}
   
# Enumerate the dropdown list in the dropdown prop

old_path = ""
old_dir = ""

def item_cb(self, context):
   global old_path, old_dir
   # Check if path is the same
   if bpy.context.scene.path == old_path:
      #print("yes") # debugging.
      return old_dir
   #Path has changed or is not set. So read the dir again.
   print("no")
   old_path = bpy.context.scene.path
   old_dir = read_dir(bpy.context.scene.path)
   return old_dir

def myindex(self, context):
   scene = context.scene
   print('called and changed to,', scene.MyEnum)
   index = scene.MyEnum
   print(index)

   print("update" + mylist[int(scene.MyEnum)])
   print("update" + my_listing[int(scene.MyEnum)][2])


class MyPanel(bpy.types.Panel):
   bl_label = "Minilib"
   bl_space_type = 'VIEW_3D'
   bl_region_type = 'UI'

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

      scene = context.scene
 
      layout.prop(scene, "MyEnum", text = "Item")
      layout.prop(context.scene, "path", text="Dir_Path") # Of interest when you want to change the path.

      print("draw" + mylist[int(scene.MyEnum)])
      print("draw" + my_listing[int(scene.MyEnum)][2])

# ------------------------------ register unregister --------------------------------------------------------

def register():
   bpy.types.Scene.MyEnum = bpy.props.EnumProperty(items = item_cb, update = myindex)   
   
   bpy.utils.register_module(__name__)
def unregister():
   del bpy.types.Scene.MyEnum
   
   bpy.utils.unregister_module(__name__)      
if __name__ == "__main__":
   register()



Mich würde trotzdem interesieren was ich da mit deiner Methode falsch mache. Hm.

Wahrscheinlich hast du deinen Aufruf vor der Initialisierung des RNA Properties gemacht.
Das habe ich aber im vorigem Post geschrieben, dass du darauf achten musst.
Oder du hastest schon den Property Namen geändert und nur Copy und Paste von meinem Code gemacht.
HG1
 
Registriert:
16.08.2010, 11:43

Re: Ordnerinhalt in template_list anzeigen

Beitragvon Tiles » 22.10.2016, 11:25

Hui, vielen Dank. Das muss ich gleich mal noch mal studieren \o/

EDIT sagt, Prinzip erkannt, und Fehler entdeckt. Vielen Dank dafür :)

Ich habe zwischenzeitlich mal das Addon weitergebaut. Das ist nun im Tool Shelf unter Create , Minilib Panel. Und eigentlich fast fertig. Es tut was es soll. Es läuft auch brav als Script. Kurioserweise lässt es sich aber noch nicht als Addon installieren :/

Auch da Edit: da scheine ich mal wieder in eine für mich unsinnige Limitierung zu rennen dass Addons keine globalen Variablen verwenden kann. Ich frage mich jetzt noch welchen Sinn das haben soll. Denn beim Scripten kann man ja. Und stehe natürlich mal wieder vor dem Problem das jetzt fixen zu müssen. Hach ...

String Property ist nun ein Directory Loader. Die Index Variable ist komplett entsorgt, das greift den Index jetzt direkt vom Prop ab. Irgendwas hatte ich da eh verbockt. Beim Laden war die Index Variable immer wieder auf Null, obwohl sie in der def myindex ja gesetzt wurde -.- . def myindex und update habe ich auch komplett entsorgt. Und auch ansonsten habe ich noch mal kräftig hin und hergeräumt und nachkommentiert.

Achtung, das Addon appendet alles im blend file ...

So siehts im Moment aus:
Code: Alles auswählen
# The script is under Apache license

# Big thanks to the helpful souls at Blendpolis

import bpy
import os

from bpy.props import StringProperty

bl_info = {
    "name": "Minilib",
    "description": "A mini library addon",
    "author": "Reiner 'Tiles' Prokein",
    "version": (0.1),
    "blender": (2, 76, 0),
    "location": "Tool Shelf > Create > Minilib",
    "warning": "",
    "wiki_url": "none",
    "category": "Create"}

 # -----------------------------------------------------------------------------------------------------
 # the Minilib panel is in the Tool Shelf in the Create tab
 # -----------------------------------------------------------------------------------------------------
 
mylist = [] # the list to retreive the files in the target folder
my_listing = [] # the list to create the dropdown box.

bpy.types.Scene.path = bpy.props.StringProperty(name="dir_path", description="", default="", maxlen=1024, subtype='DIR_PATH') # Directory loader
bpy.context.scene.path ="C:/myassets" # the directory to check

############################# Read Asset

class VIEW3D_read_asset(bpy.types.Operator):
    """Blubb"""
    bl_idname = "view3d.read_asset"
    bl_label = "View Selected All Regions"
    bl_options = {'REGISTER', 'UNDO'}
   
    def execute(self, context):

        scn = bpy.context.scene # current scene   
        filepath = scn.path + "/" + str(mylist[int(context.scene.MyEnum)] + ".blend") # path to the blend       
        link = False # append, set to true to keep the link to the original file. There is no append item.     
       
        #append all objects from .blend file
        with bpy.data.libraries.load(filepath) as (data_from, data_to):
            data_to.objects = data_from.objects
                       
         # When you want to load just specific object types
#        obj_name = "Cube" # name of object(s) in the lib file to append or link   
#        with bpy.data.libraries.load(filepath, link=link) as (data_from, data_to):
#            data_to.objects = [name for name in data_from.objects if name.startswith(obj_name)]

        #link object to current scene
        for obj in data_to.objects:
            if obj is not None:
               scn.objects.link(obj)
               obj.select = False # We don't want to have the asset selected after loading
        return {'FINISHED'}

############################# read directory

def read_dir(path):
        mylist.clear() # clear the list. We don't want double, triple, etc. entries.
        my_listing.clear() # clear the list. We don't want double, triple, etc. entries.
        for path,dirs,files in os.walk(path):
            for filename in files:
                if filename.endswith(".blend"):
                    filename = os.path.splitext(filename)[0] # just filename, no extention name
                    mylist.append(os.path.join(filename)) # add the files to the mylist list.
       
        # fill the list my_listing
        for n, entry in enumerate(mylist):
            my_listing.append((str(n), entry, entry+".blend"))
        return my_listing

class VIEW3D_read_dir(bpy.types.Operator):
    """Blubb"""
    bl_idname = "view3d.read_dir"
    bl_label = "Read Dir"

    def execute(self, context):
        read_dir(path)
        return {'FINISHED'}
   
#################### Enumerate the dropdown list in the dropdown prop

old_path = ""
old_dir = ""

def item_cb(self, context):
    global old_path, old_dir
    # Check if path is the same
    if bpy.context.scene.path == old_path:
        return old_dir
    #Path has changed or is not set. So read the dir again.
    old_path = bpy.context.scene.path
    old_dir = read_dir(bpy.context.scene.path)
    return old_dir
   
########################### the panel #############################

class MyPanel(bpy.types.Panel):
    bl_label = "Minilib"
    bl_space_type = 'VIEW_3D'
    bl_region_type = "TOOLS"
    bl_category = "Create"

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

        scene = context.scene
 
        layout.prop(scene, "MyEnum", text = "Item") # Dropdown box
        layout.operator("view3d.read_asset", text="append asset") # Load asset
        layout.prop(context.scene, "path", text="") # Here you can change the path.

# ------------------------------ register unregister --------------------------------------------------------

def register():   
    bpy.types.Scene.MyEnum = bpy.props.EnumProperty(items = item_cb)   
   
    bpy.utils.register_module(__name__)
   
def unregister():   
    del bpy.types.Scene.MyEnum
   
    bpy.utils.unregister_module(__name__)   
       
if __name__ == "__main__":
    register()
Dateianhänge
attributeerror.jpg
Zuletzt geändert von Tiles am 22.10.2016, 12:17, insgesamt 1-mal geändert.
Free Game Graphics, Freeware Games http://www.reinerstilesets.de
Benutzeravatar
Tiles
 
Registriert:
20.11.2007, 12:19

Nächste

Zurück zu Blender Python


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast