Skip to content

Commit

Permalink
Merge pull request #50 from quadproduction/release/4.0.24
Browse files Browse the repository at this point in the history
Release/4.0.24
  • Loading branch information
BenSouchet authored Feb 3, 2025
2 parents f2f05bc + bc7ab2b commit ddc562b
Show file tree
Hide file tree
Showing 23 changed files with 900 additions and 137 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ install-pyenv-win.ps1
# Developer tools
src/tools/dev_*
.github_changelog_generator

.run/custom_pre.run.xml

# Addons
########
Expand Down
28 changes: 28 additions & 0 deletions .run/custom.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="custom" type="PythonConfigurationType" factoryName="Python">
<module name="quadpype" />
<selectedOptions>
<option name="environmentVariables" visible="false" />
<option name="envPaths" visible="false" />
</selectedOptions>
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$/src" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$ProjectFileDir$/src/start.py" />
<option name="PARAMETERS" value="tray --debug --additional-env-file $ProjectFileDir$/src/tools/.env" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="true" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2">
<option name="RunConfigurationTask" enabled="true" run_configuration_name="custom_pre" run_configuration_type="PythonConfigurationType" />
</method>
</configuration>
</component>
94 changes: 93 additions & 1 deletion src/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ opentimelineio = "^0.15.0"
colorama = "0.4.6"
fastapi = ">=0.112.0,<0.113.0"
uvicorn = "^0.30.6"
htmllistparse = "^0.6.1"

[tool.poetry.dev-dependencies]
flake8 = "^6.0"
Expand Down
13 changes: 13 additions & 0 deletions src/quadpype/hosts/blender/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@

from .render_lib import prepare_rendering

from .template_resolving import (
get_resolved_name,
get_entity_collection_template,
get_task_collection_template,
update_parent_data_with_entity_prefix
)


__all__ = [
"install",
Expand Down Expand Up @@ -71,4 +78,10 @@
"capture",
# "unique_name",
"prepare_rendering",

#Templates for working:
"get_resolved_name",
"get_entity_collection_template",
"get_task_collection_template",
"update_parent_data_with_entity_prefix"
]
178 changes: 178 additions & 0 deletions src/quadpype/hosts/blender/api/template_resolving.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
from collections import OrderedDict

from quadpype.settings import get_project_settings
from quadpype.lib import (
filter_profiles,
Logger,
StringTemplate,
)

def get_resolved_name(data, template):
"""Resolve template_collections_naming with entered data.
Args:
data (Dict[str, Any]): Data to fill template_collections_naming.
template (list): template to solve
Returns:
str: Resolved template
"""
template_obj = StringTemplate(template)
# Resolve the template
output = template_obj.format_strict(data)
return output.normalized()

def _get_project_name_by_data(data):
"""
Retrieve the project name depending on given data
This can be given by an instance or an app, and they are not sorted the same way
Return:
str, bool: The project name (str) and a bool to specify if this is from anatomy or project (bool)
"""
project_name = None
is_from_anatomy = False

if data.get("project"):
project_name = data["project"]["name"]
elif data.get("anatomyData"):
is_from_anatomy = True
project_name = data["anatomyData"]["project"]["name"]

return project_name, is_from_anatomy

def _get_app_name_by_data(data):
"""
Retrieve the app name depending on given data
This can be given by an instance or an app, and they are not sorted the same way
Return:
str, bool: The app name (str) and a bool to specify if this is from anatomy or project (bool)
"""
app_name = None
is_from_anatomy = False

if data.get("app"):
app_name = data["project"]["app"]
elif data.get("anatomyData"):
is_from_anatomy = True
app_name = data["anatomyData"]["app"]

return app_name, is_from_anatomy

def _get_parent_by_data(data):
"""
Retrieve the parent asset name depending on given data
This can be given by an instance or an app, and they are not sorted the same way
Return:
str, bool: The parent name (str) and a bool to specify if this is from anatomy or project (bool)
"""
parent_name = None
is_from_anatomy = False

if data.get("parent"):
parent_name = data["parent"]
elif data.get("anatomyData"):
is_from_anatomy = True
parent_name = data["anatomyData"]["parent"]

return parent_name, is_from_anatomy

def _get_profiles(setting_key, data, project_settings=None):

project_name, is_anatomy_data = _get_project_name_by_data(data)
app_name, is_anatomy_data = _get_app_name_by_data(data)

if not project_settings:
project_settings = get_project_settings(project_name)

# Get Entity Type Name Matcher Profiles
try:
profiles = (
project_settings
[app_name]
["templated_workfile_build"]
[setting_key]
["profiles"]
)

except Exception:
raise KeyError("Project has no profiles set for {}".format(setting_key))

# By default, profiles = [], so we must stop if there's no profiles set
if not profiles:
raise KeyError("Project has no profiles set for {}".format(setting_key))

return profiles

def _get_entity_prefix(data):
"""Retrieve the asset_type (entity_type) short name for proper blender naming
Args:
data (Dict[str, Any]): Data to fill template_collections_naming.
Return:
str: A string corresponding to the short name for entered entity type
bool: bool to specify if this is from anatomy or project (bool)
"""

# Get Entity Type Name Matcher Profiles
profiles = _get_profiles("entity_type_name_matcher", data)
parent, is_anatomy = _get_parent_by_data(data)

profile_key = {"entity_types": parent}
profile = filter_profiles(profiles, profile_key)
# If a profile is found, return the prefix
return profile.get("entity_prefix"), is_anatomy

def update_parent_data_with_entity_prefix(data):
"""
Will update the input data dict to change the value of the ["parent"] key
to become the corresponding prefix
Args:
data (Dict[str, Any]): Data to fill template_collections_naming.
"""
parent_prefix, is_anatomy = _get_entity_prefix(data)

if not parent_prefix:
return

if is_anatomy:
data["anatomyData"]["parent"] = parent_prefix
else:
data["parent"] = parent_prefix

def get_entity_collection_template(data):
"""Retrieve the template for the collection depending on the entity type
Args:
data (Dict[str, Any]): Data to fill template_collections_naming.
Return:
str: A template that can be solved later
"""

# Get Entity Type Name Matcher Profiles
profiles = _get_profiles("collections_templates_by_entity_type", data)
parent, is_anatomy = _get_parent_by_data(data)
profile_key = {"entity_types": parent}
profile = filter_profiles(profiles, profile_key)
# If a profile is found, return the template
return profile.get("template")


def get_task_collection_template(data):
"""Retrieve the template for the collection depending on the task type
Args:
data (Dict[str, Any]): Data to fill template_collections_naming.
Return:
str: A template that can be solved later
"""

# Get Entity Type Name Matcher Profiles
profiles = _get_profiles("working_collections_templates_by_tasks", data)
profile_key = {"task_types": data["task"]}
profile = filter_profiles(profiles, profile_key)

if not profile:
return None
# If a profile is found, return the template
if data.get("variant", None) == "Main":
return profile["main_template"]

return profile["variant_template"]
Loading

0 comments on commit ddc562b

Please sign in to comment.