parent
e363e8e193
commit
c5de2a5675
@ -0,0 +1,111 @@ |
||||
# Byte-compiled / optimized / DLL files |
||||
__pycache__/ |
||||
*.py[cod] |
||||
*$py.class |
||||
|
||||
# C extensions |
||||
*.so |
||||
|
||||
# Distribution / packaging |
||||
.Python |
||||
build/ |
||||
develop-eggs/ |
||||
dist/ |
||||
downloads/ |
||||
eggs/ |
||||
.eggs/ |
||||
lib/ |
||||
lib64/ |
||||
parts/ |
||||
sdist/ |
||||
var/ |
||||
wheels/ |
||||
*.egg-info/ |
||||
.installed.cfg |
||||
*.egg |
||||
MANIFEST |
||||
|
||||
# PyInstaller |
||||
# Usually these files are written by a python script from a template |
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it. |
||||
*.manifest |
||||
*.spec |
||||
|
||||
# Installer logs |
||||
pip-log.txt |
||||
pip-delete-this-directory.txt |
||||
|
||||
# Unit test / coverage reports |
||||
htmlcov/ |
||||
.tox/ |
||||
.coverage |
||||
.coverage.* |
||||
.cache |
||||
nosetests.xml |
||||
coverage.xml |
||||
*.cover |
||||
.hypothesis/ |
||||
.pytest_cache/ |
||||
|
||||
# Translations |
||||
*.mo |
||||
*.pot |
||||
|
||||
# Django stuff: |
||||
*.log |
||||
local_settings.py |
||||
db.sqlite3 |
||||
|
||||
# Flask stuff: |
||||
instance/ |
||||
.webassets-cache |
||||
|
||||
# Scrapy stuff: |
||||
.scrapy |
||||
|
||||
# Sphinx documentation |
||||
docs/_build/ |
||||
|
||||
# PyBuilder |
||||
target/ |
||||
|
||||
# Jupyter Notebook |
||||
.ipynb_checkpoints |
||||
|
||||
# pyenv |
||||
.python-version |
||||
|
||||
# celery beat schedule file |
||||
celerybeat-schedule |
||||
|
||||
# SageMath parsed files |
||||
*.sage.py |
||||
|
||||
# Environments |
||||
.env |
||||
.venv |
||||
env/ |
||||
venv/ |
||||
ENV/ |
||||
env.bak/ |
||||
venv.bak/ |
||||
|
||||
# Spyder project settings |
||||
.spyderproject |
||||
.spyproject |
||||
|
||||
# Rope project settings |
||||
.ropeproject |
||||
|
||||
# mkdocs documentation |
||||
/site |
||||
|
||||
# mypy |
||||
.mypy_cache/ |
||||
|
||||
# IDE |
||||
.idea/ |
||||
.vscode/ |
||||
|
||||
# Settings |
||||
.pylintrc |
@ -0,0 +1,30 @@ |
||||
stages: |
||||
- build |
||||
- test |
||||
- deploy |
||||
|
||||
variables: |
||||
SCRIPT_PATH: "$STUDIOTECH_DIR/$STUDIOTECH_ROOT/$CI_COMMIT_REF_NAME/$STUDIOTECH_BIP/$SUBTYPE/$CI_PROJECT_NAME" |
||||
|
||||
before_script: |
||||
- mkdir $STUDIOTECH_DIR |
||||
- apk add cifs-utils |
||||
- touch /root/.smbcredentials |
||||
- echo "username=$STUDIOTECH_USER" >> /root/.smbcredentials |
||||
- echo "password=$STUDIOTECH_PASSWORD" >> /root/.smbcredentials |
||||
- echo "$CI_COMMIT_REF_NAME" |
||||
- tail /root/.smbcredentials |
||||
- chown 0.0 /root/.smbcredentials |
||||
- chmod 600 ~/.smbcredentials |
||||
- echo "//studio/tech $STUDIOTECH_DIR cifs credentials=/root/.smbcredentials,users,rw,iocharset=utf8,sec=ntlm,vers=3.0 0 0" >> /etc/fstab |
||||
- mount -a |
||||
|
||||
copy-to-production: |
||||
only: |
||||
- master |
||||
- develop |
||||
stage: deploy |
||||
script: |
||||
- mkdir -p $SCRIPT_PATH |
||||
- rm -rf $SCRIPT_PATH/* |
||||
- cp -r ./$CI_PROJECT_NAME/. $SCRIPT_PATH |
@ -0,0 +1,21 @@ |
||||
MIT License |
||||
|
||||
Copyright (c) 2019 Blinkink |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
@ -1,2 +1,2 @@ |
||||
# scenemanager |
||||
|
||||
# Scene Manager |
||||
Resource manager for Bip |
||||
|
@ -0,0 +1,27 @@ |
||||
# Scenario |
||||
|
||||
Init |
||||
- Get locale |
||||
- Get element list from: |
||||
- Locale (scene) |
||||
- Data (metadata) |
||||
- For each element: |
||||
- Get type (from metadata or collection) |
||||
- From type and context: get method |
||||
- From type and method: get presets |
||||
- Display |
||||
Contenant/Contenu = Item/Modifier !! TODO |
||||
At export |
||||
- For each item selected: |
||||
- Run selected method safety check |
||||
- Run item sanity check |
||||
- If any, display safety and sanity check message |
||||
- For each item selected: |
||||
- Run method, with preset |
||||
- Write metadata |
||||
Objects |
||||
- Item |
||||
- Model |
||||
- Rig |
||||
- ... |
||||
- Modifier |
@ -0,0 +1,145 @@ |
||||
#!/usr/bin/python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
import modo |
||||
import lx |
||||
import os |
||||
from wink.exceptions import ValidationError |
||||
from scenemanager.api import Method |
||||
|
||||
|
||||
def get_asset_type(): |
||||
scene = modo.Scene() |
||||
asset_types = ImportLayout.asset_types |
||||
if scene.filename: |
||||
for asset_type in asset_types: |
||||
if asset_type.upper() in scene.filename: |
||||
return asset_type |
||||
else: |
||||
asset_type = set_user_value("Asset Type", "list", asset_types) |
||||
if asset_type: |
||||
return asset_type |
||||
else: |
||||
raise ValidationError("You must select an asset type.") |
||||
|
||||
|
||||
def set_user_value(name, type_, values): |
||||
lx.eval("user.defNew {%s} type:integer life:momentary" % name) |
||||
lx.eval("!user.def {%s} {%s} {%s}" % (name, type_, ";".join(values))) |
||||
try: |
||||
lx.eval("?user.value {%s}" % name) |
||||
except RuntimeError: |
||||
return False |
||||
|
||||
answer = lx.eval("user.value {%s} ?" % name) |
||||
return answer |
||||
|
||||
|
||||
class ImportLayout(Method): |
||||
"""Imports and set up a basic Layout scene. |
||||
|
||||
Imports the neutral scene, neutral light rig, and camera, for modelling and lookdev reviews. |
||||
""" |
||||
asset_types = ["Characters", "Props", "Vehicles"] |
||||
neutral_scene_file = "NeutralScene_GRP" |
||||
neutral_scene_directory = ( |
||||
"\\\\studio\\jobs\\INK000_StudioTeam\\LIBRARIES\\ASSETS\\TEMPLATES\\SceneA\\MODELS" |
||||
"\\MODELLING\\ " |
||||
) |
||||
neutral_scene_item = "Lightrig_Neutral_01_GRP" |
||||
default_fps = 25.0 |
||||
default_framerange = (1001, 1100) |
||||
|
||||
def __init__(self, asset_type): |
||||
""" |
||||
Args: |
||||
asset_type (str): Must be one of the asset_types class attribute. |
||||
""" |
||||
self.asset_type = asset_type |
||||
|
||||
def run(self): |
||||
""" |
||||
Import Layout scenario. |
||||
- Set default framerange (cls.default_framerange) |
||||
- Set default fps (cls.default_fps) |
||||
- Import layout based upon scene type |
||||
- Removes duplicate folders and reparents |
||||
- Makes Asset group rotate |
||||
- Sets Render Camera |
||||
""" |
||||
self.scene.sceneRange = self.default_framerange |
||||
self.scene.fps = self.default_fps |
||||
|
||||
self.clean() |
||||
self.import_neutral_layout() |
||||
self.set_asset_group_rotation() |
||||
self.set_render_camera() |
||||
|
||||
def import_neutral_layout(self): |
||||
"""Import Neutral layout if not found. |
||||
|
||||
If an item named cls.neutral_scene_file can't be found, |
||||
the latest neutral scene is imported and parented to LIGHTRIGS |
||||
""" |
||||
try: |
||||
self.scene.item(self.neutral_scene_file) |
||||
except LookupError: |
||||
latest = False |
||||
directory = self.neutral_scene_directory + self.asset_type |
||||
for dir, sub, files in os.walk(directory): |
||||
latest = files[-1] |
||||
|
||||
if not latest: |
||||
raise ValidationError('Can not find the latest version of the neutral scene.') |
||||
|
||||
latest_file = directory + "\\" + latest |
||||
lx.eval("app.load %s" % latest_file) |
||||
|
||||
self.scene.item(self.neutral_scene_item).setParent( |
||||
self.scene.item("LIGHTRIGS") |
||||
) |
||||
|
||||
def remove_duplicate_folders(self): |
||||
"""Removes duplicates folders""" |
||||
to_remove = ["CAMERAS", "LAYOUT", "TEXTURES"] |
||||
for folder in to_remove: |
||||
self.remove_duplicate(folder) |
||||
|
||||
def remove_original_env(self): |
||||
"""Removes original environment and default lights""" |
||||
to_remove = ["Environment", "Directional Light", "Texture Group"] |
||||
for item in to_remove: |
||||
self.safe_delete(item) |
||||
|
||||
def clean(self): |
||||
"""Combines remove_duplicate_folders and remove_original_env""" |
||||
self.remove_duplicate_folders() |
||||
self.remove_original_env() |
||||
|
||||
def set_asset_group_rotation(self): |
||||
"""Transfer the Y rotation channels from the turntable to the asset group""" |
||||
source = self.scene.item("TurnTable_01_CTL") |
||||
destination = self.scene.item("ASSETS") |
||||
source.rotation.y >> destination.rotation.y |
||||
|
||||
def set_render_camera(self): |
||||
"""TODO: Write docstring""" |
||||
self.scene.item("Render").itemGraph("shadeLoc") >> self.scene.item( |
||||
"Camera_Main_01_CAM" |
||||
).itemGraph("shadeLoc") |
||||
|
||||
cams = self.scene.items("camera") |
||||
for each in cams: |
||||
self.scene.item(each.name).itemGraph("shadeLoc") << self.scene.item( |
||||
"Render" |
||||
).itemGraph("shadeLoc") |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
try: |
||||
type_ = get_asset_type() |
||||
except ValidationError as error: |
||||
print(error.message) |
||||
else: |
||||
method = ImportLayout(type_) |
||||
method.run() |
@ -0,0 +1,49 @@ |
||||
#!/usr/bin/python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
import modo |
||||
import lx |
||||
import os |
||||
from wink.exceptions import ValidationError |
||||
from scenemanager.api import Method |
||||
|
||||
|
||||
# Temporary functions for extracting pipeline data |
||||
def get_some_data(): |
||||
return 'something' |
||||
|
||||
|
||||
class SampleMethod(Method): |
||||
"""Quick description of the class. |
||||
|
||||
Detailled description of the class. |
||||
""" |
||||
# * Class-wide attributes. Sort of embeded constants. |
||||
some_class_attribute = True |
||||
|
||||
def __init__(self, arg): |
||||
""" |
||||
Args: |
||||
arg (str): Description of the expected arguments. |
||||
""" |
||||
super(SampleMethod).__init__() |
||||
self.some_attribute = arg |
||||
|
||||
def run(self): |
||||
""" |
||||
Main method. It will be executed by the Scene Manager. |
||||
""" |
||||
super(SampleMethod).run() |
||||
self.do_something() |
||||
|
||||
def do_something(self): |
||||
"""Short description. |
||||
|
||||
Longer description with details. |
||||
""" |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
some_data = get_some_data() |
||||
method = SampleMethod(some_data) |
||||
method.run() |
@ -0,0 +1,13 @@ |
||||
# /usr/bin/python |
||||
# -*- coding: utf-8 -*- |
||||
import socket |
||||
|
||||
HOST = "127.0.0.1" |
||||
PORT = 12357 |
||||
|
||||
command = 'bip.scenemanager' |
||||
|
||||
modo_connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
||||
modo_connection.connect((HOST, PORT)) |
||||
modo_connection.sendall("{}\0".format(command)) |
||||
modo_connection.close() |
@ -0,0 +1,6 @@ |
||||
PySide |
||||
components |
||||
link |
||||
wink |
||||
modo |
||||
lx |
@ -0,0 +1,52 @@ |
||||
#!/usr/bin/python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
# (c) 2019, Blinkink |
||||
# corentin@blinkink.co.uk |
||||
|
||||
# Redistribution and use in source and binary forms, with or without |
||||
# modification, are permitted provided that the following conditions are met: |
||||
|
||||
# * Redistributions of source code must retain the above copyright notice, |
||||
# this list of conditions and the following disclaimer. |
||||
|
||||
# * Redistributions in binary form must reproduce the above copyright notice, |
||||
# this list of conditions and the following disclaimer in the documentation |
||||
# and/or other materials provided with the distribution. |
||||
|
||||
# * Neither the name Blinkink nor the names of its contributors |
||||
# may be used to endorse or promote products derived from this software |
||||
# without specific prior written permission. |
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS |
||||
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, |
||||
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
||||
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
||||
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
__version__ = "0.0.1" |
||||
__status__ = "Work In Progress" |
||||
__license__ = "MIT" |
||||
|
||||
__author__ = "Blinkink" |
||||
__email__ = "corentin@blinkink.co.uk" |
||||
|
||||
__module_name__ = "scenemanager" |
||||
__description__ = "Resource scene manager" |
||||
__url__ = "http://doc.blinkink.co.uk/books/bip-developer-guide" |
||||
|
||||
from scenemanager.app import SceneManager |
||||
from scenemanager.api import Method |
||||
import scenemanager.constants |
||||
|
||||
__all__ = [ |
||||
"SceneManager", |
||||
"Method", |
||||
"constants", |
||||
] |
@ -0,0 +1,18 @@ |
||||
#!/usr/bin/python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
|
||||
import sys |
||||
from PySide.QtGui import QApplication |
||||
from scenemanager import SceneManager |
||||
from link.constants.context import STANDALONE |
||||
|
||||
|
||||
def main(): |
||||
app = QApplication(sys.argv) |
||||
window = SceneManager(context=STANDALONE) |
||||
sys.exit(app.exec_()) |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
main() |
@ -0,0 +1 @@ |
||||
from scenemanager.api.method import Method |
@ -0,0 +1,57 @@ |
||||
#!/usr/bin/python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
import modo |
||||
import lx |
||||
|
||||
|
||||
class Method(object): |
||||
"""Quick description of the class. |
||||
|
||||
Detailled description of the class. |
||||
""" |
||||
def __init__(self): |
||||
self.scene = modo.Scene() |
||||
|
||||
def run(self): |
||||
pass |
||||
|
||||
def safe_delete(self, item_name): |
||||
"""Attempts to delete an item from the scene, and catches the exception if it doesn't exists |
||||
|
||||
Args: |
||||
item_name (str): Name of the item to be deleted. |
||||
|
||||
Returns: |
||||
True if successful, False otherwise. |
||||
""" |
||||
try: |
||||
self.scene.item(item_name) |
||||
except LookupError: |
||||
return False |
||||
else: |
||||
self.scene.removeItems(item_name) |
||||
return True |
||||
|
||||
def remove_duplicate(self, item_name): |
||||
"""Look for potential duplicates of a given item, reparent children and delete duplicate |
||||
|
||||
Looks for an item named like the provide argument + " (2)", reparents its children |
||||
to the original and then deletes the duplicate. |
||||
|
||||
Args: |
||||
item_name (str): Name of the original item |
||||
|
||||
Returns: |
||||
True if successful, False otherwise. |
||||
""" |
||||
try: |
||||
duplicate = self.scene.item(item_name + " (2)") |
||||
original = self.scene.item(item_name) |
||||
except LookupError: |
||||
return False |
||||
else: |
||||
for child in duplicate.children(): |
||||
child.setParent(original) |
||||
self.scene.removeItems(duplicate) |
||||
return True |
@ -0,0 +1,30 @@ |
||||
#!/usr/bin/python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
from link.app import BipAppController |
||||
from scenemanager.view import SceneManagerView |
||||
from scenemanager.constants import * |
||||
|
||||
|
||||
class SceneManager(BipAppController): |
||||
""" |
||||
Scene Manager application |
||||
""" |
||||
|
||||
def __init__(self, context, dcc=None): |
||||
super(SceneManager, self).__init__(context=context) |
||||
self.context = context |
||||
self.dcc = dcc |
||||
|
||||
self.name = NAME |
||||
self.display_name = DISPLAY_NAME |
||||
self.description = DESCRIPTION |
||||
self.main_color = MAIN_COLOR |
||||
self.secondary_color = SECONDARY_COLOR |
||||
self.version = VERSION |
||||
self.documentation_url = DOCUMENTATION_URL |
||||
self.bugtracker_url = BUGTRACKER_URL |
||||
|
||||
self.view = SceneManagerView(controller=self) |
||||
self.view.set_stylesheet() |
||||
self.view.show() |
@ -0,0 +1,19 @@ |
||||
#!/usr/bin/python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
from scenemanager import __version__, __name__, __url__, __status__ |
||||
|
||||
NAME = __name__ |
||||
DISPLAY_NAME = NAME.capitalize() |
||||
if __status__ == "Work In Progress": |
||||
DISPLAY_NAME += " (WIP)" |
||||
DESCRIPTION = "Manage DCC resources" |
||||
MAIN_COLOR = "#C4C4C4" |
||||
SECONDARY_COLOR = "#C2C2C2" |
||||
VERSION = __version__ |
||||
DOCUMENTATION_URL = __url__ |
||||
BUGTRACKER_URL = "https://tickets.blinkink.co.uk/project/pipeline/issues?tags=exporter" |
||||
|
||||
# UI |
||||
HEIGHT = 860 |
||||
WIDTH = 1400 |
@ -0,0 +1,17 @@ |
||||
#!/usr/bin/python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
from PySide.QtGui import * |
||||
|
||||
from components import BipAppView |
||||
from scenemanager.constants import WIDTH, HEIGHT |
||||
|
||||
|
||||
class SceneManagerView(BipAppView): |
||||
def __init__(self, controller): |
||||
super(SceneManagerView, self).__init__(controller) |
||||
self.controller = controller |
||||
|
||||
self.place_holder = QWidget() |
||||
self.widget = self.place_holder |
||||
self.resize(WIDTH, HEIGHT) |
@ -0,0 +1,39 @@ |
||||
#!/usr/bin/python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
from setuptools import setup, find_packages |
||||
from os import path |
||||
from codecs import open |
||||
|
||||
from scenemanager import NAME, VERSION, LICENSE, AUTHOR, EMAIL, DESCRIPTION, URL |
||||
|
||||
|
||||
_here = path.abspath(path.dirname(__file__)) |
||||
_readme_filepath = path.join(_here, "README.md") |
||||
_requirements_filepath = path.join(_here, "requirements.txt") |
||||
|
||||
|
||||
if path.isfile(_readme_filepath): |
||||
with open(_readme_filepath, encoding="utf-8") as readme_file: |
||||
_long_description = readme_file.read() |
||||
else: |
||||
_long_description = "Unable to load README.md" |
||||
|
||||
|
||||
if path.isfile(_requirements_filepath): |
||||
with open(_requirements_filepath) as requirements_file: |
||||
_requirements = requirements_file.readlines() |
||||
else: |
||||
_requirements = list() |
||||
|
||||
setup( |
||||
name=NAME, |
||||
version=VERSION, |
||||
packages=find_packages(exclude=["tests"]), |
||||
url=URL, |
||||
license=LICENSE, |
||||
author=AUTHOR, |
||||
author_email=EMAIL, |
||||
description=DESCRIPTION, |
||||
install_requires=_requirements, |
||||
) |
Loading…
Reference in new issue