diff --git a/project_manager/helpLayer.py b/project_manager/helpLayer.py new file mode 100644 index 0000000..1becba2 --- /dev/null +++ b/project_manager/helpLayer.py @@ -0,0 +1 @@ +404: Not Found \ No newline at end of file diff --git a/project_manager/pm_console.py b/project_manager/pm_console.py new file mode 100644 index 0000000..9ca3ab6 --- /dev/null +++ b/project_manager/pm_console.py @@ -0,0 +1,168 @@ +# THIS FILE IS A PART OF VCStudio +# PYTHON 3 + +# This a console project manager. + +import os +w, h = os.get_terminal_size() + +from settings import settings +from settings import talk +from project_manager import pm_project + + +# COMPLITTER +try: + import readline +except: + pass + +commands1 = [ +"help",# - help dialogue. +"set_language",# - changes language settings. +"projects_list",# - see projects list. +"set_folder",# - set a folder where a new project is created. +"new_project",# - creates a new project. +"project",# - launch a given project. +"scan",# - scans systems for VCStudio or Blender-Organizer projects. +"convert",# - convert Blender-Organizer project to VCStudio project. (Please have a back up when using this one.) +"exit"# +] +commands = commands1.copy() + +def completer(text, state): + options = [i for i in commands if i.startswith(text)] + if state < len(options): + return options[state] + else: + return None + +try: + readline.parse_and_bind("tab: complete") + readline.set_completer(completer) +except: + print("NO TABS, SORRY!") + +def cls(): + #cleaning the terminal + os.system("clear") + +def run(): + + cls() + + + + print("\033[1;33m\n VCStudio - Console \n") + + print("\033[1;32m"+talk.text("PMConsoleExplanation")+"\n") + + + while True: + + # making sure Tab is doing autocomlete to the right functions + global commands + commands = commands1.copy() + + command = input("\033[1;35m : \033[1;m") + + ############## + + if command == "exit": + cls() + exit() + + ############## + + elif command == "help": + + print("\033[1;32m"+talk.text("pm_console_help")+"\n") + + ############## + + elif command == "set_language": + # Getting list of available languages + + commands = [] + for lang in settings.list_languages(): + print("\033[1;35m "+lang) + commands.append(lang) + + + # special input for languages + nlang = input("\033[1;33m : ") + + if nlang in settings.list_languages(): + settings.write("Language",nlang) + print("\033[1;32m"+talk.text("checked")) + + else: + print("\033[1;31m"+talk.text("failed")) + + ############## + + + elif command == "set_folder": + if settings.read("New-Project-Folder"): + print("\033[1;35m"+talk.text("Current")+\ + " : "+settings.read("New-Project-Folder")) + + nfol = input("\033[1;33m : ") + if nfol: + if os.path.exists(nfol): + settings.write("New-Project-Folder", nfol) + else: + print("\033[1;31m"+talk.text("failed")) + + ############## + + elif command == "new_project": + if not settings.read("New-Project-Folder"): + print("\033[1;33m"+talk.text("pm-do-new-project-error")) + + #if folder is configured + else: + nproj = input("\033[1;33m "+talk.text("Name")+" : ") + + if pm_project.new(nproj): + print("\033[1;32m"+talk.text("checked")) + else: + print("\033[1;31m"+talk.text("failed")) + + + ############## + + elif command == "projects_list": + # Getting list of available projects + for p in pm_project.get_list(): + print("\033[1;35m "+p) + + ############## + + elif command == "project": + + n = input("\033[1;33m : ") + print("\033[1;35m "+talk.text("Wait")) + pm_project.load(n) + + + ############## + + elif command == "scan": + print("\033[1;35m "+talk.text("Wait")) + for proj in pm_project.scan(): + print("\033[1;35m "+proj) + + + ############## + + elif command == "convert": + print("\nNot Implemented yet\n") + + ## FAIL ## + + elif command != "": + print("\033[1;31m"+talk.text("failed")) + + + print("\033[1;m") #return terminal to normality diff --git a/project_manager/pm_gtk.py b/project_manager/pm_gtk.py new file mode 100644 index 0000000..f8e976f --- /dev/null +++ b/project_manager/pm_gtk.py @@ -0,0 +1,293 @@ +# THIS FILE IS A PART OF VCStudio +# PYTHON 3 + +import os +import datetime + +# GTK module ( Graphical interface +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk +import cairo + +# Own modules +from settings import settings +from settings import talk +from project_manager import pm_project +from project_manager import pm_mainLayer +from project_manager import pm_newprojectLayer +from project_manager import pm_scanLayer +from project_manager import pm_helpLayer +from project_manager import pm_updateLayer +from project_manager import update_reader +from project_manager import pm_installUpdatesLayer +from project_manager import pm_settingsLayer + +# UI modules +from UI import UI_testing +from UI import UI_color +from UI import UI_elements + +def previous(win): + win.previous = {} + for i in win.current: + if type(win.current[i]) == list or type(win.current[i]) is dict: + win.previous[i] = win.current[i].copy() + else: + win.previous[i] = win.current[i] + +# OK let's make a window +def run(): + # In the Blender-Organizer I was putting the version into the title. Not cool. + # Because if you would snap it to the sidebar in Ubuntu. On mouse over it would + # 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. + + # Setting up the window + win = Gtk.Window() + win.maximize() + win.connect("destroy", Gtk.main_quit) + win.set_title("VCStudio : "+talk.text("project-manager")) + win.set_default_icon_from_file("tinyicon.png") + + # Setting up the events ( mouse and keyboard handling ) + win.connect("button-press-event", mouse_button_press, win) + win.connect("button-release-event", mouse_button_release, win) + win.connect("key-press-event", key_press, win) + win.connect("key-release-event", key_release, win) + + # Guess what. The entire time on Blender-Organizer 4 ( 2018 -2020 ) and + # few days of trying connecting the scroll event directly to window or to + # the drawing area. And just now I finally made it work. BY DOING THIS + # Why scroll event is only on ScrolledWindow ? OMG !!! + + scroll = Gtk.ScrolledWindow() + scroll.connect("scroll-event", scrolling, win) + + # Setting up the global variables. (kinda) + win.animations = {} + win.previous = {} + win.current = {} + win.images = {} + win.imageload = False + win.text = {} + win.textactive = "" + win.scroll = {} + win.FPS = 0 + win.url = "project_manager" + win.update = {"versions":{}} + + + + # Cashed tables + win.color = UI_color.get_table() + win.settings = settings.load_all() + + # Default values + win.current["frame"] = 0 + win.current["testing"] = False + win.current["LMB"] = False + win.current["MMB"] = False + win.current["RMB"] = False + win.current["keys"] = [] + win.current["key_letter"] = "" + win.current["scroll"] = [0,0] + win.current["project"] = "" + + previous(win) + + # Version of the software + win.version = 0.0 + try: + vfile = open("settings/update.data") + vfile = vfile.read() + vfile = vfile.split("\n") + + for line in vfile: + if line.startswith("VERSION "): + win.version = float(line.replace("VERSION ", "")) + break + except: + win.version = 0.0 + + # FPS + win.sFPS = datetime.datetime.now() + + # Setting the drawable + pmdraw = Gtk.DrawingArea() + pmdraw.set_size_request(815, 500) + scroll.set_size_request(815, 500) # This step is because GTK developers are + win.add(scroll) # well. A good, nice, people who knows + scroll.add_with_viewport(pmdraw) # what they are doing. Really. + pmdraw.connect("draw", pmdrawing, win) + + + #run + win.show_all() + Gtk.main() + + +def pmdrawing(pmdrawing, main_layer, win): + + # This function draws the actuall image. I'm doing full frames redraws. It's + # a bit simpler then making some kind of dynamic draw call system that might + # be used in such an application. But to hell with it. I did the same on the + # Blender-Organizer altho with way less cairo. And it works well enought. + + # FPS counter + win.fFPS = datetime.datetime.now() + win.tFPS = win.fFPS - win.sFPS + if win.current["frame"] % 10 == 0: + win.FPS = int ( 1.0 / ( win.tFPS.microseconds /1000000)) + + if "Auto_De-Blur" not in win.settings: + win.settings["Auto_De-Blur"] = True + + # Fail switch for Graphics. + if win.FPS < 10 and win.settings["Auto_De-Blur"]: + win.settings["Blur"] = False + + win.sFPS = datetime.datetime.now() + + # Getting update info. I've added a bit of delay. So the starting of the + # Popen would not be noticed by the user as much. + if win.current["frame"] > 50: + update_reader.get_update_info(win) + + + # Current frame (for animations and things like this) + win.current["frame"] += 1 + + # Getting data about the frame + win.current['mx'] = win.get_pointer()[0] + win.current['my'] = win.get_pointer()[1] + win.current['w'] = win.get_size()[0] + win.current['h'] = win.get_size()[1] + + + #Background color + UI_color.set(main_layer, win, "background") + main_layer.rectangle( + 0, + 0, + win.current['w'], + win.current['h']) + main_layer.fill() + + # Tooltips and other junk has to be defined here. And then drawn later to + # the screen. So here we get a special layer. That will be drawn to during + # the time of drawing. And later composeted over everything. + + win.tooltip_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, win.current['w'], + win.current['h']) + win.tooltip = cairo.Context(win.tooltip_surface) + win.tooltip.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) + + + # Layers. Order of them matter + Layers = [] + Layers.append([pm_mainLayer.layer(win),"project_manager"]) + + if win.url == "new_project": + Layers.append([pm_newprojectLayer.layer(win), "new_project"]) + elif win.url == "scan_projects": + Layers.append([pm_scanLayer.layer(win), "scan_projects"]) + elif win.url == "help_layer": + Layers.append([pm_helpLayer.layer(win), "help_layer"]) + elif win.url == "update_layer": + Layers.append([pm_updateLayer.layer(win), "update_layer"]) + elif win.url == "install_updates": + Layers.append([pm_installUpdatesLayer.layer(win), "install_updates"]) + elif win.url == "settings_layer": + Layers.append([pm_settingsLayer.layer(win), "settings_layer"]) + + + Layers.append([UI_testing.layer(win)]) + Layers.append([win.tooltip_surface]) + + # Combining layers + for layer in Layers: + if len(layer) > 1: + layer, url = layer + blur = UI_elements.animate(url+"_blur", win, 50) + if win.url != url: + blur = UI_elements.animate(url+"_blur", win, blur, 50, 2, True) + else: + blur = UI_elements.animate(url+"_blur", win, blur, 0, 2, True) + layer = UI_elements.blur(layer, win, blur) + else: + layer = layer[0] + main_layer.set_source_surface(layer, 0 , 0) + main_layer.paint() + + # If you press ESC you get back from any window to the main menu. + if 65307 in win.current["keys"] and win.url != "install_updates": + win.url = "project_manager" + win.current["project"] = "" + win.textactive = "" + + + # 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 + # of the same data. + + previous(win) # Moved it into a seprate function for obvoius reasons + + # Refreshing those that need to be refrashed + win.current["scroll"] = [0,0] + + # Refreshing the frame automatically + pmdrawing.queue_draw() + + +# This program will have things like mouse and keyboard input. And this setup +# Will be done in both PM and the actuall Project window. ( Also in the render +# Window. Basically all separate windows will have to have this setup separatelly. + +# Mouse +def mouse_button_press(widget, event, win): + + # This function marks activation of the button. Not it's deactivation. + + # I'm going to attempt something quite disturbing. Basically I want to save + # the state of the mouse as the press begun untill it's released. And I'm + # going to do in a slightly weird way. Because I'm bored I guess. The prob- + # lem is that it will require to check whether the data even exists in the + # first place. If x. Before parsing it. Because it might be False. + + for i, button in enumerate(["LMB", "MMB", "RMB"]): + if i+1 == int(event.get_button()[1]): + win.current[button] = [event.x, event.y] + + # If you folowed the code. By checking for example if win.current["LMB"] + # You can know if it's even pressed to begin with. Because if it's not + # It's False. + +def mouse_button_release(widget, event, win): + + # This function reverses the effects of the mouse_button_press() function. + + for i, button in enumerate(["LMB", "MMB", "RMB"]): + if i+1 == int(event.get_button()[1]): + win.current[button] = False + +# I guess it's time to make something similar for the keyboard keys as well. +# I'm going to reuse the old system from the Blender-Organizer. Just a list of +# pressed keys. Maybe as well a strting thingy. Because I want to type in this +# app. + +def key_press(widget, event, win): + if event.keyval not in win.current["keys"]: + win.current["keys"].append(event.keyval) + win.current["key_letter"] = event.string + +def key_release(widget, event, win): + try: + win.current["keys"].remove(event.keyval) + except: + win.current["keys"] = [] + +def scrolling(widget, event, win): + e, x, y = event.get_scroll_deltas() + win.current["scroll"] = [x,y] + diff --git a/project_manager/pm_helpLayer.py b/project_manager/pm_helpLayer.py new file mode 100644 index 0000000..1965c9a --- /dev/null +++ b/project_manager/pm_helpLayer.py @@ -0,0 +1,305 @@ +# THIS FILE IS A PART OF VCStudio +# PYTHON 3 + +import os + +# 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 project_manager import pm_project + +#UI modules +from UI import UI_elements +from UI import UI_color + + +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() + + # So it's going to be like a little window in the center of the VCStudio + # with a simple UI. Probably like 2 things. Folder and a projectname. + + UI_color.set(layer, win, "node_background") + UI_elements.roundrect(layer, win, + 100, + 100, + win.current["w"]-200, + win.current["h"]-200, + 10) + + # Exit button + def do(): + win.url = "project_manager" + win.textactive = "" + + + UI_elements.roundrect(layer, win, + win.current["w"]-140, + win.current["h"]-140, + 40, + 40, + 10, + button=do, + icon="cancel", + tip=talk.text("cancel")) + + # Clipping everything + UI_elements.roundrect(layer, win, + 100, + 110, + win.current["w"]-200, + win.current["h"]-260, + 10, + fill=False) + layer.clip() + + # Setting up the scroll + if "pm_help" not in win.scroll: + win.scroll["pm_help"] = 0 + + current_Y = 1 # The max scroll value + + # VCStudio icon. + UI_elements.image(layer, win, "tinyicon.png", win.current["w"]/2-205, + current_Y+win.scroll["pm_help"]+120 ) + + UI_color.set(layer, win, "text_normal") + layer.move_to(win.current["w"]/2-205+148, current_Y+win.scroll["pm_help"]+200) + layer.set_font_size(50) + layer.show_text("VCStudio") + + # Version + layer.move_to(win.current["w"]/2-205+148, current_Y+win.scroll["pm_help"]+230) + layer.set_font_size(20) + layer.show_text(str(win.version)) + + current_Y = current_Y+200 + + # Here I want to put my own credit. And credits of anybody else who will + # maybe help in future. For now my own credit. + + UI_elements.image(layer, win, "project_manager/help_images/Blender_Dumbass_Avatar.png", 140, + current_Y+win.scroll["pm_help"]+120 ) + + UI_color.set(layer, win, "text_normal") + layer.move_to(280, current_Y+win.scroll["pm_help"]+150) + layer.set_font_size(20) + layer.show_text(talk.text("Developer")+":") + + layer.move_to(300, current_Y+win.scroll["pm_help"]+190) + layer.set_font_size(30) + layer.show_text("J.Y.Amihud") + + layer.move_to(280, current_Y+win.scroll["pm_help"]+230) + layer.set_font_size(25) + layer.show_text("(Blender Dumbass)") + + # Links to my accounts + + # Originally I wanted YouTube to be on the list as well. As you may know + # I have a little YouTube channel called "Blender Dumbass". But I dislike + # Youtube. And I don't want to promote it. + + # I'm concidering to remove Patreon and Twitter as well. Let me thing about + # it. + + + links = { + "Devtalk":"https://devtalk.blender.org/u/blenderdumbass", + "GitHub":"https://github.com/JYamihud", + "Telegram 1":"https://t.me/blenderorganizer", + "Telegram 2":"https://t.me/blenderdumbasschat", + "Telegram 3":"https://t.me/moriasrace", + "Patreon":"https://www.patreon.com/blenderdumbass", + "Twitter":"https://twitter.com/blenderdumbass", + "Bl-chat":"https://blender.chat/channel/blenderorganizer_vcstudio", + "LBRY":"https://lbry.tv/$/invite/@BlenderDumbass:c", + "Music":"https://open.lbry.com/@J.Y.AmihudMusic:c?r=GLhXoQ3zcpvm6rzd9Z6dAyasTpmk1FUY", + "Movies":"https://open.lbry.com/@VCS:7?r=GLhXoQ3zcpvm6rzd9Z6dAyasTpmk1FUY" + } + + tileY = 50 + tileX = 0 + for link in links: + + if tileY < 130: + posX = 450 + 100 + else: + posX = 128 + + def do(): + os.system("xdg-open "+links[link]) + UI_elements.roundrect(layer, win, + tileX+posX, + current_Y+100+tileY+win.scroll["pm_help"], + 170, + 40, + 10, + button=do, + icon="internet", + tip=links[link], + clip=[ + 100, + 110, + win.current["w"]-200, + win.current["h"]-260, + ]) + + UI_color.set(layer, win, "text_normal") + layer.move_to(tileX+posX+50, current_Y+win.scroll["pm_help"]+100+tileY+30) + layer.set_font_size(20) + layer.show_text(link) + + tileX += 170 + if tileX+posX > win.current["w"]-300: + tileX = 0 + tileY += 50 + + if tileY > 130: + current_Y += tileY + else: + current_Y += 130 + + current_Y = current_Y+200 + + movies = { + "I'm Not Even Human":[ + "2018/05/01", + "Blender-Organizer 1.0 - 3.9", + "https://open.lbry.com/@VCS:7/Imnotevenhumanshortfilm:3?r=GLhXoQ3zcpvm6rzd9Z6dAyasTpmk1FUY", + "project_manager/help_images/Im_Not_Even_Human_Poster.png" + ], + "The Package, The Car & The Time Is Running Out":[ + "2018/11/06", + "Blender-Organizer 4.0 - 4.17", + "https://open.lbry.com/@VCS:7/ThePackageTheCarAndTheTimeIsRunningOut:3?r=GLhXoQ3zcpvm6rzd9Z6dAyasTpmk1FUY", + "project_manager/help_images/The_Package_The_Car_And_Time_Is_Running_Out_Poster.png" + ], + "Moria's Race":[ + talk.text("In_Production"), + "Blender-Organizer 4.18 - VCStudio "+str(win.version), + "https://t.me/moriasrace", + "project_manager/help_images/Morias_Race_Poster.png" + ] + } + + UI_color.set(layer, win, "text_normal") + layer.move_to(120, current_Y+win.scroll["pm_help"]) + layer.set_font_size(20) + layer.show_text(talk.text("help_movies_done_title")) + + current_Y = current_Y+20 + + tileX = 120 + for movie in movies: + UI_elements.image(layer, win, movies[movie][3], tileX, + current_Y+win.scroll["pm_help"] , height=300, width=226) + + def do(): + os.system("xdg-open "+movies[movie][2]) + UI_elements.roundrect(layer, win, + tileX, + current_Y+win.scroll["pm_help"], + 226, + 300, + 10, + button=do, + fill=False, + tip=movie+"\n"+movies[movie][0]+"\n"+movies[movie][1], + clip=[ + 100, + 110, + win.current["w"]-200, + win.current["h"]-260, + ]) + layer.stroke() + + tileX += 300 + if tileX > win.current["w"]-300: + tileX = 120 + current_Y = current_Y+350 + + + current_Y = current_Y+400 + + # Tutorials about VCStudio. + UI_color.set(layer, win, "text_normal") + layer.move_to(120, current_Y+win.scroll["pm_help"]) + layer.set_font_size(20) + layer.show_text(talk.text("help_tutorial_title")) + + current_Y = current_Y+20 + + tutorials = [ + [talk.text("tutorial_legacy_analitycs"), "https://open.lbry.com/@blender-organizer:5/BlenderOrganizerAnalyticsTutorial4.87:6?r=GLhXoQ3zcpvm6rzd9Z6dAyasTpmk1FUY"], + [talk.text("tutorial_legacy_storyeditor"), "https://open.lbry.com/@blender-organizer:5/BlenderOrganizerStoryEditorTutorialv4.87:0?r=GLhXoQ3zcpvm6rzd9Z6dAyasTpmk1FUY"], + [talk.text("tutorial_legacy_assets"), "https://open.lbry.com/@blender-organizer:5/BlenderOrganizerAssetsTutorialv4.87:e?r=GLhXoQ3zcpvm6rzd9Z6dAyasTpmk1FUY"] + ] + + for tutorial in tutorials: + def do(): + os.system("xdg-open "+tutorial[1]) + UI_elements.roundrect(layer, win, + 110, + current_Y+win.scroll["pm_help"], + win.current["w"]-250, + 40, + 10, + button=do, + icon="video", + tip=talk.text("ClickToWatch"), + clip=[ + 100, + 110, + win.current["w"]-200, + win.current["h"]-260, + ]) + + UI_color.set(layer, win, "text_normal") + layer.move_to(160, current_Y+win.scroll["pm_help"]+25) + layer.set_font_size(20) + layer.show_text(tutorial[0]) + + current_Y = current_Y+50 + + current_Y = current_Y+138 + current_Y = current_Y+138 + + UI_elements.scroll_area(layer, win, "pm_help", + 100, + 100, + win.current["w"] - 200, + win.current["h"] - 250, + current_Y, + bar=True, + mmb=True, + url="help_layer" + ) + + + return surface diff --git a/project_manager/pm_installUpdatesLayer.py b/project_manager/pm_installUpdatesLayer.py new file mode 100644 index 0000000..89508b4 --- /dev/null +++ b/project_manager/pm_installUpdatesLayer.py @@ -0,0 +1,126 @@ +# THIS FILE IS A PART OF VCStudio +# PYTHON 3 + +# This a console project manager. + +import os +import sys +import urllib3 + +# 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 project_manager import pm_project + +#UI modules +from UI import UI_elements +from UI import UI_color + + +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() + + # So it's going to be like a little window in the center of the VCStudio + # with a simple UI. Probably like 2 things. Folder and a projectname. + + UI_color.set(layer, win, "node_background") + UI_elements.roundrect(layer, win, + win.current["w"]/2-250, + win.current["h"]/2-50, + 500, + 200, + 10) + + # Title of the operation. Incase the user forgot. + UI_elements.text(layer, win, "installing_project_title", + win.current["w"]/2-250, + win.current["h"]/2-15, + 500, + 30, + 10, + fill=False, + centered=True, + editable=False) + + win.text["installing_project_title"]["text"] = talk.text("update_installing") + + frame = win.current["frame"] - win.update["frame"] - 50 + files = win.update["get_files"] + + UI_color.set(layer, win, "progress_background") + UI_elements.roundrect(layer, win, + win.current["w"]/2-200, + win.current["h"]/2+70, + 400, + 20, + 10) + + if frame in range(-1, len(files)): + + filename = files[frame] + + try: + UI_color.set(layer, win, "text_normal") + layer.set_font_size(15) + layer.move_to(win.current["w"]/2-(len(files[frame+1])*9)/2, + win.current["h"]/2+50) + layer.show_text(files[frame+1]) + except: + pass + + path = "https://raw.githubusercontent.com/JYamihud/VCStudio/main/" + url = path+filename + + http = urllib3.PoolManager() + r = http.request('GET', url, preload_content=False) + with open(filename, 'wb') as out: + while True: + data = r.read(1024) + if not data: + break + out.write(data) + + r.release_conn() + + + fraction = ((frame + 1) / len(files)) + if fraction > 1: + fraction = 1 + + UI_color.set(layer, win, "progress_active") + UI_elements.roundrect(layer, win, + win.current["w"]/2-200, + win.current["h"]/2+70, + (400)*fraction, + 20, + 10) + + if frame > len(files)+30: + os.execl(sys.executable, sys.executable, *sys.argv) + + return surface diff --git a/project_manager/pm_mainLayer.py b/project_manager/pm_mainLayer.py new file mode 100644 index 0000000..95438b1 --- /dev/null +++ b/project_manager/pm_mainLayer.py @@ -0,0 +1,344 @@ +# THIS FILE IS A PART OF VCStudio +# PYTHON 3 + +import os + +# 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 project_manager import pm_project + +#UI modules +from UI import UI_elements +from UI import UI_color + + +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, "darker_parts") + UI_elements.roundrect(layer, win, + 50, + 5, + win.current["w"] - 55, + win.current["h"] - 30, + 30) + + # Little verion thing in the bottom corner + UI_color.set(layer, win, "testing_banner") + layer.set_font_size(15) + layer.move_to(win.current["w"]-80, win.current["h"] - 7) + layer.show_text(str(win.version)) + + + # Side bar. First 3. New project / Search Projects / Configure Project. + + # New Project + def do(): + print("New Project") + win.url = "new_project" + + UI_elements.roundrect(layer, win, + 5, + 5, + 40, + 40, + 10, + do, + "new_file", + talk.text("createnewproject_tooltip"), + url="project_manager") + + + + # Search for projects + def do(): + + win.url = "scan_projects" + + UI_elements.roundrect(layer, win, + 5, + 55, + 40, + 40, + 10, + do, + "search_file", + talk.text("scanforprojects_tooltip"), + url="project_manager") + + + # Configure + if win.current["project"] and pm_project.is_legacy(win.current["project"]): + + def do(): + print("configure") + + UI_elements.roundrect(layer, win, + 5, + 110, + 40, + 40, + 10, + do, + "configure_file", + talk.text("convertoldproject_tooltip"), + url="project_manager") + + + # Side bar. Last 3. Internet things / Updater / Settings + + # Internet things + def do(): + win.url = "help_layer" + + UI_elements.roundrect(layer, win, + 5, + win.current["h"]-150, + 40, + 40, + 10, + do, + "question", + talk.text("pm_internet_tooltip"), + url="project_manager") + + # Update + def do(): + win.url = "update_layer" + + UI_elements.roundrect(layer, win, + 5, + win.current["h"]-95, + 40, + 40, + 10, + do, + "update", + talk.text("Update"), + url="project_manager") + + # I gonna draw a little thingy for if a new update is available + try: + if win.update["count"]: + count = str(win.update["count"]) + + 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"]-80) + layer.show_text(count) + + except: + pass + + # Settings + def do(): + win.url = "settings_layer" + + UI_elements.roundrect(layer, win, + 5, + win.current["h"]-45, + 40, + 40, + 10, + do, + "settings", + talk.text("Settings"), + url="project_manager") + + # Now let's make previews of projects. I think each one will be it's own + # layer thingy. Just so I could draw things inside them. + + # Clipping so it wont draw beyon the frame + UI_elements.roundrect(layer, win, + 50, + 5, + win.current["w"] - 55, + win.current["h"] - 30, + 30, + fill=False) + layer.clip() + + # Setting up scroll for Projects + if "pm_scroll" not in win.current: + win.current["pm_scroll"] = 0.0 + + # Setting up tilling + tileY = 0 + tileX = 0 + + if "pm_main" not in win.scroll: + win.scroll["pm_main"] = 0 + + for num, project in enumerate(pm_project.get_list()): + + + if tileX > (win.current["w"]-55)-391: + tileY += 330 + tileX = 0 + + project_node(layer, win, 60+tileX, 15+tileY+ win.scroll["pm_main"], project) + + tileX += 360 + + UI_elements.scroll_area(layer, win, "pm_main", + 50, + 5, + win.current["w"] - 55, + win.current["h"] - 30, + tileY+340, + bar=True, + mmb=True, + url="project_manager" + ) + + + + return surface + +def project_node(layer, win, x, y, project): + + # This function will draw a project to a given place. + node_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, win.current['w'], + win.current['h']) + node = cairo.Context(node_surface) + node.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) + + + # Before we gonna do clip. Let's put here the logic of the node. + def do(): + print(project) + win.current["project"] = project + + Legacytip = "" + if pm_project.is_legacy(project): + Legacytip = "\nLegacy (Blender-Organizer)" + node.set_line_width(10) + UI_elements.roundrect(node, win, + x-5, + y-5, + 350+10, + 320+10, + 20+5, + button=do, + fill=False, + tip=project+Legacytip, + url="project_manager") + node.stroke() + + # If project is selected + if win.current["project"] == project and win.previous["project"] == project: + UI_color.set(node, win, "button_active") + UI_elements.roundrect(node, win, + x-5, + y-5, + 350+10, + 320+10, + 20+5, + button=False, + fill=False + ) + node.stroke() + + def do(): + pm_project.load(project) + Gtk.main_quit() # Here I might do some kind a setting later + + UI_elements.roundrect(node, win, + x-5, + y-5, + 350+10, + 320+10, + 20+5, + button=do, + fill=False, + url="project_manager" + ) + + # Enter keys + if win.url == "project_manager": + if 65293 in win.current["keys"] or 65421 in win.current["keys"]: + do() + win.current["keys"].remove(65293) + win.current["keys"].remove(65421) + + # This next roundrect will both be the backdrop of the node and both will + # clip the node content. All folowing graphics will be drawn clipped to the + # current roundrect. + + + UI_color.set(node, win, "node_background") + UI_elements.roundrect(node, win, + x, + y, + 350, + 320, + 20) + + # Clip + UI_elements.roundrect(node, win, + x, + y, + 350, + 320, + 20, + fill=False) + node.clip() + + + if os.path.exists(project+"/py_data/banner.png"): + UI_elements.image(node, win, project+"/py_data/banner.png", + x,y,350,320) + else: + UI_elements.image(node, win, "icon.png", + x,y,350,320) + + # Top Banner thingy + if pm_project.is_legacy(project): + UI_color.set(node, win, "node_badfile") + else: + UI_color.set(node, win, "node_blendfile") + + node.rectangle(x,y,350,40) + node.fill() + + # Name of the project + nameonly = project[project.rfind("/")+1:] + UI_color.set(node, win, "text_normal") + node.set_font_size(20) + node.move_to(x+175-len(nameonly)*12/2,y+25) + node.show_text(nameonly) + + # Bottom widget part + UI_color.set(node, win, "node_background") + node.rectangle(x,y+250,350,100) + node.fill() + + + # Drawing the Node on the main layer. + layer.set_source_surface(node_surface, 0,0) + layer.paint() diff --git a/project_manager/pm_newprojectLayer.py b/project_manager/pm_newprojectLayer.py new file mode 100644 index 0000000..ab759d8 --- /dev/null +++ b/project_manager/pm_newprojectLayer.py @@ -0,0 +1,159 @@ +# THIS FILE IS A PART OF VCStudio +# PYTHON 3 + +# This a console project manager. + +import os + +# 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 project_manager import pm_project + +#UI modules +from UI import UI_elements +from UI import UI_color + + +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() + + # So it's going to be like a little window in the center of the VCStudio + # with a simple UI. Probably like 2 things. Folder and a projectname. + + UI_color.set(layer, win, "node_background") + UI_elements.roundrect(layer, win, + win.current["w"]/2-250, + win.current["h"]/2-150, + 500, + 300, + 10) + + # Title of the operation. Incase the user forgot. + UI_elements.text(layer, win, "new_project_title", + win.current["w"]/2-250, + win.current["h"]/2-110, + 500, + 30, + 10, + fill=False, + centered=True, + editable=False) + win.text["new_project_title"]["text"] = talk.text("createnewproject_tooltip") + + + + # Folder. It's so VCStudio would know WHERE does user want to create the + # final project. + + def do(): + + folderchooser = Gtk.FileChooserDialog(talk.text("select_folder"), + None, + Gtk.FileChooserAction.SELECT_FOLDER, + (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, + Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) + folderchooser.set_default_response(Gtk.ResponseType.OK) + response = folderchooser.run() + if response == Gtk.ResponseType.OK: + get = folderchooser.get_filename() + settings.write("New-Project-Folder", get) + win.settings["New-Project-Folder"] = get + folderchooser.destroy() + + UI_elements.roundrect(layer, win, + win.current["w"]/2-240, + win.current["h"]/2-30, + 480, + 40, + 10, + button=do, + icon="folder", + tip=talk.text("pm_new_project_folder_tooltip")) + + choseF = "Select Folder" + if "New-Project-Folder" in win.settings: + choseF = win.settings["New-Project-Folder"] + UI_elements.text(layer, win, "new_project_folder", + win.current["w"]/2-190, + win.current["h"]/2-30, + 430, + 40, + set_text=choseF, + fill=False, + editable=False + ) + + + # Name of the project folder. Aka Name of the project + UI_elements.text(layer, win, "new_project_name", + win.current["w"]/2-240, + win.current["h"]/2+20, + 480, + 40, + set_text=talk.text("new_project_name")) + + #win.textactive = "new_project_name" + # Okay and Cancel buttons + + def do(): + + pm_project.new(win.text["new_project_name"]["text"]) + win.url = "project_manager" + win.textactive = "" + win.text["new_project_name"]["text"] = talk.text("new_project_name") + + UI_elements.roundrect(layer, win, + win.current["w"]/2+170, + win.current["h"]/2+110, + 40, + 40, + 10, + button=do, + icon="ok", + tip=talk.text("checked")) + + def do(): + win.url = "project_manager" + win.textactive = "" + win.text["new_project_name"]["text"] = talk.text("new_project_name") + + + UI_elements.roundrect(layer, win, + win.current["w"]/2+210, + win.current["h"]/2+110, + 40, + 40, + 10, + button=do, + icon="cancel", + tip=talk.text("cancel")) + + + + return surface diff --git a/project_manager/pm_project.py b/project_manager/pm_project.py new file mode 100644 index 0000000..f2d2a8c --- /dev/null +++ b/project_manager/pm_project.py @@ -0,0 +1,149 @@ +# THIS FILE IS A PART OF VCStudio +# PYTHON 3 + +# this file handles language +import os +import subprocess +from settings import settings +from settings import talk + + +def new(name): + + # Removing all the bad characters + + name = name.replace("/","_").replace(" ", "_")\ + .replace('"',"_").replace("(","_").replace(")","_").replace("'","_")\ + .replace("[","_").replace("]","_").replace("{","_").replace("}","_") + + + # This function makes a new project. + + # If there is not such a folder. As in the settings. + if not os.path.exists(settings.read("New-Project-Folder")): + return False + + # If there is a project folder, or a file with it's name. + elif os.path.exists(settings.read("New-Project-Folder")+"/"+name): + return False + + #If all good + else: + try: + + fn = settings.read("New-Project-Folder")+"/"+name + + os.mkdir(fn) + os.mkdir(fn+"/rnd") + os.mkdir(fn+"/dev") + os.mkdir(fn+"/ast") + os.mkdir(fn+"/pln") + os.mkdir(fn+"/mus") + os.mkdir(fn+"/set") + + for f in ["chr","loc","veh","obj"]: + os.mkdir(fn+"/ast/"+f) + os.mkdir(fn+"/dev/"+f) + + register_project(fn) + + return True + + # If it fails to create a project for some reason. + except: + return False + + +def register_project(path): + + prevdata = "" + + try: + data = open("project_manager/projects_list.data") + prevdata = data.read() + except: + pass + data = open("project_manager/projects_list.data", "w") + if path not in prevdata: + data.write(prevdata+path+"\n") + else: + data.write(prevdata) + data.close() + + +def get_list(): + + ret = [] + + try: + data = open("project_manager/projects_list.data") + data = data.read() + data = data.split("\n") + + for line in data: + if os.path.exists(line): + ret.append(line) + except: + pass + + return ret + + +def scan(): + + ret = [] + + #scan the system for "ast/chr" a folder that accurs in a project + for i in [x[0] for x in os.walk("/")]: + if i.endswith("/ast/chr"): + ret.append(i.replace("/ast/chr", "")) + register_project(i.replace("/ast/chr", "")) + + return ret + +def load(path): + + #first let's figure out if it's an old Blender-Organizer + #or a new VCStudio project. + + #if new + if not is_legacy(path): + print(" Not Yet Implemented VCStudio ") + + #old organizer + else: + if not os.path.exists(path+"/MAIN_FILE"): + n = "blender-organizer" + else: + n = open(path+"/MAIN_FILE") + n = n.read() + + #let's look if there is python2 since it's legacy software + if not os.system("python2 -V") == 0: + return "No python2" + + #loading the python2 thingy + sh = open("/tmp/run_legacy_organizer.sh", "w") + sh.write("cd "+path+"\n") + sh.write("python2 "+n+"\n") + sh.write('read -p ""') + sh.close() + + if not os.path.exists(path+"/MAIN_FILE"): + os.system("gnome-terminal -- sh /tmp/run_legacy_organizer.sh") + else: + subprocess.Popen(["sh", "/tmp/run_legacy_organizer.sh"]) + + + +def is_legacy(project): + + # This function checks whether a given project is a Legacy ( Blender - + # Organizer ) project. + + if not os.path.exists(project+"/set"): + return True + else: + return False + + diff --git a/project_manager/pm_scanLayer.py b/project_manager/pm_scanLayer.py new file mode 100644 index 0000000..317d9f9 --- /dev/null +++ b/project_manager/pm_scanLayer.py @@ -0,0 +1,76 @@ +# THIS FILE IS A PART OF VCStudio +# PYTHON 3 + +# This a console project manager. + +import os + +# 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 project_manager import pm_project + +#UI modules +from UI import UI_elements +from UI import UI_color + + +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() + + # So it's going to be like a little window in the center of the VCStudio + # with a simple UI. Probably like 2 things. Folder and a projectname. + + UI_color.set(layer, win, "node_background") + UI_elements.roundrect(layer, win, + win.current["w"]/2-250, + win.current["h"]/2-50, + 500, + 100, + 10) + + # Title of the operation. Incase the user forgot. + UI_elements.text(layer, win, "scan_project_title", + win.current["w"]/2-250, + win.current["h"]/2-15, + 500, + 30, + 10, + fill=False, + centered=True, + editable=False) + + win.text["scan_project_title"]["text"] = talk.text("duringscanningforprojects") + + blur = UI_elements.animate("project_manager_blur", win) + + if blur > 49: + pm_project.scan() + win.url = "project_manager" + + return surface diff --git a/project_manager/pm_settingsLayer.py b/project_manager/pm_settingsLayer.py new file mode 100644 index 0000000..b9d8293 --- /dev/null +++ b/project_manager/pm_settingsLayer.py @@ -0,0 +1,220 @@ +# THIS FILE IS A PART OF VCStudio +# PYTHON 3 + +import os + +# 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 project_manager import pm_project + +#UI modules +from UI import UI_elements +from UI import UI_color + + +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() + + + UI_color.set(layer, win, "node_background") + UI_elements.roundrect(layer, win, + win.current["w"]/2-250, + 100, + 500, + win.current["h"]-200, + 10) + + # Exit button + def do(): + win.url = "project_manager" + win.textactive = "" + + + 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")) + + + + # Clipping everything + UI_elements.roundrect(layer, win, + win.current["w"]/2-250, + 100, + 500, + win.current["h"]-260, + 10, + fill=False) + layer.clip() + + clip = [ + win.current["w"]/2-250, + 100, + 500, + win.current["h"]-260] + + # Setting up the scroll + if "pm_settings" not in win.scroll: + win.scroll["pm_settings"] = 0 + + current_Y = 0 # The max scroll value + + # Preparing lists. + if "settings_lists" not in win.current: + + win.current["settings_lists"] = {} + win.current["settings_lists"]["languages"] = settings.list_languages() + win.current["settings_lists"]["languages_open"] = False + + + # Languages + def do(): + win.current["settings_lists"]["languages_open"] = \ + not win.current["settings_lists"]["languages_open"] + + UI_elements.roundrect(layer, win, + win.current["w"]/2-240, + 110 + current_Y + win.scroll["pm_settings"], + 450, + 40, + 10, + button=do, + icon="font", + tip=talk.text("change_language")) + + UI_color.set(layer, win, "text_normal") + layer.set_font_size(20) + layer.move_to(win.current["w"]/2-180, + current_Y + win.scroll["pm_settings"] + 140) + layer.show_text(win.settings["Language"]) + + current_Y += 50 + + if win.current["settings_lists"]["languages_open"]: + for lang in win.current["settings_lists"]["languages"]: + if lang != win.settings["Language"]: + + def do(): + win.settings["Language"] = lang + settings.write("Language", lang) + win.current["settings_lists"]["languages_open"] = False + + UI_elements.roundrect(layer, win, + win.current["w"]/2-200, + 110 + current_Y + win.scroll["pm_settings"], + 410, + 40, + 10, + button=do, + icon="font", + tip=talk.text("set_language")+lang) + + + UI_color.set(layer, win, "text_normal") + layer.set_font_size(20) + layer.move_to(win.current["w"]/2-140, + current_Y + win.scroll["pm_settings"] + 140) + layer.show_text(lang) + + current_Y += 50 + + # BLUR + + blur_ok = False + if win.settings["Blur"]: + blur_ok = "ok" + + def do(): + win.settings["Blur"] = not win.settings["Blur"] + settings.write("Blur", win.settings["Blur"]) + + UI_elements.roundrect(layer, win, + win.current["w"]/2-240, + 110 + current_Y + win.scroll["pm_settings"], + 450, + 40, + 10, + button=do, + icon=blur_ok, + tip=talk.text("Blur")) + + UI_color.set(layer, win, "text_normal") + layer.set_font_size(20) + layer.move_to(win.current["w"]/2-180, + current_Y + win.scroll["pm_settings"] + 140) + layer.show_text(talk.text("Blur")) + + current_Y += 50 + + if win.settings["Blur"]: + ablur_ok = False + if win.settings["Auto_De-Blur"]: + ablur_ok = "ok" + + def do(): + win.settings["Auto_De-Blur"] = not win.settings["Auto_De-Blur"] + settings.write("Auto_De-Blur", win.settings["Auto_De-Blur"]) + + UI_elements.roundrect(layer, win, + win.current["w"]/2-240, + 110 + current_Y + win.scroll["pm_settings"], + 450, + 40, + 10, + button=do, + icon=ablur_ok, + tip=talk.text("Auto_De-Blur")) + + UI_color.set(layer, win, "text_normal") + layer.set_font_size(20) + layer.move_to(win.current["w"]/2-180, + current_Y + win.scroll["pm_settings"] + 140) + layer.show_text(talk.text("Auto_De-Blur")) + + + current_Y += 50 + + UI_elements.scroll_area(layer, win, "pm_settings", + int(win.current["w"]/2-250), + 100, + 500, + win.current["h"]-260, + current_Y, + bar=True, + mmb=True, + url="settings_layer" + ) + + + return surface