From 6acbd7c799a3da58e612a9085f7e1e3428bf563d Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 19 Nov 2019 18:09:46 +0100 Subject: [PATCH 1/4] first version of seed action for project entities seeding --- pype/ftrack/actions/action_seed.py | 307 ++++++++++++++++++++++++ res/ftrack/action_icons/SeedProject.svg | 89 +++++++ 2 files changed, 396 insertions(+) create mode 100644 pype/ftrack/actions/action_seed.py create mode 100644 res/ftrack/action_icons/SeedProject.svg diff --git a/pype/ftrack/actions/action_seed.py b/pype/ftrack/actions/action_seed.py new file mode 100644 index 0000000000..f69e2b1514 --- /dev/null +++ b/pype/ftrack/actions/action_seed.py @@ -0,0 +1,307 @@ +from operator import itemgetter +from pype.ftrack import BaseAction + + +class SeedDebugProject(BaseAction): + '''Edit meta data action.''' + + #: Action identifier. + identifier = "seed.debug.project" + #: Action label. + label = "SeedDebugProject" + #: Action description. + description = "Description" + #: priority + priority = 100 + #: roles that are allowed to register this action + role_list = ["Pypeclub"] + # icon = "{}/ftrack/action_icons/TestAction.svg".format( + # os.environ.get("PYPE_STATICS_SERVER", "") + # ) + + # Asset names which will be created in `Assets` entity + assets = [ + "Addax", "Alpaca", "Ant", "Antelope", "Aye", "Badger", "Bear", "Bee", + "Beetle", "Bluebird", "Bongo", "Bontebok", "Butterflie", "Caiman", + "Capuchin", "Capybara", "Cat", "Caterpillar", "Coyote", "Crocodile", + "Cuckoo", "Deer", "Dragonfly", "Duck", "Eagle", "Egret", "Elephant", + "Falcon", "Fossa", "Fox", "Gazelle", "Gecko", "Gerbil", + "GiantArmadillo", "Gibbon", "Giraffe", "Goose", "Gorilla", + "Grasshoper", "Hare", "Hawk", "Hedgehog", "Heron", "Hog", + "Hummingbird", "Hyena", "Chameleon", "Cheetah", "Iguana", "Jackal", + "Jaguar", "Kingfisher", "Kinglet", "Kite", "Komodo", "Lemur", + "Leopard", "Lion", "Lizard", "Macaw", "Malachite", "Mandrill", + "Mantis", "Marmoset", "Meadowlark", "Meerkat", "Mockingbird", + "Mongoose", "Monkey", "Nyal", "Ocelot", "Okapi", "Oribi", "Oriole", + "Otter", "Owl", "Panda", "Parrot", "Pelican", "Pig", "Porcupine", + "Reedbuck", "Rhinocero", "Sandpiper", "Servil", "Skink", "Sloth", + "Snake", "Spider", "Squirrel", "Sunbird", "Swallow", "Swift", "Tiger", + "Sylph", "Tanager", "Vulture", "Warthog", "Waterbuck", "Woodpecker", + "Zebra" + ] + + # Tasks which will be created for Assets + asset_tasks = [ + "Modeling", "Lookdev", "Rigging" + ] + # Tasks which will be created for Shots + shot_tasks = [ + "Animation", "Lighting", "Compositing", "FX" + ] + + # Define how much assets will be created(each will be created once if None) + # - you can enter more or less then assets mentioned in assets + asset_count = None + # Define how much sequences will be created + seq_count = 5 + # Define how much shots will be created for each sequence + shots_count = 10 + + existing_projects = None + new_project_item = "< New Project >" + + def discover(self, session, entities, event): + ''' Validation ''' + return True + + def interface(self, session, entities, event): + if event["data"].get("values", {}): + return + + title = "Select Project where you want to create seed data" + + items = [] + item_splitter = {"type": "label", "value": "---"} + + description_label = { + "type": "label", + "value": ( + "WARNING: Action does NOT check if entities already exist !!!" + ) + } + items.append(description_label) + + all_projects = session.query("select full_name from Project").all() + self.existing_projects = [proj["full_name"] for proj in all_projects] + projects_items = [ + {"label": proj, "value": proj} for proj in self.existing_projects + ] + + data_items = [] + + data_items.append({ + "label": self.new_project_item, + "value": self.new_project_item + }) + data_items.extend(sorted( + projects_items, + key=itemgetter("label"), + reverse=False + )) + projects_item = { + "label": "Choose Project", + "type": "enumerator", + "name": "project_name", + "data": data_items, + "value": self.new_project_item + } + items.append(projects_item) + items.append(item_splitter) + + note_label = { + "type": "label", + "value": ( + "

NOTE: Enter project name and choose schema if you " + "chose `\"< New Project >\"`(code is optional)

" + ) + } + items.append(note_label) + items.append({ + "label": "Project name", + "name": "new_project_name", + "type": "text", + "value": "" + }) + + project_schemas = [ + sch["name"] for sch in self.session.query("ProjectSchema").all() + ] + schemas_item = { + "label": "Choose Schema", + "type": "enumerator", + "name": "new_schema_name", + "data": [ + {"label": sch, "value": sch} for sch in project_schemas + ], + "value": project_schemas[0] + } + items.append(schemas_item) + + items.append({ + "label": "*Project code", + "name": "new_project_code", + "type": "text", + "value": "", + "empty_text": "Optional..." + }) + + return { + "items": items, + "title": title + } + + def launch(self, session, in_entities, event): + if "values" not in event["data"]: + return + + # THIS IS THE PROJECT PART + values = event["data"]["values"] + selected_project = values["project_name"] + if selected_project == self.new_project_item: + project_name = values["new_project_name"] + if project_name in self.existing_projects: + msg = "Project \"{}\" already exist".format(project_name) + self.log.error(msg) + return {"success": False, "message": msg} + + project_code = values["new_project_code"] + project_schema_name = values["new_schema_name"] + if not project_code: + project_code = project_name + project_code = project_code.lower().replace(" ", "_").strip() + _project = session.query( + "Project where name is \"{}\"".format(project_code) + ).first() + if _project: + msg = "Project with code \"{}\" already exist".format( + project_code + ) + self.log.error(msg) + return {"success": False, "message": msg} + + project_schema = session.query( + "ProjectSchema where name is \"{}\"".format( + project_schema_name + ) + ).one() + # Create the project with the chosen schema. + self.log.debug(( + "*** Creating Project: name <{}>, code <{}>, schema <{}>" + ).format(project_name, project_code, project_schema_name)) + project = session.create("Project", { + "name": project_code, + "full_name": project_name, + "project_schema": project_schema + }) + session.commit() + + else: + project = session.query("Project where full_name is \"{}\"".format( + selected_project + )).one() + project_schema = project["project_schema"] + self.log.debug(( + "*** Using Project: name <{}>, code <{}>, schema <{}>" + ).format( + project["full_name"], project["name"], project_schema["name"] + )) + + # THIS IS THE MAGIC PART + task_types = {} + for _type in project_schema["_task_type_schema"]["types"]: + if _type["name"] not in task_types: + task_types[_type["name"]] = _type + self.task_types = task_types + + self.create_assets(project) + self.create_shots(project) + + return True + + def create_assets(self, project): + self.log.debug("*** Creating assets:") + + asset_count = self.asset_count + if asset_count is None: + asset_count = len(self.assets) + + main_entity = self.session.create("Folder", { + "name": "Assets", + "parent": project + }) + self.log.debug("- Assets") + available_assets = len(self.assets) + repetitive_times = ( + int(asset_count / available_assets) + + (asset_count % available_assets > 0) + ) + created_assets = 0 + for _asset_name in self.assets: + if created_assets >= asset_count: + break + for asset_num in range(1, repetitive_times + 1): + if created_assets >= asset_count: + break + asset_name = "%s_%02d" % (_asset_name, asset_num) + asset = self.session.create("AssetBuild", { + "name": asset_name, + "parent": main_entity + }) + created_assets += 1 + self.log.debug("- Assets/{}".format(asset_name)) + + for task_name in self.asset_tasks: + self.session.create("Task", { + "name": task_name, + "parent": asset, + "type": self.task_types[task_name] + }) + self.log.debug("- Assets/{}/{}".format( + asset_name, task_name + )) + + self.log.debug("*** Commiting Assets") + self.session.commit() + + def create_shots(self, project): + self.log.debug("*** Creating shots:") + main_entity = self.session.create("Folder", { + "name": "Shots", + "parent": project + }) + self.log.debug("- Shots") + + for seq_num in range(1, self.seq_count+1): + seq_name = "sq%03d" % seq_num + seq = self.session.create("Sequence", { + "name": seq_name, + "parent": main_entity + }) + self.log.debug("- Shots/{}".format(seq_name)) + + for shot_num in range(1, self.shots_count+1): + shot_name = "%ssh%04d" % (seq_name, (shot_num*10)) + shot = self.session.create("Shot", { + "name": shot_name, + "parent": seq + }) + self.log.debug("- Shots/{}/{}".format(seq_name, shot_name)) + + for task_name in self.shot_tasks: + self.session.create("Task", { + "name": task_name, + "parent": shot, + "type": self.task_types[task_name] + }) + self.log.debug("- Shots/{}/{}/{}".format( + seq_name, shot_name, task_name + )) + + self.log.debug("*** Commiting Shots") + self.session.commit() + + +def register(session, plugins_presets={}): + '''Register plugin. Called when used as an plugin.''' + + SeedDebugProject(session, plugins_presets).register() diff --git a/res/ftrack/action_icons/SeedProject.svg b/res/ftrack/action_icons/SeedProject.svg new file mode 100644 index 0000000000..19ab22e411 --- /dev/null +++ b/res/ftrack/action_icons/SeedProject.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + From 9e74d086709c7bc7513a6ef1782f03cc2f274391 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 19 Nov 2019 18:14:19 +0100 Subject: [PATCH 2/4] added icon --- pype/ftrack/actions/action_seed.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pype/ftrack/actions/action_seed.py b/pype/ftrack/actions/action_seed.py index f69e2b1514..fd23b399dc 100644 --- a/pype/ftrack/actions/action_seed.py +++ b/pype/ftrack/actions/action_seed.py @@ -1,3 +1,4 @@ +import os from operator import itemgetter from pype.ftrack import BaseAction @@ -15,9 +16,9 @@ class SeedDebugProject(BaseAction): priority = 100 #: roles that are allowed to register this action role_list = ["Pypeclub"] - # icon = "{}/ftrack/action_icons/TestAction.svg".format( - # os.environ.get("PYPE_STATICS_SERVER", "") - # ) + icon = "{}/ftrack/action_icons/SeedProject.svg".format( + os.environ.get("PYPE_STATICS_SERVER", "") + ) # Asset names which will be created in `Assets` entity assets = [ From 81dbc9a17ebb23c7059c267dd06138a6be91eb65 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 19 Nov 2019 18:33:38 +0100 Subject: [PATCH 3/4] user can change number of created instances --- pype/ftrack/actions/action_seed.py | 47 ++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/pype/ftrack/actions/action_seed.py b/pype/ftrack/actions/action_seed.py index fd23b399dc..e4b47c4e6a 100644 --- a/pype/ftrack/actions/action_seed.py +++ b/pype/ftrack/actions/action_seed.py @@ -50,13 +50,10 @@ class SeedDebugProject(BaseAction): "Animation", "Lighting", "Compositing", "FX" ] - # Define how much assets will be created(each will be created once if None) - # - you can enter more or less then assets mentioned in assets - asset_count = None # Define how much sequences will be created - seq_count = 5 + default_seq_count = 5 # Define how much shots will be created for each sequence - shots_count = 10 + default_shots_count = 10 existing_projects = None new_project_item = "< New Project >" @@ -109,6 +106,26 @@ class SeedDebugProject(BaseAction): items.append(projects_item) items.append(item_splitter) + items.append({ + "label": "Number of assets", + "type": "number", + "name": "asset_count", + "value": len(self.assets) + }) + items.append({ + "label": "Number of sequences", + "type": "number", + "name": "seq_count", + "value": self.default_seq_count + }) + items.append({ + "label": "Number of shots", + "type": "number", + "name": "shots_count", + "value": self.default_shots_count + }) + items.append(item_splitter) + note_label = { "type": "label", "value": ( @@ -214,18 +231,18 @@ class SeedDebugProject(BaseAction): task_types[_type["name"]] = _type self.task_types = task_types - self.create_assets(project) - self.create_shots(project) + asset_count = values.get("asset_count") or len(self.assets) + seq_count = values.get("seq_count") or self.default_seq_count + shots_count = values.get("shots_count") or self.default_shots_count + + self.create_assets(project, asset_count) + self.create_shots(project, seq_count, shots_count) return True - def create_assets(self, project): + def create_assets(self, project, asset_count): self.log.debug("*** Creating assets:") - asset_count = self.asset_count - if asset_count is None: - asset_count = len(self.assets) - main_entity = self.session.create("Folder", { "name": "Assets", "parent": project @@ -264,7 +281,7 @@ class SeedDebugProject(BaseAction): self.log.debug("*** Commiting Assets") self.session.commit() - def create_shots(self, project): + def create_shots(self, project, seq_count, shots_count): self.log.debug("*** Creating shots:") main_entity = self.session.create("Folder", { "name": "Shots", @@ -272,7 +289,7 @@ class SeedDebugProject(BaseAction): }) self.log.debug("- Shots") - for seq_num in range(1, self.seq_count+1): + for seq_num in range(1, seq_count+1): seq_name = "sq%03d" % seq_num seq = self.session.create("Sequence", { "name": seq_name, @@ -280,7 +297,7 @@ class SeedDebugProject(BaseAction): }) self.log.debug("- Shots/{}".format(seq_name)) - for shot_num in range(1, self.shots_count+1): + for shot_num in range(1, shots_count+1): shot_name = "%ssh%04d" % (seq_name, (shot_num*10)) shot = self.session.create("Shot", { "name": shot_name, From 413dfc6a03e815573ff87277d6e35e967bdfde1f Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 19 Nov 2019 18:33:51 +0100 Subject: [PATCH 4/4] added current project to project list --- pype/ftrack/actions/action_seed.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/pype/ftrack/actions/action_seed.py b/pype/ftrack/actions/action_seed.py index e4b47c4e6a..cf0a4b0445 100644 --- a/pype/ftrack/actions/action_seed.py +++ b/pype/ftrack/actions/action_seed.py @@ -57,6 +57,7 @@ class SeedDebugProject(BaseAction): existing_projects = None new_project_item = "< New Project >" + current_project_item = "< Current Project >" def discover(self, session, entities, event): ''' Validation ''' @@ -91,6 +92,12 @@ class SeedDebugProject(BaseAction): "label": self.new_project_item, "value": self.new_project_item }) + + data_items.append({ + "label": self.current_project_item, + "value": self.current_project_item + }) + data_items.extend(sorted( projects_items, key=itemgetter("label"), @@ -101,7 +108,7 @@ class SeedDebugProject(BaseAction): "type": "enumerator", "name": "project_name", "data": data_items, - "value": self.new_project_item + "value": self.current_project_item } items.append(projects_item) items.append(item_splitter) @@ -213,6 +220,21 @@ class SeedDebugProject(BaseAction): }) session.commit() + elif selected_project == self.current_project_item: + entity = in_entities[0] + if entity.entity_type.lower() == "project": + project = entity + else: + if "project" in entity: + project = entity["project"] + else: + project = entity["parent"]["project"] + project_schema = project["project_schema"] + self.log.debug(( + "*** Using Project: name <{}>, code <{}>, schema <{}>" + ).format( + project["full_name"], project["name"], project_schema["name"] + )) else: project = session.query("Project where full_name is \"{}\"".format( selected_project