Move Anim_Setup module into Blender_Kitsu #5

Merged
Nick Alberelli merged 27 commits from :feature/merge_anim_setup_into_blender_kitsu into master 2023-04-05 17:38:41 +02:00
33 changed files with 697 additions and 753 deletions
Showing only changes of commit b2aeefcc50 - Show all commits

View File

@ -20,6 +20,7 @@
import bpy
from blender_kitsu import (
shot_builder,
lookdev,
bkglobals,
types,
@ -92,6 +93,7 @@ def register():
# tasks.register()
playblast.register()
anim.register()
shot_builder.register()
LoggerLevelManager.configure_levels()
logger.info("Registered blender-kitsu")
@ -109,6 +111,7 @@ def unregister():
prefs.unregister()
lookdev.unregister()
playblast.unregister()
shot_builder.unregister()
LoggerLevelManager.restore_levels()

View File

@ -285,6 +285,15 @@ class KITSU_addon_preferences(bpy.types.AddonPreferences):
type=KITSU_media_update_search_paths
)
production_path: bpy.props.StringProperty( # type: ignore
name="Production Root",
description="The location to load configuration files from when "
"they couldn't be found in any parent folder of the current "
"file. Folder must contain a sub-folder named `shot-builder` "
"that holds the configuration files",
subtype='DIR_PATH',
)
session: Session = Session()
tasks: bpy.props.CollectionProperty(type=KITSU_task)

View File

@ -18,30 +18,28 @@
# <pep8 compliant>
from shot_builder.ui import *
from shot_builder.connectors.kitsu import *
from shot_builder.operators import *
from shot_builder.properties import *
from blender_kitsu.shot_builder.ui import *
from blender_kitsu.shot_builder.connectors.kitsu import *
from blender_kitsu.shot_builder.operators import *
import bpy
# import logging
# logging.basicConfig(level=logging.DEBUG)
bl_info = {
'name': 'Shot Builder',
"author": "Jeroen Bakker",
'version': (0, 1),
'blender': (2, 90, 0),
'location': 'Addon Preferences panel and file new menu',
'description': 'Shot builder production tool.',
'category': 'Studio',
}
# bl_info = {
# 'name': 'Shot Builder',
# "author": "Jeroen Bakker",
# 'version': (0, 1),
# 'blender': (2, 90, 0),
# 'location': 'Addon Preferences panel and file new menu',
# 'description': 'Shot builder production tool.',
# 'category': 'Studio',
# }
classes = (
KitsuPreferences,
ShotBuilderPreferences,
SHOTBUILDER_OT_NewShotFile,
)

View File

@ -1,13 +1,13 @@
from shot_builder.project import Production
from shot_builder.task_type import TaskType
from shot_builder.asset import Asset, AssetRef
from shot_builder.builder.build_step import BuildStep, BuildContext
from shot_builder.builder.init_asset import InitAssetStep
from shot_builder.builder.init_shot import InitShotStep
from shot_builder.builder.set_render_settings import SetRenderSettingsStep
from shot_builder.builder.new_scene import NewSceneStep
from shot_builder.builder.invoke_hook import InvokeHookStep
from shot_builder.builder.save_file import SaveFileStep
from blender_kitsu.shot_builder.project import Production
from blender_kitsu.shot_builder.task_type import TaskType
from blender_kitsu.shot_builder.asset import Asset, AssetRef
from blender_kitsu.shot_builder.builder.build_step import BuildStep, BuildContext
from blender_kitsu.shot_builder.builder.init_asset import InitAssetStep
from blender_kitsu.shot_builder.builder.init_shot import InitShotStep
from blender_kitsu.shot_builder.builder.set_render_settings import SetRenderSettingsStep
from blender_kitsu.shot_builder.builder.new_scene import NewSceneStep
from blender_kitsu.shot_builder.builder.invoke_hook import InvokeHookStep
from blender_kitsu.shot_builder.builder.save_file import SaveFileStep
import bpy

View File

@ -1,11 +1,11 @@
import bpy
import typing
from shot_builder.project import Production
from shot_builder.shot import Shot
from shot_builder.task_type import TaskType
from shot_builder.render_settings import RenderSettings
from shot_builder.asset import Asset
from blender_kitsu.shot_builder.project import Production
from blender_kitsu.shot_builder.shot import Shot
from blender_kitsu.shot_builder.task_type import TaskType
from blender_kitsu.shot_builder.render_settings import RenderSettings
from blender_kitsu.shot_builder.asset import Asset
class BuildContext:

View File

@ -1,7 +1,7 @@
from shot_builder.builder.build_step import BuildStep, BuildContext
from shot_builder.asset import *
from shot_builder.project import *
from shot_builder.shot import *
from blender_kitsu.shot_builder.builder.build_step import BuildStep, BuildContext
from blender_kitsu.shot_builder.asset import *
from blender_kitsu.shot_builder.project import *
from blender_kitsu.shot_builder.shot import *
import bpy

View File

@ -1,7 +1,7 @@
from shot_builder.builder.build_step import BuildStep, BuildContext
from shot_builder.asset import *
from shot_builder.project import *
from shot_builder.shot import *
from blender_kitsu.shot_builder.builder.build_step import BuildStep, BuildContext
from blender_kitsu.shot_builder.asset import *
from blender_kitsu.shot_builder.project import *
from blender_kitsu.shot_builder.shot import *
import bpy

View File

@ -1,5 +1,5 @@
from shot_builder.builder.build_step import BuildStep, BuildContext
from shot_builder.hooks import HookFunction
from blender_kitsu.shot_builder.builder.build_step import BuildStep, BuildContext
from blender_kitsu.shot_builder.hooks import HookFunction
import bpy
import typing

View File

@ -1,5 +1,5 @@
from shot_builder.builder.build_step import BuildStep, BuildContext
from shot_builder.render_settings import RenderSettings
from blender_kitsu.shot_builder.builder.build_step import BuildStep, BuildContext
from blender_kitsu.shot_builder.render_settings import RenderSettings
import bpy
import logging

View File

@ -1,7 +1,7 @@
from shot_builder.builder.build_step import BuildStep, BuildContext
from shot_builder.asset import *
from shot_builder.project import *
from shot_builder.shot import *
from blender_kitsu.shot_builder.builder.build_step import BuildStep, BuildContext
from blender_kitsu.shot_builder.asset import *
from blender_kitsu.shot_builder.project import *
from blender_kitsu.shot_builder.shot import *
import pathlib
import bpy

View File

@ -1,4 +1,4 @@
from shot_builder.builder.build_step import BuildStep, BuildContext
from blender_kitsu.shot_builder.builder.build_step import BuildStep, BuildContext
import bpy
import typing

View File

@ -21,16 +21,16 @@
This module contains the Connector class. It is an abstract base class for concrete connectors.
"""
from shot_builder.shot import Shot, ShotRef
from shot_builder.asset import Asset, AssetRef
from shot_builder.task_type import TaskType
from shot_builder.render_settings import RenderSettings
from blender_kitsu.shot_builder.shot import Shot, ShotRef
from blender_kitsu.shot_builder.asset import Asset, AssetRef
from blender_kitsu.shot_builder.task_type import TaskType
from blender_kitsu.shot_builder.render_settings import RenderSettings
from typing import *
if TYPE_CHECKING:
from shot_builder.project import Production
from shot_builder.properties import ShotBuilderPreferences
from blender_kitsu.shot_builder.project import Production
from blender_kitsu.shot_builder.properties import ShotBuilderPreferences
class Connector:
@ -58,8 +58,8 @@ class Connector:
Example of using predefined connectors in a production config file:
```shot-builder/config.py
from shot_builder.connectors.default import DefaultConnector
from shot_builder.connectors.kitsu import KitsuConnector
from blender_kitsu.shot_builder.connectors.default import DefaultConnector
from blender_kitsu.shot_builder.connectors.kitsu import KitsuConnector
PRODUCTION_NAME = DefaultConnector
TASK_TYPES = KitsuConnector

View File

@ -17,11 +17,11 @@
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
from shot_builder.shot import Shot, ShotRef
from shot_builder.asset import Asset, AssetRef
from shot_builder.task_type import TaskType
from shot_builder.render_settings import RenderSettings
from shot_builder.connectors.connector import Connector
from blender_kitsu.shot_builder.shot import Shot, ShotRef
from blender_kitsu.shot_builder.asset import Asset, AssetRef
from blender_kitsu.shot_builder.task_type import TaskType
from blender_kitsu.shot_builder.render_settings import RenderSettings
from blender_kitsu.shot_builder.connectors.connector import Connector
from typing import *

View File

@ -18,13 +18,16 @@
# <pep8 compliant>
import bpy
from shot_builder import vars
from shot_builder.shot import Shot, ShotRef
from shot_builder.asset import Asset, AssetRef
from shot_builder.task_type import TaskType
from shot_builder.render_settings import RenderSettings
from shot_builder.connectors.connector import Connector
from blender_kitsu.shot_builder import vars
from blender_kitsu.shot_builder.shot import Shot, ShotRef
from blender_kitsu.shot_builder.asset import Asset, AssetRef
from blender_kitsu.shot_builder.task_type import TaskType
from blender_kitsu.shot_builder.render_settings import RenderSettings
from blender_kitsu.shot_builder.connectors.connector import Connector
import requests
from blender_kitsu import cache
from blender_kitsu.gazu.asset import all_assets_for_shot
from blender_kitsu.gazu.shot import all_shots_for_project, all_sequences_for_project
import typing
import logging
@ -131,47 +134,9 @@ class KitsuConnector(Connector):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.__jwt_access_token = ""
self.__validate()
self.__authorize()
def __validate(self) -> None:
self._preferences.kitsu._validate()
if not self._production.config.get('KITSU_PROJECT_ID'):
raise KitsuException(
"KITSU_PROJECT_ID is not configured in config.py")
def __authorize(self) -> None:
kitsu_pref = self._preferences.kitsu
backend = kitsu_pref.backend
username = kitsu_pref.username
password = kitsu_pref.password
logger.info(f"authorize {username} against {backend}")
response = requests.post(
url=f"{backend}/auth/login", data={'email': username, 'password': password})
if response.status_code != 200:
self.__jwt_access_token = ""
raise KitsuException(
f"unable to authorize (status code={response.status_code})")
json_response = response.json()
self.__jwt_access_token = json_response['access_token']
def __api_get(self, api: str) -> typing.Any:
kitsu_pref = self._preferences.kitsu
backend = kitsu_pref.backend
response = requests.get(url=f"{backend}{api}", headers={
"Authorization": f"Bearer {self.__jwt_access_token}"
})
if response.status_code != 200:
raise KitsuException(
f"unable to call kitsu (api={api}, status code={response.status_code})")
return response.json()
def __get_production_data(self) -> KitsuProject:
project_id = self._production.config['KITSU_PROJECT_ID']
production = self.__api_get(f"data/projects/{project_id}")
production = cache.project_active_get()
project = KitsuProject(typing.cast(
typing.Dict[str, typing.Any], production))
return project
@ -181,22 +146,23 @@ class KitsuConnector(Connector):
return production.get_name()
def get_task_types(self) -> typing.List[TaskType]:
task_types = self.__api_get(f"data/task_types/")
project = cache.project_active_get()
task_types = project.task_types
import pprint
pprint.pprint(task_types)
return []
def get_shots(self) -> typing.List[ShotRef]:
project_id = self._production.config['KITSU_PROJECT_ID']
kitsu_sequences = self.__api_get(f"data/projects/{project_id}/sequences")
project = cache.project_active_get()
kitsu_sequences = all_sequences_for_project(project.id)
sequence_lookup = {sequence_data['id']: KitsuSequenceRef(
kitsu_id=sequence_data['id'],
name=sequence_data['name'],
code=sequence_data['code'],
) for sequence_data in kitsu_sequences}
kitsu_shots = self.__api_get(f"data/projects/{project_id}/shots")
kitsu_shots = all_shots_for_project(project.id)
shots: typing.List[ShotRef] = []
for shot_data in kitsu_shots:
@ -232,8 +198,8 @@ class KitsuConnector(Connector):
return shots
def get_assets_for_shot(self, shot: Shot) -> typing.List[AssetRef]:
kitsu_assets = self.__api_get(
f"data/shots/{shot.kitsu_id}/assets")
kitsu_assets = all_assets_for_shot(shot.kitsu_id)
return [AssetRef(name=asset_data['name'], code=asset_data['code'])
for asset_data in kitsu_assets]
@ -241,7 +207,5 @@ class KitsuConnector(Connector):
"""
Retrieve the render settings for the given shot.
"""
kitsu_project = self.__get_production_data()
resolution = kitsu_project.get_resolution()
frames_per_second = shot.frames_per_second
return RenderSettings(width=resolution[0], height=resolution[1], frames_per_second=frames_per_second)
project = cache.project_active_get()
return RenderSettings(width=int(project.resolution.split('x')[0]), height=int(project.resolution.split('x')[1]), frames_per_second=project.fps)

View File

@ -1,4 +1,4 @@
from shot_builder.asset import Asset
from blender_kitsu.shot_builder.asset import Asset
class SpriteFrightAsset(Asset):

View File

@ -1,4 +1,4 @@
from shot_builder.connectors.kitsu import KitsuConnector
from blender_kitsu.shot_builder.connectors.kitsu import KitsuConnector
PRODUCTION_NAME = KitsuConnector
SHOTS = KitsuConnector

View File

@ -1,8 +1,8 @@
import bpy
from shot_builder.hooks import hook, Wildcard
from shot_builder.asset import Asset
from shot_builder.shot import Shot
from shot_builder.project import Production
from blender_kitsu.shot_builder.hooks import hook, Wildcard
from blender_kitsu.shot_builder.asset import Asset
from blender_kitsu.shot_builder.shot import Shot
from blender_kitsu.shot_builder.project import Production
import logging

View File

@ -0,0 +1,6 @@
# Example configuration files
This folder contains an example shot builder configuration. It shows the part
that a TD would do to incorporate the shot builder in a production.

View File

@ -1,5 +1,5 @@
from shot_builder.shot import Shot
from shot_builder.project import Production
from blender_kitsu.shot_builder.shot import Shot
from blender_kitsu.shot_builder.project import Production
class SpriteFrightShot(Shot):

View File

@ -78,7 +78,7 @@ class Hooks:
def _register_hook(func: types.FunctionType) -> None:
from shot_builder.project import get_active_production
from blender_kitsu.shot_builder.project import get_active_production
production = get_active_production()
production.hooks.register(func)

View File

@ -19,10 +19,11 @@
# <pep8 compliant>
from typing import *
import bpy
from shot_builder.shot import ShotRef
from shot_builder.project import *
from shot_builder.builder import ShotBuilder
from shot_builder.task_type import TaskType
from blender_kitsu.shot_builder.shot import ShotRef
from blender_kitsu.shot_builder.project import ensure_loaded_production, get_active_production
from blender_kitsu.shot_builder.builder import ShotBuilder
from blender_kitsu.shot_builder.task_type import TaskType
from blender_kitsu import prefs, cache
_production_task_type_items: List[Tuple[str, str, str]] = []
@ -103,18 +104,34 @@ class SHOTBUILDER_OT_NewShotFile(bpy.types.Operator):
)
def invoke(self, context: bpy.types.Context, event: bpy.types.Event) -> Set[str]:
addon_prefs = prefs.addon_prefs_get(bpy.context)
project = cache.project_active_get()
production_root = get_production_root(context)
if production_root is None:
if addon_prefs.session.is_auth() is False:
self.report(
{'WARNING'}, "Operator is cancelled due to inability to determine the production path. Make sure the a default path in configured in the preferences.")
{'ERROR'}, "Must be logged into Kitsu to continue. Check login status in 'Blender Kitsu' addon preferences.")
return {'CANCELLED'}
if project.id == "":
self.report(
{'ERROR'}, "Operator is not able to determine the Kitsu production's name. Check project is selected in 'Blender Kitsu' addon preferences.")
return {'CANCELLED'}
if not addon_prefs.is_project_root_valid:
self.report(
{'ERROR'}, "Operator is not able to determine the project root directory. Check project root directiory is configured in 'Blender Kitsu' addon preferences.")
return {'CANCELLED'}
self.production_root = addon_prefs.project_root_dir
self.production_name = project.name
ensure_loaded_production(context)
production = get_active_production()
self.production_root = str(production.path)
self.production_name = production.get_name(context=context)
self.production_root = addon_prefs.project_root_dir
self.production_name = project.name
global _production_task_type_items
_production_task_type_items = production.get_task_type_items(

View File

@ -23,15 +23,18 @@ from collections import defaultdict
import bpy
from shot_builder.task_type import *
from shot_builder.shot import Shot, ShotRef
from shot_builder.render_settings import RenderSettings
from shot_builder.asset import Asset, AssetRef
from shot_builder.sys_utils import *
from shot_builder.hooks import Hooks, register_hooks
from blender_kitsu.shot_builder.task_type import *
from blender_kitsu.shot_builder.shot import Shot, ShotRef
from blender_kitsu.shot_builder.render_settings import RenderSettings
from blender_kitsu.shot_builder.asset import Asset, AssetRef
from blender_kitsu.shot_builder.sys_utils import *
from blender_kitsu.shot_builder.hooks import Hooks, register_hooks
from shot_builder.connectors.default import DefaultConnector
from shot_builder.connectors.connector import Connector
from blender_kitsu.shot_builder.connectors.default import DefaultConnector
from blender_kitsu.shot_builder.connectors.connector import Connector
from blender_kitsu import prefs
from pathlib import Path
from typing import *
import types
@ -77,7 +80,7 @@ class Production:
connector_cls: Type[Connector],
context: bpy.types.Context) -> Connector:
# TODO: Cache connector
preferences = context.preferences.addons[__package__].preferences
preferences = context.preferences.addons["blender_kitsu"].preferences
return connector_cls(production=self, preferences=preferences)
def __format_shot_name(self, shot: Shot) -> str:
@ -382,8 +385,9 @@ def get_production_root(context: bpy.types.Context) -> Optional[pathlib.Path]:
production_root = _find_production_root(current_file)
if production_root:
return production_root
production_root = pathlib.Path(
context.preferences.addons[__package__].preferences.production_path)
addon_prefs = prefs.addon_prefs_get(bpy.context)
production_root = Path(addon_prefs.project_root_dir)
if is_valid_production_root(production_root):
return production_root
return None

View File

@ -18,7 +18,7 @@
# <pep8 compliant>
from shot_builder.asset import Asset
from blender_kitsu.shot_builder.asset import Asset
from typing import *

View File

@ -19,7 +19,7 @@
# <pep8 compliant>
import bpy
from typing import *
from shot_builder.operators import *
from blender_kitsu.shot_builder.operators import *
def topbar_file_new_draw_handler(self: Any, context: bpy.types.Context) -> None:

View File

@ -1,57 +0,0 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
import pathlib
from shot_builder.project import is_valid_production_root
from shot_builder.connectors.kitsu import KitsuPreferences
class ShotBuilderPreferences(bpy.types.AddonPreferences):
bl_idname = __package__
production_path: bpy.props.StringProperty( # type: ignore
name="Production Root",
description="The location to load configuration files from when "
"they couldn't be found in any parent folder of the current "
"file. Folder must contain a sub-folder named `shot-builder` "
"that holds the configuration files",
subtype='DIR_PATH',
)
kitsu: bpy.props.PointerProperty( # type: ignore
name="Kitsu Preferences",
type=KitsuPreferences
)
def draw(self, context: bpy.types.Context) -> None:
layout = self.layout
is_valid = is_valid_production_root(pathlib.Path(self.production_path))
layout.prop(self, "production_path",
icon='NONE' if is_valid else 'ERROR')
if not is_valid:
layout.label(text="Folder must contain a sub-folder named "
"`shot-builder` that holds the configuration "
"files.",
icon="ERROR")
sublayout = layout.box()
self.kitsu.draw(sublayout, context)