Blender-Pipeline/studio/bpy_do_linking.py

267 lines
13 KiB
Python

# THIS FILE IS A PART OF VCStudio
# PYTHON 3
# BPY ( WITH IN BLENDER )
#################################################################
# This file is running with in Blender to link assets from their
# AST files into the animation files. And make library overrides.
# NOTE: It's using BPY module which is not available outside of
# blender. So in order to test any changes to it. You have to
# run it with in Blender. Or Using blender -P <your_script>.
# See blender --help for details.
#################################################################
import bpy
import os
# The main problem with running from with in blender is that we
# have no access to all the outside modules. And this script
# will be there on it's own. So it need a way of knowing where
# are the assets.
blendpath = bpy.data.filepath # Animation file path
folder = blendpath[:blendpath.rfind("/")] # Animation shot folder
pf = folder[:folder.rfind("/rnd/")] # Project's folder
# In order for VCStudio or Blender-Organizer to know what is going
# on I use print(). It's not going to be outputted into terminal.
# since we are piping everything directly into VCStudio. Which is
# going to parse those lines to give the user some graphical feed
# back.
print("BLENDPATH : ", blendpath)
print("FOLDER : ", folder)
print("PROJECT FOLDER : ", pf)
# Now we are going to abort the process if there is no file in the
# shot folder that has the info about the linked data. autolink.data
if os.path.exists(folder+"/extra/autolink.data"):
print("FOUND AUTOLINK.DATA YEY :)")
# Now let's parse the extra/autolink.data file
df = open(folder+"/extra/autolink.data" , "r")
df = df.read()
# These 2 values will be our location in the blender space since
# I don't think any user wants all of their assets to be in the
# same exact spot.
movey = 0
movex = 0
# We need to get our mode first. Because the user might want to
# just link. Or make the old proxy.
mode = "link"
for num, line in enumerate(df.split("\n")):
if line.startswith("Mode : "):
mode = line[7:]
# Let's see if there any lines that say what we want to link.
for num, line in enumerate(df.split("\n")):
if line.startswith("Link : "):
# So here is out item. ( asset ). NOTE: THe item in
# autolink.data will have /dev/ added to the begining
# like all links in Blender-Organizer.
item = line[7:]
print("\nLINKING ITEM : "+item)
# Now let's see if the asset also has an autolink.data
# configured. Because if not. Script would not know what
# to link.
itemsdf = pf+item+"/autolink.data"
if os.path.exists(itemsdf):
print("FOUND "+item+"'S AUTOLINK.DATA :)")
# Now let's parse the autolink.data of the asset.
idf = open(itemsdf, "r")
idf = idf.read()
# We need to find 2 types of data. What collections
# to link. Since not all of them are nessesary. And
# whether to do library-overrides.
# At the time of Blender-Organizer library-overrides
# was still a very unstable thing. So I was going
# proxies. Now I don't want to break backward compati-
# bility with Blender-Organizer. So we are going to
# read the full list of Proxies. And if they exist
# we are going to use library override instead. So
# keep in mind. They called proxies in the script. But
# they are library-overrides.
linkdata = [] # Lits of colletions to link
proxydata = [] # Lits of "Proxies" so to speak.
for iline in idf.split("\n"):
if iline.startswith("Link : "):
linkdata.append(iline[7:])
elif iline.startswith("Proxy : "):
proxydata.append(iline[8:])
print("LINKDATA ", linkdata)
print("PROXYDATA ", proxydata)
# Okay. Now we got both lists. Let's see if there is
# an asset blend file. Because for any reason it might
# not exists.
astblend = pf+"/ast/"+item[5:]+".blend"
print("AST BLEND : "+astblend)
if os.path.exists(astblend):
print("YAY FOUND THE BLENDFILE :)")
# We found our asset blend file. So now let's do
# the linking.
for collection in linkdata:
print("ATTEMPTING TO LINK : "+collection)
# Now let's try actually doing it.
try:
with bpy.data.libraries.load(astblend, link=True) as (data_from, data_to):
data_to.collections = [c for c in data_from.collections if c == collection]
for num2, new_coll in enumerate(data_to.collections):
print("TRYING LINKING ", new_coll.name)
try:
if new_coll.name:
instance = bpy.data.objects.new(new_coll.name, None)
instance.instance_type = 'COLLECTION'
instance.instance_collection = new_coll
bpy.context.scene.collection.objects.link(instance)
if not item[5:].startswith("loc"):
bpy.data.objects[collection].location[1] = movey
bpy.data.objects[collection].location[0] = movex
# So here we already linked our data. And placed the
# objects. Next we want to do library-overrides.
if proxydata and mode == "override":
# With library overrides there is one little problem.
# It nullifies the location. Because the location is
# now also overriden.
bpy.data.objects[collection].select_set(True)
bpy.context.view_layer.objects.active = bpy.data.objects[collection]
bpy.ops.object.make_override_library()
# So after we do the override we need to change the
# location again.
if not item[5:].startswith("loc"):
bpy.data.objects[proxydata[0]].location[1] = movey
bpy.data.objects[proxydata[0]].location[0] = movex
# And while we are on it. In the Blender-Organizer
# linker there was one inconvinience that you had
# to hide the rig from viewport since if not you will
# have both linked and proxy rig drawn on screen at
# the same time. So let's unhide it.
bpy.data.objects[proxydata[0]].hide_viewport = False
# Also while we are here. Let's use the size of the
# rig to offset it's location instead of 5. If the
# rig exists.
movey = movey + bpy.data.objects[proxydata[0]].dimensions.y+1
if movey > 25:
movey = 0
movex = movex + 5
elif proxydata and mode == "proxy":
# Now the used could select to do it the old way.
# using a proxy. Then this is the way.
for proxymake in proxydata:
print("TRYING PROXING ", proxymake)
try:
ob = bpy.context.scene.objects[new_coll.name]
ob.select_set(True)
bpy.context.view_layer.objects.active = ob
bpy.ops.object.proxy_make(object=proxymake)
except Exception as e:
print("PROXY FAILED ", proxymake)
print(e, "ERROR IN PROXY")
movey = movey + 5
if movey > 25:
movey = 0
movex = movex + 5
else:
# If ther is no library - override enabled. The instance
# empty has a size of 0. So this same dimension thing
# would not work here. :(. I might come up with something
# later.
movey = movey + 5
if movey > 25:
movey = 0
movex = movex + 5
# Now I want to save the file. BUT. In the old way of
# doing it I made a mistake to save without checking
# that all paths should be RELATIVE. And so copying the
# project to another computer bloke all the files.
bpy.ops.file.make_paths_relative()
bpy.ops.wm.save_mainfile()
# So ther is 2 line now when saving.
# Now I'd like to print out the current fraction of
# the linking progress done. So I could make a progress
# bar in the VCStudio.
print("FRACTION:", (num+1)/len(df.split("\n")))
except Exception as e:
print(e, "ERROR IN LINING")
except Exception as e:
print(e, "ERROR IN GENERAL")
else:
print("NO BLENDFILE DOEN'T EXIST :(")
else:
print("NO "+item+"'S AUTOLINK.DATA :(")
else:
print("NO AUTOLINK.DATA SORRY :(")
print("FINISHED")