Blender Python - Ordnerinhalt in template_list anzeigen

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Tiles

Blender Python - Ordnerinhalt in template_list anzeigen

Beitrag von Tiles »

Huhu :)

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()
    
    
Uha, es zertrümmert mir wieder die Einrückungen. Da war doch noch was? Wie ging das denn ? Ich hänge mal so lang ein zipfile mit dem script an.
Dateianhänge
template_list_problem.zip
(900 Bytes) 326-mal heruntergeladen
listinlist.jpg
Benutzeravatar
xq
Establishment
Beiträge: 1590
Registriert: 07.10.2012, 14:56
Alter Benutzername: MasterQ32
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

Re: Blender Python - Ordnerinhalt in template_list anzeigen

Beitrag von xq »

Ich versuch mal, die template_list zu entziffern:

listtype_name: Der Typ der Liste, sollte wohl "UI_UL_list" sein.

list_id: Der Name der Liste

dataptr: Ein Pointer auf ein Objekt, welches deine Liste enthält.
propname: Der Name der Property des dataptr-Objekts, welches die Liste in Form einer Collection enthält.

active_dataptr, active_propname: Selbes Konzept wie bei dataptr, propname, nur diesmal nicht auf eine Collection, sondern auf einen Integer.

item_dyntip_propname Eine String-Eigenschaft des Items, welches den Tooltip enthält.

rows: Minimale Zeilenanzahl des Listcontrols

maxrows: Maximale Zeilenzahl

type: Typ der Auflisting, siehe Doku
columns: Anzahl der Spalten, wenn type=GRID.

Wie genau jetzt aber die dataptr, active_dataptr aussehen müssen, weis ich auch noch nicht...





Für deine Listeneinträge musst du wohl eine eigene Klasse machen:

Code: Alles auswählen

# Assign a collection
class ListItem(bpy.types.PropertyGroup):
    name = bpy.props.StringProperty(name="name", default="Unknown")
    tooltip = bpy.props.StringProperty(name="tooltip", default="Hover me!")
    value = bpy.props.IntProperty(name="value", default=22)
bpy.utils.register_class(ListItem)
Um jetzt die template_list zu verwenden, brauchst du noch eine Sammelklasse:

Code: Alles auswählen

class ListOfItems(bpy.types.PropertyGroup)
    selection = bpy.props.IntProperty(name="selection", default=0)
    list = bpy.props.CollectionProperty(name="list", type=SceneSettingItem)
Die Templatelist kannst du jetzt hiermit erstellen:

Code: Alles auswählen

loi = ListOfItems()
item0 = loi.list.add()
item0.name = "Item 1"
item0.tooltip = "Ich bin Item 1"
item1 = loi.list.add()
item1.name = "Item 2"
item1.tooltip = "Ich bin Item 2"

row.template_list("UI_UL_LIST", list_id="keying_sets", dataptr=loi, propname="list", active_dataptr="loi", active_propname="selection", item_dyntip_propname="tooltop", rows=5, maxrows=5, type='DEFAULT', columns=9)
Ich bin noch nicht komplett sicher, ich programmiere erst seit 2 Tagen Python, aber ich bin mir relativ sicher, dass das ganze so läuft. Nur das mit dem AnyPtr ist mir noch nicht ganz klar, ob das so korrekt ist.

Grüße
Felix
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…

Programmiert viel in ⚡️Zig⚡️ und nervt Leute damit.
Tiles

Re: Blender Python - Ordnerinhalt in template_list anzeigen

Beitrag von Tiles »

Ah, sorry dass ich das nicht sofort gesehen hatte.

Super. Danke für die Hinweise. Mal schauen ob mir das auf die Sprünge hilft :)

LG Tiles
Tiles

Re: Blender Python - Ordnerinhalt in template_list anzeigen

Beitrag von Tiles »

Hm.

list = bpy.props.CollectionProperty(name="list", type=SceneSettingItem)
müsste wohl das hier sein:
list = bpy.props.CollectionProperty(name="list", type=ListItem)

An dem Punkt musste ich aber leider aussteigen: loi = ListOfItems()

Error ... expected a single argument

WAT?
Benutzeravatar
xq
Establishment
Beiträge: 1590
Registriert: 07.10.2012, 14:56
Alter Benutzername: MasterQ32
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

Re: Blender Python - Ordnerinhalt in template_list anzeigen

Beitrag von xq »

Stimmt, das obere ist ein Typo.

Zu der Konstruktion von Objekten in Python muss dir jemand anders helfen, da bin ich leider selber unbegabt. Eigentlicht ist das ein Konstruktor-Aufruf der Klasse ListOfItems.
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…

Programmiert viel in ⚡️Zig⚡️ und nervt Leute damit.
Tiles

Re: Blender Python - Ordnerinhalt in template_list anzeigen

Beitrag von Tiles »

Ja, tierisch verzwickt das Ganze. Ich steige da einfach nicht dahinter wie das verbunden sein muss. Ich habe auch schon direkt in zwei Asset Addons geschaut. Aber da ist dann so viel anderer Code im Weg dass das Ganze noch unverständlicher wird.

Jedenfalls Danke für deinen Einsatz bisher :)
Tiles

Re: Blender Python - Ordnerinhalt in template_list anzeigen

Beitrag von Tiles »

Borr, ich geb auf XD

Mal eine andere Methode probieren. Muss ja kein template_list sein ^^
PiIstGenauDrei
Beiträge: 87
Registriert: 23.09.2010, 17:18

Re: Blender Python - Ordnerinhalt in template_list anzeigen

Beitrag von PiIstGenauDrei »

Hi Tiles, du musst noch nicht aufgeben! ;) Ich fand das ganze recht interessant und habe trotz mangelnder Kenntnisse in der Blender-Infrastruktur mich daran gewagt. Mein Vorschlag siehe hier: http://pastebin.com/napPykF5

Meine Erklärungen und Anmerkungen:

* Zuerst habe ich mich darum gekümmert, dass die Liste von Einträgen überhaupt in Blender gespeichert wird. Dazu sieht die Blender-Python-Integration die Properties vor, die an verschiedenen Stellen injiziert werden können (z.B. Scene, Screen o.ä.) - je nachdem was für die Aufgabe gerade sinnvoll erscheint. In deinem Fall habe ich das Property an die Scene gehangen und "view3d_files" benannt (klassisches Monkey-Patchen also. Python! Yay! :D). Falls hier eine Kollision mit existierenden Properties stattfinden sollte, muss ein anderer Name verwendet werden. Es ist übrigens vom Type PointerProperty, womit wir auch geklärt hätten, was bei dataptr vom Type AnyPtr in der Methode template_list übergeben werden muss.
* Die Klasse VIEW3D_read_dir leert/füllt die Liste und hinterlegt sie im o.g. Property. In der Klasse FilesPanel wiederum liest dieses Property.
* Ansonsten wird noch etwas gehaushaltet, damit das Property bei Deaktivierung des Scripts alles sauber entfernt wird. Die Bezeichnungen habe ich allesamt auch nach eigenem Gutdünken angepasst.
* Es wurde ansonsten ja noch gegrübelt, wie diese ominöse Liste initialisiert wird. Ich vermute, dass dies die Python-Integration selber erledigt. Jedenfalls konnte ich nichts derartiges in Tutorials zu Addons für Blender finden. Es wäre zumindest nicht ungewöhnlich in Pythonwelt, wenn sowas automagisch geschieht.

PS.: Das Forum musste mich leider zwischendrin ausloggen. :x Musste also alles neu tippen. Mir sei es also verziehen, wenn die Erklärungen etwas knapper ausfielen...
Tiles

Re: Blender Python - Ordnerinhalt in template_list anzeigen

Beitrag von Tiles »

Ah, super. Noch ein Beispiel zum studieren \o/

Vielen Dank. Und ein noch fetteres Danke für die Erklärungen :)

Ich versuche inzwischen das Ganze erst mal über ein einfaches Dropdown Menü zu lösen. Manche Sachen bekomme ich einfach nicht (so einfach) in meinen lädierten Schädel. Und das nächste Problem, bei einem Klick dann auch was zu laden, steht ja auch schon wieder vor der Tür. Wenn das mal über das Dropdown Menü funktioniert nehme ich mir aber noch mal das template_list zur Brust. Versprochen :)

EDIT sagt, in Zeile 15 fehlte ein Doppelpunkt nach class FilesProperties(bpy.types.PropertyGroup) . Easy Fix.

Aber selbige Klasse weigert sich hartnäckig sich registrieren zu lassen. registration error: ... items could not register. Ich sehe da aber keinen Fehler. Eigentlich müsste das funzen. Was übersehen wir denn hier? O_O

Code: Alles auswählen

------------------------------
TypeError: CollectionProperty(...): expected an RNA type derived from PropertyGr
oup
Traceback (most recent call last):
  File "\blender_files_panel_f├╝r_tiles.py", line 86, in <module>
  File "\blender_files_panel_f├╝r_tiles.py", line 68, in register
ValueError: bpy_struct "FilesProperties" registration error: items could not reg
ister

Error: Python script fail, look in the console for now...
EDIT2 sagt, das muss mit der CollectionProperty aus items = bpy.props.CollectionProperty(name="items", type=FileItem) zusammenhängen. Das mag Blender Python wohl nicht. Hm. Eigentlich wollte ich ja an meiner Dropdown Box Lösung weiterstochern :D
Antworten