Implemented Branch/Rank objects in ranks.py
This commit is contained in:
parent
6e056fcef7
commit
6ff5b6b4f5
@ -41,7 +41,6 @@ from . import copy_anim
|
|||||||
from abx import ink_paint
|
from abx import ink_paint
|
||||||
from . import render_profile
|
from . import render_profile
|
||||||
|
|
||||||
|
|
||||||
#configfile = os.path.join(os.path.dirname(__file__), 'config.yaml')
|
#configfile = os.path.join(os.path.dirname(__file__), 'config.yaml')
|
||||||
|
|
||||||
#print("Configuration file path: ", os.path.abspath(configfile))
|
#print("Configuration file path: ", os.path.abspath(configfile))
|
||||||
@ -223,6 +222,17 @@ class LunaticsSceneProperties(bpy.types.PropertyGroup):
|
|||||||
NOTE: due to be replaced by 'ProjectProperties', using the schema data
|
NOTE: due to be replaced by 'ProjectProperties', using the schema data
|
||||||
retrieved by file_context.
|
retrieved by file_context.
|
||||||
"""
|
"""
|
||||||
|
name_context_id = bpy.props.StringProperty(options={'HIDDEN', 'LIBRARY_EDITABLE'})
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name_context(self):
|
||||||
|
if self.name_context_id in BlendFile.name_contexts:
|
||||||
|
return BlendFile.name_contexts[self.name_context_id]
|
||||||
|
else:
|
||||||
|
name_context = BlendFile.new_name_context()
|
||||||
|
self.name_context_id = str(id(name_context))
|
||||||
|
return name_context
|
||||||
|
|
||||||
series_id = bpy.props.EnumProperty(
|
series_id = bpy.props.EnumProperty(
|
||||||
items=[
|
items=[
|
||||||
('S1', 'S1', 'Series One'),
|
('S1', 'S1', 'Series One'),
|
||||||
|
@ -1344,7 +1344,7 @@ class FileContext(NameContext):
|
|||||||
|
|
||||||
# Containers
|
# Containers
|
||||||
#self.notes = []
|
#self.notes = []
|
||||||
self.name_contexts = []
|
self.name_contexts = {}
|
||||||
|
|
||||||
# Status / Settings
|
# Status / Settings
|
||||||
self.filepath = None
|
self.filepath = None
|
||||||
@ -1637,7 +1637,10 @@ class FileContext(NameContext):
|
|||||||
namepath_segment = []
|
namepath_segment = []
|
||||||
ranks = [s.rank for s in self.schemas]
|
ranks = [s.rank for s in self.schemas]
|
||||||
i_rank = len(self.namepath)
|
i_rank = len(self.namepath)
|
||||||
old_rank = ranks[i_rank -1]
|
if i_rank == 0:
|
||||||
|
old_rank = None
|
||||||
|
else:
|
||||||
|
old_rank = ranks[i_rank -1]
|
||||||
|
|
||||||
# The new rank will be the highest rank mentioned, or the
|
# The new rank will be the highest rank mentioned, or the
|
||||||
# explicitly requested rank or
|
# explicitly requested rank or
|
||||||
@ -1655,7 +1658,11 @@ class FileContext(NameContext):
|
|||||||
if ranks.index(schema.rank) <= ranks.index(rank):
|
if ranks.index(schema.rank) <= ranks.index(rank):
|
||||||
new_rank = schema.rank
|
new_rank = schema.rank
|
||||||
|
|
||||||
delta_rank = ranks.index(new_rank) - ranks.index(old_rank)
|
if old_rank:
|
||||||
|
delta_rank = ranks.index(new_rank) - ranks.index(old_rank)
|
||||||
|
else:
|
||||||
|
# I think in this case, it's as if the old_rank number is -1?
|
||||||
|
delta_rank = ranks.index(new_rank) + 1
|
||||||
|
|
||||||
# Truncate to the new rank:
|
# Truncate to the new rank:
|
||||||
namepath_segment = namepath_segment[:delta_rank]
|
namepath_segment = namepath_segment[:delta_rank]
|
||||||
@ -1663,9 +1670,12 @@ class FileContext(NameContext):
|
|||||||
fields['rank'] = new_rank
|
fields['rank'] = new_rank
|
||||||
fields['code'] = namepath_segment[-1]
|
fields['code'] = namepath_segment[-1]
|
||||||
|
|
||||||
self.name_contexts.append(NameContext(self, fields,
|
name_context = NameContext(self, fields,
|
||||||
namepath_segment=namepath_segment))
|
namepath_segment=namepath_segment)
|
||||||
return self.name_contexts[-1]
|
|
||||||
|
self.name_contexts[str(id(name_context))] = name_context
|
||||||
|
|
||||||
|
return name_context
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
247
abx/ranks.py
Normal file
247
abx/ranks.py
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
# ranks.py
|
||||||
|
"""
|
||||||
|
Branches and ranks objects.
|
||||||
|
|
||||||
|
Objects for representing the ranks of a hierarchy, with the
|
||||||
|
possibility of branching at nodes with redefined ranks via
|
||||||
|
the 'project_schema' directives in project YAML files.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import numbers
|
||||||
|
|
||||||
|
class Branch(object):
|
||||||
|
"""
|
||||||
|
Branch represents a ranking system in the tree of schemas.
|
||||||
|
|
||||||
|
It takes the name of the project_unit where the ranking system
|
||||||
|
is overridden, and controls how all ranks defined within it
|
||||||
|
are interpreted.
|
||||||
|
"""
|
||||||
|
def __init__(self, parent, code, start, ranks):
|
||||||
|
self.parent = parent
|
||||||
|
self.code = str(code)
|
||||||
|
self.start = int(start)
|
||||||
|
|
||||||
|
self._ranks = RankList(self,[])
|
||||||
|
if parent:
|
||||||
|
for rank in parent.ranks:
|
||||||
|
if int(rank) < start:
|
||||||
|
self._ranks.append(rank)
|
||||||
|
|
||||||
|
for num, name in enumerate(ranks):
|
||||||
|
rank = Rank(self, num + start, name)
|
||||||
|
self._ranks.append(rank)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
ranklist = ', '.join([str(r) for r in self.ranks[1:]])
|
||||||
|
if self.code:
|
||||||
|
code = self.code
|
||||||
|
else:
|
||||||
|
code = 'trunk'
|
||||||
|
return "<branch '%s': %s>" % (code, ranklist)
|
||||||
|
|
||||||
|
def __contains__(self, other):
|
||||||
|
if isinstance(other, Rank) and other in self._ranks:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def rank(self, n):
|
||||||
|
"""
|
||||||
|
Coerce int or string to rank, if it matches a rank in this Branch.
|
||||||
|
"""
|
||||||
|
if isinstance(n, int) and 0 < n < len(self._ranks):
|
||||||
|
return self._ranks[n]
|
||||||
|
elif isinstance(n, str):
|
||||||
|
for rank in self._ranks:
|
||||||
|
if str(rank) == n:
|
||||||
|
return rank
|
||||||
|
else:
|
||||||
|
raise TypeError
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ranks(self):
|
||||||
|
# Read-only property.
|
||||||
|
return self._ranks
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Rank(object):
|
||||||
|
"""
|
||||||
|
Ranks are named numbers indicating the position in a hierarchy.
|
||||||
|
|
||||||
|
They can be incremented and decremented. The value 0 represents the top
|
||||||
|
rank, with increasing numbers indicating finer grades in taxonomic rank.
|
||||||
|
|
||||||
|
They can have integers added to or subtracted from them, meaning to go
|
||||||
|
down or up in rank. They cannot be added to each other, though. Note that
|
||||||
|
higher and lower rank in the real world since of more or less scope is
|
||||||
|
inverted as a number -- the lower rank has a higher number.
|
||||||
|
|
||||||
|
There are upper and lower bounds to rank, defined by the schema 'Branch'.
|
||||||
|
|
||||||
|
Coercing a rank to an integer (int()) returns the numeric rank.
|
||||||
|
|
||||||
|
Coercing a rank to a string (str()) returns the rank name.
|
||||||
|
|
||||||
|
The representation includes the branch name and rank name.
|
||||||
|
|
||||||
|
Ranks can be subtracted, returning an integer representing the difference
|
||||||
|
in rank.
|
||||||
|
"""
|
||||||
|
def __init__(self, branch, num, name):
|
||||||
|
self.num = num
|
||||||
|
self.name = name
|
||||||
|
self.branch = branch
|
||||||
|
|
||||||
|
def __index__(self):
|
||||||
|
return self.num
|
||||||
|
|
||||||
|
def __int__(self):
|
||||||
|
return self.num
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<%s:%d-%s>' % (self.branch.code, self.num, self.name)
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash((self.branch, self.num, self.name))
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, Rank):
|
||||||
|
if hash(self) == hash(other):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
elif isinstance(other, str):
|
||||||
|
if other == self.name:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
elif isinstance(other, int):
|
||||||
|
if other == self.num:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __gt__(self, other):
|
||||||
|
if isinstance(other, Rank):
|
||||||
|
if self.num > other.num:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
elif isinstance(other, int):
|
||||||
|
if self.num > other:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
raise TypeError("Rank can't compare to %s" % type(other))
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
if isinstance(other, Rank):
|
||||||
|
if self.num < other.num:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
elif isinstance(other, int):
|
||||||
|
if self.num < other:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
raise TypeError("Rank can't compare to %s" % type(other))
|
||||||
|
|
||||||
|
def __ge__(self, other):
|
||||||
|
return (self > other or self == other)
|
||||||
|
|
||||||
|
def __le__(self, other):
|
||||||
|
return (self < other or self == other)
|
||||||
|
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
if isinstance(other, int):
|
||||||
|
if (self.num + other) < len(self.branch.ranks):
|
||||||
|
return self.branch.ranks[self.num+other]
|
||||||
|
elif (self.num + other) < 1:
|
||||||
|
return trunk
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
raise TypeError("Changes in rank must be integers.")
|
||||||
|
|
||||||
|
def __radd__(self, other):
|
||||||
|
return self.__add__(other)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
if isinstance(other, Rank):
|
||||||
|
return (self.num - other.num)
|
||||||
|
elif isinstance(other, int):
|
||||||
|
if 0 < (self.num - other) < len(self.branch.ranks):
|
||||||
|
return self.branch.ranks[self.num-other]
|
||||||
|
elif (self.num - other) < 1:
|
||||||
|
return trunk
|
||||||
|
elif (self.num - other) > len(self.branch.ranks):
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
raise TypeError("Rank subtraction not defined for %s" % type(other))
|
||||||
|
|
||||||
|
def __rsub__(self, other):
|
||||||
|
if isinstance(other, Rank):
|
||||||
|
return (other.num - self.num)
|
||||||
|
else:
|
||||||
|
raise TypeError("Rank subtraction not defined for %s" % type(other))
|
||||||
|
|
||||||
|
|
||||||
|
class RankList(list):
|
||||||
|
"""
|
||||||
|
Convenience wrapper for a list of ranks, with simplified look-up.
|
||||||
|
|
||||||
|
This allows indexes and slices on the ranks to use Rank objects and/or
|
||||||
|
string names in addition to integers for accessing the elements of the
|
||||||
|
list.
|
||||||
|
|
||||||
|
The RankList also has to know what branch it is indexing, so it includes
|
||||||
|
a 'branch' attribute.
|
||||||
|
"""
|
||||||
|
def __init__(self, branch, ranks):
|
||||||
|
self.branch = branch
|
||||||
|
for rank in ranks:
|
||||||
|
self.append(rank)
|
||||||
|
|
||||||
|
def __getitem__(self, rank):
|
||||||
|
if isinstance(rank, Rank):
|
||||||
|
i = int(rank)
|
||||||
|
elif isinstance(rank, str):
|
||||||
|
i = [r.name for r in self].index(rank)
|
||||||
|
elif isinstance(rank, int):
|
||||||
|
i = rank
|
||||||
|
elif isinstance(rank, slice):
|
||||||
|
if rank.start is None:
|
||||||
|
j = 0
|
||||||
|
else:
|
||||||
|
j = self.__getitem__(rank.start)
|
||||||
|
|
||||||
|
if rank.stop is None:
|
||||||
|
k = len(self)
|
||||||
|
else:
|
||||||
|
k = self.__getitem__(rank.stop)
|
||||||
|
|
||||||
|
s = []
|
||||||
|
for i in range(j,k):
|
||||||
|
s.append(super().__getitem__(i))
|
||||||
|
|
||||||
|
return s
|
||||||
|
else:
|
||||||
|
raise IndexError("Type %s not a valid index for RankList" % type(rank))
|
||||||
|
return super().__getitem__(i)
|
||||||
|
|
||||||
|
|
||||||
|
# Define the trunk branch object
|
||||||
|
# This schema will make sense for any unaffiliated Blender document,
|
||||||
|
# even if it hasn't been saved as a file yet:
|
||||||
|
trunk = Branch(None, '', 0, ('', 'file', 'scene'))
|
690
doc/Illus/ranks_branches.svg
Normal file
690
doc/Illus/ranks_branches.svg
Normal file
@ -0,0 +1,690 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="1920"
|
||||||
|
height="1080"
|
||||||
|
viewBox="0 0 1920 1080"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="1.0.2 (1.0.2+r75+1)"
|
||||||
|
sodipodi:docname="ranks_branches.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="1"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.0854167"
|
||||||
|
inkscape:cx="877.18978"
|
||||||
|
inkscape:cy="510.01846"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
showgrid="false"
|
||||||
|
units="px"
|
||||||
|
inkscape:window-width="2880"
|
||||||
|
inkscape:window-height="1620"
|
||||||
|
inkscape:window-x="455"
|
||||||
|
inkscape:window-y="44"
|
||||||
|
inkscape:window-maximized="0" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:32px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle"
|
||||||
|
x="859.29395"
|
||||||
|
y="75.932449"
|
||||||
|
id="text835"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="859.29395"
|
||||||
|
y="75.932449"
|
||||||
|
id="tspan920">"trunk"</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:24px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="833.41034"
|
||||||
|
y="144.69955"
|
||||||
|
id="text841"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan839"
|
||||||
|
x="833.41034"
|
||||||
|
y="144.69955">-</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="833.41034"
|
||||||
|
y="168.69955"
|
||||||
|
id="tspan843">file</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="833.41034"
|
||||||
|
y="192.69955"
|
||||||
|
id="tspan845">scene</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:32px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="814.9588"
|
||||||
|
y="282.52191"
|
||||||
|
id="text849"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan847"
|
||||||
|
x="814.9588"
|
||||||
|
y="282.52191">MyProject</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:24px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="836.71967"
|
||||||
|
y="346.81601"
|
||||||
|
id="text871"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan869"
|
||||||
|
x="836.71967"
|
||||||
|
y="346.81601"
|
||||||
|
style="fill:#b3b3b3">-</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="836.71967"
|
||||||
|
y="370.81601"
|
||||||
|
id="tspan1126">project</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="836.71967"
|
||||||
|
y="394.81601"
|
||||||
|
id="tspan873">series</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="836.71967"
|
||||||
|
y="418.81601"
|
||||||
|
id="tspan875">episode</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="836.71967"
|
||||||
|
y="442.81601"
|
||||||
|
id="tspan877">sequence</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="836.71967"
|
||||||
|
y="466.81601"
|
||||||
|
id="tspan879">block</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="836.71967"
|
||||||
|
y="490.81601"
|
||||||
|
id="tspan881">camera</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="836.71967"
|
||||||
|
y="514.81604"
|
||||||
|
id="tspan883">shot</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="836.71967"
|
||||||
|
y="538.81604"
|
||||||
|
id="tspan885">element</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:24px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="1324.7578"
|
||||||
|
y="703.01611"
|
||||||
|
id="text889"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan887"
|
||||||
|
x="1324.7578"
|
||||||
|
y="703.01611"
|
||||||
|
style="font-size:24px;fill:#cccccc">-</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1324.7578"
|
||||||
|
y="727.01611"
|
||||||
|
style="font-size:24px;fill:#cccccc"
|
||||||
|
id="tspan1128">project</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1324.7578"
|
||||||
|
y="751.01611"
|
||||||
|
id="tspan891">library</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1324.7578"
|
||||||
|
y="775.01611"
|
||||||
|
id="tspan893">department</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1324.7578"
|
||||||
|
y="799.01611"
|
||||||
|
id="tspan895">category</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1324.7578"
|
||||||
|
y="823.01611"
|
||||||
|
id="tspan897">subcategory</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:32px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="1303.8707"
|
||||||
|
y="640.34381"
|
||||||
|
id="text901"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan899"
|
||||||
|
x="1303.8707"
|
||||||
|
y="640.34381">Library</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:21.3333px;line-height:1;font-family:'Courier New';-inkscape-font-specification:'Courier New Bold';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
x="1290.4512"
|
||||||
|
y="277.65115"
|
||||||
|
id="text905"
|
||||||
|
transform="translate(13.419556,387.89022)"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan903"
|
||||||
|
x="1290.4512"
|
||||||
|
y="277.65115">library.yaml</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:21.3333px;line-height:1;font-family:'Courier New';-inkscape-font-specification:'Courier New Bold';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="814.9588"
|
||||||
|
y="305.64523"
|
||||||
|
id="text909"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan907"
|
||||||
|
x="814.9588"
|
||||||
|
y="305.64523">myproject.yaml</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:21.3333px;line-height:1;font-family:'Courier New';-inkscape-font-specification:'Courier New Bold';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
x="1326.4742"
|
||||||
|
y="67.188583"
|
||||||
|
id="text913"
|
||||||
|
transform="translate(-513.53124,35.760744)"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan911"
|
||||||
|
x="1326.4742"
|
||||||
|
y="67.188583">abx/abx.yaml</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:32px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="121.5862"
|
||||||
|
y="640.34381"
|
||||||
|
id="text917"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan915"
|
||||||
|
x="121.5862"
|
||||||
|
y="640.34381">Episodes</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:32px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="121.5862"
|
||||||
|
y="789.91241"
|
||||||
|
id="text921"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan919"
|
||||||
|
x="121.5862"
|
||||||
|
y="789.91241">A.001-Pilot</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:32px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="121.5862"
|
||||||
|
y="826.12451"
|
||||||
|
id="text925"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan923"
|
||||||
|
x="121.5862"
|
||||||
|
y="826.12451">Seq</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:32px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="121.5862"
|
||||||
|
y="862.33655"
|
||||||
|
id="text929"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan927"
|
||||||
|
x="121.5862"
|
||||||
|
y="862.33655">LP-LastPoint</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:32px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="121.5862"
|
||||||
|
y="898.54865"
|
||||||
|
id="text933"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan931"
|
||||||
|
x="121.5862"
|
||||||
|
y="898.54865">A.001-LP-1-BeginningOfEnd-anim.blend</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:32px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="121.5862"
|
||||||
|
y="753.70032"
|
||||||
|
id="text937"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan935"
|
||||||
|
x="121.5862"
|
||||||
|
y="753.70032">A</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:16px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic Semi-Bold';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="814.9588"
|
||||||
|
y="330.56796"
|
||||||
|
id="text960"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan958"
|
||||||
|
x="814.9588"
|
||||||
|
y="330.56796">Ranks:</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:16px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic Semi-Bold';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="812.7821"
|
||||||
|
y="126.22813"
|
||||||
|
id="text964"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan962"
|
||||||
|
x="812.7821"
|
||||||
|
y="126.22813">Ranks:</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:16px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic Semi-Bold';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="1303.8707"
|
||||||
|
y="690.45233"
|
||||||
|
id="text989"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan987"
|
||||||
|
x="1303.8707"
|
||||||
|
y="690.45233">Ranks:</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic Oblique';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="944.66821"
|
||||||
|
y="628.16779"
|
||||||
|
id="text993"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="628.16779"
|
||||||
|
id="tspan1006">At any level in the hierarchy, a project unit</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="641.5011"
|
||||||
|
id="tspan1333">may define a new schema with a 'project_schema'</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="654.83441"
|
||||||
|
id="tspan1335">key.</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="668.16766"
|
||||||
|
id="tspan1337" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="681.50098"
|
||||||
|
id="tspan1339">This key cannot change the interpretation of ranks</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="694.83429"
|
||||||
|
id="tspan1341">above the current unit, but only the ones below it</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="708.1676"
|
||||||
|
id="tspan1343">(and the current unit itself).</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="721.50085"
|
||||||
|
id="tspan1349" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="734.83417"
|
||||||
|
id="tspan1351">This creates a branch of the rank/schema</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="748.16748"
|
||||||
|
id="tspan1353">tree, which takes the name of the project</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="761.50079"
|
||||||
|
id="tspan1355">unit where the branch starts.</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="774.83411"
|
||||||
|
id="tspan1345" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="788.16736"
|
||||||
|
id="tspan1347">(And the first unit that is not inherited from</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="944.66821"
|
||||||
|
y="801.50067"
|
||||||
|
id="tspan1365">its parent Branch).</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:21.3333px;line-height:1;font-family:'Courier New';-inkscape-font-specification:'Courier New Bold';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="121.5862"
|
||||||
|
y="665.03693"
|
||||||
|
id="text911"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan909"
|
||||||
|
x="121.5862"
|
||||||
|
y="665.03693">episodes.yaml</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1;font-family:'Courier New';-inkscape-font-specification:'Courier New';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="189.16733"
|
||||||
|
y="684.3067"
|
||||||
|
id="text915"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="189.16733"
|
||||||
|
y="684.3067"
|
||||||
|
id="tspan917">project_unit:</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="189.16733"
|
||||||
|
y="700.3067"
|
||||||
|
id="tspan924"> from_folders: True</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="189.16733"
|
||||||
|
y="716.3067"
|
||||||
|
id="tspan926" /></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic Oblique';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="449.34958"
|
||||||
|
y="629.32965"
|
||||||
|
id="text944"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="629.32965"
|
||||||
|
id="tspan951">The Episodes directory is not</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="642.66296"
|
||||||
|
id="tspan1028">a unit, but each of the folders under it is (they</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="655.99628"
|
||||||
|
id="tspan1541">are 'series' units, all sharing the same 'series' rank</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="669.32953"
|
||||||
|
id="tspan1547">in the 'myproject' branch.</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="682.66284"
|
||||||
|
id="tspan1559" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="695.99615"
|
||||||
|
id="tspan1551">Rather than using a separate YAML files for each</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="709.32947"
|
||||||
|
id="tspan1567">series, this sample project uses a single file at the</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="722.66272"
|
||||||
|
id="tspan1569">top with 'project_unit' key that is used as a template.</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="735.99603"
|
||||||
|
id="tspan1571" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="749.32935"
|
||||||
|
id="tspan1573">It is distinguished from a normal 'project_unit' key</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="762.66266"
|
||||||
|
id="tspan1575">by providing the 'from_folders' setting, and not</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="775.99597"
|
||||||
|
id="tspan1577">containing a 'code', 'name', or 'title' setting.</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="789.32922"
|
||||||
|
id="tspan1579" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="802.66254"
|
||||||
|
id="tspan1581">Instead, these values will be set by the directory names</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="815.99585"
|
||||||
|
id="tspan1583">under the current directory (this also means all directories</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="829.32916"
|
||||||
|
id="tspan1585">must be project units at this level).</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="842.66248"
|
||||||
|
id="tspan1587" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="449.34958"
|
||||||
|
y="855.99573"
|
||||||
|
id="tspan1589">This allows for a simple fanout without needing lots of YAML files.</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic Oblique';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="1029.5554"
|
||||||
|
y="261.4942"
|
||||||
|
id="text969"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="261.4942"
|
||||||
|
id="tspan1135">The project folder defines a schema in a YAML file matching the project directory name.</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="274.82751"
|
||||||
|
id="tspan1139">(you can also call the file 'project.yaml' or 'kitcat.yaml' if you prefer).</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="288.1608"
|
||||||
|
id="tspan1159" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="301.49411"
|
||||||
|
id="tspan1161">Three keys are mandatory for this file:</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="314.82739"
|
||||||
|
id="tspan1163" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="328.16071"
|
||||||
|
id="tspan1165">project_root:</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="341.49399"
|
||||||
|
id="tspan1169"> The 'project_root' key only has to exist. It can be as simple as having</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="354.8273"
|
||||||
|
id="tspan1173"> a value of True. But this is an ideal place to store basic metadata about</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="368.16058"
|
||||||
|
id="tspan1177"> your organization and this project.</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="381.4939"
|
||||||
|
id="tspan1179" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="394.82721"
|
||||||
|
id="tspan1181">project_unit:</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="408.16049"
|
||||||
|
id="tspan1183"> The 'project_unit' key identifies the top rank of the project (the current directory). It</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="421.4938"
|
||||||
|
id="tspan1187"> should contain a bullet list with a single entry identifying the code ('myproject'), 'name',</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="434.82709"
|
||||||
|
id="tspan1191"> 'title', and other details.</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="448.1604"
|
||||||
|
id="tspan1193" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="461.49368"
|
||||||
|
id="tspan1195">project_schema:</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="474.827"
|
||||||
|
id="tspan1143"> The 'project_schema' key defines the default hierarchy of project assets, and</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="488.16031"
|
||||||
|
id="tspan1553"> creates the 'myproject' branch of ranks, overriding the default "trunk" branch.</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="501.49359"
|
||||||
|
id="tspan1555"> All project files are of rank 'project' or below (with each having a higher rank</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1029.5554"
|
||||||
|
y="514.8269"
|
||||||
|
id="tspan1557"> number). As defined here, the default ranking is organized for episode shot files.</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic Oblique';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="515.06158"
|
||||||
|
y="63.621597"
|
||||||
|
id="text1038"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="63.621597"
|
||||||
|
id="tspan1036">Before any file is loaded (filepath is ''),</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="76.954895"
|
||||||
|
id="tspan1045">the rank hierarchy is controlled solely</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="90.288193"
|
||||||
|
id="tspan1047">by the default schema in the ABX</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="103.62149"
|
||||||
|
id="tspan1049">program folder.</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="116.95479"
|
||||||
|
id="tspan1051" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="130.2881"
|
||||||
|
id="tspan1053">It sets only the 'trunk' (rank 0),</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="143.6214"
|
||||||
|
id="tspan1055">'file' (the level of the Blender file)</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="156.9547"
|
||||||
|
id="tspan1057">and 'scene' (the level of a scene</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="170.28799"
|
||||||
|
id="tspan1059">in thefile) as ranks.</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="183.62129"
|
||||||
|
id="tspan1061" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="196.95459"
|
||||||
|
id="tspan1063">These are imposed by the nature of</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="210.28789"
|
||||||
|
id="tspan1065">the program, so we can safely use</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="223.62119"
|
||||||
|
id="tspan1067">those as defaults.</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="236.95448"
|
||||||
|
id="tspan1069" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="250.2878"
|
||||||
|
id="tspan1071">Any additional structure needs to be</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="263.62109"
|
||||||
|
id="tspan1073">given by a YAML file in the project</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="515.06158"
|
||||||
|
y="276.95438"
|
||||||
|
id="tspan1075">directory.</tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 889.51282,213.88591 0,27.1624"
|
||||||
|
id="path1077"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic Oblique';letter-spacing:0px;word-spacing:0px"
|
||||||
|
x="119.42168"
|
||||||
|
y="924.96472"
|
||||||
|
id="text1085"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="119.42168"
|
||||||
|
y="924.96472"
|
||||||
|
id="tspan1083">The name path for this file is derived almost</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="119.42168"
|
||||||
|
y="938.29803"
|
||||||
|
id="tspan1092">entirely from the filename. Only the 'project'</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="119.42168"
|
||||||
|
y="951.63135"
|
||||||
|
id="tspan1094">and 'series' ranks are specified above.</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="119.42168"
|
||||||
|
y="964.9646"
|
||||||
|
id="tspan1108" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="119.42168"
|
||||||
|
y="978.29791"
|
||||||
|
id="tspan1110">ABX currently ignores the folder names above</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="119.42168"
|
||||||
|
y="991.63123"
|
||||||
|
id="tspan1112">this, even though they could be used to give</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="119.42168"
|
||||||
|
y="1004.9645"
|
||||||
|
id="tspan1114">more information (e.g. this sequence is called</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="119.42168"
|
||||||
|
y="1018.2978"
|
||||||
|
id="tspan1116">"LastPoint", but without YAML, this is left unspecified.</tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 130.76843,682.08859 V 716.8141"
|
||||||
|
id="path1118" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 889.8041,553.82368 0,18.17606 H 136.617 v 32.46778"
|
||||||
|
id="path1120"
|
||||||
|
sodipodi:nodetypes="cccc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 889.8041,553.82368 0,18.17606 h 421.5589 v 32.46778"
|
||||||
|
id="path1122"
|
||||||
|
sodipodi:nodetypes="cccc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 1312.781,834.80279 V 869.5283"
|
||||||
|
id="path1124" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
159
tests/test_ranks.py
Normal file
159
tests/test_ranks.py
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
# test_ranks
|
||||||
|
"""
|
||||||
|
Test the ranks module, which implements the branch and rank semantics and math.
|
||||||
|
"""
|
||||||
|
import unittest, os
|
||||||
|
|
||||||
|
import sys
|
||||||
|
print("__file__ = ", __file__)
|
||||||
|
sys.path.append(os.path.normpath(os.path.join(__file__, '..', '..')))
|
||||||
|
|
||||||
|
from abx import ranks
|
||||||
|
|
||||||
|
class BranchTests(unittest.TestCase):
|
||||||
|
def test_trunk_branch(self):
|
||||||
|
t = ranks.trunk.rank('')
|
||||||
|
f = ranks.trunk.rank('file')
|
||||||
|
s = ranks.trunk.rank('scene')
|
||||||
|
self.assertEqual(repr(ranks.trunk), "<branch 'trunk': file, scene>")
|
||||||
|
self.assertIn(t, ranks.trunk)
|
||||||
|
self.assertIn(f, ranks.trunk)
|
||||||
|
self.assertIn(s, ranks.trunk)
|
||||||
|
|
||||||
|
|
||||||
|
def test_defining_branch(self):
|
||||||
|
b = ranks.Branch(ranks.trunk, 'myproject', 1,
|
||||||
|
('project', 'series', 'episode', 'sequence',
|
||||||
|
'block', 'shot', 'element'))
|
||||||
|
|
||||||
|
self.assertEqual(len(b._ranks), 8)
|
||||||
|
|
||||||
|
class RanksTests(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.b = ranks.Branch(ranks.trunk, 'myproject', 1,
|
||||||
|
('project', 'series', 'episode', 'sequence',
|
||||||
|
'block', 'shot', 'element'))
|
||||||
|
|
||||||
|
def test_rank_knows_branch(self):
|
||||||
|
sh = self.b.rank('shot')
|
||||||
|
self.assertIs(sh.branch, self.b)
|
||||||
|
self.assertEqual(sh.num, 6)
|
||||||
|
|
||||||
|
def test_rank_representation(self):
|
||||||
|
ep = self.b.rank('episode')
|
||||||
|
self.assertEqual(repr(ep), '<myproject:3-episode>')
|
||||||
|
self.assertEqual(int(ep), 3)
|
||||||
|
self.assertEqual(str(ep), 'episode')
|
||||||
|
|
||||||
|
sq = self.b.rank(4)
|
||||||
|
self.assertEqual(repr(sq), '<myproject:4-sequence>')
|
||||||
|
self.assertEqual(int(sq), 4)
|
||||||
|
self.assertEqual(str(sq), 'sequence')
|
||||||
|
|
||||||
|
def test_rank_addition(self):
|
||||||
|
ep = self.b.rank('episode')
|
||||||
|
sq = self.b.rank(4)
|
||||||
|
|
||||||
|
self.assertEqual(sq, ep + 1)
|
||||||
|
self.assertEqual(sq, 1 + ep)
|
||||||
|
|
||||||
|
def test_rank_subtraction(self):
|
||||||
|
ep = self.b.rank('episode')
|
||||||
|
sq = self.b.rank(4)
|
||||||
|
|
||||||
|
self.assertEqual(ep, sq - 1)
|
||||||
|
self.assertEqual(sq, ep - (-1))
|
||||||
|
self.assertEqual(sq - ep, 1)
|
||||||
|
self.assertEqual(ep - sq, -1)
|
||||||
|
|
||||||
|
def test_rank_increment_decrement(self):
|
||||||
|
ep = self.b.rank('episode')
|
||||||
|
sq = self.b.rank(4)
|
||||||
|
|
||||||
|
r = ep
|
||||||
|
r += 1
|
||||||
|
self.assertEqual(r, sq)
|
||||||
|
|
||||||
|
r = sq
|
||||||
|
r -= 1
|
||||||
|
self.assertEqual(r, ep)
|
||||||
|
|
||||||
|
def test_rank_comparisons_direct(self):
|
||||||
|
sh = self.b.rank('shot')
|
||||||
|
se = self.b.rank('series')
|
||||||
|
s1 = self.b.rank(2)
|
||||||
|
|
||||||
|
self.assertEqual(se, s1)
|
||||||
|
self.assertGreater(sh, se)
|
||||||
|
self.assertLess(se, sh)
|
||||||
|
|
||||||
|
def test_rank_comparisons_compound(self):
|
||||||
|
sh = self.b.rank('shot')
|
||||||
|
se = self.b.rank('series')
|
||||||
|
s1 = self.b.rank(2)
|
||||||
|
|
||||||
|
self.assertNotEqual(sh, se)
|
||||||
|
self.assertGreaterEqual(sh, se)
|
||||||
|
self.assertLessEqual(se, sh)
|
||||||
|
self.assertLessEqual(s1, se)
|
||||||
|
self.assertGreaterEqual(se, s1)
|
||||||
|
|
||||||
|
def test_rank_too_high(self):
|
||||||
|
sh = self.b.rank('shot')
|
||||||
|
el = self.b.rank('element')
|
||||||
|
|
||||||
|
r = sh + 1
|
||||||
|
s = sh + 2
|
||||||
|
t = sh + 3
|
||||||
|
|
||||||
|
self.assertEqual(r, el)
|
||||||
|
self.assertEqual(s, None)
|
||||||
|
self.assertEqual(t, None)
|
||||||
|
|
||||||
|
def test_rank_too_low(self):
|
||||||
|
se = self.b.rank('series')
|
||||||
|
pr = self.b.rank('project')
|
||||||
|
|
||||||
|
r = se - 1 # Normal - 'project' is one below 'series'
|
||||||
|
s = se - 2 # ? Should this be 'project' or 'trunk'/None?
|
||||||
|
t = se - 3 # "` "
|
||||||
|
|
||||||
|
self.assertEqual(r, pr)
|
||||||
|
self.assertEqual(s, ranks.trunk)
|
||||||
|
self.assertEqual(t, ranks.trunk)
|
||||||
|
|
||||||
|
|
||||||
|
def test_rank_slices_from_branch(self):
|
||||||
|
ranks = self.b.ranks
|
||||||
|
self.assertEqual(
|
||||||
|
ranks[1:4],
|
||||||
|
ranks[self.b.rank('project'):self.b.rank('sequence')])
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
ranks[:],
|
||||||
|
ranks)
|
||||||
|
|
||||||
|
def test_ranklist_slice_access(self):
|
||||||
|
ranks = self.b.ranks
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
ranks[1:4],
|
||||||
|
ranks['project':'sequence'])
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
ranks[:'sequence'],
|
||||||
|
ranks[0:4])
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
ranks[1:'shot'],
|
||||||
|
ranks['project':6])
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
ranks[self.b.ranks['sequence']:7],
|
||||||
|
ranks['sequence':7])
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
ranks.branch,
|
||||||
|
self.b)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user