266 lines
13 KiB
Python
266 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")
|