# 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")  
