2021-12-19 19:14:53 +01:00
####################################
# #
# COPYRIGHT NOTICE #
# #
# This file is a part of Victori- #
# ous Children Studio Organizer. #
# Or simply VCStudio. Copyright #
# of J.Y.Amihud. But don't be sad #
# because I released the entire #
# project under a GNU GPL license. #
# You may use Version 3 or later. #
# See www.gnu.org/licenses if your #
# copy has no License file. Please #
# note. Ones I used the GPL v2 for #
# it. It's no longer the case. #
# #
####################################
2020-12-13 04:06:44 +01:00
import os
import datetime
# 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
# story
from studio import story
from studio import checklist
from studio import analytics
from studio import studio_dialogs
from studio import schedule
2020-12-14 04:21:25 +01:00
from studio import history
2020-12-13 04:06:44 +01:00
2023-01-04 19:05:16 +01:00
def datetip ( win , date ) :
# Function that outputs basic analytics about a given date
# in text form
# TODO: This function is in a prototype stage. Meaning it's
# not translated to multiple languages. This should be fixed.
# See settings/talk.py file.
2020-12-13 04:06:44 +01:00
2023-01-04 19:05:16 +01:00
text = date
try :
data = win . analytics [ " dates " ] [ date ]
# Expected
startdate = win . analytics [ " startdate " ]
deadline = win . analytics [ " deadline " ]
duration = win . analytics [ " duration " ]
new_date_format = " % Y/ % m/ %d "
sd = datetime . datetime . strptime ( startdate , new_date_format )
nd = datetime . datetime . strptime ( date , new_date_format )
dn = nd - sd
daysin = int ( dn . days )
expected = round ( 100 / duration * daysin , 2 )
text = text + " \n \n Expected: " + str ( expected ) + " % "
# Actual
frac = round ( data . get ( " fractions " , { } ) . get ( " project " ) * 100 , 2 )
text = text + " \n Actual: " + str ( frac ) + " % "
# Productivity
productivity = int ( round ( frac - expected + 100 ) )
text = text + " \n \n Productivity: " + str ( productivity ) + " % "
except Exception as e :
pass
return text
def layer ( win ) :
# This is very important. I makes live easier. LOL.
win . current [ " shot_left_side_scroll_please_work_omg_wtf " ] = True
2020-12-13 04:06:44 +01:00
# 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 " ] / 4 ,
10 ,
win . current [ " w " ] / 2 ,
win . current [ " h " ] - 20 ,
10 )
############################################################################
# This is the Analitycs window. This time I want to do something crazy.
# There will be 5 sections on the screen.
############################################################################
# # # #
# # # #
# # PROGRESS BARS # #
# # # #
# # # #
# # ####################################### # #
# # # #
# SCHEDULING # ANALYTICS GRAPH # MAIN #
# # # CHECKLIS #
# # # #
# # ####################################### # #
# # # #
# # CALENDAR / DAY SELECTOR # #
# # # #
# # X # #
############################################################################
# The idea is that you could be in Assets or Script Editor and drag the
# tasks from the checklist down to Calendar and leave it there. So when you
# move the task and mouse comes into the center part, you automatically
# transferred to the analytics layer for untill you leave the task somewhere
# or return it back to the checklist.
# I want to do the same with the SCHEDULING. So you could simple drag it to
# the Calendar to change it's date. Let's see how terribly hard will it be
# to implement. Because I'm already fighting with the Scedules all day.
############################################################################
############## PROGRESS BARS #############
timepassed = 0.0
projectdone = 0.0
chrdone = 0.0
vehdone = 0.0
locdone = 0.0
objdone = 0.0
rnddone = 0.0
try :
timepassed = win . analytics [ " timepassed " ]
projectdone = win . analytics [ " fraction " ]
chrdone = win . analytics [ " chr " ]
vehdone = win . analytics [ " veh " ]
locdone = win . analytics [ " loc " ]
objdone = win . analytics [ " obj " ]
rnddone = win . analytics [ " rnd " ]
except :
pass
# MAIN PROGRESS
2023-02-04 18:52:33 +01:00
2020-12-13 04:06:44 +01:00
UI_elements . image ( layer , win , " settings/themes/ " \
2023-02-04 18:52:33 +01:00
+ win . settings [ " Theme " ] + " /icons/star.png " ,
2020-12-13 04:06:44 +01:00
win . current [ " w " ] / 4 + 10 ,
15 ,
40 ,
40 )
# Progressbar
UI_color . set ( layer , win , " progress_background " )
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 60 ,
25 ,
win . current [ " w " ] / 2 - 80 ,
20 ,
2023-01-04 19:05:16 +01:00
10 ,
2023-02-04 18:52:33 +01:00
tip = " Today ' s requirement is: " + str ( round ( win . analytics . get ( " needed " , 0 ) * 100 , 1 ) ) + " % ( " + str ( round ( win . analytics . get ( " star " , 0 ) * 100 , 1 ) ) + " % o f which is done ) " )
2023-01-04 19:05:16 +01:00
2023-02-04 18:52:33 +01:00
UI_color . set ( layer , win , " text_link " )
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 60 ,
25 ,
2023-02-04 18:52:33 +01:00
( win . current [ " w " ] / 2 - 80 ) * min ( win . analytics . get ( " star " , 0 ) , 1 ) ,
2020-12-13 04:06:44 +01:00
20 ,
10 )
2023-02-04 18:52:33 +01:00
# # Icon
# UI_elements.image(layer, win, "settings/themes/"\
# +win.settings["Theme"]+"/icons/analytics.png",
# win.current["w"]/4+10,
# 15,
# 40,
# 40)
# # Progressbar
# UI_color.set(layer, win, "progress_background")
# UI_elements.roundrect(layer, win,
# win.current["w"]/4+60,
# 25,
# win.current["w"]/2-80,
# 20,
# 10,
# tip=str(round(projectdone*100, 1))+"%")
# # Project Done
# UI_color.set(layer, win, "progress_active")
# UI_elements.roundrect(layer, win,
# win.current["w"]/4+60,
# 25,
# (win.current["w"]/2-80)*projectdone,
# 20,
# 10)
2020-12-13 04:06:44 +01:00
# TIME PASSED
# Icon
UI_elements . image ( layer , win , " settings/themes/ " \
+ win . settings [ " Theme " ] + " /icons/schedule.png " ,
win . current [ " w " ] / 4 + 10 ,
55 ,
40 ,
40 )
UI_color . set ( layer , win , " progress_background " )
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 60 ,
65 ,
win . current [ " w " ] / 2 - 80 ,
20 ,
2023-01-04 19:05:16 +01:00
10 ,
2023-02-04 18:52:33 +01:00
tip = " Time: " + str ( round ( timepassed * 100 , 1 ) ) + " % Project: " + str ( round ( projectdone * 100 , 1 ) ) + " % " )
2020-12-13 04:06:44 +01:00
# Timepassed
UI_color . set ( layer , win , " progress_time " )
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 60 ,
65 ,
( win . current [ " w " ] / 2 - 80 ) * timepassed ,
20 ,
10 )
2023-02-04 18:52:33 +01:00
# Project Done
UI_color . set ( layer , win , " progress_active " )
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 60 ,
65 ,
( win . current [ " w " ] / 2 - 80 ) * projectdone ,
20 ,
10 )
2020-12-13 04:06:44 +01:00
# SCENES DONE ( RND )
# Icon
UI_elements . image ( layer , win , " settings/themes/ " \
2023-01-04 19:05:16 +01:00
+ win . settings [ " Theme " ] + " /icons/shot.png " ,
2020-12-13 04:06:44 +01:00
win . current [ " w " ] / 4 + 10 ,
95 ,
40 ,
40 )
2023-01-04 19:05:16 +01:00
UI_color . set ( layer , win , " shot_5 " )
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 60 ,
105 ,
win . current [ " w " ] / 2 - 80 ,
20 ,
2023-01-04 19:05:16 +01:00
10 ,
tip = str ( round ( rnddone * 100 , 1 ) ) + " % " ,
fill = False )
layer . stroke ( )
2020-12-13 04:06:44 +01:00
# Scenes
2023-01-04 19:05:16 +01:00
UI_color . set ( layer , win , " shot_5 " )
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 60 ,
105 ,
( win . current [ " w " ] / 2 - 80 ) * rnddone ,
20 ,
10 )
# CHR DONE
# Icon
UI_elements . image ( layer , win , " settings/themes/ " \
+ win . settings [ " Theme " ] + " /icons/chr.png " ,
win . current [ " w " ] / 4 + 10 ,
135 ,
40 ,
40 )
2023-01-04 19:05:16 +01:00
UI_color . set ( layer , win , " shot_1 " )
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 60 ,
145 ,
win . current [ " w " ] / 4 - 80 ,
20 ,
2023-01-04 19:05:16 +01:00
10 ,
tip = str ( round ( chrdone * 100 , 1 ) ) + " % " ,
fill = False )
layer . stroke ( )
2020-12-13 04:06:44 +01:00
# progress
2023-01-04 19:05:16 +01:00
UI_color . set ( layer , win , " shot_1 " )
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 60 ,
145 ,
( win . current [ " w " ] / 4 - 80 ) * chrdone ,
20 ,
10 )
# VEH DONE
# Icon
UI_elements . image ( layer , win , " settings/themes/ " \
+ win . settings [ " Theme " ] + " /icons/veh.png " ,
win . current [ " w " ] / 2 ,
135 ,
40 ,
40 )
2023-01-04 19:05:16 +01:00
UI_color . set ( layer , win , " shot_2 " )
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 2 + 60 ,
145 ,
win . current [ " w " ] / 4 - 80 ,
20 ,
2023-01-04 19:05:16 +01:00
10 ,
tip = str ( round ( vehdone * 100 , 1 ) ) + " % " ,
fill = False )
layer . stroke ( )
2020-12-13 04:06:44 +01:00
# progress
2023-01-04 19:05:16 +01:00
UI_color . set ( layer , win , " shot_2 " )
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 2 + 60 ,
145 ,
( win . current [ " w " ] / 4 - 80 ) * vehdone ,
20 ,
10 )
# LOC DONE
# Icon
UI_elements . image ( layer , win , " settings/themes/ " \
+ win . settings [ " Theme " ] + " /icons/loc.png " ,
win . current [ " w " ] / 4 + 10 ,
175 ,
40 ,
40 )
2023-01-04 19:05:16 +01:00
UI_color . set ( layer , win , " shot_3 " )
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 60 ,
185 ,
win . current [ " w " ] / 4 - 80 ,
20 ,
2023-01-04 19:05:16 +01:00
10 ,
tip = str ( round ( locdone * 100 , 1 ) ) + " % " ,
fill = False )
layer . stroke ( )
2020-12-13 04:06:44 +01:00
# progress
2023-01-04 19:05:16 +01:00
UI_color . set ( layer , win , " shot_3 " )
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 60 ,
185 ,
( win . current [ " w " ] / 4 - 80 ) * locdone ,
20 ,
10 )
# OBJ DONE
# Icon
UI_elements . image ( layer , win , " settings/themes/ " \
+ win . settings [ " Theme " ] + " /icons/obj.png " ,
win . current [ " w " ] / 2 ,
175 ,
40 ,
40 )
2023-01-04 19:05:16 +01:00
UI_color . set ( layer , win , " shot_4 " )
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 2 + 60 ,
185 ,
win . current [ " w " ] / 4 - 80 ,
20 ,
2023-01-04 19:05:16 +01:00
10 ,
tip = str ( round ( objdone * 100 , 1 ) ) + " % " ,
fill = False )
layer . stroke ( )
2020-12-13 04:06:44 +01:00
# progress
2023-01-04 19:05:16 +01:00
UI_color . set ( layer , win , " shot_4 " )
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 2 + 60 ,
185 ,
( win . current [ " w " ] / 4 - 80 ) * objdone ,
20 ,
10 )
############### THE GRAPH ##################
# This graph going to show the entire time of the whole project from
# StartDate till Deadline. It will fill up with data overtime.
# We are going to have a couple of modes.
# Regular mode: Showing actuall values represented on the graph
# it's going to be a diagonal line if the work was done
# linearly.
# Normalized : This this a graph of true values compared to time. So let's
# say at a second day you had to be only at 3%. Being at 3% will
# make graph show 100%. The expected value is linear from 0%
# to 100% over the whole project.
# Pulse mode : This mode will give a graph compared to the previous day.
# if on a given day there was a gib jump in percentage there
# will be a big spike on the graph.
# Let's make a mode selector.
if " analytics_middle_graph_mode " not in win . current :
2023-01-04 19:05:16 +01:00
win . current [ " analytics_middle_graph_mode " ] = " linear "
2020-12-13 04:06:44 +01:00
for num , thing in enumerate ( [ " linear " , " analytics " , " pulse " ] ) : # By icons
if win . current [ " analytics_middle_graph_mode " ] == thing :
UI_color . set ( layer , win , " progress_time " )
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 10 + ( 40 * num ) ,
225 ,
40 ,
40 ,
10 )
def do ( ) :
win . current [ " analytics_middle_graph_mode " ] = thing
del win . current [ " graph_cashe " ]
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 10 + ( 40 * num ) ,
225 ,
40 ,
40 ,
10 ,
do ,
thing )
# And before we start a little settings icon.
2020-12-25 15:20:34 +01:00
# Documentation entry
def do ( ) :
def after ( win , var ) :
pass
studio_dialogs . help ( win , " help " , after , SEARCH = talk . text ( " documentation_analytics " ) )
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 * 3 - 110 ,
225 ,
40 ,
40 ,
10 ,
do ,
" question " )
2020-12-13 04:06:44 +01:00
# Settings
def do ( ) :
win . url = " settings_layer "
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 * 3 - 60 ,
225 ,
40 ,
40 ,
10 ,
do ,
" settings " ,
talk . text ( " Settings " ) )
# Now let's make a filter by type. As you maybe already know appart from
# the main progress I'm reading all the other things too. Every progress
# bar on the screen should have a corrisponding graph. But sometimes if
# paths go too far appart, this aint helpfull. So a filter is required to
# switch a category on and off.
if " analytics_middle_graph_switch " not in win . current :
win . current [ " analytics_middle_graph_switch " ] = {
" project " : [ True , " analytics " , " progress_active " ] ,
2023-01-04 19:05:16 +01:00
" checklist " : [ True , " checklist " , " node_videofile " ] ,
" rnd " : [ True , " shot " , " shot_5 " ] ,
" chr " : [ True , " chr " , " shot_1 " ] ,
" veh " : [ True , " veh " , " shot_2 " ] , # Name in data : [ Active, Icon name, color ]
" loc " : [ True , " loc " , " shot_3 " ] ,
" obj " : [ True , " obj " , " shot_4 " ]
2020-12-13 04:06:44 +01:00
}
cat = win . current [ " analytics_middle_graph_switch " ]
mode = win . current [ " analytics_middle_graph_mode " ]
for num , thing in enumerate ( cat ) :
if cat [ thing ] [ 0 ] :
UI_color . set ( layer , win , cat [ thing ] [ 2 ] )
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 160 + ( 40 * num ) ,
225 ,
2023-01-04 19:05:16 +01:00
38 ,
2020-12-13 04:06:44 +01:00
40 ,
2023-01-04 19:05:16 +01:00
10 ,
fill = False )
layer . stroke ( )
2020-12-13 04:06:44 +01:00
def do ( ) :
cat [ thing ] [ 0 ] = not cat [ thing ] [ 0 ]
del win . current [ " graph_cashe " ]
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] / 4 + 160 + ( 40 * num ) ,
225 ,
2023-01-04 19:05:16 +01:00
38 ,
2020-12-13 04:06:44 +01:00
40 ,
10 ,
do ,
cat [ thing ] [ 1 ] )
# Let's set up some very handy values
new_date_format = " % Y/ % m/ %d "
startdate = win . analytics [ " startdate " ]
deadline = win . analytics [ " deadline " ]
duration = win . analytics [ " duration " ]
# Let's setup the little graph layer. So nothing come out of the frame.
x = win . current [ " w " ] / 4
y = 280
width = win . current [ " w " ] / 2
2021-12-19 19:14:53 +01:00
height = 100
2020-12-13 04:06:44 +01:00
# Now let's make a layer.
2023-01-04 19:05:16 +01:00
# CURRENT DATE
today = datetime . datetime . strftime ( datetime . datetime . today ( ) , new_date_format )
2020-12-14 04:21:25 +01:00
2020-12-13 04:06:44 +01:00
if " graph_cashe " not in win . current :
# Making the layer
graphsurface = cairo . ImageSurface ( cairo . FORMAT_ARGB32 , int ( width ) , int ( height ) )
node = cairo . Context ( graphsurface )
node . select_font_face ( " Monospace " , cairo . FONT_SLANT_NORMAL , cairo . FONT_WEIGHT_NORMAL )
# Background
#UI_color.set(node, win, "dark_overdrop")
#node.rectangle(0,0,width, height)
#node.fill()
# helping line
2023-01-04 19:05:16 +01:00
UI_color . set ( node , win , " progress_time " )
2020-12-13 04:06:44 +01:00
if mode == " analytics " :
node . move_to ( 0 , height / 2 )
node . line_to ( width , height / 2 )
elif mode == " pulse " :
ty = height / duration
node . move_to ( 0 , height / 2 - ty )
node . line_to ( width , height / 2 - ty )
else :
node . move_to ( 0 , height )
node . line_to ( width , 0 )
node . stroke ( )
2023-01-04 19:05:16 +01:00
todayX = 0
2020-12-13 04:06:44 +01:00
for num , thing in enumerate ( reversed ( cat ) ) :
if cat [ thing ] [ 0 ] :
UI_color . set ( node , win , cat [ thing ] [ 2 ] )
if mode == " linear " :
node . move_to ( 0 , height )
else :
node . move_to ( 0 , height / 2 )
pfrac = 0
dates = win . analytics [ " dates " ]
2023-01-04 19:05:16 +01:00
for date in dates :
2020-12-13 04:06:44 +01:00
# Let's calculate the X position of a given part on a graph
sd = datetime . datetime . strptime ( startdate , new_date_format )
nd = datetime . datetime . strptime ( date , new_date_format )
dn = nd - sd
dn = int ( dn . days )
graphX = width / duration * dn
2023-01-04 19:05:16 +01:00
if date == today :
todayX = graphX
2020-12-13 04:06:44 +01:00
# Let's calculate the Y position of a given part on a graph
if " fractions " in dates [ date ] :
fracs = dates [ date ] [ " fractions " ]
if mode == " linear " :
gfraction = fracs [ thing ]
graphY = height - height * gfraction
node . line_to ( graphX , graphY )
elif mode == " analytics " :
gfraction = fracs [ thing ]
tfraction = dn / duration
gfraction = gfraction / tfraction / 2
graphY = height - height * gfraction
node . line_to ( graphX , graphY )
else :
gfraction = fracs [ thing ]
gfraction = gfraction - pfrac
graphY = height - height * gfraction - height / 2
node . line_to ( graphX , graphY )
pfrac = fracs [ thing ]
node . stroke ( )
2023-01-04 19:05:16 +01:00
# Today
UI_color . set ( node , win , " button_clicked " )
node . move_to ( todayX , 0 )
node . line_to ( todayX , height )
node . stroke ( )
2020-12-13 04:06:44 +01:00
win . current [ " graph_cashe " ] = graphsurface
2023-01-04 19:05:16 +01:00
# Dynamic elements of the graph!
# I sense a possible bug here, since I will draw these on top
# of a prebaked image. And something sometimes might not align
# properly. I don't know how to deal with it quite yet, perhaps
# you can try fixing the issue. LOL.
# Bottom Graph position on the top graph.
try :
posX = width / ( duration * 50 ) * win . scroll [ " days " ]
posX2 = ( width / ( duration * 50 ) * ( win . scroll [ " days " ] + width ) ) - posX
except :
posX = 0
posX2 = 20
UI_color . set ( layer , win , " dark_overdrop " )
UI_elements . roundrect ( layer , win ,
x - posX ,
y ,
posX2 ,
height ,
5 ,
fill = True )
layer . stroke ( )
# Mouse drag thingy
if x < win . current [ " mx " ] < x + width \
and y < win . current [ " my " ] < y + height :
if win . current [ " LMB " ] :
win . scroll [ " days " ] = 0 - ( ( win . current [ " mx " ] - x ) / width * ( duration * 50 ) ) + ( width / 2 )
sd = datetime . datetime . strptime ( startdate , new_date_format )
daysin = int ( round ( duration / width * ( x - win . current [ " mx " ] ) ) ) * - 1
td = datetime . timedelta ( days = daysin )
hoverdate = sd + td
hoverdate = hoverdate . strftime ( new_date_format )
UI_elements . tooltip ( win , datetip ( win , hoverdate ) )
UI_color . set ( layer , win , " progress_background " )
layer . move_to ( win . current [ " mx " ] , y )
layer . line_to ( win . current [ " mx " ] , y + height )
layer . stroke ( )
2020-12-13 04:06:44 +01:00
# Outputting the layer
layer . set_source_surface ( win . current [ " graph_cashe " ] , x , y )
2023-01-04 19:05:16 +01:00
layer . paint ( )
2020-12-14 04:21:25 +01:00
# Let's force graph to refresh on each click
if not win . current [ " LMB " ] and win . previous [ " LMB " ] :
try :
del win . current [ " graph_cashe " ]
except :
pass
2020-12-13 04:06:44 +01:00
############### SCHEDULING / DATE SELECTION ################
# So here I want to put a dialog that in the Blender-Organizer legacy was
# in the center of the frame. I thought here it makes a bit more sense. Tho
# I will remove the graph from it. I have a very good graph on the top from
# it. And in my opinion this is enough. In you think otherwise let me know.
# or fork VCStudio and implement it yourself. See what I can do with free-
# software. I can just tell you to do everything yourself. Imaging doing this
# when developing proprietery software.
# Anyway back to the thing. I do want to draw schedules inside the days cells.
# and by their colors. RED or GREY or PURPLE or GREEN you will have an idea of
# how much stuff is done and how much stuff is not yet done. A kind of second
# graph, so to speak. But representing differnt kind of data.
2021-12-19 19:14:53 +01:00
2020-12-13 04:06:44 +01:00
# OKAY. SETTINGS.
if " schedule_analytics_settings " not in win . current :
win . current [ " schedule_analytics_settings " ] = {
" checked " : False ,
" multiuser " : False
}
for num , button in enumerate ( win . current [ " schedule_analytics_settings " ] ) :
if win . current [ " schedule_analytics_settings " ] [ button ] :
UI_color . set ( layer , win , " progress_time " )
UI_elements . roundrect ( layer , win ,
x + 10 + ( 40 * num ) ,
y + height + 10 ,
40 ,
40 ,
10 )
def do ( ) :
win . current [ " schedule_analytics_settings " ] [ button ] = not win . current [ " schedule_analytics_settings " ] [ button ]
UI_elements . roundrect ( layer , win ,
x + 10 + ( 40 * num ) ,
y + height + 10 ,
40 ,
40 ,
10 ,
do ,
button )
UI_elements . text ( layer , win , " current_date_setting " ,
x + 100 ,
y + height + 10 ,
200 ,
40 ,
set_text = win . current [ " date " ] )
if win . text [ " current_date_setting " ] [ " text " ] != win . current [ " date " ] \
and analytics . ifdate ( win . text [ " current_date_setting " ] [ " text " ] ) :
def do ( ) :
win . current [ " date " ] = win . text [ " current_date_setting " ] [ " text " ]
2020-12-14 04:21:25 +01:00
win . textactive = " "
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( layer , win ,
x + 260 ,
y + height + 10 ,
40 ,
40 ,
10 ,
button = do ,
icon = " ok " ,
tip = talk . text ( " checked " ) )
elif win . current [ " date " ] != today :
def do ( ) :
win . current [ " date " ] = today
win . text [ " current_date_setting " ] [ " text " ] = today
2020-12-14 04:21:25 +01:00
win . textactive = " "
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( layer , win ,
x + 260 ,
y + height + 10 ,
40 ,
40 ,
10 ,
button = do ,
icon = " cancel " ,
tip = talk . text ( " cancel " ) )
y = y + height + 60
2021-12-19 19:14:53 +01:00
height = win . current [ " h " ] - 500
2020-12-13 04:06:44 +01:00
# Making the layer
graphsurface = cairo . ImageSurface ( cairo . FORMAT_ARGB32 , int ( width ) , int ( height ) )
node = cairo . Context ( graphsurface )
node . select_font_face ( " Monospace " , cairo . FONT_SLANT_NORMAL , cairo . FONT_WEIGHT_NORMAL )
if " days " not in win . scroll :
win . scroll [ " days " ] = 0 - win . analytics [ " dayspassed " ] * 50 + width / 2 - 25
current_X = 0
prevyear = [ startdate . split ( " / " ) [ 0 ] , win . scroll [ " days " ] ]
prevmonth = [ startdate . split ( " / " ) [ 1 ] , win . scroll [ " days " ] ]
2023-01-04 19:05:16 +01:00
prevday = " 1997/07/30 "
pfrac = { }
2020-12-13 04:06:44 +01:00
for doffset in range ( duration + 1 ) : # FOR ALL DAYS. NO MATTER IF THEY ARE IN DATA
sd = datetime . datetime . strptime ( startdate , new_date_format )
theday = datetime . datetime . strftime ( sd + datetime . timedelta ( days = doffset ) , new_date_format )
nowyear = [ theday . split ( " / " ) [ 0 ] , current_X + win . scroll [ " days " ] ]
nowmonth = [ theday . split ( " / " ) [ 1 ] , current_X + win . scroll [ " days " ] ]
# Focusing if selected
if win . current [ " date " ] != win . previous [ " date " ] and win . current [ " date " ] == theday :
win . scroll [ " days " ] = 0 - current_X + width / 2 - 25
# YEARS
if nowyear [ 0 ] != prevyear [ 0 ] :
UI_color . set ( node , win , " dark_overdrop " )
UI_elements . roundrect ( node , win ,
5 + prevyear [ 1 ] + 2 ,
0 ,
nowyear [ 1 ] - prevyear [ 1 ] - 7 ,
20 ,
10 )
UI_color . set ( node , win , " text_normal " )
node . set_font_size ( 15 )
node . move_to (
max ( prevyear [ 1 ] + 200 , min ( width / 2 - 23 , nowyear [ 1 ] - 200 ) ) ,
15 ,
)
node . show_text ( prevyear [ 0 ] )
prevyear = nowyear
# MONTHS
if nowmonth [ 0 ] != prevmonth [ 0 ] :
UI_color . set ( node , win , " dark_overdrop " )
UI_elements . roundrect ( node , win ,
5 + prevmonth [ 1 ] + 2 ,
22 ,
nowmonth [ 1 ] - prevmonth [ 1 ] - 7 ,
20 ,
10 )
UI_color . set ( node , win , " text_normal " )
node . set_font_size ( 15 )
node . move_to (
max ( prevmonth [ 1 ] + 12 , min ( width / 2 - 12 , nowmonth [ 1 ] - 35 ) ) ,
38 ,
)
node . show_text ( prevmonth [ 0 ] )
prevmonth = nowmonth
# DAYS
if - 50 < current_X + win . scroll [ " days " ] < width :
UI_color . set ( node , win , " dark_overdrop " )
UI_elements . roundrect ( node , win ,
5 + current_X + win . scroll [ " days " ] ,
44 ,
40 ,
20 ,
10 )
UI_color . set ( node , win , " text_normal " )
node . set_font_size ( 15 )
node . move_to (
15 + current_X + win . scroll [ " days " ] ,
59 ,
)
node . show_text ( theday . split ( " / " ) [ 2 ] )
UI_color . set ( node , win , " dark_overdrop " )
2021-12-19 19:14:53 +01:00
if theday > = today :
if theday == today :
UI_color . set ( node , win , " button_clicked " )
UI_elements . roundrect ( node , win ,
5 + current_X + win . scroll [ " days " ] ,
67 ,
40 ,
height - 67 ,
10 )
2020-12-13 04:06:44 +01:00
if win . current [ " date " ] == theday :
UI_color . set ( node , win , " progress_background " )
UI_elements . roundrect ( node , win ,
5 + current_X + win . scroll [ " days " ] ,
67 ,
40 ,
height - 67 ,
10 ,
fill = False )
node . stroke ( )
2020-12-14 04:21:25 +01:00
# STARTDATE & DEADLINE
elif theday in [ startdate , deadline ] :
UI_color . set ( node , win , " node_badfile " )
UI_elements . roundrect ( node , win ,
5 + current_X + win . scroll [ " days " ] ,
67 ,
40 ,
height - 67 ,
10 ,
fill = False )
node . stroke ( )
2020-12-13 04:06:44 +01:00
# SELECTION BUTTON
def do ( ) :
2020-12-14 04:21:25 +01:00
if win . current [ " tool " ] == " schedule " :
# If it's a scheduling.
path , back , cur , schedulepath , username = win . current [ " grab_data " ] . copy ( )
path = path . replace ( win . project , " " )
path = path [ path . find ( cur ) + len ( cur ) : ]
if theday not in win . analytics [ " dates " ] :
win . analytics [ " dates " ] [ theday ] = { }
name = cur [ cur . rfind ( " / " ) + 1 : ]
acur = cur . replace ( name , " " ) . replace ( " / " , " " )
if acur in [ " chr " , " veh " , " loc " , " obj " ] :
itemtype = " assets "
elif not acur :
itemtype = " files "
else :
itemtype = " scenes "
if itemtype not in win . analytics [ " dates " ] [ theday ] :
win . analytics [ " dates " ] [ theday ] [ itemtype ] = { }
if cur not in win . analytics [ " dates " ] [ theday ] [ itemtype ] :
win . analytics [ " dates " ] [ theday ] [ itemtype ] [ cur ] = [ ]
2020-12-15 21:38:04 +01:00
#print("test 1")
2020-12-14 04:21:25 +01:00
win . analytics [ " dates " ] [ theday ] [ itemtype ] [ cur ] . append (
[ " 00:00:00 " ,
" schedule " ,
path ,
" [Un-Checked] " ,
schedulepath ,
username ]
)
2020-12-15 21:38:04 +01:00
#print("test 2")
2020-12-14 04:21:25 +01:00
# RETURNING BACK TO NORMAL
win . url = back
win . current [ " tool " ] = " selection "
analytics . save ( win . project , win . analytics )
win . analytics = analytics . load ( win . project )
win . checklists = { }
2021-01-03 00:33:34 +01:00
# Multiuser sycning
win . multiuser [ " request " ] = " analytics "
2020-12-15 21:38:04 +01:00
#print("test 3")
2020-12-14 04:21:25 +01:00
else :
win . current [ " date " ] = theday
win . text [ " current_date_setting " ] [ " text " ] = theday
2020-12-13 04:06:44 +01:00
UI_elements . roundrect ( node , win ,
5 + current_X + win . scroll [ " days " ] ,
67 ,
40 ,
height - 67 ,
10 ,
button = do ,
offset = [ x , y ] ,
2023-01-04 19:05:16 +01:00
fill = False ,
tip = datetip ( win , theday ) )
2020-12-13 04:06:44 +01:00
node . stroke ( )
2021-12-19 19:14:53 +01:00
##################### BOTTOM GRAPH #######################
# Blender-Organizer legacy had two graphs. One smaller
# that shows all the project from start to finish
# ( Implemented above ) and one bigger. That shows a
# Zoomed in version of the graph. Back then I made it
# executing the same code twice. Which was fine. Since
# I had to make a change only ones. Now it's a bit of a
# problem to do so. Since the graph above is baked. And
# need to be able to navigate with in the bottom graph.
# So instead I'm going to redo the graph, but since we
2023-01-04 19:05:16 +01:00
# are re-doing it. I orignally wanted to do a different
# design. But it ended up looking confusing. It needs lines!
# Roundrects will not do.
2021-12-19 19:14:53 +01:00
2023-02-04 18:52:33 +01:00
2023-01-04 19:05:16 +01:00
2021-12-19 19:14:53 +01:00
for num , thing in enumerate ( reversed ( cat ) ) :
if cat [ thing ] [ 0 ] :
UI_color . set ( node , win , cat [ thing ] [ 2 ] )
try :
2023-01-04 19:05:16 +01:00
sd = datetime . datetime . strptime ( startdate , new_date_format )
nd = datetime . datetime . strptime ( theday , new_date_format )
dn = nd - sd
dn = int ( dn . days )
2021-12-19 19:14:53 +01:00
fracs = win . analytics [ " dates " ] [ theday ] [ " fractions " ]
2023-01-04 19:05:16 +01:00
Pfracs = win . analytics [ " dates " ] [ prevday ] [ " fractions " ]
2021-12-19 19:14:53 +01:00
gfraction = fracs [ thing ]
2023-01-04 19:05:16 +01:00
if mode == " linear " :
graphY = ( ( height - 80 ) - ( height - 80 ) * gfraction ) + 60
elif mode == " analytics " :
tfraction = dn / duration
gfraction = gfraction / tfraction / 2
graphY = ( ( height - 80 ) - ( height - 80 ) * gfraction ) + 60
else :
try :
gfraction = fracs [ thing ]
gfraction = gfraction - Pfracs [ thing ]
except :
gfraction = 0
graphY = ( ( height - 80 ) - ( height - 80 ) * gfraction - ( height - 80 ) / 2 ) + 60
PgraphY = pfrac . get ( thing , graphY )
pfrac [ thing ] = graphY
node . move_to ( current_X + win . scroll [ " days " ] - 25 ,
PgraphY )
node . line_to ( current_X + win . scroll [ " days " ] + 25 ,
graphY )
node . stroke ( )
except Exception as e :
if theday < today and theday not in win . analytics [ " dates " ] :
UI_color . set ( node , win , " node_badfile " )
UI_elements . roundrect ( node , win ,
5 + current_X + win . scroll [ " days " ] ,
67 ,
40 ,
height - 67 ,
10 ,
fill = False )
node . stroke ( )
2021-12-19 19:14:53 +01:00
2023-01-04 19:05:16 +01:00
2021-12-19 19:14:53 +01:00
2020-12-13 04:06:44 +01:00
# Now here I want to draw the representations of scheduled
2023-01-04 19:05:16 +01:00
# tasks that are inside
# Icons of what was done at the day
icons_stuff = { " assets " : " obj " ,
" scenes " : " shot " ,
" files " : " checklist " }
icons = [ ]
for t in icons_stuff :
if t in win . analytics [ " dates " ] . get ( theday , { } ) and t != " assets " :
icons . append ( icons_stuff [ t ] )
elif t in win . analytics [ " dates " ] . get ( theday , { } ) :
for at in [ " chr " , " obj " , " loc " , " veh " ] :
for stuff in win . analytics [ " dates " ] . get ( theday , { } ) [ t ] :
if at in stuff and at not in icons :
icons . append ( at )
for nicon , icon in enumerate ( icons ) :
UI_elements . image ( node , win , " settings/themes/ " \
+ win . settings [ " Theme " ] + " /icons/ " + icon + " .png " ,
6 + current_X + win . scroll [ " days " ] ,
height - ( 50 * nicon ) - 50 ,
40 ,
40 )
2023-02-04 18:52:33 +01:00
# Stars! If the day was exceptional.
try :
if win . analytics [ " needed " ] < = fracs . get ( " project " , 0 ) - Pfracs . get ( " project " , 0 ) and theday < = today :
2023-03-06 21:18:27 +01:00
stars = ( fracs . get ( " project " , 0 ) - Pfracs . get ( " project " , 0 ) ) / win . analytics [ " needed " ]
for star in range ( int ( round ( stars ) ) ) :
UI_elements . image ( node , win , " settings/themes/ " \
+ win . settings [ " Theme " ] + " /icons/star.png " ,
6 + current_X + win . scroll [ " days " ] ,
height - ( 50 * ( nicon + star - 1 ) ) - 150 ,
40 ,
40 )
2023-02-04 18:52:33 +01:00
except :
pass
2020-12-13 04:06:44 +01:00
2023-02-04 18:52:33 +01:00
# Schedules
2020-12-13 04:06:44 +01:00
sch = [ ]
if theday in win . analytics [ " dates " ] :
date = win . analytics [ " dates " ] [ theday ]
2020-12-15 21:38:04 +01:00
2020-12-13 04:06:44 +01:00
for i in [ " files " , " assets " , " scenes " ] :
if i in date :
for item in date [ i ] :
for stuff in date [ i ] [ item ] :
if stuff [ 1 ] == " schedule " :
2020-12-15 21:38:04 +01:00
2020-12-13 04:06:44 +01:00
if not win . current [ " schedule_analytics_settings " ] [ " multiuser " ] :
if win . settings [ " Username " ] != stuff [ - 1 ] :
continue
if " [Checked] " in stuff :
if win . current [ " schedule_analytics_settings " ] [ " checked " ] :
sch . append ( True )
else :
sch . append ( False )
for n , s in enumerate ( sch ) :
UI_color . set ( node , win , " node_background " )
if theday < today :
UI_color . set ( node , win , " node_badfile " )
elif theday > today :
UI_color . set ( node , win , " node_asset " )
if s :
UI_color . set ( node , win , " node_blendfile " )
UI_elements . roundrect ( node , win ,
8 + current_X + win . scroll [ " days " ] ,
70 + 13 * n ,
35 ,
8 ,
5 )
2023-01-04 19:05:16 +01:00
2020-12-13 04:06:44 +01:00
current_X = current_X + 50
2023-01-04 19:05:16 +01:00
prevday = theday
2020-12-13 04:06:44 +01:00
2021-12-19 19:14:53 +01:00
2020-12-13 04:06:44 +01:00
UI_color . set ( node , win , " dark_overdrop " )
UI_elements . roundrect ( node , win ,
5 + prevyear [ 1 ] + 2 ,
0 ,
nowyear [ 1 ] - prevyear [ 1 ] - 4 + 50 ,
20 ,
10 )
UI_color . set ( node , win , " text_normal " )
node . set_font_size ( 15 )
node . move_to (
max ( prevyear [ 1 ] + 200 , min ( width / 2 - 23 , nowyear [ 1 ] - 200 ) ) ,
15 ,
)
node . show_text ( prevyear [ 0 ] )
UI_color . set ( node , win , " dark_overdrop " )
UI_elements . roundrect ( node , win ,
5 + prevmonth [ 1 ] + 2 ,
22 ,
nowmonth [ 1 ] - prevmonth [ 1 ] - 4 + 50 ,
20 ,
10 )
UI_color . set ( node , win , " text_normal " )
node . set_font_size ( 15 )
node . move_to (
max ( prevmonth [ 1 ] + 12 , min ( width / 2 - 12 , nowmonth [ 1 ] - 35 ) ) ,
38 ,
)
node . show_text ( prevmonth [ 0 ] )
# Outputting the layer
layer . set_source_surface ( graphsurface , x , y )
layer . paint ( )
# Scroll
UI_elements . scroll_area ( layer , win , " days " ,
x ,
y ,
width ,
height + 30 ,
current_X ,
bar = True ,
mmb = True ,
sideways = True )
############## CHECKLIST ################
if win . current [ " tool " ] == " schedule " :
2020-12-14 04:21:25 +01:00
# If the tool is scheduling I want to make sure that the user sees where
# he needs to place the task. A higlight.
UI_color . set ( layer , win , " progress_background " )
UI_elements . roundrect ( layer , win ,
x ,
y + 67 ,
width ,
height - 67 ,
10 ,
fill = False )
layer . stroke ( )
2020-12-13 04:06:44 +01:00
2020-12-14 04:21:25 +01:00
path , back , cur , schedulepath , username = win . current [ " grab_data " ] . copy ( )
2020-12-13 04:06:44 +01:00
2020-12-15 21:38:04 +01:00
2020-12-13 04:06:44 +01:00
checklist . draw ( layer , win , path , back )
UI_color . set ( layer , win , " node_background " )
UI_elements . roundrect ( layer , win ,
win . current [ " mx " ] ,
win . current [ " my " ] ,
40 ,
40 ,
10 )
UI_elements . image ( layer , win ,
" settings/themes/ " + win . settings [ " Theme " ] + " /icons/schedule.png " ,
win . current [ " mx " ] ,
win . current [ " my " ] ,
40 ,
40 )
elif os . path . exists ( win . project + " /set/project.progress " ) :
checklist . draw ( layer , win , win . project + " /set/project.progress " , back = win . url )
elif os . path . exists ( win . project + " /project.progress " ) :
checklist . draw ( layer , win , win . project + " /project.progress " , back = win . url )
2020-12-14 04:21:25 +01:00
# In the analytics window there will a choise of whether to see schedules. Or to
# see history.
if " analytics_left_panel " not in win . current :
win . current [ " analytics_left_panel " ] = " schedule "
2020-12-13 04:06:44 +01:00
UI_color . set ( layer , win , " node_background " )
UI_elements . roundrect ( layer , win ,
10 ,
10 ,
win . current [ " w " ] / 4 - 20 ,
50 ,
10 )
2020-12-14 04:21:25 +01:00
for num , thing in enumerate ( [ " schedule " , " history " ] ) :
if win . current [ " analytics_left_panel " ] == thing :
UI_color . set ( layer , win , " progress_time " )
UI_elements . roundrect ( layer , win ,
20 + ( 40 * num ) ,
15 ,
40 ,
40 ,
10 )
def do ( ) :
win . current [ " analytics_left_panel " ] = thing
2020-12-13 04:06:44 +01:00
2020-12-14 04:21:25 +01:00
UI_elements . roundrect ( layer , win ,
20 + ( 40 * num ) ,
15 ,
40 ,
40 ,
10 ,
do ,
thing )
##### SCHEDULE ######
if win . current [ " analytics_left_panel " ] == " schedule " :
schedule . draw ( layer , win )
##### HISTORY #######
else :
history . draw ( layer , win )
2020-12-13 04:06:44 +01:00
# CANCEl
def do ( ) :
win . url = " story_editor "
win . assets = { }
win . current [ " asset_file_selected " ] = " "
UI_elements . roundrect ( layer , win ,
win . current [ " w " ] - 40 - win . current [ " w " ] / 4 ,
win . current [ " h " ] - 50 ,
40 ,
40 ,
10 ,
button = do ,
icon = " cancel " ,
tip = talk . text ( " cancel " ) )
# Short cut ESC
if 65307 in win . current [ " keys " ] and not win . textactive :
do ( )
return surface