Sunday, February 27, 2011

Blender: il selettore di istanze cresce...

Continua il lavoro sullo script... per quello che serve a me in realtà è già finito.
Ora viene definito un operatore che è possibile utilizzare come shortcut (screen.select_instances()) e che io ho assegnato a "SHIFT+I"
C'è un controllo sulla selezione attiva e un report in console e sulla finestra principale di blender.

Cose da fare: selezionare in base al nome. Non voglio in ogni caso farlo diventare un tool pesante con finestre ed altro: è una piccola utility per uso interno i cui pregi devono essere rapidità e leggerezza.
Chiedo scusa per la scrittura un po' raffazzonata ma ho studiato python giovedì scorso e le API di blender venerdì, tra l'altro le API sono soggette a continui cambiamenti e tanti esempi sul sito non funzionano sempre.

Ecco qui il codice ampliato:


#!BPY
"""
Name: 'Select object instances'
Blender: 256
Group: 'Object'
Tooltip: 'Select object instances'
"""
#author: Pietro Grandi (pietro909.blogspot.com)
#
#Release 0.4
# - now the script is an operator that can be added as a shortcut
# under Preferences->Input->Screen
# - the script performs a control in order to check if there is something active
# - messages are printed in console (verbose output) and as report on the top
#
# TODO: select by name, i'd like to have a popup to choose the selection type.
#


import bpy
class SelectInstances(bpy.types.Operator):
bl_idname = "screen.select_instances"
bl_label = "Select Instances"
def execute(self, context):
top = '[si-0.4]' #intestazione per i messaggi in console
scena = bpy.context.scene #punta alla scena attiva

i = 0 #contatore ciclo for
k = 0 #contatore di oggetti selezionati

sel_obj = bpy.context.active_object #oggetto attivo
if sel_obj == None: #se non ci sono oggetti attivi
print(top+'Error: no object selected') #segnala errore in console
self.report({'ERROR'}, 'no object selected') #segnala nel report
return{'CANCELLED'} #ed esci

#se invece la selezione e' valida continua#
sel_obj_type = sel_obj.data.name #tipo di oggetto selezionato
sel_obj_name = sel_obj.name #nome dell'oggetto selezionato


print(top+'Active object: '+sel_obj_name+' -> '+sel_obj_type)
print('Instances:')

for object in scena.objects: #per ogni oggetto in scena
current_obj = scena.objects[i] #prendi il nome dell'oggetto
if current_obj.data.name == sel_obj_type: #controlla se è del tipo selezionato
print('Selected '+current_obj.name) #stampalo
current_obj.select = True #selezionalo
k+=1
i+=1 #avanza il contatore
print('Total objects found and selected: '+str(k)) #stampa il risultato in console
report_string=str(k)+' instances of '+sel_obj_type+' found'
self.report({'INFO'}, report_string) #e nel report
return {'FINISHED'} #fine

if __name__ == "__main__":
bpy.ops.screen.select_instances()

EDIT: lo script è stato testato con una scena di oltre 2700000 poligoni e circa 8000 istanze per oggetto (cubi, coni, sfere, parallelepipedi)

Friday, February 25, 2011

Blender Script: Selezionare gli oggetti istanziati

Eccomi qui, dopo una lunga pausa.
Finalmente (e dico davvero: FINALMENTE!) ho integrato blender nel mio flusso produttivo, utilizzandolo come software principale in un lavoro nuovo che sto seguendo.

Appena avrò più tempo a disposizione ho intenzione di pubblicare un piccolo studio riguardante l'organizzazione della nuova pipeline, ma per ora sono pieno e soprattutto sto valutando quale motore di rendering entrerà a far parte della squadra una volta pensionato definitivamente 3DStudioMax (Thea e VRay sono i candidati per via dello stato di avanzamento degli exporter di blender).

Comunque... perchè scrivo?
Perchè lavorando con Blender su una scena con numerose istanze ho notato che l'outliner putroppo non ha tutte le funzioni di selezione che offre invece Max. Quindi, in piena filosofia open source, ho deciso di scrivermi degli script per fare questo lavoro :)

Questo è una "beta" di un selettore di istanze: cerca le istanze dell'oggetto attivo e le seleziona. Molto semplice, molto stupido se volete ma anche moooolto comodo.
Appena saprò usare meglio le API di Blender 2.6 voglio espanderlo ed integrare un pop-up.

Naturalmente è a disposizione di chiunque, rilasciato sotto licenza GPL:

# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####


#!BPY
"""
Name: 'Select object instances'
Blender: 256
Group: 'Object'
Tooltip: 'Select object instances'
"""
#author: Pietro Grandi (pietro909.blogspot.com)
#inspired by "atylmo" (http://atylmo.wordpress.com)
#

import bpy

scena = bpy.context.scene #punta alla scena attiva

i = 0 #contatore ciclo for

sel_obj = bpy.context.active_object #oggetto attivo
sel_obj_type = sel_obj.data.name #tipo di oggetto selezionato
sel_obj_name = sel_obj.name #nome dell'oggetto selezionato


print("E' attivo l'oggetto "+sel_obj_name+" di tipo "+sel_obj_type)
print("Istanze:")

for object in scena.objects: #per ogni oggetto in scena
current_obj = scena.objects[i] #prendi il nome dell'oggetto
if current_obj.data.name == sel_obj_type: #controlla se è del tipo selezionato
print("Selezionato "+current_obj.name) #stampalo
current_obj.select = True #selezionalo
i+=1 #avanza il contatore