Upload files to 'studio'
This commit is contained in:
parent
ba673f4109
commit
f735f00f86
6 changed files with 828 additions and 4 deletions
22
studio/bpy_get_render_settings.py
Normal file
22
studio/bpy_get_render_settings.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# THIS FILE IS A PART OF VCStudio
|
||||||
|
# PYTHON 3
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
# This file is going to output render setting from the blend file to our
|
||||||
|
# renderer. NOTE: This file is using BPY module that is running inside
|
||||||
|
# blender and is not going to run on standard python3.
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
# The following print() commands are going to be piped into VCStudio.
|
||||||
|
# You can extend the data by adding more lines here. Keep in mind that
|
||||||
|
# you have to also write support for the lines you add into the render layer.
|
||||||
|
# See:
|
||||||
|
# studio/studio_renderLayer.py
|
||||||
|
|
||||||
|
print("Start_frame :", bpy.context.scene.frame_start)
|
||||||
|
print("End_frame :", bpy.context.scene.frame_end)
|
||||||
|
|
|
@ -74,6 +74,7 @@ from studio import studio_file_selectLayer
|
||||||
from studio import studio_asset_selectLayer
|
from studio import studio_asset_selectLayer
|
||||||
from studio import studio_shot_linkLayer
|
from studio import studio_shot_linkLayer
|
||||||
from studio import studio_asset_configureLayer
|
from studio import studio_asset_configureLayer
|
||||||
|
from studio import studio_renderLayer
|
||||||
|
|
||||||
#################
|
#################
|
||||||
|
|
||||||
|
@ -240,6 +241,37 @@ def asset_configure(win, name, call, asset, force=False):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Wiping the history of the assets. See studio/studio_asset_selectLayer.py
|
||||||
|
win.assets = {}
|
||||||
|
|
||||||
|
# Let's clear the LMB just in case
|
||||||
|
win.previous["LMB"] = False
|
||||||
|
|
||||||
|
def render(win, name, call, filename="", force=False):
|
||||||
|
|
||||||
|
# This function going to launch a window that shows all current renders and
|
||||||
|
# confuge them.
|
||||||
|
|
||||||
|
print("Test 2")
|
||||||
|
|
||||||
|
if name not in win.current["calls"]:
|
||||||
|
win.current["calls"][name] = {
|
||||||
|
"var" :None, # This is the variable that we are waiting for
|
||||||
|
"call":call, # This is what it's going to run when it's done
|
||||||
|
"url" :"render",
|
||||||
|
"back":win.url,# This is where it's going to come back when it's done
|
||||||
|
"draw":studio_renderLayer.layer
|
||||||
|
}
|
||||||
|
|
||||||
|
# let's prepare the data for this operation
|
||||||
|
|
||||||
|
if force or "renders_window" not in win.current\
|
||||||
|
or win.current["renders_window"]["filename"] != filename:
|
||||||
|
win.current["renders_window"] = {
|
||||||
|
"filename":filename
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# Wiping the history of the assets. See studio/studio_asset_selectLayer.py
|
# Wiping the history of the assets. See studio/studio_asset_selectLayer.py
|
||||||
win.assets = {}
|
win.assets = {}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,9 @@ from UI import UI_testing
|
||||||
from UI import UI_color
|
from UI import UI_color
|
||||||
from UI import UI_elements
|
from UI import UI_elements
|
||||||
|
|
||||||
|
# Network
|
||||||
|
from network import network_renders
|
||||||
|
|
||||||
def previous(win):
|
def previous(win):
|
||||||
win.previous = {}
|
win.previous = {}
|
||||||
for i in win.current:
|
for i in win.current:
|
||||||
|
@ -94,6 +97,7 @@ def run(project, win):
|
||||||
win.layercashe = {} # Here I gonna store layers that are inactive to speed up stuff
|
win.layercashe = {} # Here I gonna store layers that are inactive to speed up stuff
|
||||||
win.checklists = {}
|
win.checklists = {}
|
||||||
win.blink = False # Cursor blinking thing.
|
win.blink = False # Cursor blinking thing.
|
||||||
|
win.renders = {} # List of current active renders.
|
||||||
|
|
||||||
if pm_project.is_legacy(project):
|
if pm_project.is_legacy(project):
|
||||||
win.story = story.get_legacy(project)
|
win.story = story.get_legacy(project)
|
||||||
|
@ -290,7 +294,7 @@ def pmdrawing(pmdrawing, main_layer, win):
|
||||||
|
|
||||||
del win.current["calls"][call]
|
del win.current["calls"][call]
|
||||||
except:
|
except:
|
||||||
pass
|
raise() # WHILE DEVELOPING DIALOGS SET THIS TO raise()
|
||||||
|
|
||||||
Layers.append([UI_testing.layer(win)])
|
Layers.append([UI_testing.layer(win)])
|
||||||
Layers.append([win.tooltip_surface])
|
Layers.append([win.tooltip_surface])
|
||||||
|
@ -324,6 +328,12 @@ def pmdrawing(pmdrawing, main_layer, win):
|
||||||
win.current["keys"] = []
|
win.current["keys"] = []
|
||||||
win.textactive = ""
|
win.textactive = ""
|
||||||
|
|
||||||
|
# For the rendering I will need to read render info at each frame and parse
|
||||||
|
# it in various windows.
|
||||||
|
|
||||||
|
network_renders.read_renders(win)
|
||||||
|
|
||||||
|
|
||||||
# There is a but in the Gnome I guess. That autopresses the Shift and Ctrl
|
# There is a but in the Gnome I guess. That autopresses the Shift and Ctrl
|
||||||
# keys when you scroll to different windows. So here is a little fix.
|
# keys when you scroll to different windows. So here is a little fix.
|
||||||
if not win.is_active():
|
if not win.is_active():
|
||||||
|
@ -389,6 +399,11 @@ def key_release(widget, event, win):
|
||||||
except:
|
except:
|
||||||
win.current["keys"] = []
|
win.current["keys"] = []
|
||||||
|
|
||||||
|
# I also want to clean the key letter. Because other wise in the
|
||||||
|
# script writer I had weird key presses all the time.
|
||||||
|
|
||||||
|
win.current["key_letter"] = ""
|
||||||
|
|
||||||
def scrolling(widget, event, win):
|
def scrolling(widget, event, win):
|
||||||
e, x, y = event.get_scroll_deltas()
|
e, x, y = event.get_scroll_deltas()
|
||||||
win.current["scroll"] = [x,y]
|
win.current["scroll"] = [x,y]
|
||||||
|
|
727
studio/studio_renderLayer.py
Normal file
727
studio/studio_renderLayer.py
Normal file
|
@ -0,0 +1,727 @@
|
||||||
|
# THIS FILE IS A PART OF VCStudio
|
||||||
|
# PYTHON 3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
import json
|
||||||
|
from subprocess import *
|
||||||
|
|
||||||
|
# GTK module ( Graphical interface
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import GLib
|
||||||
|
from gi.repository import Gdk
|
||||||
|
import cairo
|
||||||
|
|
||||||
|
# Own modules
|
||||||
|
from settings import settings
|
||||||
|
from settings import talk
|
||||||
|
from settings import fileformats
|
||||||
|
from settings import oscalls
|
||||||
|
from project_manager import pm_project
|
||||||
|
|
||||||
|
#UI modules
|
||||||
|
from UI import UI_elements
|
||||||
|
from UI import UI_color
|
||||||
|
from UI import UI_math
|
||||||
|
|
||||||
|
# Studio
|
||||||
|
from studio import studio_dialogs
|
||||||
|
from studio import analytics
|
||||||
|
from studio import story
|
||||||
|
|
||||||
|
# Network / Rendering
|
||||||
|
from network import network_renders
|
||||||
|
|
||||||
|
def save_settings(win, filename):
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
# This function will save the render settings file.
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
folder = filename[:filename.rfind("/")]+"/extra"
|
||||||
|
savefile = folder+filename[filename.rfind("/"):]+".json"
|
||||||
|
|
||||||
|
# First let's make sure that the extra folder exists.
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.makedirs(win.project+folder)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Then let's write the file in there.
|
||||||
|
|
||||||
|
with open(win.project+savefile, 'w') as fp:
|
||||||
|
json.dump(win.renders[filename], fp, sort_keys=True, indent=4)
|
||||||
|
|
||||||
|
|
||||||
|
def layer(win, call):
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
# This file will setup and manage rendering of shots. It's a bit complex
|
||||||
|
# in function. I have 2 network scripts at the moment. And it might grow
|
||||||
|
# beyond that.
|
||||||
|
|
||||||
|
# See:
|
||||||
|
# network/during_render.py
|
||||||
|
# network/network_renders.py
|
||||||
|
|
||||||
|
# This file is the UI part of the process. ( The maing UI ) Some beats and
|
||||||
|
# peaces will exists in various windows through out the program.
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
|
||||||
|
# Making the layer
|
||||||
|
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, win.current['w'],
|
||||||
|
win.current['h'])
|
||||||
|
layer = cairo.Context(surface)
|
||||||
|
|
||||||
|
|
||||||
|
#text setting
|
||||||
|
layer.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "dark_overdrop")
|
||||||
|
layer.rectangle(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
win.current["w"],
|
||||||
|
win.current["h"],
|
||||||
|
)
|
||||||
|
layer.fill()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "node_background")
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
win.current["w"]/2-250,
|
||||||
|
100,
|
||||||
|
500,
|
||||||
|
win.current["h"]-200,
|
||||||
|
10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
is_rendering = False # This will determen whether
|
||||||
|
|
||||||
|
for render in win.renders:
|
||||||
|
if win.renders[render]["rendering"]:
|
||||||
|
is_rendering = True
|
||||||
|
|
||||||
|
|
||||||
|
if not is_rendering:
|
||||||
|
# Render button
|
||||||
|
def do():
|
||||||
|
|
||||||
|
# This here will launch a script that will be on it's on from now
|
||||||
|
# on. See:
|
||||||
|
# network/during_render.py
|
||||||
|
|
||||||
|
Popen(["python3", "network/during_render.py", win.project, oscalls.get_current_blender(win)])
|
||||||
|
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
win.current["w"]/2-20,
|
||||||
|
win.current["h"]-140,
|
||||||
|
40,
|
||||||
|
40,
|
||||||
|
10,
|
||||||
|
button=do,
|
||||||
|
icon="right")
|
||||||
|
else:
|
||||||
|
# Stop Render button
|
||||||
|
|
||||||
|
def do():
|
||||||
|
|
||||||
|
network_renders.stop_render(win)
|
||||||
|
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
win.current["w"]/2-20,
|
||||||
|
win.current["h"]-140,
|
||||||
|
40,
|
||||||
|
40,
|
||||||
|
10,
|
||||||
|
button=do,
|
||||||
|
icon="stop")
|
||||||
|
|
||||||
|
# Exit button
|
||||||
|
def do():
|
||||||
|
win.current["calls"][call]["var"] = False
|
||||||
|
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
win.current["w"]/2+210,
|
||||||
|
win.current["h"]-140,
|
||||||
|
40,
|
||||||
|
40,
|
||||||
|
10,
|
||||||
|
button=do,
|
||||||
|
icon="cancel",
|
||||||
|
tip=talk.text("cancel"))
|
||||||
|
|
||||||
|
|
||||||
|
x = win.current["w"]/2-250 + 10
|
||||||
|
y = 100 + 10
|
||||||
|
width = 500 - 20
|
||||||
|
height = win.current["h"]-200 - 20
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height-60,
|
||||||
|
10,
|
||||||
|
fill=False)
|
||||||
|
layer.clip()
|
||||||
|
|
||||||
|
clip = [
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height-60]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Let's get the filename of the current file that we want to setup.
|
||||||
|
filename = win.current["renders_window"]["filename"]
|
||||||
|
|
||||||
|
# So this window could be accessed from both main window and from the script.
|
||||||
|
# One is to see where each render is. And ther other is to configure and add
|
||||||
|
# renders to the list.
|
||||||
|
|
||||||
|
if filename:
|
||||||
|
|
||||||
|
# Basically if any file is inputted. It means that it's to configure.
|
||||||
|
# but sometimes. ( I'm tyring to see myself using it ) the user will
|
||||||
|
# click on the render button to just access the render. And to hell with
|
||||||
|
# it. Let's make the filename variable the selection of the file.
|
||||||
|
|
||||||
|
if filename not in win.renders:
|
||||||
|
|
||||||
|
# So on the initialization we want to do a couple of things.
|
||||||
|
# First of which will be to get render settings data from the
|
||||||
|
# blend file.
|
||||||
|
|
||||||
|
# I think a quick bpy script could do.
|
||||||
|
# See:
|
||||||
|
# studio/bpy_get_render_settings.py
|
||||||
|
|
||||||
|
blenderpath = oscalls.get_current_blender(win)
|
||||||
|
blend = win.project+filename
|
||||||
|
|
||||||
|
checkframes = Popen([blenderpath, "-b", blend , "-P",
|
||||||
|
os.getcwd()+"/studio/bpy_get_render_settings.py"],stdout=PIPE, universal_newlines=True)
|
||||||
|
checkframes.wait()
|
||||||
|
checkstring = checkframes.stdout.read()
|
||||||
|
|
||||||
|
# We are going to need the following options.
|
||||||
|
|
||||||
|
start_frame = 0
|
||||||
|
end_frame = 250
|
||||||
|
image_format = "PNG"
|
||||||
|
save_folder = "storyboard"
|
||||||
|
|
||||||
|
|
||||||
|
for line in checkstring.split("\n"):
|
||||||
|
|
||||||
|
if line.startswith("Start_frame"):
|
||||||
|
try:
|
||||||
|
start_frame = int(line[line.find(":")+1:])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if line.startswith("End_frame"):
|
||||||
|
try:
|
||||||
|
end_frame = int(line[line.find(":")+1:])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Now since we've got the data. Let's write it to the dictionary first.
|
||||||
|
|
||||||
|
win.renders[filename] = {
|
||||||
|
"start_frame" :start_frame , # The frame we want to start on
|
||||||
|
"end_frame" :end_frame , # The frame we want to end on
|
||||||
|
"image_format" :image_format, # What format to save the images
|
||||||
|
"save_folder" :save_folder , # Into what folder to save images
|
||||||
|
"clean_folder" :False , # Whether to delete current frames before rendering
|
||||||
|
"current_frame":0 , # What is current frame rendering
|
||||||
|
"rendering" :False , # Whether it's currently rendering
|
||||||
|
"analytics" :{} # Times of each frame
|
||||||
|
}
|
||||||
|
|
||||||
|
# Now in order not to loose the data immediatly. We are going to need
|
||||||
|
# to add the filename into a special file.
|
||||||
|
|
||||||
|
s = open(win.project+"/set/active_renders.data", "a")
|
||||||
|
s.write(filename+"\n")
|
||||||
|
s.close()
|
||||||
|
|
||||||
|
# Also we want to make a little json file in the extra folder of
|
||||||
|
# the shot. This will contain our settings. And the file will be
|
||||||
|
# read by the renderer script while it's running. It has to be on
|
||||||
|
# it's own. So it's good to have extendable files.
|
||||||
|
|
||||||
|
save_settings(win, filename)
|
||||||
|
|
||||||
|
# Now let's get to the actuall UI of the stuff. Basically I want it to
|
||||||
|
# always give us a list of the currently set renders. And one of them
|
||||||
|
# might be selected and expendet to see they settings / current data.
|
||||||
|
|
||||||
|
# Setting up the scroll
|
||||||
|
if "render" not in win.scroll:
|
||||||
|
win.scroll["render"] = 0
|
||||||
|
|
||||||
|
current_Y = 0
|
||||||
|
|
||||||
|
# So let's do this.
|
||||||
|
|
||||||
|
is_rendering = False # This will determen whether
|
||||||
|
|
||||||
|
# Before we dive into settings and graphs. Let's make a deletion
|
||||||
|
if 65535 in win.current["keys"] and not win.renders[win.current["renders_window"]["filename"]]["rendering"]:
|
||||||
|
try:
|
||||||
|
del win.renders[win.current["renders_window"]["filename"]]
|
||||||
|
|
||||||
|
active_renders = open(win.project+"/set/active_renders.data")
|
||||||
|
active_renders = active_renders.read()
|
||||||
|
active_renders = active_renders.split("\n")
|
||||||
|
|
||||||
|
s = open(win.project+"/set/active_renders.data", "w")
|
||||||
|
|
||||||
|
for i in active_renders:
|
||||||
|
if i != win.current["renders_window"]["filename"] and i:
|
||||||
|
s.write(i+"\n")
|
||||||
|
|
||||||
|
s.close()
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
win.current["renders_window"]["filename"] = ""
|
||||||
|
win.current["keys"] = []
|
||||||
|
|
||||||
|
for render in win.renders:
|
||||||
|
|
||||||
|
# Let's get a shot name for each render.
|
||||||
|
|
||||||
|
shot = render[:render.rfind("/")].replace("/rnd", "")
|
||||||
|
blend = render[render.rfind("/"):]
|
||||||
|
|
||||||
|
tip = (shot+blend).replace("/", "", 1).replace("/", " | ")
|
||||||
|
|
||||||
|
if win.renders[render]["rendering"]:
|
||||||
|
tip = win.renders[render]["rendering"]
|
||||||
|
|
||||||
|
def do():
|
||||||
|
win.current["renders_window"]["filename"] = render
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x,
|
||||||
|
y+current_Y+win.scroll["render"],
|
||||||
|
width,
|
||||||
|
80,
|
||||||
|
10,
|
||||||
|
button=do,
|
||||||
|
tip=tip,
|
||||||
|
clip=clip)
|
||||||
|
|
||||||
|
# I think the render logo could be cool.
|
||||||
|
|
||||||
|
UI_elements.image(layer, win,
|
||||||
|
"settings/themes/"+win.settings["Theme"]+"/icons/render.png",
|
||||||
|
x+5, y+current_Y+win.scroll["render"]+5, 40, 40)
|
||||||
|
|
||||||
|
# And the name of the shot
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "text_normal")
|
||||||
|
layer.set_font_size(20)
|
||||||
|
layer.move_to(x+60,
|
||||||
|
y+current_Y + win.scroll["render"]+30)
|
||||||
|
layer.show_text((shot+blend).replace("/", "", 1).replace("/", " | "))
|
||||||
|
|
||||||
|
# And let's draw the fraction
|
||||||
|
|
||||||
|
fraction = (win.renders[render]["current_frame"] - win.renders[render]["start_frame"])\
|
||||||
|
/ (win.renders[render]["end_frame"] - win.renders[render]["start_frame"])
|
||||||
|
|
||||||
|
fraction = min(1, fraction)
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "progress_background")
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x+20,
|
||||||
|
y+current_Y + win.scroll["render"]+55,
|
||||||
|
width-40,
|
||||||
|
0,
|
||||||
|
5)
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "progress_active")
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x+20,
|
||||||
|
y+current_Y + win.scroll["render"]+55,
|
||||||
|
(width-40)*fraction,
|
||||||
|
0,
|
||||||
|
5)
|
||||||
|
|
||||||
|
# Now selection. When you click on one you expend it. And you can see
|
||||||
|
# what settings are inside.
|
||||||
|
|
||||||
|
if win.current["renders_window"]["filename"] == render:
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "progress_background")
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x,
|
||||||
|
y+current_Y+win.scroll["render"],
|
||||||
|
width,
|
||||||
|
80,
|
||||||
|
10,
|
||||||
|
fill=False)
|
||||||
|
layer.stroke()
|
||||||
|
|
||||||
|
current_Y = current_Y + 90
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# We are going to have 2 differnt UI's for those who are rendering
|
||||||
|
# and those who are not rendering.
|
||||||
|
|
||||||
|
if not win.renders[render]["rendering"]:
|
||||||
|
|
||||||
|
# We need to choose the folder of where the given render will be done.
|
||||||
|
# For the user tho I don't think nessesary to understand that it's a
|
||||||
|
# folder nessesary. They will see 4 circles. 4 render qualities. And
|
||||||
|
# will decide stuff based on that.
|
||||||
|
|
||||||
|
fouricons = [ "storyboard", "opengl", "test_rnd", "rendered"]
|
||||||
|
|
||||||
|
for num, f in enumerate(fouricons):
|
||||||
|
if f == win.renders[render]["save_folder"]:
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "progress_time")
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x+20+(40*num),
|
||||||
|
y+current_Y + win.scroll["render"],
|
||||||
|
40,
|
||||||
|
40,
|
||||||
|
10)
|
||||||
|
|
||||||
|
def do():
|
||||||
|
win.renders[render]["save_folder"] = f
|
||||||
|
save_settings(win, render)
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x+20+(40*num),
|
||||||
|
y+current_Y + win.scroll["render"],
|
||||||
|
40,
|
||||||
|
40,
|
||||||
|
10,
|
||||||
|
button=do,
|
||||||
|
icon=f,
|
||||||
|
tip=f)
|
||||||
|
|
||||||
|
# Here also I want to have a little clean icon. This will make sure
|
||||||
|
# to clean the current frames that are currently inside the folder.
|
||||||
|
# I know it's slightly counter intuitive compared to the rest of
|
||||||
|
# the program in that it's better not to give the user the ability
|
||||||
|
# to delete any actuall files. But in this case it makes a bit
|
||||||
|
# sense. Since for the user rendering again is like replacing the
|
||||||
|
# previous files with new ones. And the algorythm always renders
|
||||||
|
# from the last frame in the folder. So it never deletes anything
|
||||||
|
# by defaul. So I guess a button to clean frames could be a good
|
||||||
|
# thing.
|
||||||
|
|
||||||
|
if win.renders[render]["clean_folder"]:
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "progress_time")
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x+width-40,
|
||||||
|
y+current_Y + win.scroll["render"],
|
||||||
|
40,
|
||||||
|
40,
|
||||||
|
10)
|
||||||
|
|
||||||
|
def do():
|
||||||
|
win.renders[render]["clean_folder"] = not win.renders[render]["clean_folder"]
|
||||||
|
save_settings(win, render)
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x+width-40,
|
||||||
|
y+current_Y + win.scroll["render"],
|
||||||
|
40,
|
||||||
|
40,
|
||||||
|
10,
|
||||||
|
button=do,
|
||||||
|
icon="clean",
|
||||||
|
tip=talk.text("clean_render_folder"))
|
||||||
|
|
||||||
|
|
||||||
|
current_Y = current_Y + 50
|
||||||
|
|
||||||
|
# I will give 4 formats to save the renders too. The user will have
|
||||||
|
# to select 1 of those 4.
|
||||||
|
|
||||||
|
# PNG: The good old PNG. Which is an open format and is widly used
|
||||||
|
# in GNU / Linux operating system. Also it has lossless compre-
|
||||||
|
# ssion and an alha channel to store transparent parts.
|
||||||
|
|
||||||
|
# JPEG: A standard JPEG image type. Widly used to store photos. It
|
||||||
|
# content aware compression. Which is lossy, but more effective
|
||||||
|
# then PNG. Tho JPEG lacks alpha channel.
|
||||||
|
|
||||||
|
# EXR: In comparison to PNG or JPEG EXR format stores way broader
|
||||||
|
# range of values for each channel. Not simply from black to
|
||||||
|
# white. But also values that can be less then black and more
|
||||||
|
# then white. Giving you a High Dynamic Range look. And a
|
||||||
|
# possibility to store data such as Z depth.
|
||||||
|
|
||||||
|
# HDR: Similar to EXR. But more industry standard. And has bit more
|
||||||
|
# effective compression.
|
||||||
|
|
||||||
|
# I will not add any video files since the algoryhm will require
|
||||||
|
# actuall frames to be stored as separate files. This will insure
|
||||||
|
# that ALL frames were rendered. And in case of crash the algorythm
|
||||||
|
# will pick up from a previous frame in a folder. With video is not
|
||||||
|
# only impossible. But in case of a crash with video all the previous
|
||||||
|
# frames will be lost.
|
||||||
|
|
||||||
|
formats = ["JPEG", "PNG", "EXR", "HDR"]
|
||||||
|
|
||||||
|
for num, f in enumerate(formats):
|
||||||
|
|
||||||
|
if f == win.renders[render]["image_format"]:
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "progress_time")
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x+20+(80*num),
|
||||||
|
y+current_Y + win.scroll["render"],
|
||||||
|
70,
|
||||||
|
40,
|
||||||
|
10)
|
||||||
|
|
||||||
|
def do():
|
||||||
|
win.renders[render]["image_format"] = f
|
||||||
|
save_settings(win, render)
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x+20+(80*num),
|
||||||
|
y+current_Y + win.scroll["render"],
|
||||||
|
70,
|
||||||
|
40,
|
||||||
|
10,
|
||||||
|
button=do)
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "text_normal")
|
||||||
|
layer.set_font_size(20)
|
||||||
|
layer.move_to(x+30+(80*num),
|
||||||
|
y+current_Y + win.scroll["render"]+30)
|
||||||
|
layer.show_text(f)
|
||||||
|
|
||||||
|
current_Y = current_Y + 50
|
||||||
|
|
||||||
|
# Now let's put the settings them selves.
|
||||||
|
# First thing is we need start and end frames. And we also need it
|
||||||
|
# somehow readable for the user. I think a schedule logo would
|
||||||
|
# go fine here.
|
||||||
|
|
||||||
|
UI_elements.image(layer, win,
|
||||||
|
"settings/themes/"+win.settings["Theme"]+"/icons/schedule.png",
|
||||||
|
x+5, y+current_Y+win.scroll["render"], 40, 40)
|
||||||
|
|
||||||
|
# And the stuff it self
|
||||||
|
|
||||||
|
# I will probably need this.
|
||||||
|
def is_number(string):
|
||||||
|
try:
|
||||||
|
int(string)
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# START FRAME
|
||||||
|
|
||||||
|
UI_elements.text(layer, win, render+"start_frame",
|
||||||
|
x+60,
|
||||||
|
y+current_Y+win.scroll["render"],
|
||||||
|
200,
|
||||||
|
40,
|
||||||
|
set_text=str(win.renders[render]["start_frame"]))
|
||||||
|
|
||||||
|
if win.text[render+"start_frame"]["text"] != str(win.renders[render]["start_frame"])\
|
||||||
|
and is_number(win.text[render+"start_frame"]["text"]):
|
||||||
|
def do():
|
||||||
|
win.renders[render]["start_frame"] = int(win.text[render+"start_frame"]["text"])
|
||||||
|
save_settings(win, render)
|
||||||
|
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x+215,
|
||||||
|
y+current_Y+win.scroll["render"],
|
||||||
|
40,
|
||||||
|
40,
|
||||||
|
10,
|
||||||
|
button=do,
|
||||||
|
icon="ok",
|
||||||
|
tip=talk.text("checked"))
|
||||||
|
|
||||||
|
# END FRAME
|
||||||
|
UI_elements.text(layer, win, render+"end_frame",
|
||||||
|
x+60+210,
|
||||||
|
y+current_Y+win.scroll["render"],
|
||||||
|
200,
|
||||||
|
40,
|
||||||
|
set_text=str(win.renders[render]["end_frame"]))
|
||||||
|
|
||||||
|
if win.text[render+"end_frame"]["text"] != str(win.renders[render]["end_frame"])\
|
||||||
|
and is_number(win.text[render+"end_frame"]["text"]):
|
||||||
|
def do():
|
||||||
|
win.renders[render]["end_frame"] = int(win.text[render+"end_frame"]["text"])
|
||||||
|
save_settings(win, render)
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x+215+210,
|
||||||
|
y+current_Y+win.scroll["render"],
|
||||||
|
40,
|
||||||
|
40,
|
||||||
|
10,
|
||||||
|
button=do,
|
||||||
|
icon="ok",
|
||||||
|
tip=talk.text("checked"))
|
||||||
|
|
||||||
|
|
||||||
|
current_Y = current_Y + 50
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
# And here comes the UI of when it's during RENDERING
|
||||||
|
|
||||||
|
# First thing will be to draw a little graph. This will show current
|
||||||
|
# frame and analytics data about render times.
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "dark_overdrop")
|
||||||
|
layer.rectangle(
|
||||||
|
x+5,
|
||||||
|
y+current_Y+win.scroll["render"],
|
||||||
|
width-10,
|
||||||
|
100)
|
||||||
|
layer.fill()
|
||||||
|
|
||||||
|
for frame in range(win.renders[render]["start_frame"], win.renders[render]["end_frame"]+1):
|
||||||
|
|
||||||
|
numofis = win.renders[render]["end_frame"] - win.renders[render]["start_frame"]
|
||||||
|
|
||||||
|
if frame == win.renders[render]["current_frame"]:
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "progress_time")
|
||||||
|
layer.rectangle(
|
||||||
|
x+5+(width-10)/numofis*(frame-1),
|
||||||
|
y+current_Y+win.scroll["render"],
|
||||||
|
(width-10)/numofis,
|
||||||
|
100)
|
||||||
|
layer.fill()
|
||||||
|
|
||||||
|
# Now I want to be able to interact with the graph. For this I want to
|
||||||
|
# add a little mouse sensitive region. That will give me data about the
|
||||||
|
# current frame. In a tooltip?
|
||||||
|
|
||||||
|
if int(win.current["mx"]) in range(int(x+5+(width-10)/numofis*frame),int(x+5+(width-10)/numofis*frame+(width-10)/numofis))\
|
||||||
|
and int(win.current["my"]) in range(int(y+current_Y+win.scroll["render"]), int(y+current_Y+win.scroll["render"]+100)):
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "progress_background")
|
||||||
|
layer.move_to(x+5+(width-10)/numofis*(frame-0.5),
|
||||||
|
y+current_Y+win.scroll["render"]
|
||||||
|
)
|
||||||
|
layer.line_to(
|
||||||
|
x+5+(width-10)/numofis*(frame-0.5),
|
||||||
|
y+current_Y+win.scroll["render"]+100
|
||||||
|
)
|
||||||
|
layer.stroke()
|
||||||
|
if win.renders[render]["save_folder"] in win.renders[render]["analytics"]:
|
||||||
|
if str(frame) in win.renders[render]["analytics"][win.renders[render]["save_folder"]]:
|
||||||
|
|
||||||
|
value = win.renders[render]["analytics"][win.renders[render]["save_folder"]][str(frame)]
|
||||||
|
|
||||||
|
UI_elements.tooltip(win, UI_math.timestring(value/1000000))
|
||||||
|
|
||||||
|
# Now let's draw a graph. I love graphs. They are cool AF. First of all tho
|
||||||
|
# we need to know the maximum value. Because who know how long was the render
|
||||||
|
|
||||||
|
mx = 0
|
||||||
|
allvalues = []
|
||||||
|
if win.renders[render]["save_folder"] in win.renders[render]["analytics"]:
|
||||||
|
for v in win.renders[render]["analytics"][win.renders[render]["save_folder"]]:
|
||||||
|
mx = max(win.renders[render]["analytics"][win.renders[render]["save_folder"]][v], mx)
|
||||||
|
allvalues.append(win.renders[render]["analytics"][win.renders[render]["save_folder"]][v])
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "progress_background")
|
||||||
|
layer.move_to(x+5, y+current_Y+win.scroll["render"]+100)
|
||||||
|
for frame in range(win.renders[render]["start_frame"], win.renders[render]["end_frame"]+1):
|
||||||
|
numofis = win.renders[render]["end_frame"] - win.renders[render]["start_frame"]
|
||||||
|
if win.renders[render]["save_folder"] in win.renders[render]["analytics"]:
|
||||||
|
if str(frame) in win.renders[render]["analytics"][win.renders[render]["save_folder"]]:
|
||||||
|
|
||||||
|
value = win.renders[render]["analytics"][win.renders[render]["save_folder"]][str(frame)]
|
||||||
|
|
||||||
|
layer.line_to(
|
||||||
|
x+5+(width-10)/numofis*(frame-0.5),
|
||||||
|
(y+current_Y+win.scroll["render"]+100)-(100/mx*value)
|
||||||
|
)
|
||||||
|
layer.stroke()
|
||||||
|
|
||||||
|
current_Y = current_Y + 110
|
||||||
|
|
||||||
|
# Now let's put out some data in the text format. For the user to
|
||||||
|
# know stuff he or she might want to know.
|
||||||
|
|
||||||
|
# AVARAGE TIME
|
||||||
|
|
||||||
|
avarage = 0
|
||||||
|
try:
|
||||||
|
avarage = sum(allvalues) / len(allvalues)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "text_normal")
|
||||||
|
layer.set_font_size(20)
|
||||||
|
layer.move_to(x+10,
|
||||||
|
y+current_Y + win.scroll["render"]+30)
|
||||||
|
layer.show_text(talk.text("render_avarage_time")+" "+UI_math.timestring(avarage/1000000))
|
||||||
|
|
||||||
|
current_Y = current_Y + 40
|
||||||
|
|
||||||
|
# REMAINING TIME
|
||||||
|
|
||||||
|
remaining = avarage * (win.renders[render]["end_frame"] - win.renders[render]["current_frame"])
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "text_normal")
|
||||||
|
layer.set_font_size(20)
|
||||||
|
layer.move_to(x+10,
|
||||||
|
y+current_Y + win.scroll["render"]+30)
|
||||||
|
layer.show_text(talk.text("render_remaining_time")+" "+UI_math.timestring(remaining/1000000))
|
||||||
|
|
||||||
|
current_Y = current_Y + 40
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
current_Y = current_Y + 85
|
||||||
|
|
||||||
|
###########################
|
||||||
|
|
||||||
|
UI_elements.scroll_area(layer, win, "render",
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height-60,
|
||||||
|
current_Y,
|
||||||
|
bar=True,
|
||||||
|
mmb=True,
|
||||||
|
url="render"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
return surface
|
|
@ -2263,7 +2263,9 @@ def layer(win):
|
||||||
40,
|
40,
|
||||||
20,
|
20,
|
||||||
button=do,
|
button=do,
|
||||||
icon=icon)
|
icon=icon,
|
||||||
|
tip=icon)
|
||||||
|
|
||||||
|
|
||||||
current_Y_shots = current_Y_shots + 50
|
current_Y_shots = current_Y_shots + 50
|
||||||
|
|
||||||
|
@ -2615,7 +2617,10 @@ def layer(win):
|
||||||
|
|
||||||
# Render
|
# Render
|
||||||
def do():
|
def do():
|
||||||
print("Render")
|
def after(win, var):
|
||||||
|
pass
|
||||||
|
|
||||||
|
studio_dialogs.render(win, "render_setup", after, "/rnd"+win.cur+"/"+blend)
|
||||||
|
|
||||||
UI_elements.roundrect(layer, win,
|
UI_elements.roundrect(layer, win,
|
||||||
x+tileX+65,
|
x+tileX+65,
|
||||||
|
|
|
@ -493,7 +493,10 @@ def layer(win):
|
||||||
|
|
||||||
# Renders
|
# Renders
|
||||||
def do():
|
def do():
|
||||||
print("Renders")
|
def after(win, var):
|
||||||
|
pass
|
||||||
|
|
||||||
|
studio_dialogs.render(win, "current_renders", after)
|
||||||
|
|
||||||
UI_elements.roundrect(layer, win,
|
UI_elements.roundrect(layer, win,
|
||||||
5,
|
5,
|
||||||
|
@ -506,6 +509,26 @@ def layer(win):
|
||||||
talk.text("render_lists_tooltip"),
|
talk.text("render_lists_tooltip"),
|
||||||
url="story_editor")
|
url="story_editor")
|
||||||
|
|
||||||
|
# Let's draw on top of this button a little indicator of how many renders
|
||||||
|
# are currently setup.
|
||||||
|
|
||||||
|
if win.renders:
|
||||||
|
count = str(len(win.renders))
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "node_background")
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
30,
|
||||||
|
405,
|
||||||
|
len(count)*12+6,
|
||||||
|
25,
|
||||||
|
5)
|
||||||
|
layer.fill()
|
||||||
|
UI_color.set(layer, win, "text_normal")
|
||||||
|
layer.set_font_size(20)
|
||||||
|
layer.move_to(33,425)
|
||||||
|
layer.show_text(count)
|
||||||
|
|
||||||
|
|
||||||
# Edit Video
|
# Edit Video
|
||||||
def do():
|
def do():
|
||||||
print("Edit Video")
|
print("Edit Video")
|
||||||
|
|
Loading…
Reference in a new issue