Adding project files to project template
This commit is contained in:
262
test.py
Normal file
262
test.py
Normal file
@@ -0,0 +1,262 @@
|
||||
import bpy
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
|
||||
from queue import Queue
|
||||
from threading import Thread, Event
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
|
||||
from bpy.types import Panel, Operator, PropertyGroup
|
||||
from bpy.props import (StringProperty,
|
||||
BoolProperty,
|
||||
IntProperty,
|
||||
FloatProperty,
|
||||
EnumProperty,
|
||||
PointerProperty,
|
||||
CollectionProperty
|
||||
)
|
||||
|
||||
|
||||
class BlendFileProperty(PropertyGroup):
|
||||
path = StringProperty(subtype="FILE_PATH")
|
||||
filename = StringProperty(subtype="FILE_NAME")
|
||||
blending_enabled = BoolProperty(
|
||||
name="Enable or Disable",
|
||||
description="Enable blend file for blending",
|
||||
default=False)
|
||||
status = StringProperty(
|
||||
name="Status",
|
||||
description="Status of current file",
|
||||
default=""
|
||||
)
|
||||
|
||||
|
||||
class PushBlendPullProperties(PropertyGroup):
|
||||
project_folder = StringProperty(
|
||||
name="Project folder",
|
||||
description="Path to project folder",
|
||||
default="//",
|
||||
subtype="DIR_PATH"
|
||||
)
|
||||
remote_host = StringProperty(
|
||||
name="Remote host",
|
||||
description="Address or host of remote",
|
||||
defaul =""
|
||||
)
|
||||
remote_folder = StringProperty(
|
||||
name="Remote project folder",
|
||||
description="Path to remote project folder",
|
||||
default=""
|
||||
)
|
||||
blend_file_list = CollectionProperty(type=BlendFileProperty)
|
||||
upload_status = StringProperty(
|
||||
name="Upload status",
|
||||
description="Status of current upload",
|
||||
default=""
|
||||
)
|
||||
|
||||
|
||||
class ProjectManagerRefreshBlenFileOperator(Operator):
|
||||
bl_idname = "wm.pm_refresh_blend"
|
||||
bl_label = "Refresh Blender Files"
|
||||
|
||||
def execute(self, context):
|
||||
blendFileList = context.window_manager.project_manager.blend_file_list
|
||||
enabled = []
|
||||
for blendFile in blendFileList:
|
||||
if blendFile.blending_enabled:
|
||||
enabled.append(blendFile.path)
|
||||
|
||||
blendFileList.clear()
|
||||
path = bpy.path.abspath(context.window_manager.project_manager.project_folder)
|
||||
for root, dirs, files in os.walk(path):
|
||||
for file in files:
|
||||
if file.endswith(".blend"):
|
||||
blendFile = blendFileList.add()
|
||||
blendFile.filename = os.path.splitext(file)[0]
|
||||
blendFile.path = os.path.join(root, file)
|
||||
blendFile.name = bpy.path.relpath(blendFile.path)
|
||||
blendFile.blending_enabled = blendFile.path in enabled
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class ProjectManagerStartBlend(Operator):
|
||||
bl_idname = "wm.project_manager"
|
||||
bl_label = "Start blend"
|
||||
|
||||
_timer = None
|
||||
_queue = None
|
||||
_worker = None
|
||||
|
||||
def execute(self, context):
|
||||
wm = context.window_manager
|
||||
|
||||
self._queue = Queue()
|
||||
self._worker = RemoteThreadHandler(
|
||||
self._queue,
|
||||
wm.project_manager.blend_file_list,
|
||||
bpy.path.abspath(wm.project_manager.project_folder),
|
||||
wm.project_manager.remote_host,
|
||||
wm.project_manager.remote_folder
|
||||
)
|
||||
self._worker.start()
|
||||
|
||||
self._timer = wm.event_timer_add(1, context.window)
|
||||
wm.modal_handler_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
def modal(self, context, event):
|
||||
if event.type in {'ESC'}:
|
||||
self.cancel(context)
|
||||
print("canceled")
|
||||
return {'CANCELLED'}
|
||||
|
||||
if event.type == 'TIMER':
|
||||
while not self._queue.empty():
|
||||
self.handle_message(self._queue.get(), context.window_manager.project_manager)
|
||||
self._queue.task_done()
|
||||
if not self._worker.is_alive():
|
||||
self.cancel(context)
|
||||
print("finished")
|
||||
return {'FINISHED'}
|
||||
|
||||
return {'PASS_THROUGH'}
|
||||
|
||||
def cancel(self, context):
|
||||
wm = context.window_manager
|
||||
wm.event_timer_remove(self._timer)
|
||||
self._worker.stop()
|
||||
|
||||
def handle_message(self, msg, pm):
|
||||
if msg[0] == "push":
|
||||
print(msg)
|
||||
pm.upload_status = "push "+msg[1]
|
||||
elif msg[0] == "pull":
|
||||
msg[2].status = "pull "+msg[1]
|
||||
elif msg[0] == "blend":
|
||||
msg[2].status = "blend "+msg[1]
|
||||
|
||||
|
||||
class RemoteThreadHandler(Thread):
|
||||
def __init__(self, q, blendFileList, localFolder, remoteHost, remoteFolder):
|
||||
super(RemoteThreadHandler, self).__init__()
|
||||
|
||||
self._queue = q
|
||||
self.blendFileList = blendFileList
|
||||
self.remotePath = "{}:{}".format(remoteHost,remoteFolder)
|
||||
self.localFolder = localFolder
|
||||
self.remoteHost = remoteHost
|
||||
self.remoteFolder = remoteFolder
|
||||
|
||||
self._stop_event = Event()
|
||||
|
||||
def stop(self):
|
||||
self._stop_event.set()
|
||||
|
||||
def stopped(self):
|
||||
return self._stop_event.is_set()
|
||||
|
||||
ARGS_PUSH = "rsync -azP --info=progress2 --exclude '*.blend1' --exclude 'README.md' {} {}"
|
||||
ARGS_PULL = "rsync -azP --info=progress2 --exclude '*.blend' {} {}"
|
||||
ARGS_BLEND = "ssh -t hawat 'blender -b {} -a'"
|
||||
|
||||
REGEX_PUSHPULL_STATUS = "\d+%"
|
||||
|
||||
def handleLinePush(self, line, current_file=None):
|
||||
if line == 'end':
|
||||
self._queue.put(("push", "end",))
|
||||
return
|
||||
t = re.search(self.REGEX_PUSHPULL_STATUS, line)
|
||||
if t is not None:
|
||||
self._queue.put(("push", t[0],))
|
||||
|
||||
def handleLinePull(self, line, current_file):
|
||||
if line == 'end':
|
||||
self._queue.put(("pull", "end", current_file,))
|
||||
return
|
||||
t = re.search(self.REGEX_PUSHPULL_STATUS, line)
|
||||
if t is not None:
|
||||
self._queue.put(("pull", t[0], current_file,))
|
||||
|
||||
def run(self):
|
||||
self.start_process_handle_queue(self.ARGS_PUSH.format(self.localFolder, self.remotePath), self.handleLinePush)
|
||||
|
||||
for blendFile in self.blendFileList:
|
||||
if blendFile.blending_enabled:
|
||||
remoteBlendFilePath = blendFile.path.replace(self.localFolder, self.remoteFolder)
|
||||
self.start_process_handle_queue(self.ARGS_BLEND.format(remoteBlendFilePath), self.handleLineBlend, blendFile)
|
||||
|
||||
pullWorker = Thread(
|
||||
target=self.start_process_handle_queue,
|
||||
args=(self.ARGS_PULL.format(self.remotePath, self.localFolder) , self.handleLinePull, blendFile)
|
||||
)
|
||||
pullWorker.start()
|
||||
|
||||
def start_process_handle_queue(self, args, lineHandler, current_file = None):
|
||||
if self.stopped():
|
||||
return
|
||||
print(args)
|
||||
p = Popen(args, shell=True, stdout=PIPE, stderr=STDOUT, universal_newlines=True, bufsize=1)
|
||||
last_line = ''
|
||||
while not self.stopped():
|
||||
line = p.stdout.readline()
|
||||
if line == '':
|
||||
if p.poll() is not None:
|
||||
break
|
||||
elif line != last_line:
|
||||
lineHandler(line, current_file)
|
||||
last_line = line
|
||||
|
||||
if self.stopped():
|
||||
p.kill()
|
||||
|
||||
lineHandler('end', current_file)
|
||||
|
||||
|
||||
class ProjectManagerPanel(Panel):
|
||||
bl_idname = "OBJECT_PT_project_manager"
|
||||
bl_label = "Project Management"
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = ""
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator(ProjectManagerStartBlend.bl_idname)
|
||||
|
||||
configuration = context.window_manager.project_manager
|
||||
layout.label(text="Configuration")
|
||||
layout = self.layout
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(configuration, "project_folder")
|
||||
row = layout.row(align=True)
|
||||
row.prop(configuration, "remote_host")
|
||||
row = layout.row(align=True)
|
||||
row.prop(configuration, "remote_folder")
|
||||
row = layout.row(align=True)
|
||||
row.prop(configuration, "upload_status")
|
||||
|
||||
layout.operator(ProjectManagerRefreshBlenFileOperator.bl_idname)
|
||||
fileList = configuration.blend_file_list
|
||||
for blendFile in sorted(fileList.values(), key=lambda file: file.path):
|
||||
row = layout.row()
|
||||
row.prop(blendFile, "blending_enabled", text=bpy.path.relpath(blendFile.path))
|
||||
row.prop(blendFile, "status", text="")
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_module(__name__)
|
||||
bpy.types.WindowManager.project_manager = PointerProperty(type=ProjectManagerProperties)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_module(__name__)
|
||||
del bpy.types.WindowManager.project_manage
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
Reference in New Issue
Block a user