Multiuser Alpha 1.0
These are the UI and studio system part of The implementation
This commit is contained in:
parent
ba370b7cb1
commit
d067b6c64c
10 changed files with 701 additions and 16 deletions
|
@ -470,7 +470,6 @@ def draw(outlayer, win, path, back="story_editor"):
|
||||||
if win.current["schedule_task_selected"] and win.cur == win.current["schedule_task_selected"][-1]:
|
if win.current["schedule_task_selected"] and win.cur == win.current["schedule_task_selected"][-1]:
|
||||||
csl = win.current["schedule_task_selected"][0][0][4]
|
csl = win.current["schedule_task_selected"][0][0][4]
|
||||||
|
|
||||||
print(win.current["schedule_task_selected"])
|
|
||||||
|
|
||||||
if " "+task["string"] in csl and not task["open"]:
|
if " "+task["string"] in csl and not task["open"]:
|
||||||
task["open"] = True
|
task["open"] = True
|
||||||
|
@ -496,6 +495,7 @@ def draw(outlayer, win, path, back="story_editor"):
|
||||||
win.checklists = {}
|
win.checklists = {}
|
||||||
win.assets = {}
|
win.assets = {}
|
||||||
win.analytics = analytics.load(win.project)
|
win.analytics = analytics.load(win.project)
|
||||||
|
win.multiuser["last_request"] = ""
|
||||||
|
|
||||||
#### THE GRABBING FUNCTION ####
|
#### THE GRABBING FUNCTION ####
|
||||||
|
|
||||||
|
@ -637,6 +637,7 @@ def draw(outlayer, win, path, back="story_editor"):
|
||||||
win.checklists = {}
|
win.checklists = {}
|
||||||
win.assets = {}
|
win.assets = {}
|
||||||
win.analytics = analytics.load(win.project)
|
win.analytics = analytics.load(win.project)
|
||||||
|
win.multiuser["last_request"] = ""
|
||||||
|
|
||||||
elif win.current["LMB"]:
|
elif win.current["LMB"]:
|
||||||
|
|
||||||
|
@ -670,6 +671,7 @@ def draw(outlayer, win, path, back="story_editor"):
|
||||||
win.checklists = {}
|
win.checklists = {}
|
||||||
win.assets = {}
|
win.assets = {}
|
||||||
win.analytics = analytics.load(win.project)
|
win.analytics = analytics.load(win.project)
|
||||||
|
win.multiuser["last_request"] = ""
|
||||||
|
|
||||||
elif win.current["LMB"]:
|
elif win.current["LMB"]:
|
||||||
inside = True
|
inside = True
|
||||||
|
@ -758,6 +760,7 @@ def draw(outlayer, win, path, back="story_editor"):
|
||||||
save(path, win.checklists[path])
|
save(path, win.checklists[path])
|
||||||
win.checklists = {}
|
win.checklists = {}
|
||||||
win.assets = {}
|
win.assets = {}
|
||||||
|
win.multiuser["last_request"] = ""
|
||||||
#win.analytics = analytics.load(win.project)
|
#win.analytics = analytics.load(win.project)
|
||||||
|
|
||||||
UI_elements.roundrect(layer, win,
|
UI_elements.roundrect(layer, win,
|
||||||
|
@ -846,7 +849,7 @@ def draw(outlayer, win, path, back="story_editor"):
|
||||||
win.current["schedule_task_selected"] = False
|
win.current["schedule_task_selected"] = False
|
||||||
# Saving
|
# Saving
|
||||||
save(path, win.checklists[path])
|
save(path, win.checklists[path])
|
||||||
|
win.multiuser["last_request"] = ""
|
||||||
|
|
||||||
UI_elements.roundrect(layer, win,
|
UI_elements.roundrect(layer, win,
|
||||||
sx,
|
sx,
|
||||||
|
@ -878,7 +881,8 @@ def draw(outlayer, win, path, back="story_editor"):
|
||||||
win.checklists = {}
|
win.checklists = {}
|
||||||
win.assets = {}
|
win.assets = {}
|
||||||
win.analytics = analytics.load(win.project)
|
win.analytics = analytics.load(win.project)
|
||||||
|
win.multiuser["last_request"] = ""
|
||||||
|
|
||||||
if not task["editing"]:
|
if not task["editing"]:
|
||||||
layer.set_font_size(20)
|
layer.set_font_size(20)
|
||||||
layer.move_to(
|
layer.move_to(
|
||||||
|
@ -920,6 +924,7 @@ def draw(outlayer, win, path, back="story_editor"):
|
||||||
|
|
||||||
# Saving
|
# Saving
|
||||||
save(path, win.checklists[path])
|
save(path, win.checklists[path])
|
||||||
|
win.multiuser["last_request"] = ""
|
||||||
|
|
||||||
def button():
|
def button():
|
||||||
do()
|
do()
|
||||||
|
@ -1057,7 +1062,7 @@ def draw(outlayer, win, path, back="story_editor"):
|
||||||
win.checklists = {}
|
win.checklists = {}
|
||||||
win.assets = {}
|
win.assets = {}
|
||||||
win.analytics = analytics.load(win.project)
|
win.analytics = analytics.load(win.project)
|
||||||
|
win.multiuser["last_request"] = ""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -159,6 +159,9 @@ def record(win, filename, task, checklist=[] ):
|
||||||
analytics.save(win.project, win.analytics)
|
analytics.save(win.project, win.analytics)
|
||||||
win.analytics = analytics.load(win.project)
|
win.analytics = analytics.load(win.project)
|
||||||
|
|
||||||
|
# Multiuser sycning
|
||||||
|
win.multiuser["request"] = "analytics"
|
||||||
|
|
||||||
def draw(outlayer, win):
|
def draw(outlayer, win):
|
||||||
|
|
||||||
x = 10
|
x = 10
|
||||||
|
|
|
@ -459,6 +459,9 @@ def draw(outlayer, win):
|
||||||
analytics.save(win.project, win.analytics)
|
analytics.save(win.project, win.analytics)
|
||||||
win.analytics = analytics.load(win.project)
|
win.analytics = analytics.load(win.project)
|
||||||
win.checklists = {}
|
win.checklists = {}
|
||||||
|
|
||||||
|
# Multiuser sycning
|
||||||
|
win.multiuser["request"] = "analytics"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -630,6 +633,8 @@ def draw(outlayer, win):
|
||||||
thing[0][-1] = win.text["schedule_username_setting"]["text"]
|
thing[0][-1] = win.text["schedule_username_setting"]["text"]
|
||||||
analytics.save(win.project, win.analytics)
|
analytics.save(win.project, win.analytics)
|
||||||
|
|
||||||
|
# Multiuser sycning
|
||||||
|
win.multiuser["request"] = "analytics"
|
||||||
|
|
||||||
UI_elements.roundrect(layer, win,
|
UI_elements.roundrect(layer, win,
|
||||||
width-40,
|
width-40,
|
||||||
|
@ -698,6 +703,9 @@ def draw(outlayer, win):
|
||||||
analytics.save(win.project, win.analytics)
|
analytics.save(win.project, win.analytics)
|
||||||
win.analytics = analytics.load(win.project)
|
win.analytics = analytics.load(win.project)
|
||||||
|
|
||||||
|
# Multiuser sycning
|
||||||
|
win.multiuser["request"] = "analytics"
|
||||||
|
|
||||||
UI_elements.roundrect(layer, win,
|
UI_elements.roundrect(layer, win,
|
||||||
(width-80)/2+20,
|
(width-80)/2+20,
|
||||||
win.scroll["schedule"] + current_Y+5,
|
win.scroll["schedule"] + current_Y+5,
|
||||||
|
@ -728,6 +736,8 @@ def draw(outlayer, win):
|
||||||
analytics.save(win.project, win.analytics)
|
analytics.save(win.project, win.analytics)
|
||||||
win.analytics = analytics.load(win.project)
|
win.analytics = analytics.load(win.project)
|
||||||
|
|
||||||
|
# Multiuser sycning
|
||||||
|
win.multiuser["request"] = "analytics"
|
||||||
|
|
||||||
UI_elements.roundrect(layer, win,
|
UI_elements.roundrect(layer, win,
|
||||||
width-40,
|
width-40,
|
||||||
|
|
|
@ -825,6 +825,10 @@ def layer(win):
|
||||||
analytics.save(win.project, win.analytics)
|
analytics.save(win.project, win.analytics)
|
||||||
win.analytics = analytics.load(win.project)
|
win.analytics = analytics.load(win.project)
|
||||||
win.checklists = {}
|
win.checklists = {}
|
||||||
|
|
||||||
|
# Multiuser sycning
|
||||||
|
win.multiuser["request"] = "analytics"
|
||||||
|
|
||||||
#print("test 3")
|
#print("test 3")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -231,8 +231,6 @@ def layer(win):
|
||||||
20)
|
20)
|
||||||
layer.paint()
|
layer.paint()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Name of the asset
|
# Name of the asset
|
||||||
UI_elements.image(layer, win,
|
UI_elements.image(layer, win,
|
||||||
"settings/themes/"+win.settings["Theme"]+"/icons/"+acur+".png",
|
"settings/themes/"+win.settings["Theme"]+"/icons/"+acur+".png",
|
||||||
|
@ -308,6 +306,10 @@ def layer(win):
|
||||||
|
|
||||||
# In case the user made the folder manually.
|
# In case the user made the folder manually.
|
||||||
try:
|
try:
|
||||||
|
os.mkdir(win.project+"/dev/"+win.cur)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
os.mkdir(win.project+"/dev/"+win.cur+"/renders")
|
os.mkdir(win.project+"/dev/"+win.cur+"/renders")
|
||||||
os.mkdir(win.project+"/dev/"+win.cur+"/reference")
|
os.mkdir(win.project+"/dev/"+win.cur+"/reference")
|
||||||
os.mkdir(win.project+"/dev/"+win.cur+"/tex")
|
os.mkdir(win.project+"/dev/"+win.cur+"/tex")
|
||||||
|
@ -807,6 +809,9 @@ def layer(win):
|
||||||
if win.current["asset_left_panel"] == "history":
|
if win.current["asset_left_panel"] == "history":
|
||||||
history.draw(layer, win)
|
history.draw(layer, win)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### SCENES ###
|
### SCENES ###
|
||||||
|
|
||||||
# Documentation entry
|
# Documentation entry
|
||||||
|
|
|
@ -10,7 +10,7 @@ gi.require_version('Gtk', '3.0')
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
import cairo
|
import cairo
|
||||||
import datetime
|
import datetime
|
||||||
|
import threading
|
||||||
|
|
||||||
# Own modules
|
# Own modules
|
||||||
from settings import settings
|
from settings import settings
|
||||||
|
@ -26,6 +26,7 @@ from studio import studio_settingsLayer
|
||||||
from studio import studio_assetLayer
|
from studio import studio_assetLayer
|
||||||
from studio import studio_analyticsLayer
|
from studio import studio_analyticsLayer
|
||||||
from studio import studio_scriptLayer
|
from studio import studio_scriptLayer
|
||||||
|
from studio import studio_multiuserLayer
|
||||||
|
|
||||||
# UI modules
|
# UI modules
|
||||||
from UI import UI_testing
|
from UI import UI_testing
|
||||||
|
@ -34,6 +35,8 @@ from UI import UI_elements
|
||||||
|
|
||||||
# Network
|
# Network
|
||||||
from network import network_renders
|
from network import network_renders
|
||||||
|
from network import network_multiuser
|
||||||
|
from network import multiuser_terminal
|
||||||
|
|
||||||
def previous(win):
|
def previous(win):
|
||||||
win.previous = {}
|
win.previous = {}
|
||||||
|
@ -50,7 +53,11 @@ def run(project, win):
|
||||||
# show the first ever version. So there will be a better way to see version.
|
# show the first ever version. So there will be a better way to see version.
|
||||||
# I think let's do that like in Blender. Drawn with in the window somewhere.
|
# I think let's do that like in Blender. Drawn with in the window somewhere.
|
||||||
|
|
||||||
win.destroy()
|
try:
|
||||||
|
win.destroy()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
# Setting up the window
|
# Setting up the window
|
||||||
win = Gtk.Window()
|
win = Gtk.Window()
|
||||||
win.maximize()
|
win.maximize()
|
||||||
|
@ -100,6 +107,20 @@ def run(project, win):
|
||||||
win.renders = {} # List of current active renders.
|
win.renders = {} # List of current active renders.
|
||||||
win.undo_history = []
|
win.undo_history = []
|
||||||
win.undo_index = 0
|
win.undo_index = 0
|
||||||
|
win.multiuser = {
|
||||||
|
"server":False, # Whether we are connected to the server. And the server ID
|
||||||
|
"userid":"", # The id of current user in the server
|
||||||
|
"last_request": "", # The last request send to the server. ( for stopping bloat )
|
||||||
|
"curs":{}, # The information about various items on other users machines.
|
||||||
|
"request":[["story"]], # Requests done in UI space
|
||||||
|
"users":{}, # List of users information Names, IPs etc.
|
||||||
|
"messages":[], # List of messages
|
||||||
|
"unread":0 , # Amount of unread messages
|
||||||
|
"terminal":[], # The outputs from the server
|
||||||
|
"asset_list_check":False, # Whether the initial update happened when connecting to the server
|
||||||
|
"story_check":False, # Whether the first story check was done.
|
||||||
|
"analytics_check":False
|
||||||
|
}
|
||||||
|
|
||||||
if pm_project.is_legacy(project):
|
if pm_project.is_legacy(project):
|
||||||
win.story = story.get_legacy(project)
|
win.story = story.get_legacy(project)
|
||||||
|
@ -158,12 +179,21 @@ def run(project, win):
|
||||||
|
|
||||||
# Setting the drawable
|
# Setting the drawable
|
||||||
pmdraw = Gtk.DrawingArea()
|
pmdraw = Gtk.DrawingArea()
|
||||||
pmdraw.set_size_request(1280, 720)
|
pmdraw.set_size_request(1040, 720)
|
||||||
scroll.set_size_request(1280, 720) # This step is because GTK developers are
|
scroll.set_size_request(1040, 720) # This step is because GTK developers are
|
||||||
win.add(scroll) # well. A good, nice, people who knows
|
win.add(scroll) # well. A good, nice, people who knows
|
||||||
scroll.add_with_viewport(pmdraw) # what they are doing. Really.
|
scroll.add_with_viewport(pmdraw) # what they are doing. Really.
|
||||||
pmdraw.connect("draw", pmdrawing, win)
|
pmdraw.connect("draw", pmdrawing, win)
|
||||||
|
|
||||||
|
# Before we run the UI. Let's run the mutliuser client.
|
||||||
|
multiuser = threading.Thread(target=network_multiuser.client, args=(win,))
|
||||||
|
multiuser.setDaemon(True)
|
||||||
|
multiuser.start()
|
||||||
|
|
||||||
|
# And let's start also the multiuser_terminal
|
||||||
|
multiuser_term = threading.Thread(target=multiuser_terminal.listen, args=(win,))
|
||||||
|
multiuser_term.setDaemon(True)
|
||||||
|
multiuser_term.start()
|
||||||
|
|
||||||
#run
|
#run
|
||||||
win.show_all()
|
win.show_all()
|
||||||
|
@ -273,6 +303,9 @@ def pmdrawing(pmdrawing, main_layer, win):
|
||||||
elif win.url == "script":
|
elif win.url == "script":
|
||||||
Layers.append([studio_scriptLayer.layer(win), "script"])
|
Layers.append([studio_scriptLayer.layer(win), "script"])
|
||||||
|
|
||||||
|
elif win.url == "multiuser":
|
||||||
|
Layers.append([studio_multiuserLayer.layer(win), "multiuser"])
|
||||||
|
|
||||||
# Call layers. See studio/studio_dialogs.py for explanation. It's wild.
|
# Call layers. See studio/studio_dialogs.py for explanation. It's wild.
|
||||||
|
|
||||||
win.calllayer = False
|
win.calllayer = False
|
||||||
|
@ -339,6 +372,12 @@ def pmdrawing(pmdrawing, main_layer, win):
|
||||||
# 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():
|
||||||
win.current["keys"] = []
|
win.current["keys"] = []
|
||||||
|
|
||||||
|
elif "is_active" in win.previous and not win.previous["is_active"]:
|
||||||
|
win.multiuser["last_request"] = ""
|
||||||
|
UI_elements.reload_images(win)
|
||||||
|
|
||||||
|
win.current["is_active"] = win.is_active()
|
||||||
|
|
||||||
# Saving data about this frame for the next one. A bit hard to get WTF am I
|
# Saving data about this frame for the next one. A bit hard to get WTF am I
|
||||||
# doing here. Basically trying to avoid current and previous data to be links
|
# doing here. Basically trying to avoid current and previous data to be links
|
||||||
|
@ -402,8 +441,8 @@ def key_release(widget, event, win):
|
||||||
|
|
||||||
# I also want to clean the key letter. Because other wise in the
|
# I also want to clean the key letter. Because other wise in the
|
||||||
# script writer I had weird key presses all the time.
|
# script writer I had weird key presses all the time.
|
||||||
|
if not win.current["keys"]:
|
||||||
win.current["key_letter"] = ""
|
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()
|
||||||
|
|
510
studio/studio_multiuserLayer.py
Normal file
510
studio/studio_multiuserLayer.py
Normal file
|
@ -0,0 +1,510 @@
|
||||||
|
# THIS FILE IS A PART OF VCStudio
|
||||||
|
# PYTHON 3
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
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 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 analytics
|
||||||
|
from studio import history
|
||||||
|
|
||||||
|
# network
|
||||||
|
from network import multiuser_terminal
|
||||||
|
|
||||||
|
def layer(win):
|
||||||
|
|
||||||
|
# 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()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
# This is our multiuser UI. From here the user will start and stop the server
|
||||||
|
# for the multiuser. See what that server has to say. And write text messages
|
||||||
|
# to all the other users. Like a little messaging app, so they will not use
|
||||||
|
# closed source apps for this. I know a lot of companies that ustilize
|
||||||
|
# whatsapp for this. This is not cool. And I can make a little app here.
|
||||||
|
|
||||||
|
# The way it's going to look it the folosing.
|
||||||
|
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
# START / STOP BUTTON # #
|
||||||
|
###################################################### BOB: Hello World #
|
||||||
|
# # #
|
||||||
|
# server started # Steve: What's Up #
|
||||||
|
# BOB connected # #
|
||||||
|
# Steve connected # John: Hey guys #
|
||||||
|
# John connected # who can make the #
|
||||||
|
# Steve updated Moria # rig for Moria? #
|
||||||
|
# John reqested Moria # #
|
||||||
|
# Steve sent Moria to John # Steve: I can. #
|
||||||
|
# # #
|
||||||
|
#################################################### # John: Thanks. #
|
||||||
|
# 3 users connected: # #
|
||||||
|
# BOB # #
|
||||||
|
# John #######################
|
||||||
|
# Steve # # #
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
# I know that it's a bit unfair to give so much space to a terminal like
|
||||||
|
# output window. But this is kind of the most important thing in the
|
||||||
|
# entire Multiuser. The server. Actually the server will run only on one
|
||||||
|
# computer. But all users will feel like they are controlling the server.
|
||||||
|
|
||||||
|
# I don't like when one user thinks that he is more important then the other
|
||||||
|
# . Because in the film production. Usually the director listens even to
|
||||||
|
# the guy who makes the tea. In the case of this program I want everybody
|
||||||
|
# to feel exactly the same amount of power.
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
win.multiuser["unread"] = 0
|
||||||
|
|
||||||
|
# SERVER PEACE FRAME
|
||||||
|
UI_color.set(layer, win, "node_background")
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
80,
|
||||||
|
80,
|
||||||
|
win.current["w"]/3*2-160,
|
||||||
|
win.current["h"]/2-100,
|
||||||
|
10)
|
||||||
|
|
||||||
|
# USERS PEACE FRAME
|
||||||
|
UI_color.set(layer, win, "node_background")
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
80,
|
||||||
|
win.current["h"]/2,
|
||||||
|
win.current["w"]/3*2-160,
|
||||||
|
win.current["h"]/2-80,
|
||||||
|
10)
|
||||||
|
|
||||||
|
# THE SIDE PEACE FRAME
|
||||||
|
UI_color.set(layer, win, "node_background")
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
win.current["w"]/3*2-60,
|
||||||
|
80,
|
||||||
|
win.current["w"]/3-20,
|
||||||
|
win.current["h"]-160,
|
||||||
|
10)
|
||||||
|
|
||||||
|
####### SERVER PART #######
|
||||||
|
|
||||||
|
# On the top panel first button will be either make a server. Or if server exists,
|
||||||
|
# close the server. This will require a little dialog similar to when deleting
|
||||||
|
# scenes in the story editor.
|
||||||
|
|
||||||
|
# I'm going to hack my way into checking the server. Basically it autoconnects to
|
||||||
|
# it if one is up. So..
|
||||||
|
|
||||||
|
if win.multiuser["server"]:
|
||||||
|
|
||||||
|
def do():
|
||||||
|
|
||||||
|
# Simple UDP message
|
||||||
|
multiuser_terminal.message("VCStudio ABORT MULTIUSER")
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
90,
|
||||||
|
90,
|
||||||
|
40,
|
||||||
|
40,
|
||||||
|
10,
|
||||||
|
button=do,
|
||||||
|
icon="server_close")
|
||||||
|
else:
|
||||||
|
def do():
|
||||||
|
|
||||||
|
# Simple Popen
|
||||||
|
Popen(["python3", "network/multiuser_server.py", win.analytics["name"]])
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
90,
|
||||||
|
90,
|
||||||
|
40,
|
||||||
|
40,
|
||||||
|
10,
|
||||||
|
button=do,
|
||||||
|
icon="server_new")
|
||||||
|
|
||||||
|
# Server outputs part. I'm creating a layer for it just because it needs
|
||||||
|
# a clipping.
|
||||||
|
|
||||||
|
x = 90
|
||||||
|
y = 140
|
||||||
|
width = win.current["w"]/3*2-160-20
|
||||||
|
height = win.current["h"]/2-170
|
||||||
|
|
||||||
|
|
||||||
|
# Making the layer
|
||||||
|
surface2 = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
|
||||||
|
node = cairo.Context(surface2)
|
||||||
|
node.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
|
||||||
|
|
||||||
|
# Clip
|
||||||
|
UI_elements.roundrect(node, win,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
10,
|
||||||
|
fill=False)
|
||||||
|
node.clip()
|
||||||
|
|
||||||
|
# Background tester
|
||||||
|
#UI_color.set(node, win, "dark_overdrop")
|
||||||
|
#node.rectangle(0,0,width, height)
|
||||||
|
#node.fill()
|
||||||
|
|
||||||
|
# Here I want to have the output of the server in a raw fasion.
|
||||||
|
if "multiuser_terminal" not in win.scroll:
|
||||||
|
win.scroll["multiuser_terminal"] = 0
|
||||||
|
|
||||||
|
current_Y = 10
|
||||||
|
|
||||||
|
for message in win.multiuser["terminal"]:
|
||||||
|
|
||||||
|
# We are going to draw a little server icon.
|
||||||
|
UI_elements.image(node, win,
|
||||||
|
"settings/themes/"+win.settings["Theme"]+"/icons/server.png",
|
||||||
|
10,
|
||||||
|
current_Y+win.scroll["multiuser_terminal"],
|
||||||
|
40,
|
||||||
|
40)
|
||||||
|
|
||||||
|
# And we want to have the text of the message
|
||||||
|
|
||||||
|
UI_color.set(node, win, "text_normal")
|
||||||
|
node.set_font_size(15)
|
||||||
|
node.move_to( 60, current_Y+win.scroll["multiuser_terminal"]+27)
|
||||||
|
node.show_text(message)
|
||||||
|
|
||||||
|
current_Y = current_Y + 50
|
||||||
|
|
||||||
|
# Outputting the layer
|
||||||
|
layer.set_source_surface(surface2, x, y)
|
||||||
|
layer.paint()
|
||||||
|
|
||||||
|
UI_elements.scroll_area(layer, win, "multiuser_terminal",
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
current_Y,
|
||||||
|
bar=True,
|
||||||
|
mmb=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
############ USERS PART ##############
|
||||||
|
|
||||||
|
# Here in this part I want to put a complite list of currently connected users.
|
||||||
|
# I have few ideas of what functionality could be added to here. But at this
|
||||||
|
# point I'm just trying to make the window somewhat busy looking.
|
||||||
|
|
||||||
|
# So we need to make layer here. Since I want to clip it. But be able to draw outisde
|
||||||
|
# the clipping area later.
|
||||||
|
|
||||||
|
x = 90
|
||||||
|
y = win.current["h"]/2+10
|
||||||
|
width = win.current["w"]/3*2-160-20
|
||||||
|
height = win.current["h"]/2-80-60
|
||||||
|
|
||||||
|
|
||||||
|
# Making the layer
|
||||||
|
surface2 = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
|
||||||
|
node = cairo.Context(surface2)
|
||||||
|
node.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
|
||||||
|
|
||||||
|
# Clip
|
||||||
|
UI_elements.roundrect(node, win,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
10,
|
||||||
|
fill=False)
|
||||||
|
node.clip()
|
||||||
|
|
||||||
|
# Background tester
|
||||||
|
#UI_color.set(node, win, "dark_overdrop")
|
||||||
|
#node.rectangle(0,0,width, height)
|
||||||
|
#node.fill()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if "multiuser_users" not in win.scroll:
|
||||||
|
win.scroll["multiuser_users"] = 0
|
||||||
|
|
||||||
|
current_Y = 10
|
||||||
|
|
||||||
|
for ip in list(win.multiuser["users"].keys()):
|
||||||
|
try:
|
||||||
|
user = win.multiuser["users"][ip]
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
username = user["username"]
|
||||||
|
|
||||||
|
# For each user I want to show the name, then IP:PORT
|
||||||
|
|
||||||
|
# If it's us on the list I want to draw a little rectangle arround
|
||||||
|
# this particular user
|
||||||
|
|
||||||
|
if ip == win.multiuser["userid"]:
|
||||||
|
UI_color.set(node, win, "node_blendfile")
|
||||||
|
UI_elements.roundrect(node, win,
|
||||||
|
0,
|
||||||
|
current_Y+win.scroll["multiuser_users"]-5,
|
||||||
|
width,
|
||||||
|
45,
|
||||||
|
10)
|
||||||
|
|
||||||
|
|
||||||
|
# User Icon
|
||||||
|
UI_elements.image(node, win,
|
||||||
|
"settings/themes/"+win.settings["Theme"]+"/icons/user.png",
|
||||||
|
10,
|
||||||
|
current_Y+win.scroll["multiuser_users"],
|
||||||
|
40,
|
||||||
|
40)
|
||||||
|
|
||||||
|
# Text
|
||||||
|
|
||||||
|
UI_color.set(node, win, "text_normal")
|
||||||
|
node.set_font_size(20)
|
||||||
|
node.move_to( 60, current_Y+win.scroll["multiuser_users"]+25)
|
||||||
|
node.show_text(username+" | "+ip)
|
||||||
|
|
||||||
|
current_Y = current_Y + 50
|
||||||
|
|
||||||
|
|
||||||
|
# Outputting the layer
|
||||||
|
layer.set_source_surface(surface2, x, y)
|
||||||
|
layer.paint()
|
||||||
|
|
||||||
|
UI_elements.scroll_area(layer, win, "multiuser_users",
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
current_Y,
|
||||||
|
bar=True,
|
||||||
|
mmb=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# At the bottom I want to have a little multiuser icon with the count of users.
|
||||||
|
# then a user icon and a name selection.
|
||||||
|
|
||||||
|
UI_elements.image(layer, win,
|
||||||
|
"settings/themes/"+win.settings["Theme"]+"/icons/multiuser.png",
|
||||||
|
x,
|
||||||
|
y+height+5,
|
||||||
|
40,
|
||||||
|
40)
|
||||||
|
|
||||||
|
# The little count thing at the corner
|
||||||
|
if win.multiuser["users"]:
|
||||||
|
count = str(len(win.multiuser["users"]))
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "node_background")
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x+25,
|
||||||
|
y+height,
|
||||||
|
len(count)*12+6,
|
||||||
|
25,
|
||||||
|
5)
|
||||||
|
layer.fill()
|
||||||
|
UI_color.set(layer, win, "text_normal")
|
||||||
|
layer.set_font_size(20)
|
||||||
|
layer.move_to(x+28,y+height+20)
|
||||||
|
layer.show_text(count)
|
||||||
|
|
||||||
|
|
||||||
|
# CANCEl
|
||||||
|
|
||||||
|
def do():
|
||||||
|
win.url = "story_editor"
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
win.current["w"]/3*2-120,
|
||||||
|
win.current["h"]-120,
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
########## THE MESSANGER APP ON THE RIGHT ##########
|
||||||
|
|
||||||
|
# I'm creating a layer for it just because it needs a clipping.
|
||||||
|
|
||||||
|
x = win.current["w"]/3*2-50
|
||||||
|
y = 90
|
||||||
|
width = win.current["w"]/3-40
|
||||||
|
height = win.current["h"]-220
|
||||||
|
|
||||||
|
|
||||||
|
# Making the layer
|
||||||
|
surface2 = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
|
||||||
|
node = cairo.Context(surface2)
|
||||||
|
node.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
|
||||||
|
|
||||||
|
# Clip
|
||||||
|
UI_elements.roundrect(node, win,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
10,
|
||||||
|
fill=False)
|
||||||
|
node.clip()
|
||||||
|
|
||||||
|
# Background tester
|
||||||
|
#UI_color.set(node, win, "dark_overdrop")
|
||||||
|
#node.rectangle(0,0,width, height)
|
||||||
|
#node.fill()
|
||||||
|
|
||||||
|
|
||||||
|
# So here I want to present all the messages by all the users.
|
||||||
|
if "multiuser_messages" not in win.scroll:
|
||||||
|
win.scroll["multiuser_messages"] = 0
|
||||||
|
|
||||||
|
current_Y = 10
|
||||||
|
|
||||||
|
for message in win.multiuser["messages"]:
|
||||||
|
|
||||||
|
# let's get the name of the user
|
||||||
|
username = message[0]
|
||||||
|
|
||||||
|
if username == "Multiuser Server":
|
||||||
|
continue
|
||||||
|
|
||||||
|
# User Icon
|
||||||
|
UI_elements.image(node, win,
|
||||||
|
"settings/themes/"+win.settings["Theme"]+"/icons/user.png",
|
||||||
|
10,
|
||||||
|
current_Y+win.scroll["multiuser_messages"],
|
||||||
|
40,
|
||||||
|
40)
|
||||||
|
|
||||||
|
UI_color.set(node, win, "text_normal")
|
||||||
|
node.set_font_size(20)
|
||||||
|
node.move_to(60,
|
||||||
|
current_Y+win.scroll["multiuser_messages"]+25)
|
||||||
|
node.show_text(username)
|
||||||
|
|
||||||
|
current_Y = current_Y + 50
|
||||||
|
|
||||||
|
# Now the message it self going to need to have line breaks. For this
|
||||||
|
# we are going to make similar rendering to the one in the script
|
||||||
|
# writer. But simpler.
|
||||||
|
|
||||||
|
tileX = 10
|
||||||
|
|
||||||
|
for word in message[1].split(" "):
|
||||||
|
|
||||||
|
|
||||||
|
if tileX + len(word)*12+12 > width-10:
|
||||||
|
tileX = 10
|
||||||
|
current_Y = current_Y + 30
|
||||||
|
|
||||||
|
UI_color.set(node, win, "text_normal")
|
||||||
|
node.set_font_size(20)
|
||||||
|
node.move_to(tileX,
|
||||||
|
current_Y+win.scroll["multiuser_messages"]+25)
|
||||||
|
node.show_text(word)
|
||||||
|
|
||||||
|
tileX = tileX + len(word)*12+12
|
||||||
|
|
||||||
|
current_Y = current_Y + 50
|
||||||
|
|
||||||
|
# Outputting the layer
|
||||||
|
layer.set_source_surface(surface2, x, y)
|
||||||
|
layer.paint()
|
||||||
|
|
||||||
|
UI_elements.scroll_area(layer, win, "multiuser_messages",
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
current_Y,
|
||||||
|
bar=True,
|
||||||
|
mmb=True)
|
||||||
|
|
||||||
|
# So here after the messages I want to make a little input for the new
|
||||||
|
# message and a send button
|
||||||
|
|
||||||
|
UI_elements.text(layer, win, "multiuser_message",
|
||||||
|
x,
|
||||||
|
y+height+5,
|
||||||
|
width-50,
|
||||||
|
40)
|
||||||
|
|
||||||
|
# Send button
|
||||||
|
|
||||||
|
def do():
|
||||||
|
|
||||||
|
if win.text["multiuser_message"]["text"]:
|
||||||
|
win.multiuser["request"] = ["message", win.text["multiuser_message"]["text"]]
|
||||||
|
win.text["multiuser_message"]["text"] = ""
|
||||||
|
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
x+width-40,
|
||||||
|
y+height+5,
|
||||||
|
40,
|
||||||
|
40,
|
||||||
|
10,
|
||||||
|
button=do,
|
||||||
|
icon="send")
|
||||||
|
|
||||||
|
# ENTER
|
||||||
|
if 65293 in win.current["keys"]:
|
||||||
|
do()
|
||||||
|
win.current["keys"] = []
|
||||||
|
|
||||||
|
return surface
|
|
@ -1060,6 +1060,8 @@ def link_node(outlayer, win, x, y, width=150, height=150, name="", num=0, linkty
|
||||||
UI_elements.tooltip(win, name)
|
UI_elements.tooltip(win, name)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
|
|
||||||
if os.path.exists(win.project+"/"+name):
|
if os.path.exists(win.project+"/"+name):
|
||||||
UI_elements.image(layer, win,
|
UI_elements.image(layer, win,
|
||||||
win.project+"/"+name,
|
win.project+"/"+name,
|
||||||
|
@ -1460,4 +1462,70 @@ def marker(outlayer, win, name ,x, y ):
|
||||||
fill=False)
|
fill=False)
|
||||||
outlayer.stroke()
|
outlayer.stroke()
|
||||||
|
|
||||||
|
|
||||||
|
def user(outlayer, win, name ,x, y ):
|
||||||
|
|
||||||
|
# This function will draw users from multiuser to the screen.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if int(x) in range(int(60), int(win.current["w"]-100))\
|
||||||
|
and int(y) in range(int(60), int(win.current["h"]-80)):
|
||||||
|
width = 200
|
||||||
|
height = 40
|
||||||
|
|
||||||
|
inscreen = True
|
||||||
|
else:
|
||||||
|
|
||||||
|
x = min(max(x, 60), win.current["w"]-100)
|
||||||
|
y = min(max(y, 60), win.current["h"]-80)
|
||||||
|
|
||||||
|
width = 40
|
||||||
|
height = 40
|
||||||
|
|
||||||
|
inscreen = False
|
||||||
|
|
||||||
|
# Making the layer
|
||||||
|
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
|
||||||
|
layer = cairo.Context(surface)
|
||||||
|
|
||||||
|
# Clip
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
10,
|
||||||
|
fill=False)
|
||||||
|
layer.clip()
|
||||||
|
|
||||||
|
# Background
|
||||||
|
UI_color.set(layer, win, "dark_overdrop")
|
||||||
|
layer.rectangle(0,0,width, height)
|
||||||
|
layer.fill()
|
||||||
|
|
||||||
|
# Pin Icon
|
||||||
|
UI_elements.image(layer, win,
|
||||||
|
"settings/themes/"+win.settings["Theme"]+"/icons/user.png",
|
||||||
|
0, 0, 40, 40)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Outputting the layer
|
||||||
|
outlayer.set_source_surface(surface, x, y)
|
||||||
|
outlayer.paint()
|
||||||
|
|
||||||
|
if inscreen:
|
||||||
|
|
||||||
|
|
||||||
|
# Text editor for the marker's name.
|
||||||
|
|
||||||
|
UI_elements.text(outlayer, win, name+"_user",
|
||||||
|
x+40,
|
||||||
|
y,
|
||||||
|
width-40,
|
||||||
|
40,
|
||||||
|
set_text=name,
|
||||||
|
editable=False)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1379,6 +1379,8 @@ def layer(win):
|
||||||
|
|
||||||
if win.current["key_letter"] not in nonhistory and ORD not in [26, 25]:
|
if win.current["key_letter"] not in nonhistory and ORD not in [26, 25]:
|
||||||
story.undo_record(win)
|
story.undo_record(win)
|
||||||
|
# Multiuser sycning
|
||||||
|
win.multiuser["request"] = "story"
|
||||||
|
|
||||||
# Now let's retrive out data.
|
# Now let's retrive out data.
|
||||||
|
|
||||||
|
|
|
@ -555,7 +555,7 @@ def layer(win):
|
||||||
|
|
||||||
# Multiuser
|
# Multiuser
|
||||||
def do():
|
def do():
|
||||||
win.url = "multiuser_layer"
|
win.url = "multiuser"
|
||||||
|
|
||||||
UI_elements.roundrect(layer, win,
|
UI_elements.roundrect(layer, win,
|
||||||
5,
|
5,
|
||||||
|
@ -568,6 +568,22 @@ def layer(win):
|
||||||
talk.text("multiuser_tooltip"),
|
talk.text("multiuser_tooltip"),
|
||||||
url="story_editor")
|
url="story_editor")
|
||||||
|
|
||||||
|
if win.multiuser["unread"]:
|
||||||
|
count = str(win.multiuser["unread"])
|
||||||
|
|
||||||
|
UI_color.set(layer, win, "node_background")
|
||||||
|
UI_elements.roundrect(layer, win,
|
||||||
|
30,
|
||||||
|
win.current["h"]-100,
|
||||||
|
len(count)*12+6,
|
||||||
|
25,
|
||||||
|
5)
|
||||||
|
layer.fill()
|
||||||
|
UI_color.set(layer, win, "text_normal")
|
||||||
|
layer.set_font_size(20)
|
||||||
|
layer.move_to(33,win.current["h"]-83)
|
||||||
|
layer.show_text(count)
|
||||||
|
|
||||||
# Settings
|
# Settings
|
||||||
def do():
|
def do():
|
||||||
win.url = "settings_layer"
|
win.url = "settings_layer"
|
||||||
|
@ -909,6 +925,14 @@ def layer(win):
|
||||||
lx = link[2][0] + cx
|
lx = link[2][0] + cx
|
||||||
ly = link[2][1] + cy
|
ly = link[2][1] + cy
|
||||||
|
|
||||||
|
# For the one inside the project. They should be always relative
|
||||||
|
# so even if the project is in a complitely different location
|
||||||
|
# on another machine. Where we have our Multiuser data. It should
|
||||||
|
# be able to load these.
|
||||||
|
|
||||||
|
if win.project in link[1]:
|
||||||
|
link[1] = link[1].replace(win.project, "")
|
||||||
|
|
||||||
|
|
||||||
studio_nodes.link_node(layer, win, lx, ly, name=linkname, num=num, linktype=linktype )
|
studio_nodes.link_node(layer, win, lx, ly, name=linkname, num=num, linktype=linktype )
|
||||||
|
|
||||||
|
@ -948,6 +972,19 @@ def layer(win):
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# MARKERS
|
||||||
|
try:
|
||||||
|
for user in win.multiuser["users"]:
|
||||||
|
if user != win.multiuser["userid"]:
|
||||||
|
|
||||||
|
mx = 0-win.multiuser["users"][user]["camera"][0] +cx + win.current["w"]/2
|
||||||
|
my = 0-win.multiuser["users"][user]["camera"][1] +cy + win.current["h"]/2
|
||||||
|
|
||||||
|
studio_nodes.user(layer, win, win.multiuser["users"][user]["username"], mx, my)
|
||||||
|
except Exception as e:
|
||||||
|
print(e, "USER RENDERING")
|
||||||
|
|
||||||
########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
|
########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
|
||||||
fif = datetime.datetime.now()
|
fif = datetime.datetime.now()
|
||||||
mil = fif - stf
|
mil = fif - stf
|
||||||
|
@ -1119,8 +1156,7 @@ def layer(win):
|
||||||
|
|
||||||
|
|
||||||
if savenow:
|
if savenow:
|
||||||
|
|
||||||
|
|
||||||
# Now let's run the history record.
|
# Now let's run the history record.
|
||||||
story.undo_record(win)
|
story.undo_record(win)
|
||||||
|
|
||||||
|
@ -1129,7 +1165,10 @@ def layer(win):
|
||||||
|
|
||||||
# Need to reload the story to reload the fractions of the scenes.
|
# Need to reload the story to reload the fractions of the scenes.
|
||||||
win.story = story.load(win.project)
|
win.story = story.load(win.project)
|
||||||
|
|
||||||
|
# Multiuser sycning
|
||||||
|
win.multiuser["request"] = "story"
|
||||||
|
|
||||||
########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
|
########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
|
||||||
fif = datetime.datetime.now()
|
fif = datetime.datetime.now()
|
||||||
mil = fif - stf
|
mil = fif - stf
|
||||||
|
|
Loading…
Add table
Reference in a new issue