Files
IWaniHugThatGator-Demo-Public/game/dev/actioneditor/ActionEditor.rpy
2024-03-06 19:57:33 -06:00

3681 lines
162 KiB
Plaintext

#既知の問題
#cameraではset_childを使用していないのでat節の再現ができない
#課題
#childのみならばparallelなくてよい
#removeボタンを画像タグの右クリックメニューへ追加
#動画およびat節で指定されたアニメーションtransformと同期できない(要本体の最適化)
#vpunch等Move transtion, ATLtranstionが動作しない
#ATLtransitionのdelayを所得できない
#極座標表示対応
#ATLではalignaroundはradius, angle変更時に参照されて始めて効果を持ち、単独で動かしても反映されない
#posも同時に動かせるが基準が不明(未定義?) Editorではalignaroundを動かしている間radiusかangleを動かし続けるか
#functionプロパティーでalignaroundを動かしても反映されない。最小構成では動く、最初の一回は反映されている
#グループにせず直接編集しても効果なし boxの影響?
init -1098 python:
# Added keymap
config.underlay.append(renpy.Keymap(
action_editor = renpy.curry(renpy.invoke_in_new_context)(_viewers.open_action_editor),
image_viewer = _viewers.open_image_viewer,
sound_viewer = _viewers.open_sound_viewer,
))
init -1600 python in _viewers:
from renpy.store import Solid, Fixed, Transform, persistent, Null, Matrix, config, Movie
from renpy import config
def check_version(version_date):
if renpy.version_tuple[3] >= version_date:
return True
else:
return False
init python in _viewers:
from renpy.store import RotateMatrix, OffsetMatrix, ScaleMatrix, _MultiplyMatrix
from renpy.store import InvertMatrix, ContrastMatrix, SaturationMatrix, BrightnessMatrix, HueMatrix
def action_editor_version():
return "230825_1"
if check_version(23032500):
euler_slerp = renpy.display.quaternion.euler_slerp
else:
euler_slerp = renpy.display.accelerator.quaternion
#z -> y -> x order roate
def rotate_matrix2(_, x, y, z):
from math import sin, cos, pi
sinx = sin(pi*x/180)
cosx = cos(pi*x/180)
siny = sin(pi*y/180)
cosy = cos(pi*y/180)
sinz = sin(pi*z/180)
cosz = cos(pi*z/180)
rv = Matrix(None)
rv.xdx = cosy*cosz
rv.xdy = -cosy*sinz
rv.xdz = siny
rv.ydx = cosx*sinz + sinx*siny*cosz
rv.ydy = cosx*cosz - sinx*siny*sinz
rv.ydz = -sinx*cosy
rv.zdx = sinx*sinz - cosx*siny*cosz
rv.zdy = sinx*cosz + cosx*siny*sinz
rv.zdz = cosx*cosy
rv.wdw = 1
return rv
#Rzyx(a, b, c)をRxyz(x, y, z)に変換
def zyx_to_xyz(a, b, c):
from math import sin, cos, pi, sqrt, acos, asin
sina = sin(pi*a/180)
cosa = cos(pi*a/180)
sinb = sin(pi*b/180)
cosb = cos(pi*b/180)
sinc = sin(pi*c/180)
cosc = cos(pi*c/180)
siny = min(1, max(-sina * sinc + cosa * sinb * cosc, -1))
cosy = sqrt(1 - siny**2)
if cosy != 0:
cosx = min(1, max(cosa * cosb / cosy, -1))
cosz = min(1, max(cosb * cosc / cosy, -1))
else:
cosx = 1
cosz = 1
x = acos(cosx) * 180 /pi
y = asin(siny) * 180 /pi
z = acos(cosz) * 180 /pi
#assume cosy > 0
if sina * cosc + cosa * sinb * sinc < 0:
x = 360 - x
if cosa * sinc + sina * sinb * cosc < 0:
z = 360 - z
return (x, y, z)
class RotateMatrix2(renpy.store.TransformMatrix):
nargs = 3
function = rotate_matrix2
init -1598 python in _viewers:
from copy import deepcopy
from math import sqrt
from collections import defaultdict
from renpy.display.image import images
from traceback import format_exc
debug = False
class DuringTransitionDisplayble(renpy.Displayable):
# create the image which is doing transition at the given time.
# TransitionDisplayble(dissolve(old_widget, new_widget), 0, 0)
def __init__(self, transition, old, new, st, at, **properties):
super(DuringTransitionDisplayble, self).__init__(**properties)
self.transition = transition(old_widget=old, new_widget=new)
self.st = st
self.at = at
def render(self, width, height, st, at):
#st, at is 0 allways?
return self.transition.render(width, height, self.st, self.at)
class FixedTimeDisplayable(renpy.Displayable):
def __init__(self, d, st, at, **properties):
super(FixedTimeDisplayable, self).__init__(**properties)
self.d = d
self.fixed_st = st
self.fixed_at = at
#単純にst, atを上書きしただけでは動作しない accelerator.pyx等とatl.pyを確認する
def render(self, width, height, st, at):
return self.d.render(width, height, self.fixed_st, self.fixed_at)
class RenderToDisplayable(renpy.Displayable):
def __init__(self, render, **properties):
super(RenderToDisplayable, self).__init__(**properties)
self.render = render
def render(self, width, height, st, at):
#st, at is 0 allways?
return self.render
def action_editor_init():
global image_state, image_state_org, camera_state_org, movie_cache
sle = renpy.game.context().scene_lists
# layer->tag->property->value
image_state_org = []
image_state = []
camera_state_org = []
image_state_org.append({})
image_state.append({})
camera_state_org.append({})
movie_cache = {}
d = sle.camera_transform["master"]
# child = getattr(d, "child", None)
# child = getattr(child, "child", None)
# if child is not None:
# renpy.store._viewers.at_clauses_flag = True
child = getattr(d, "child", None)
at_list = []
while child is not None and type(child) is not renpy.display.layout.MultiBox:
trans = get_transform_name(child)
if trans is not None:
at_list.append(trans)
child = getattr(child, "child", None)
at_list.reverse()
camera_state_org[current_scene]["at_list"] = at_list
#cameraはget_placementを使用すると座標が所得できない
# if d is not None:
# pos = renpy.get_placement(d)
pos = d
state = getattr(d, "state", None)
for p in {"xpos", "ypos", "xanchor", "yanchor", "xoffset", "yoffset"}:
camera_state_org[current_scene][p] = getattr(pos, p, None)
for p in camera_props:
if p not in camera_state_org[current_scene]:
if p in ("matrixtransform", "matrixcolor"):
for prop, v in load_matrix(p, getattr(state, p, None)):
if is_force_float(p) and isinstance(v, int):
v = float(v)
camera_state_org[current_scene][prop] = v
else:
v = getattr(state, p, None)
if is_force_float(p) and isinstance(v, int):
v = float(v)
camera_state_org[current_scene][p] = v
for gn, ps in props_groups.items():
for p in camera_props:
if p in ps:
pvs = getattr(state, gn, None)
if pvs is not None:
for gp, v in zip(ps, pvs):
if is_force_float(gp) and isinstance(v, int):
v = float(v)
camera_state_org[current_scene][gp] = v
break
for layer in config.layers:
image_state_org[current_scene][layer] = {}
image_state[current_scene][layer] = {}
for image in sle.layers[layer]:
if not image[0]:
continue
tag = image[0]
d = sle.get_displayable_by_tag(layer, tag)
if isinstance(d, renpy.display.screen.ScreenDisplayable):
continue
image_name_tuple = getattr(d, "name", None)
child = d
while image_name_tuple is None:
if child is None:
break
child = getattr(child, "child", None)
image_name_tuple = getattr(child, "name", None)
child = d
while image_name_tuple is None:
if child is None:
break
child = getattr(child, "raw_child", None)
image_name_tuple = getattr(child, "name", None)
if image_name_tuple is None:
continue
name = " ".join(image.name)
try:
image_name = " ".join(image_name_tuple)
except:
if debug:
raise Exception(image_name_tuple, layer, tag)
continue
image_state_org[current_scene][layer][tag] = {}
child = getattr(d, "child", None)
at_list = []
while child is not None:
trans = get_transform_name(child)
if trans is not None:
at_list.append(trans)
child = getattr(child, "child", None)
at_list.reverse()
image_state_org[current_scene][layer][tag]["at_list"] = at_list
pos = renpy.get_placement(d)
state = getattr(d, "state", None)
for p in {"xpos", "ypos", "xanchor", "yanchor", "xoffset", "yoffset"}:
image_state_org[current_scene][layer][tag][p] = getattr(pos, p, None)
for p in transform_props:
if p not in image_state_org[current_scene][layer][tag]:
if p == "child":
image_state_org[current_scene][layer][tag][p] = (image_name, None)
elif p in ("matrixtransform", "matrixcolor"):
for prop, v in load_matrix(p, getattr(state, p, None)):
if is_force_float(prop) and isinstance(v, int):
v = float(v)
image_state_org[current_scene][layer][tag][prop] = v
else:
v = getattr(state, p, None)
if is_force_float(p) and isinstance(v, int):
v = float(v)
image_state_org[current_scene][layer][tag][p] = v
for gn, ps in props_groups.items():
for p in transform_props:
if p in ps:
pvs = getattr(state, gn, None)
if pvs is not None:
for gp, v in zip(ps, pvs):
if is_force_float(gp) and isinstance(v, int):
v = float(v)
image_state_org[current_scene][layer][tag][gp] = v
break
# init camera, layer and images
for layer in config.layers:
renpy.scene(layer)
sle.set_layer_at_list(layer, [], camera=True)
sle.set_layer_at_list(layer, [])
def get_transform_name(obj):
atl = getattr(obj, "atl", None)
if atl is None:
return None
for name, _, _ in renpy.dump.transforms:
transform = getattr(renpy.store, name, None)
if transform is not None:
#定義場所が同じなら同じと判定
#リロードで再定義されるのでisでは判定できない
if transform.atl.loc == atl.loc:
return (name, obj.context.context)
else:
return None
def apply_at_list(child, at_list):
if not at_list:
return child
for name, kwargs in at_list:
child = getattr(renpy.store, name)(child=child, **kwargs)
#この方法では位置プロパティーは継承できない
return child
def get_at_list_props(at_list, prop, st, at):
if not at_list:
return None
at_list_d = []
for name, kwargs in at_list:
at_list_d.append(getattr(renpy.store, name)(**kwargs))
# rv = None
# for i in at_list_d:
# v = getattr(i, prop, None)
# if v is not None:
# rv = v
rv = at_list_d[0]()
for i in at_list_d[1:]:
rv = i(rv)
rv = getattr(renpy.get_placement(rv), prop, None)
return rv
# def expand_at_list(at_list):
# rv = ""
# for name, kwargs in at_list:
# if kwargs:
# para = ""
# for k, v in kwargs.items():
# para += "{}={}, ".format(k, v)
# else:
# para = para[:-2]
# rv += "{}({}), ".format(name, para)
# else:
# rv += "{}, ".format(name)
# else:
# rv = rv[:-2]
# return rv
def check_props_group(prop, tag=None, scene_num=None):
if prop.count("_") == 3 and prop.split("_")[0] in ("matrixtransform", "matrixcolor"):
if scene_num is None:
scene_num = current_scene
if tag == "camera":
state = camera_state_org[scene_num]
else:
tag, layer = tag
state = get_image_state(layer, scene_num)[tag]
gn = prop.split("_")[0]
matrixargs = []
for p in state:
if p.count("_") == 3:
sign, _, _, _ = p.split("_")
if sign == gn:
matrixargs.append(p)
matrixargs.sort()
return gn, matrixargs
for gn, ps in props_groups.items():
if prop in ps:
return gn, ps
else:
return None
def load_matrix(matrix, value):
if matrix == "matrixtransform":
if value is None:
return default_matrixtransform
else:
rv = []
for i, (type, args) in enumerate(get_matrix_info(value)):
if isinstance(type, ScaleMatrix):
for j, x in enumerate(("X", "Y", "Z")):
rv.append(("matrixtransform_{}_{}_{}{}".format(i+1, j+1, "scale", x), args[j]))
elif isinstance(type, OffsetMatrix):
for j, x in enumerate(("X", "Y", "Z")):
rv.append(("matrixtransform_{}_{}_{}{}".format(i+1, j+1, "offset", x), args[j]))
elif isinstance(type, RotateMatrix):
for j, x in enumerate(("X", "Y", "Z")):
rv.append(("matrixtransform_{}_{}_{}{}".format(i+1, j+1, "rotate", x), args[j]))
# else:
# renpy.notify(_("ActionEditor doesn't support ") + str(type))
return rv
else:
if value is None:
return default_matrixcolor
else:
rv = []
for i, (type, args) in enumerate(get_matrix_info(value)):
if isinstance(type, InvertMatrix):
rv.append(("matrixcolor_{}_{}_{}".format(i+1, 1, "invert"), args))
elif isinstance(type, ContrastMatrix):
rv.append(("matrixcolor_{}_{}_{}".format(i+1, 1, "contrast"), args))
elif isinstance(type, SaturationMatrix):
rv.append(("matrixcolor_{}_{}_{}".format(i+1, 1, "saturate"), args))
elif isinstance(type, BrightnessMatrix):
rv.append(("matrixcolor_{}_{}_{}".format(i+1, 1, "bright"), args))
elif isinstance(type, HueMatrix):
rv.append(("matrixcolor_{}_{}_{}".format(i+1, 1, "hue"), args))
# else:
# renpy.notify(_("ActionEditor doesn't support ") + str(type))
return rv
def get_matrix_info(matrix):
matrix_info = []
def _get_matrix_info(origin):
if isinstance(origin, _MultiplyMatrix):
args = getattr(origin.right, "args", None)
if args is None:
args = getattr(origin.right, "value", None)
if args is None:
args = getattr(origin.right, "color")
matrix_info.append((origin.right, args))
_get_matrix_info(origin.left)
else:
args = getattr(origin, "args", None)
if args is None:
args = getattr(origin, "value", None)
if args is None:
args = getattr(origin, "color")
matrix_info.append((origin, args))
origin = getattr(matrix, "origin", False)
if not origin:
return matrix_info
else:
_get_matrix_info(origin)
matrix_info.reverse()
return matrix_info
def is_force_float(prop):
if prop.count("_") == 3:
sign, _, _, prop2 = prop.split("_")
if sign in ("matrixtransform", "matrixcolor"):
prop = prop2
return prop in force_float
def is_force_plus(prop):
if prop is None:
return False
if prop.count("_") == 3:
sign, _, _, prop2 = prop.split("_")
if sign in ("matrixtransform", "matrixcolor"):
prop = prop2
return prop in force_plus
def is_wide_range(key, scene_num=None):
if scene_num is None:
scene_num = current_scene
if isinstance(key, tuple):
tag, layer, prop = key
else:
prop = key
if prop.count("_") == 3:
sign, _, _, prop2 = prop.split("_")
if sign in ("matrixtransform", "matrixcolor"):
if prop2 in force_wide_range:
return True
if prop2 in force_narrow_range:
return False
if prop in force_wide_range:
return True
if prop in force_narrow_range:
return False
if key in all_keyframes[current_scene]:
v = all_keyframes[current_scene][key][-1][0]
else:
if isinstance(key, tuple):
state = get_image_state(layer)[tag]
else:
state = camera_state_org[current_scene]
if state[prop] is not None:
v = state[prop]
else:
v = get_default(prop)
return isinstance(v, int)
def reset(key_list, time=None):
if time is None:
time = current_time
if time < scene_keyframes[current_scene][1]:
renpy.notify(_("can't change values before the start tiem of the current scene"))
return
if not isinstance(key_list, list):
key_list = [key_list]
for key in key_list:
if isinstance(key, tuple):
tag, layer, prop = key
state = get_image_state(layer)[tag]
else:
prop = key
state = camera_state_org[current_scene]
v = state[prop]
if v is None:
v = get_default(prop)
#もともとNoneでNoneとデフォルトで結果が違うPropertyはリセット時にずれるが、デフォルの値で入力すると考えてキーフレーム設定した方が自然
set_keyframe(key, v, time=time)
change_time(time)
def image_reset():
key_list = [(tag, layer, prop) for layer in config.layers for tag, props in get_image_state(layer).items() for prop in props]
reset(key_list)
def camera_reset():
reset([p for p in camera_state_org[current_scene]])
def generate_changed(key):
if isinstance(key, tuple):
tag, layer, prop = key
state = get_image_state(layer)[tag]
else:
prop = key
state = camera_state_org[current_scene]
def changed(v, time=None, knot_number=None):
if time is None:
time = current_time
time = round(float(time), 2)
if time < scene_keyframes[current_scene][1]:
renpy.notify(_("can't change values before the start tiem of the current scene"))
return
default = get_default(prop)
if is_wide_range(key):
if isinstance(get_value(key, default=True), float):
if not is_force_plus(prop):
v -= persistent._wide_range
elif v < 0:
v = 0
v = round(float(v), 2)
else:
if not is_force_plus(prop):
v -= persistent._wide_range
elif v < 0:
v = 0
v = int(v)
else:
if isinstance(get_value(key, default=True), float):
if not is_force_plus(prop):
v -= persistent._narrow_range
elif v < 0:
v = 0
v = round(float(v), 2)
else:
if not is_force_plus(prop):
v -= persistent._narrow_range
elif v < 0:
v = 0
v = int(v)
if knot_number is None:
default_warper_org = persistent._viewer_warper
if key in all_keyframes[current_scene]:
for _, t, w in all_keyframes[current_scene][key]:
if t == time:
persistent._viewer_warper = w
set_keyframe(key, v, time=time)
persistent._viewer_warper = default_warper_org
else:
splines[current_scene][key][time][knot_number] = v
update_gn_spline(key, time)
change_time(time)
return changed
def to_changed_value(value, force_plus, use_wide_range):
if use_wide_range:
range = persistent._wide_range
else:
range = persistent._narrow_range
if force_plus:
return value
else:
return value + range
def set_keyframe(key, value, recursion=False, time=None):
if isinstance(key, tuple):
tag, layer, prop = key
mkey = (tag, layer)
state = get_image_state(layer)[tag]
else:
prop = key
mkey = "camera"
state = camera_state_org[current_scene]
if time is None:
time = current_time
keyframes = all_keyframes[current_scene].get(key, [])
if keyframes:
for i, (v, t, w) in enumerate(keyframes):
if time < t:
keyframes.insert(i, (value, time, persistent._viewer_warper))
break
elif time == t:
keyframes[i] = ( value, time, persistent._viewer_warper)
break
else:
keyframes.append((value, time, persistent._viewer_warper))
else:
if time == scene_keyframes[current_scene][1]:
all_keyframes[current_scene][key] = [(value, time, persistent._viewer_warper)]
else:
org = state[prop]
if org is None:
org = get_default(prop)
if prop == "child" and ((current_scene == 0 and tag in image_state[current_scene][layer])
or (current_scene != 0 and time > scene_keyframes[current_scene][1])):
org = (None, None)
all_keyframes[current_scene][key] = [
(org, scene_keyframes[current_scene][1], persistent._viewer_warper),
(value, time, persistent._viewer_warper)]
if not recursion:
check_result = check_props_group(prop, mkey)
if check_result is not None:
gn, ps = check_result
if gn != "focusing":
ps_set = set(ps)
ps_set.remove(prop)
for p in ps_set:
if isinstance(key, tuple):
key2 = (tag, layer, p)
else:
key2 = p
set_keyframe(key2, get_value(key2, default=True), True, time=time)
if not recursion:
for s in range(current_scene+1, len(scene_keyframes)):
for i in range(s, -1, -1):
if camera_keyframes_exist(i):
break
for p in camera_state_org[i]:
if p in camera_state_org[s]:
middle_value = get_value(p, scene_keyframes[s][1], False, i)
if isinstance(middle_value, float):
camera_state_org[s][p] = round(middle_value, 2)
else:
camera_state_org[s][p] = middle_value
def generate_matrix_strings(args, matrix, ps, side_view=False):
rv = ""
if matrix == "matrixtransform":
for i in range(0, len(ps), 3):
_, _, _, prop = ps[i].split("_")
if prop.startswith("offset"):
rv += "OffsetMatrix({}, {}, {})*"
elif prop.startswith("rotate"):
if side_view:
rv += "_viewers.RotateMatrix2({}, {}, {})*"
else:
rv += "RotateMatrix({}, {}, {})*"
elif prop.startswith("scale"):
rv += "ScaleMatrix({}, {}, {})*"
rv = rv[:-1].format(*args)
else:
for p in ps:
_, _, _, prop = p.split("_")
if prop == "invert":
rv += "InvertMatrix({})*"
elif prop == "contrast":
rv += "ContrastMatrix({})*"
elif prop == "saturate":
rv += "SaturationMatrix({})*"
elif prop == "bright":
rv += "BrightnessMatrix({})*"
elif prop == "hue":
rv += "HueMatrix({})*"
rv = rv[:-1].format(*args)
return rv
def play(play):
if play:
for channel, times in sound_keyframes.items():
time = 0
files = []
sorted_times = sorted(list(times.keys()))
if sorted_times:
for t in sorted_times:
duration = t - time
if duration > 0:
files.append("<silence {}>".format(duration))
file = renpy.python.py_eval(times[t], locals=renpy.python.store_dicts["store.audio"])
files += file
time = t
for f in file:
time += get_file_duration(f)
renpy.music.play(files, channel, loop=False)
else:
for channel, times in sound_keyframes.items():
if current_time in times:
files = renpy.python.py_eval(times[current_time], locals=renpy.python.store_dicts["store.audio"])
renpy.music.play(files, channel, loop=False)
camera_check_points = []
viewer_check_points = []
loop = []
spline = []
for s, (_, t, _) in enumerate(scene_keyframes):
check_points = {}
vcheck_points = {}
camera_is_used = False
props_use_default = []
at_list = camera_state_org[0].get("at_list")
check_points["at_list"] = [(at_list, 0, None)]
for prop in camera_state_org[s]:
if not exclusive_check(prop, s):
continue
if prop in all_keyframes[s]:
check_points[prop] = all_keyframes[s][prop]
camera_is_used = True
else:
if camera_state_org[s][prop] is not None:
check_points[prop] = [(get_value(prop, default=False, scene_num=s), t, None)]
elif prop not in not_used_by_default:
check_points[prop] = [(get_value(prop, default=True, scene_num=s), t, None)]
props_use_default.append(prop)
check_points["props_use_default"] = [(props_use_default, t, None)]
#focusing以外のグループプロパティーはここで纏める
included_gp = {}
for p in check_points:
check_result = check_props_group(p, "camera", s)
if check_result is not None:
gn, ps = check_result
if gn != "focusing" and gn not in included_gp:
args = []
for prop in ps:
args.append(check_points[prop])
group_cs = []
for cs in zip(*args):
v = tuple(c[0] for c in cs)
if gn in ("matrixtransform", "matrixcolor"):
v = generate_matrix_strings(v, gn, ps)
v = renpy.python.py_eval(v)
group_cs.append((v, cs[0][1], cs[0][2]))
included_gp[gn] = (ps, group_cs)
#viewer上ではmatrixtransformは符号と順番が反転する。回転順も反転するためz-y-x順の回転行列がないと対応不可
if gn == "matrixtransform" and persistent._viewer_sideview:
viewer_group_cs = []
#ScaleMatrixのみ逆数をとる
scale_ps = []
for i, prop in enumerate(ps):
_, _, _, p_name = prop.split("_")
if p_name.startswith("scale"):
scale_ps.append(i)
for cs in zip(*args):
org_v = tuple(c[0] for c in cs)
viewer_v = []
for i, e in enumerate(org_v):
if i in scale_ps:
if e == 0:
viewer_v.append(1000.) #inf
else:
viewer_v.append(1.0/e)
else:
viewer_v.append(-e)
#matrixの順番を反転 marixの引数が3個単位と前提
viewer_ps = []
rviewer_v = []
start_index = range(0, len(ps), 3)
start_index.reverse()
for i in start_index:
viewer_ps.extend((ps[i], ps[i+1], ps[i+2]))
rviewer_v.extend((viewer_v[i], viewer_v[i+1], viewer_v[i+2]))
viewer_v = generate_matrix_strings(tuple(rviewer_v), gn, viewer_ps, True)
viewer_v = renpy.python.py_eval(viewer_v)
viewer_group_cs.append((viewer_v, cs[0][1], cs[0][2]))
vcheck_points[gn] = viewer_group_cs
for gn, (ps, group_cs) in included_gp.items():
for prop in ps:
del check_points[prop]
check_points[gn] = group_cs
#viewerで使用するプロパティー(functionはblur等が含まれる可能性がある)
#These properties are shown in side viewer(function property has danger of including blur)
if persistent._viewer_sideview:
for p in ("xpos", "xanchor", "xoffset", "ypos", "yanchor", "yoffset", "zpos", "rotate", "xrotate", "yrotate", "zrotate", "orientation", "point_to"):
if p in check_points:
vcheck_points[p] = check_points[p]
vcheck_points["props_use_default"] = check_points["props_use_default"]
vcheck_points["at_list"] = check_points["at_list"]
if not camera_is_used and s > 0:
loop.append(loop[s-1])
spline.append(spline[s-1])
camera_check_points.append(camera_check_points[s-1])
viewer_check_points.append(viewer_check_points[s-1])
else:
loop.append({key+"_loop": loops[s][key] for key in loops[s] if not isinstance(key, tuple)})
spline.append({key+"_spline": splines[s][key] for key in splines[s] if not isinstance(key, tuple)})
camera_check_points.append(check_points)
viewer_check_points.append(vcheck_points)
image_check_points = []
for s, (_, t, _) in enumerate(scene_keyframes):
check_points = {}
for layer in config.layers:
state = get_image_state(layer, s)
check_points[layer] = {}
for tag in state:
check_points[layer][tag] = {}
props_use_default = []
at_list = state[tag].get("at_list")
check_points[layer][tag]["at_list"] = [(at_list, t, None)]
for prop in state[tag]:
if not exclusive_check((tag, layer, prop), s):
continue
if (tag, layer, prop) in all_keyframes[s]:
check_points[layer][tag][prop] = all_keyframes[s][(tag, layer, prop)]
elif prop in props_groups["focusing"] and prop in camera_check_points[s]:
check_points[layer][tag][prop] = camera_check_points[s][prop]
else:
if state[tag][prop] is not None:
check_points[layer][tag][prop] = [(get_value((tag, layer, prop), default=False, scene_num=s), t, None)]
elif prop not in not_used_by_default:
check_points[layer][tag][prop] = [(get_value((tag, layer, prop), default=True, scene_num=s), t, None)]
props_use_default.append(prop)
check_points[layer][tag]["props_use_default"] = [(props_use_default, t, None)]
#focusing以外のグループプロパティーはここで纏める
included_gp = {}
for p in check_points[layer][tag]:
check_result = check_props_group(p, (tag, layer), s)
if check_result is not None:
gn, ps = check_result
if gn != "focusing":
args = []
for prop in ps:
args.append(check_points[layer][tag][prop])
group_cs = []
for cs in zip(*args):
v = tuple(c[0] for c in cs)
if gn in ("matrixtransform", "matrixcolor"):
v = generate_matrix_strings(v, gn, ps)
v = renpy.python.py_eval(v)
group_cs.append((v, cs[0][1], cs[0][2]))
included_gp[gn] = (ps, group_cs)
for gn, (ps, group_cs) in included_gp.items():
for prop in ps:
del check_points[layer][tag][prop]
check_points[layer][tag][gn] = group_cs
if persistent._viewer_focusing and perspective_enabled(s, time=t):
if "blur" in check_points[layer][tag]:
del check_points[layer][tag]["blur"]
else:
for p in ("focusing", "dof"):
if p in check_points[layer][tag]:
del check_points[layer][tag][p]
image_check_points.append(check_points)
for css in camera_check_points:
for p in props_groups["focusing"]:
if p in css:
del css[p]
if play:
renpy.show("action_preview", what=Transform(function=renpy.curry(viewer_transform)(
camera_check_points=camera_check_points, image_check_points=image_check_points, scene_checkpoints=deepcopy(scene_keyframes),
viewer_check_points=viewer_check_points, zorder_list=zorder_list, loop=loop, spline=spline, start_time=0., end_time=get_animation_delay())))
else:
renpy.show("action_preview", what=Transform(function=renpy.curry(viewer_transform)(
camera_check_points=camera_check_points, image_check_points=image_check_points, scene_checkpoints=deepcopy(scene_keyframes),
viewer_check_points=viewer_check_points, zorder_list=zorder_list, loop=loop, spline=spline, time=current_time)))
def viewer_transform(tran, st, at, camera_check_points, image_check_points, scene_checkpoints, viewer_check_points,
zorder_list, loop, spline=None, subpixel=True, time=None, start_time=None, end_time=None):
global current_time, playing
if time is None:
time = st
if st <= end_time + return_margin+.1:
playing = True
if st <= end_time:
current_time = st + start_time
else:
playing = False
else:
playing = False
box = renpy.display.layout.MultiBox(layout='fixed')
for i in range(-1, -len(scene_checkpoints), -1):
checkpoint = scene_checkpoints[i][1]
if time >= checkpoint:
goal = scene_checkpoints[i]
if time - checkpoint >= get_transition_delay(goal[0]):
child = FixedTimeDisplayable(Transform(function=renpy.curry(
camera_transform)(camera_check_points=camera_check_points[i], image_check_points=image_check_points[i],
scene_checkpoints=scene_checkpoints, viewer_check_points=viewer_check_points[i],
zorder_list=zorder_list, loop=loop[i], spline=spline[i], subpixel=subpixel, time=time, scene_num=i)), time, at)
else:
old_widget = FixedTimeDisplayable(Transform(function=renpy.curry(
camera_transform)(camera_check_points=camera_check_points[i-1], image_check_points=image_check_points[i-1],
scene_checkpoints=scene_checkpoints, viewer_check_points=viewer_check_points[i-1],
zorder_list=zorder_list, loop=loop[i-1], spline=spline[i-1], subpixel=subpixel, time=time, scene_num=i-1)), time, at)
new_widget = FixedTimeDisplayable(Transform(function=renpy.curry(
camera_transform)(camera_check_points=camera_check_points[i], image_check_points=image_check_points[i],
scene_checkpoints=scene_checkpoints, viewer_check_points=viewer_check_points[i],
zorder_list=zorder_list, loop=loop[i], spline=spline[i], subpixel=subpixel, time=time, scene_num=i)), time, at)
transition = renpy.python.py_eval("renpy.store."+goal[0])
during_transition_displayable = DuringTransitionDisplayble(transition, old_widget, new_widget, time - checkpoint, 0)
child = during_transition_displayable
break
else:
child = Transform(function=renpy.curry(camera_transform)(
camera_check_points=camera_check_points[0], image_check_points=image_check_points[0],
scene_checkpoints=scene_checkpoints, viewer_check_points=viewer_check_points[0],
zorder_list=zorder_list, loop=loop[0], spline=spline[0], subpixel=subpixel, time=time, scene_num=0))
if not persistent._viewer_legacy_gui:
if aspect_16_9:
box.add(Transform(zoom=preview_size, xpos=(1 - preview_size)/2)(child))
if persistent._viewer_rot:
for i in range(1, 3):
box.add(Solid("#F00", xsize=preview_size, ysize=1, xpos=(1-preview_size)/2, ypos=preview_size*i/3))
box.add(Solid("#F00", xsize=1, ysize=preview_size, xpos=preview_size*i/3+(1-preview_size)/2))
else:
box.add(Transform(zoom=preview_size)(child))
if persistent._viewer_rot:
for i in range(1, 3):
box.add(Solid("#F00", xsize=preview_size, ysize=1, ypos=preview_size*i/3))
box.add(Solid("#F00", xsize=1, ysize=preview_size, xpos=preview_size*i/3))
else:
box.add(child)
if persistent._viewer_rot:
for i in range(1, 3):
box.add(Solid("#F00", xsize=1., ysize=1, ypos=config.screen_height*i//3))
box.add(Solid("#F00", xsize=1, ysize=1., xpos=config.screen_width*i//3))
tran.set_child(box)
return 0
def add_thick(child):
w, h = renpy.render(child, 0, 0, 0, 0).get_size()
w = int(w)
h = int(h)
bold=50
rv = renpy.display.layout.MultiBox(layout='fixed', xsize=w, ysize=h)
rv.add(Transform(matrixtransform=Matrix.rotate( 90, 0, 0), matrixanchor=(.5, 1.))(Solid("#FFF" , xpos=0 , ypos=-bold , xsize=w , ysize=bold) ))
rv.add(Transform(matrixtransform=Matrix.rotate(-90, 0, 0), matrixanchor=(.5, 0.))(Solid("#FFF" , xpos=0 , ypos=h , xsize=w , ysize=bold) ))
rv.add(Transform(matrixtransform=Matrix.rotate( 0, -90, 0), matrixanchor=(1., .5))(Solid("#FFF" , xpos=-bold , ypos=-bold , xsize=bold , ysize=h+2*bold)))
rv.add(Transform(matrixtransform=Matrix.rotate( 0, 90, 0), matrixanchor=(0., .5))(Solid("#FFF" , xpos=w , ypos=-bold , xsize=bold , ysize=h+2*bold)))
rv.add(child)
return rv
def define_camera_model(z11):
from math import atan2, degrees
camera_model = renpy.display.layout.MultiBox(layout='fixed')
inf = 10000000
bold = 50
d1 = degrees(atan2(config.screen_height, config.screen_width))
d2 = (90 - d1)*2
d3 = degrees(atan2(z11, sqrt(config.screen_height**2 + config.screen_width**2)/2))
camera_model.add(Transform(yanchor=.5, matrixanchor=(0, 0.5), matrixtransform=Matrix.rotate(0, d3, d1))(Solid("#F00", xsize=inf, ysize=bold)))
camera_model.add(Transform(yanchor=.5, matrixanchor=(0, 0.5), matrixtransform=Matrix.rotate(0, d3, d1+d2))(Solid("#0F0", xsize=inf, ysize=bold)))
camera_model.add(Transform(yanchor=.5, matrixanchor=(0, 0.5), matrixtransform=Matrix.rotate(0, d3, 3*d1+d2))(Solid("#0FF", xsize=inf, ysize=bold)))
camera_model.add(Transform(yanchor=.5, matrixanchor=(0, 0.5), matrixtransform=Matrix.rotate(0, d3, 3*d1+2*d2))(Solid("#939", xsize=inf, ysize=bold)))
width = renpy.config.screen_width
height = renpy.config.screen_height
return Transform(align=(.5, .5), matrixtransform=Matrix.offset(width/2, height/2, z11))(camera_model)
def camera_transform(tran, st, at, camera_check_points, image_check_points, scene_checkpoints, viewer_check_points, zorder_list, loop, spline=None, subpixel=True, time=None, scene_num=0):
global third_view_child
image_box = renpy.display.layout.MultiBox(layout='fixed')
sideview_image_box = renpy.display.layout.MultiBox(layout='fixed')
for layer in image_check_points:
for tag, zorder in zorder_list[scene_num][layer]:
if tag in image_check_points[layer]:
image_loop = {key[2]+"_loop": loops[scene_num][key] for key in loops[scene_num] if isinstance(key, tuple) and key[0] == tag and key[1] == layer}
image_spline = {key[2]+"_spline": splines[scene_num][key] for key in splines[scene_num] if isinstance(key, tuple) and key[0] == tag and key[1] == layer}
for p in props_groups["focusing"]:
image_loop[p+"_loop"] = loops[scene_num][p]
image_spline[p+"_spline"] = splines[scene_num][p]
image_box.add(Transform(function=renpy.curry(transform)(
check_points=image_check_points[layer][tag],
loop=image_loop, spline=image_spline,
subpixel=subpixel, time=time, scene_num=scene_num, scene_checkpoints=scene_checkpoints)))
if persistent._viewer_sideview and scene_num == current_scene and perspective_enabled(scene_num) and not persistent._viewer_legacy_gui:
sideview_image_box.add(Transform(function=renpy.curry(transform)(
check_points=image_check_points[layer][tag], loop=image_loop, spline=image_spline, subpixel=subpixel,
time=time, scene_num=scene_num, scene_checkpoints=scene_checkpoints, side_view=True)))
if persistent._viewer_sideview and scene_num == current_scene and perspective_enabled(scene_num) and not persistent._viewer_legacy_gui:
preview_box = renpy.display.layout.MultiBox(layout='fixed')
preview_box.add(sideview_image_box)
perspective = camera_check_points["perspective"][0][0]
if perspective is True:
perspective = config.perspective
if isinstance(perspective, (int, float)):
z11 = perspective
else:
z11 = perspective[1]
camera_model = define_camera_model(z11)
# preview_box.add(camera_model)
camera_model = Transform(function=renpy.curry(transform)(
check_points=viewer_check_points, loop=loop, spline=spline, subpixel=subpixel, time=time,
scene_num=scene_num, scene_checkpoints=scene_checkpoints, camera=True, side_view=True))(camera_model)
preview_box.add(camera_model)
inf = 1000000
third_view_child = []
for i, r in enumerate(((-90, 0, 0), (0, -90, 0), (0, 0, 0))):
sd = Transform(perspective=(0, inf, inf*10), matrixtransform=Matrix.scale(0.2, 0.2, 1.0)*Matrix.rotate(*r))(preview_box)
sd = renpy.store.AlphaMask(sd, Solid("#000"))
if aspect_16_9:
sd = Transform(zoom=(1 - preview_size)/2, ypos=i*preview_size/3)(sd)
else:
sd = Transform(zoom=(1 - preview_size)/2, xpos=preview_size, ypos=i*preview_size/3)(sd)
third_view_child.append(sd)
camera_box = renpy.display.layout.MultiBox(layout='fixed')
#camera position doesn't have effect whithout box
camera_box.add(Transform(function=renpy.curry(transform)(
check_points=camera_check_points, loop=loop, spline=spline,
subpixel=subpixel, time=time, camera=True, scene_num=scene_num, scene_checkpoints=scene_checkpoints))(image_box))
tran.set_child(camera_box)
return 0
def transform(tran, st, at, check_points, loop, spline=None, subpixel=True, crop_relative=True, time=None, camera=False, scene_num=None, scene_checkpoints=None, side_view=False):
# check_points = { prop: [ (value, time, warper).. ] }
if subpixel is not None:
tran.subpixel = subpixel
if crop_relative is not None:
tran.crop_relative = crop_relative
if time is None:
time = st
group_cache = {}
sle = renpy.game.context().scene_lists
if in_editor and camera and not side_view:
tran.perspective = get_value("perspective", scene_keyframes[scene_num][1], True)
for p, cs in check_points.items():
if not cs: #恐らく不要
break
scene_start = cs[0][1]
looped_time = time
if p+"_loop" in loop and loop[p+"_loop"] and cs[-1][1]:
if (time - scene_start) % (cs[-1][1] - scene_start) != 0:
looped_time = (time - scene_start) % (cs[-1][1] - scene_start) + scene_start
for i in range(1, len(cs)):
checkpoint = cs[i][1]
pre_checkpoint = cs[i-1][1]
if looped_time >= scene_start and looped_time < checkpoint:
start = cs[i-1]
goal = cs[i]
if p not in ("child", "function", "at_list", "props_use_default"):
if checkpoint != pre_checkpoint:
if goal[2].startswith("warper_generator"):
warper = renpy.python.py_eval(goal[2])
else:
warper = renpy.atl.warpers[goal[2]]
complete = warper((looped_time - pre_checkpoint) / (checkpoint - pre_checkpoint))
else:
complete = 1.
knots = []
if spline is not None and p+"_spline" in spline and checkpoint in spline[p+"_spline"]:
knots = spline[p+"_spline"][checkpoint]
if knots:
knots = [start[0]] + knots + [goal[0]]
if knots:
v = renpy.atl.interpolate_spline(complete, knots)
elif p not in props_groups["focusing"]:
old = start[0]
new = goal[0]
if p == "orientation":
if old is None:
old = (0.0, 0.0, 0.0)
if new is not None:
v = euler_slerp(complete, old, new)
elif complete >= 1:
v = None
else:
v = old
else:
if p in ("matrixtransform", "matrixcolor"):
old = start[0](None, 1.0)
old.origin = start[0]
v = renpy.atl.interpolate(complete, old, new, renpy.atl.PROPERTIES[p])
if p in props_groups["focusing"]:
if not side_view:
group_cache[p] = complete * (goal[0] - start[0]) + start[0]
if len(group_cache) == len(props_groups["focusing"]):
focusing = group_cache["focusing"]
dof = group_cache["dof"]
image_zpos = 0
if tran.zpos:
image_zpos = tran.zpos
if tran.matrixtransform:
image_zpos += tran.matrixtransform.zdw
camera_zpos = 0
if in_editor:
camera_zpos = get_value("zpos", default=True, scene_num=scene_num)
else:
if "master" in sle.camera_transform:
props = sle.camera_transform["master"]
if props.zpos:
camera_zpos = props.zpos
result = camera_blur_amount(image_zpos, camera_zpos, dof, focusing)
setattr(tran, "blur", result)
else:
setattr(tran, p, v)
break
else:
if looped_time < scene_start:
fixed_index = 0
else:
fixed_index = -1
if p in props_groups["focusing"]:
if not side_view:
group_cache[p] = cs[fixed_index][0]
if len(group_cache) == len(props_groups["focusing"]):
focusing = group_cache["focusing"]
dof = group_cache["dof"]
image_zpos = 0
if tran.zpos:
image_zpos = tran.zpos
if tran.matrixtransform:
image_zpos += tran.matrixtransform.zdw
camera_zpos = 0
if in_editor:
camera_zpos = get_value("zpos", default=True, scene_num=scene_num)
else:
if "master" in sle.camera_transform:
props = sle.camera_transform["master"]
if props.zpos:
camera_zpos = props.zpos
result = camera_blur_amount(image_zpos, camera_zpos, dof, focusing)
setattr(tran, "blur", result)
else:
if p not in ("child", "function", "at_list", "props_use_default"):
v = cs[fixed_index][0]
#inherit position properties from 'at clauses' if not given.
if p in check_points["props_use_default"][0][0] and p in {"xpos", "ypos", "xanchor", "yanchor", "xoffset", "yoffset"}:
at_v = get_at_list_props(check_points["at_list"][0][0], p, time, at)
if at_v is not None:
v = at_v
# if "child" in check_points and check_points["child"][0][0][0] == "t0 a" and p == "xpos":
# raise Exception(check_points["child"], check_points["props_use_default"][0][0])
if p in ("matrixtransform", "matrixcolor"):
v = v(1.0, None)
setattr(tran, p, v)
if "child" in check_points and check_points["child"]:
at_list = check_points["at_list"][0][0]
cs = check_points["child"]
scene_start = cs[0][1]
looped_time = time
if "child_loop" in loop and loop["child_loop"] and cs[-1][1]:
if (time - scene_start) % (cs[-1][1] - scene_start) != 0:
looped_time = (time - scene_start) % (cs[-1][1] - scene_start) + scene_start
for i in range(-1, -len(cs), -1):
checkpoint = cs[i][1]
pre_checkpoint = cs[i-1][1]
if looped_time >= scene_start and looped_time >= checkpoint:
start = cs[i-1]
goal = cs[i]
if start[0][0] is None and goal[0][0] is None:
tran.set_child(Null())
break
elif start[0][0] is None:
new_widget = get_widget(goal[0][0], looped_time, at, at_list)
w, h = renpy.render(new_widget, 0, 0, 0, 0).get_size()
old_widget = Null(w, h)
elif goal[0][0] is None:
old_widget = get_widget(start[0][0], looped_time, at, at_list)
w, h = renpy.render(old_widget, 0, 0, 0, 0).get_size()
new_widget = Null(w, h)
else:
old_widget = get_widget(start[0][0], looped_time, at, at_list)
new_widget = get_widget(goal[0][0], looped_time, at, at_list)
if looped_time - checkpoint >= get_transition_delay(goal[0][1]):
child = new_widget
else:
transition = renpy.python.py_eval("renpy.store."+goal[0][1])
during_transition_displayable = DuringTransitionDisplayble(transition, old_widget, new_widget, looped_time-checkpoint, 0)
child = during_transition_displayable
if side_view:
child = add_thick(child)
tran.set_child(child)
break
else:
start = ((None, None), 0, None)
goal = cs[0]
checkpoint = goal[1]
if goal[0][0] is None:
child = Null()
else:
fixed_time = looped_time-checkpoint
if fixed_time < 0:
fixed_time = 0
new_widget = get_widget(goal[0][0], looped_time, at, at_list)
w, h = renpy.render(new_widget, 0, 0, 0, 0).get_size()
old_widget = Null(w, h)
if fixed_time >= get_transition_delay(goal[0][1]):
child = new_widget
else:
transition = renpy.python.py_eval("renpy.store."+goal[0][1])
child = DuringTransitionDisplayble(transition, old_widget, new_widget, fixed_time, 0)
if side_view:
child = add_thick(child)
tran.set_child(child)
if "function" in check_points and check_points["function"]:
f = check_points["function"][0][0][1]
if f is not None:
f(tran, time, at)
if in_editor:
point_to = getattr(tran, "point_to", None)
perspective = get_value("perspective", scene_keyframes[scene_num][1], True)
if perspective and (isinstance(point_to, renpy.display.transform.Camera) or (side_view and camera)):
if perspective is True:
perspective = renpy.config.perspective
elif isinstance(perspective, (int, float)):
perspective = (renpy.config.perspective[0], perspective, renpy.config.perspective[2])
if perspective:
z11 = perspective[1]
width = renpy.config.screen_width
height = renpy.config.screen_height
placement = (get_value("xpos", default=True, scene_num=scene_num), get_value("ypos", default=True, scene_num=scene_num), get_value("xanchor", default=True, scene_num=scene_num), get_value("yanchor", default=True, scene_num=scene_num), get_value("xoffset", default=True, scene_num=scene_num), get_value("yoffset", default=True, scene_num=scene_num), True)
xplacement, yplacement = renpy.display.core.place(width, height, width, height, placement)
zpos = get_value("zpos", default=True, scene_num=scene_num)
# direct displayable toward camera
if point_to is not None and isinstance(point_to, renpy.display.transform.Camera):
point_to = (xplacement + width / 2, yplacement + height / 2, zpos + z11)
setattr(tran, "point_to", point_to)
elif side_view and camera:
mrotation = None
xrotate = getattr(tran, "xrotate", None)
yrotate = getattr(tran, "yrotate", None)
zrotate = getattr(tran, "zrotate", None)
if (xrotate is not None) or (yrotate is not None) or (zrotate is not None):
xrotate, yrotate, zrotate = zyx_to_xyz(xrotate, yrotate, zrotate)
mrotation = Matrix.rotate(xrotate, yrotate, zrotate)
setattr(tran, "xrotate", None)
setattr(tran, "yrotate", None)
setattr(tran, "zrotate", None)
morientation = None
orientation = getattr(tran, "orientation", None)
if orientation is not None:
orientation = zyx_to_xyz(*orientation)
morientation = Matrix.rotate(*orientation)
setattr(tran, "orientation", None)
mpoint_to = None
poi = getattr(tran, "point_to", None)
if poi is not None:
from math import sin, cos, asin, atan, degrees, pi, sqrt
start_pos = (xplacement + width / 2, yplacement + height / 2, zpos + z11)
a, b, c = ( float(e - s) for s, e in zip(start_pos, poi) )
#cameras is rotated in z, y, x order.
#It is because rotating stage in x, y, z order means rotating a camera in z, y, x order.
#rotating around z axis isn't rotating around the center of the screen when rotating camera in x, y, z order.
v_len = sqrt(a**2 + b**2 + c**2) # math.hypot is better in py3.8+
if v_len == 0:
xpoi = ypoi = zpoi = 0
else:
a /= v_len
b /= v_len
c /= v_len
sin_ypoi = min(1., max(-a, -1.))
ypoi = asin(sin_ypoi)
if c == 0:
if abs(a) == 1:
xpoi = 0
else:
sin_xpoi = min(1., max(b / cos(ypoi), -1.))
xpoi = asin(sin_xpoi)
else:
xpoi = atan(-b/c)
if c > 0:
ypoi = pi - ypoi
if xpoi != 0.0 and ypoi != 0.0:
if xpoi == pi / 2 or xpoi == - pi / 2:
if -sin(xpoi) * sin(ypoi) > 0.0:
zpoi = pi / 2
else:
zpoi = - pi / 2
else:
zpoi = atan(-(sin(xpoi) * sin(ypoi)) / cos(xpoi))
else:
zpoi = 0
xpoi = degrees(xpoi)
ypoi = degrees(ypoi)
zpoi = degrees(zpoi)
xpoi, ypoi, zpoi = zyx_to_xyz(xpoi, ypoi, zpoi)
mpoint_to = Matrix.rotate(xpoi, ypoi, zpoi)
setattr(tran, "point_to", None)
m = Matrix.identity()
mt = getattr(tran, "matrixtransform", None)
if mt is not None:
matrixanchor = getattr(tran, "matrixanchor", None)
if matrixanchor is None:
manchorx = width / 2.0
manchory = height / 2.0
else:
manchorx, manchory = matrixanchor
if type(manchorx) is float:
manchorx *= width
if type(manchory) is float:
manchory *= height
m = Matrix.offset(-manchorx, -manchory, 0.0) * m
m = mt * m
m = Matrix.offset(manchorx, manchory, 0.0) * m
setattr(tran, "matrixanchor", (0, 0))
rotate = getattr(tran, "rotate", None)
if rotate is not None:
setattr(tran, "rotate", None)
m = Matrix.offset(-width / 2, -height / 2, 0) * m
m = Matrix.rotate(0, 0, rotate) * m
m = Matrix.offset(width / 2, height / 2, 0) * m
if mrotation is not None or morientation is not None or mpoint_to is not None:
#original code width /2
m = Matrix.offset(-width / 2, -height / 2, -z11) * m
if mrotation is not None:
m = mrotation * m
if morientation is not None:
m = morientation * m
if mpoint_to is not None:
m = mpoint_to * m
#original code width /2
m = Matrix.offset(width / 2, height / 2, z11) * m
if xplacement:
setattr(tran, "xpos", 0)
setattr(tran, "xanchor", 0)
setattr(tran, "xoffset", 0)
if yplacement:
setattr(tran, "ypos", 0)
setattr(tran, "yanchor", 0)
setattr(tran, "yoffset", 0)
if zpos:
setattr(tran, "zpos", 0)
m = Matrix.offset(xplacement, yplacement, zpos) * m
setattr(tran, "matrixtransform", m)
# if not camera:
# showing_pool = {
# "scene_num":scene_num
# "tag":tag
# "pos": getattr(tran, "pos")
# }
# if not camera:
# tran.alignaround = (0.5+time*0.1, 0.5)
# tran.angle = 0
# tran.alignaround = (0.5, 0.5)
# tran.angle = 315
# tran.radius=0.71
# renpy.store.test = tran.alignaround
return 0
def get_widget(name, time, at, at_list):
name_tuple = tuple(name.split())
if name_tuple in images and isinstance(images[name_tuple], Movie):
d_org = images[name_tuple]
file_name = d_org._play
mask_file_name = d_org.mask
prefix_org = ""
if file_name.find(">") > 0:
prefix_org = file_name[:file_name.find(">")+1]
file_name = file_name[file_name.find(">")+1:]
if mask_file_name:
mask_prefix_org = ""
if mask_file_name.find(">") > 0:
mask_prefix_org = file_name[:mask_file_name.find(">")+1]
mask_file_name = file_name[mask_file_name.find(">")+1:]
prefix = "<from {} to {}>".format(time, time)
if mask_file_name:
mask_prefix = "<from {} to {}>".format(time, time)
play = prefix + file_name
if mask_file_name:
mask = mask_prefix + mask_file_name
else:
mask = None
if name_tuple in movie_cache:
d = movie_cache[name_tuple]
else:
d = deepcopy(d_org)
movie_cache[name_tuple] = d
d._play = play
d.mask = None
d.loop = False
# d = FixedTimeDisplayable(Movie(play=prefix+file_name, mask=None, loop=False), time, at)
widget = d
# raise Exception((d._play, d.mask))
# elif name_tuple in images:
# child = images[name_tuple]
# child = apply_at_list(child, at_list)
# widget = FixedTimeDisplayable(child, time, at)
else:
#easy displayableではすべてImageReference objectになるがなにか問題あるか?
child = renpy.easy.displayable(name)
child = apply_at_list(child, at_list)
widget = FixedTimeDisplayable(child, time, at)
return widget
def exclusive_check(key, scene_num=None):
#check exclusive properties
if scene_num is None:
scene_num = current_scene
if isinstance(key, tuple):
tag, layer, prop = key
state = get_image_state(layer, scene_num)
camera = False
else:
prop = key
state = camera_state_org[scene_num]
camera = True
for set1, set2 in exclusive:
if prop in set1 or prop in set2:
if prop in set1:
one_set = set1
other_set = set2
else:
one_set = set2
other_set = set1
for p in one_set:
if camera:
key2 = p
else:
key2 = (tag, layer, p)
if key2 in all_keyframes[scene_num]:
return True
if key2 in state and (state[key2] is not None and state[key2] != get_default(p)):
return True
for p in other_set:
if camera:
key2 = p
else:
key2 = (tag, layer, p)
if key2 in all_keyframes[scene_num]:
return False
if key2 in state and (state[key2] is not None and state[key2] != get_default(p)):
return False
else:
if prop in set1:
return True
else:
return False
else:
return True
def edit_value(function, default, use_wide_range=False, force_plus=False, time=None):
v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=default)
if v:
try:
v = renpy.python.py_eval(v)
v = to_changed_value(v, force_plus, use_wide_range)
except Exception as e:
message = _("Please type value") + "\n" \
+ format_exc()
renpy.notify(message)
return
function(v, time=time)
def edit_default_transition():
v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", message=_("Type transition"))
if v:
if v == "None":
v = None
else:
try:
renpy.python.py_eval(v)
except Exception as e:
message = _("Please Input Transition") + "\n" \
+ format_exc()
renpy.notify(message)
return
persistent._viewer_transition = v
return
renpy.notify(_("Please Input Transition"))
def edit_transition(tag, layer, time=None):
if time is None:
time = current_time
if time < scene_keyframes[current_scene][1]:
renpy.notify(_("can't change values before the start tiem of the current scene"))
return
v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen")
if v:
if (tag, layer, "child") in all_keyframes[current_scene]:
cs = all_keyframes[current_scene][(tag, layer, "child")]
for i in range(-1, -len(cs)-1, -1):
if time >= cs[i][1]:
(n, tran), t, w = cs[i]
break
else:
n = get_value((tag, layer, "child"), default=True)[0]
if v == "None":
v = None
else:
try:
renpy.python.py_eval(v)
except Exception as e:
message = _("Please Input Transition") + "\n" \
+ format_exc()
renpy.notify(message)
return
set_keyframe((tag, layer, "child"), (n, v), time=time)
change_time(time)
return
renpy.notify(_("Please Input Transition"))
def edit_channel_list():
v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=persistent._viewer_channel_list , message=_("Please type the list of channel names(ex [['sound', 'sound2'])"))
message1 = _("Please type the list of channel names(ex ['sound', 'sound2'])")
try:
v = renpy.python.py_eval(v)
except:
renpy.notify(message1)
return
if v and isinstance(v, list):
for c in v:
try:
renpy.audio.music.get_channel(c)
except:
break
if c == "audio":
renpy.notify(_("can't include audio channel"))
else:
for c in v:
if c not in persistent._viewer_channel_list:
sound_keyframes[c] = {}
for c in persistent._viewer_channel_list:
if c not in v:
del sound_keyframes[c]
persistent._viewer_channel_list = v
return
renpy.notify(message1)
def add_image(layer):
if current_time < scene_keyframes[current_scene][1]:
renpy.notify(_("can't change values before the start tiem of the current scene"))
return
name = renpy.invoke_in_new_context(renpy.call_screen, "_image_selecter")
state = get_image_state(layer)
if not isinstance(name, tuple):
name = tuple(name.split())
for n in get_image_name_candidates():
if set(n) == set(name):
for tag in state:
if tag == n[0]:
for i in range(2, 999):
for tag2 in state:
if n[0]+str(i) == tag2:
break
else:
name = n[0]+str(i)+" "+" ".join(n[1:])
break
else:
renpy.notify(_("too many same tag images is used"))
return
break
else:
name = " ".join(n)
image_name = " ".join(n)
added_tag = name.split()[0]
image_state[current_scene][layer][added_tag] = {}
image_state[current_scene][layer][added_tag]["at_list"] = [("default", {})]
zorder_list[current_scene][layer].append((added_tag, 0))
for p in transform_props:
if p == "child":
image_state[current_scene][layer][added_tag][p] = (image_name, None)
if current_scene == 0 or current_time > scene_keyframes[current_scene][1]:
set_keyframe((added_tag, layer, p), (image_name, persistent._viewer_transition))
elif p in ("matrixtransform", "matrixcolor"):
for prop, v in load_matrix(p, None):
image_state[current_scene][layer][added_tag][prop] = v
else:
image_state[current_scene][layer][added_tag][p] = None
change_time(current_time)
# if persistent._viewer_legacy_gui:
# renpy.show_screen("_action_editor")
# else:
# renpy.show_screen("_new_action_editor")
return
else:
renpy.notify(_("Please type image name"))
return
def get_image_name_candidates():
from itertools import combinations
result = []
for n, d in images.items():
if isinstance(d, renpy.store.Live2D):
name = n[0]
expression = d.common.expressions
nonexclusive = d.common.nonexclusive
motions = d.common.motions
attribute_filter = d.common.attribute_filter
nonexclusive_sets = []
for i in range(1,len(nonexclusive)+1):
for comb in combinations(nonexclusive, n):
nonexclusive_sets.append(comb)
filtered_nonexclusive_sets = set()
if attribute_filter is not None:
for nes in nonexclusive_sets:
filtered_nonexclusive_sets.add(attribute_filter(nes))
for m in motions:
result.append((name, m))
for e in expression:
result.append((name, m, e))
for nes in filtered_nonexclusive_sets:
result.append((name, m, )+nes)
result.append((name, m, e)+nes)
else:
result.append(n)
return result
def change_child(tag, layer, time=None, default=None):
if time is None:
time = current_time
if time < scene_keyframes[current_scene][1]:
renpy.notify(_("can't change values before the start tiem of the current scene"))
return
org = default
if org is None:
default = tag
new_image = renpy.invoke_in_new_context(renpy.call_screen, "_image_selecter", default=default)
if not isinstance(new_image, tuple): #press button
new_image = tuple(new_image.split())
for n in images:
if set(n) == set(new_image) and n[0] == new_image[0]:
# if org is not None and set(new_image) == set(org.split()):
# renpy.notify(_("That is already shown"))
# return
string = " ".join(n)
set_keyframe((tag, layer, "child"), (string, persistent._viewer_transition), time=time)
return
else:
if new_image and new_image[0] == "None" and org is not None:
set_keyframe((tag, layer, "child"), (None, persistent._viewer_transition), time=time)
return
renpy.notify(_("Please type image name"))
return
def edit_function(key):
value = get_value(key)
if isinstance(value, tuple):
value = value[0]
value = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=value)
if value:
if value == "None":
remove_keyframe(scene_keyframes[current_scene][1], key)
else:
try:
f = renpy.python.py_eval("renpy.store."+value)
if not callable(f):
renpy.notify(_(value + " is not callable."))
return
except Exception as e:
message = _("Please type a valid data") + "\n" \
+ format_exc()
renpy.notify(message)
return
set_keyframe(key, (value, f), time=scene_keyframes[current_scene][1])
change_time(current_time)
def edit_any(key, time=None):
if time is None:
time = current_time
if isinstance(key, tuple):
prop = key[2]
else:
prop = key
value = get_value(key, time)
if prop in menu_props:
global _return
_return = value
renpy.invoke_in_new_context(renpy.call_screen, "_value_menu", prop=prop, default=value)
value = _return
else:
if isinstance(value, str):
value = "'" + value + "'"
value = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=value)
if value:
try:
value = renpy.python.py_eval(value)
if prop in check_any_props and not check_any_props[prop](value):
renpy.notify(_("{} is an invalid data".format(value)))
return
except Exception as e:
message = _("Please type a valid data") + "\n" \
+ format_exc()
renpy.notify(message)
return
else:
return
set_keyframe(key, value, time=time)
change_time(current_time)
def toggle_boolean_property(key):
if isinstance(key, tuple):
tag, layer, prop = key
value_org = get_image_state(layer)[tag][prop]
else:
value_org = camera_state_org[current_scene][key]
value = get_value(key, scene_keyframes[current_scene][1], True)
#assume default is False
if value == value_org or (not value and not value_org):
set_keyframe(key, not value, time=scene_keyframes[current_scene][1])
else:
remove_keyframe(scene_keyframes[current_scene][1], key)
change_time(current_time)
def perspective_enabled(scene_num=None, time=None):
if scene_num is None:
scene_num = current_scene
if time is None:
time = scene_keyframes[scene_num][1]
v = get_value("perspective", scene_keyframes[scene_num][1], True, scene_num)
return v or (v is not False and v == 0)
def remove_image(layer, tag):
def remove_keyframes(layer, tag):
for k in (k for k in all_keyframes[current_scene] if isinstance(k, tuple) and k[0] == tag and k[1] == layer):
del all_keyframes[current_scene][k]
renpy.hide(tag, layer)
del image_state[current_scene][layer][tag]
remove_keyframes(tag, layer)
zorder_list[current_scene][layer] = [(ztag, z) for (ztag, z) in zorder_list[current_scene][layer] if ztag != tag]
def get_default(prop):
if prop.count("_") == 3:
_, _, _, prop = prop.split("_")
return property_default_value[prop]
def get_value(key, time=None, default=False, scene_num=None):
if scene_num is None:
scene_num = current_scene
if isinstance(key, tuple):
tag, layer, prop = key
if prop in props_groups["focusing"]:
key = prop
if isinstance(key, tuple):
tag, layer, prop = key
mkey = (tag, layer)
state = get_image_state(layer, scene_num)[tag]
else:
prop = key
mkey = "camera"
state = camera_state_org[scene_num]
if key not in all_keyframes[scene_num]:
v = state[prop]
if v is not None or prop in boolean_props | any_props:
if prop == "child":
return v[0], None
else:
return v
elif default:
return get_default(prop)
else:
return None
cs = all_keyframes[scene_num][key]
if time is None:
time = current_time
if prop == "child":
for i in range(-1, -len(cs)-1, -1):
if time >= cs[i][1]:
return cs[i][0]
scene_start = cs[0][1]
looped_time = time
if loops[scene_num][key] and cs[-1][1]:
if (time - scene_start) % (cs[-1][1] - scene_start) != 0:
looped_time = (time - scene_start) % (cs[-1][1] - scene_start) + scene_start
for i in range(1, len(cs)):
checkpoint = cs[i][1]
pre_checkpoint = cs[i-1][1]
if looped_time >= scene_start and looped_time < checkpoint:
start = cs[i-1]
goal = cs[i]
if checkpoint != pre_checkpoint:
if goal[2].startswith("warper_generator"):
warper = renpy.python.py_eval(goal[2])
else:
warper = renpy.atl.warpers[goal[2]]
complete = warper((looped_time - pre_checkpoint) / (checkpoint - pre_checkpoint))
else:
complete = 1.
if goal[0] is not None or prop in boolean_props | any_props:
check_result = check_props_group(prop, mkey, scene_num)
if check_result:
gn, ps = check_result
if check_result and gn not in ("focusing", "matrixtransform", "matrixcolor"):
old = []
new = []
default_value = get_default(prop)
for p in ps:
if isinstance(key, tuple):
key2 = (key[0], key[1], p)
else:
key2 = p
old.append(all_keyframes[scene_num][key2][i-1][0])
new.append(all_keyframes[scene_num][key2][i][0])
old = tuple(old)
new = tuple(new)
knots = []
if checkpoint in splines[scene_num][gn]:
knots = splines[scene_num][gn][checkpoint]
if knots:
knots = [old] + knots + [new]
else:
default_value = get_default(prop)
if start[0] is None:
old = default_value
else:
old = start[0]
new = goal[0]
knots = []
if checkpoint in splines[scene_num][key]:
knots = splines[scene_num][key][checkpoint]
if knots:
knots = [old] + knots + [new]
if knots:
v = renpy.atl.interpolate_spline(complete, knots)
elif check_result and gn in ("focusing", "matrixtransform", "matrixcolor"):
v = complete*(new-old)+old
elif check_result:
if gn == "orientation":
new = new
if old is None:
old = (0.0, 0.0, 0.0)
if new is not None:
v = euler_slerp(complete, old, new)
elif complete >= 1:
v = None
else:
v = old
else:
v = renpy.atl.interpolate(complete, old, new, renpy.atl.PROPERTIES[gn])
else:
if prop == "orientation":
new = new
if old is None:
old = (0.0, 0.0, 0.0)
if new is not None:
v = euler_slerp(complete, old, new)
elif complete >= 1:
v = None
else:
v = old
else:
v = renpy.atl.interpolate(complete, old, new, renpy.atl.PROPERTIES[prop])
if check_result and gn not in ("focusing", "matrixtransform", "matrixcolor"):
index = ps.index(prop)
v = v[index]
if isinstance(new, int):
v = int(v)
return v
break
else:
if looped_time >= scene_start:
return cs[-1][0]
else:
return cs[0][0]
def put_camera_clipboard():
camera_keyframes = {}
for k in all_keyframes[current_scene]:
if not isinstance(k, tuple) and k != "function":
value = get_value(k, current_time)
if isinstance(value, float):
value = round(value, 3)
elif k in any_props and isinstance(value, str):
value = "'" + value + "'"
camera_keyframes[k] = [(value, 0, None)]
camera_keyframes = set_group_keyframes(camera_keyframes, "camera")
camera_properties = []
for p in camera_state_org[current_scene]:
check_result = check_props_group(p, "camera")
if check_result is not None:
gn, ps = check_result
if gn not in camera_properties:
camera_properties.append(gn)
else:
if p not in special_props:
camera_properties.append(p)
string = """
camera"""
for p, cs in x_and_y_to_xy([(p, camera_keyframes[p]) for p in camera_properties if p in camera_keyframes]):
if string.find(":") < 0:
string += ":\n "
string += "{property} {value}".format(property=p, value=cs[0][0])
if persistent._one_line_one_prop:
string += "\n "
else:
string += " "
string = '\n'.join(filter(lambda x: x.strip(), string.split('\n')))
string = "\n"+ string + "\n\n"
try:
from pygame import scrap, locals
scrap.put(locals.SCRAP_TEXT, string.encode("utf-8"))
except Exception as e:
message = _("Can't open clipboard") + "\n" \
+ format_exc()
renpy.notify(message)
else:
renpy.notify(__('Placed \n"%s"\n on clipboard') % string)
def put_image_clipboard(tag, layer):
image_keyframes = {}
for k in all_keyframes[current_scene]:
if isinstance(k, tuple) and k[0] == tag and k[1] == layer and k[2] != "function":
value = get_value(k, current_time)
if isinstance(value, float):
value = round(value, 3)
elif k[2] in any_props and isinstance(value, str):
value = "'" + value + "'"
image_keyframes[k[2]] = [(value, 0, None)]
image_keyframes = set_group_keyframes(image_keyframes, (tag, layer))
if check_focusing_used() and "blur" in image_keyframes:
del image_keyframes["blur"]
image_properties = []
for p in get_image_state(layer)[tag]:
check_result = check_props_group(p, (tag, layer))
if check_result is not None:
gn, ps = check_result
if gn not in image_properties:
image_properties.append(gn)
else:
if p not in special_props:
image_properties.append(p)
state = get_image_state(layer)
child = state[tag]["child"][0]
string = """
show {imagename}""".format(imagename=child)
if tag != child.split()[0]:
string += " as {tagname}".format(tagname=tag)
if layer != "master":
string += " onlayer {layer}".format(layer=layer)
for p, cs in x_and_y_to_xy([(p, image_keyframes[p]) for p in image_properties if p in image_keyframes]):
if string.find(":") < 0:
string += ":\n "
string += "{property} {value}".format(property=p, value=cs[0][0])
if persistent._one_line_one_prop:
string += "\n "
else:
string += " "
if check_focusing_used():
focus = get_value("focusing", current_time, True)
dof = get_value("dof", current_time, True)
result = "function camera_blur({'focusing':[({}, 0, None)], 'dof':[({}, 0, None)]})".format(focus, dof)
string += "\n "
string += result
string = '\n'.join(filter(lambda x: x.strip(), string.split('\n')))
string = "\n"+ string + "\n\n"
try:
from pygame import scrap, locals
scrap.put(locals.SCRAP_TEXT, string.encode("utf-8"))
except Exception as e:
message = _("Can't open clipboard") + "\n" \
+ format_exc()
renpy.notify(message)
else:
renpy.notify(__('Placed \n"%s"\n on clipboard') % string)
def put_sound_clipboard():
string = ""
for channel, times in sound_keyframes.items():
time = 0
files = "[\n " #]"
sorted_times = sorted(list(times.keys()))
if sorted_times:
for t in sorted_times:
duration = t - time
if duration > 0:
files += "'<silence {}>',\n ".format(duration)
fs = times[t]
files += fs[1:-1] + ",\n "
file = renpy.python.py_eval(fs, locals=renpy.python.store_dicts["store.audio"])
time = t
for f in file:
time += get_file_duration(f)
files = files[:-4] + "]\n"
string += "\n play {} {}".format(channel, files)
string = string.replace("u'", "'", 999)
try:
from pygame import scrap, locals
scrap.put(locals.SCRAP_TEXT, string.encode("utf-8"))
except Exception as e:
message = _("Can't open clipboard") + "\n" \
+ format_exc()
renpy.notify(message)
else:
renpy.notify(__('Placed \n"%s"\n on clipboard') % string)
def edit_warper(check_points, old, value_org):
warper = renpy.invoke_in_new_context(renpy.call_screen, "_warper_selecter", current_warper=value_org)
if warper:
if not isinstance(check_points[0], list):
check_points = [check_points]
for cs in check_points:
for i, (v, t, w) in enumerate(cs):
if t == old:
cs[i] = (v, t, warper)
break
renpy.restart_interaction()
def edit_move_keyframe(keys, old, is_sound=False):
v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=old)
if v:
try:
v = renpy.python.py_eval(v)
if v < scene_keyframes[current_scene][1]:
return
if not isinstance(keys, list):
keys = [keys]
move_keyframe(v, old, keys, is_sound)
except Exception as e:
message = _("Please type value") + "\n" \
+ format_exc()
renpy.notify(message)
def edit_move_all_keyframe():
v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=moved_time)
if v:
try:
v = renpy.python.py_eval(v)
if v < scene_keyframes[current_scene][1]:
return
move_all_keyframe(v, moved_time)
except Exception as e:
message = _("Please type value") + "\n" \
+ format_exc()
renpy.notify(message)
def edit_time():
v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=current_time)
if v:
try:
v = renpy.python.py_eval(v)
if v < scene_keyframes[current_scene][1]:
return
change_time(v)
except Exception as e:
message = _("Please type value") + "\n" \
+ format_exc()
renpy.notify(message)
def edit_range_value(object, field, use_int):
v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=getattr(object, field))
if v:
try:
v = renpy.python.py_eval(v)
if v <= 0:
renpy.notify(_("Please type plus value"))
return
if (isinstance(v, int) and use_int) or (isinstance(v, float) and not use_int):
setattr(object, field, v)
else:
if use_int:
renpy.notify(_("Please type float value"))
else:
renpy.notify(_("Please type int value"))
except Exception as e:
message = _("Please type value") + "\n" \
+ format_exc()
renpy.notify(message)
def next_time():
if not get_sorted_keyframes(current_scene):
change_time(scene_keyframes[current_scene][1])
return
else:
for t in get_sorted_keyframes(current_scene):
if current_time < t:
change_time(t)
return
change_time(scene_keyframes[current_scene][1])
def prev_time():
if not get_sorted_keyframes(current_scene):
change_time(scene_keyframes[current_scene][1])
return
else:
for t in reversed(get_sorted_keyframes(current_scene)):
if t < current_time and scene_keyframes[current_scene][1] <= t:
change_time(t)
return
else:
if current_time == scene_keyframes[current_scene][1]:
change_time(get_sorted_keyframes(current_scene)[-1])
else:
change_time(scene_keyframes[current_scene][1])
def add_scene():
global current_scene
# 途中にシーンも挟めるがスクリーンの画面で末尾に+ボタンがあるので末尾追加でないと挙動に違和感
# 名前も連番なので、見失う
# for i, (v, t, _) in enumerate(scene_keyframes):
# if t > current_time:
# break
# elif t == current_time:
# i += 1
# break
# else:
# i = len(scene_keyframes)
if scene_keyframes[-1][1] >= current_time:
renpy.notify(_("the new scene must be later than the start time of the previous scene."))
return
i = len(scene_keyframes)
current_scene = i
scene_keyframes.insert(current_scene, (persistent._viewer_transition, current_time, None))
image_state.insert(current_scene, {})
image_state_org.insert(current_scene, {})
camera_state_org.insert(current_scene, {})
zorder_list.insert(current_scene, {})
all_keyframes.insert(current_scene, {})
for l in config.layers:
image_state[current_scene][l] = {}
image_state_org[current_scene][l] = {}
zorder_list[current_scene][l] = []
loops.insert(current_scene, defaultdict(_False))
splines.insert(current_scene, defaultdict(dict))
for i in range(current_scene-1, -1, -1):
if camera_keyframes_exist(i):
break
for p in camera_state_org[i]:
middle_value = get_value(p, scene_keyframes[current_scene][1], False, i)
if isinstance(middle_value, float):
camera_state_org[current_scene][p] = round(middle_value, 2)
else:
camera_state_org[current_scene][p] = middle_value
# if persistent._viewer_legacy_gui:
# renpy.show_screen("_action_editor")
# elif persistent._open_only_one_page:
# renpy.show_screen("_new_action_editor")
renpy.restart_interaction()
def camera_keyframes_exist(scene_num):
for p in camera_state_org[scene_num]:
if p in all_keyframes[scene_num]:
break
else:
return False
return True
def remove_scene(scene_num):
global current_scene
if scene_num == 0:
return
if current_scene >= scene_num:
current_scene -= 1
del scene_keyframes[scene_num]
del image_state[scene_num]
del image_state_org[scene_num]
del camera_state_org[scene_num]
del zorder_list[scene_num]
del all_keyframes[scene_num]
del loops[scene_num]
del splines[scene_num]
for s in range(scene_num, len(scene_keyframes)):
for i in range(s, -1, -1):
if camera_keyframes_exist(i):
break
for p in camera_state_org[i]:
middle_value = get_value(p, scene_keyframes[s][1], False, i)
if isinstance(middle_value, float):
camera_state_org[s][p] = round(middle_value, 2)
else:
camera_state_org[s][p] = middle_value
# if persistent._viewer_legacy_gui:
# renpy.show_screen("_action_editor")
# elif persistent._open_only_one_page:
# renpy.show_screen("_new_action_editor")
change_time(current_time)
def move_scene(new, scene_num):
scene_num_scene_keyframes = scene_keyframes.pop(scene_num)
scene_num_image_state = image_state.pop(scene_num)
scene_num_image_state_org = image_state_org.pop(scene_num)
scene_num_camera_state_org = camera_state_org.pop(scene_num)
scene_num_zorder_list = zorder_list.pop(scene_num)
scene_num_all_keyframes = all_keyframes.pop(scene_num)
scene_num_loops = loops.pop(scene_num)
scene_num_splines = splines.pop(scene_num)
for i, s in enumerate(scene_keyframes):
if s[1] > new:
scene_keyframes.insert(i, scene_num_scene_keyframes)
image_state.insert(i, scene_num_image_state)
image_state_org.insert(i, scene_num_image_state_org)
camera_state_org.insert(i, scene_num_camera_state_org)
zorder_list.insert(i, scene_num_zorder_list)
all_keyframes.insert(i, scene_num_all_keyframes)
loops.insert(i, scene_num_loops)
splines.insert(i, scene_num_splines)
new_scene_num = i
break
elif s[1] == new:
scene_keyframes.insert(scene_num, scene_num_scene_keyframes)
image_state.insert(scene_num, scene_num_image_state)
image_state_org.insert(scene_num, scene_num_image_state_org)
camera_state_org.insert(scene_num, scene_num_camera_state_org)
zorder_list.insert(scene_num, scene_num_zorder_list)
all_keyframes.insert(scene_num, scene_num_all_keyframes)
loops.insert(scene_num, scene_num_loops)
splines.insert(scene_num, scene_num_splines)
return
else:
scene_keyframes.append(scene_num_scene_keyframes)
image_state.append(scene_num_image_state)
image_state_org.append(scene_num_image_state_org)
camera_state_org.append(scene_num_camera_state_org)
zorder_list.append(scene_num_zorder_list)
all_keyframes.append(scene_num_all_keyframes)
loops.append(scene_num_loops)
splines.append(scene_num_splines)
new_scene_num = len(scene_keyframes)-1
new = round(float(new), 2)
tran, old, w = scene_keyframes[new_scene_num]
scene_keyframes[new_scene_num] = (tran, new, w)
for s in range(new_scene_num, len(scene_keyframes)):
for i in range(s, -1, -1):
if camera_keyframes_exist(i):
break
for p in camera_state_org[i]:
middle_value = get_value(p, scene_keyframes[s][1], False, i)
if isinstance(middle_value, float):
camera_state_org[s][p] = round(middle_value, 2)
else:
camera_state_org[s][p] = middle_value
for k, cs in all_keyframes[new_scene_num].items():
for i, (v, t, w) in enumerate(cs):
cs[i] = (v, t - (old - new), w)
if splines[new_scene_num][k]:
for t in splines[new_scene_num][k]:
knots = splines[new_scene_num][k].pop(t)
splines[new_scene_num][k][t - (old - new)] = knots
# if persistent._viewer_legacy_gui:
# renpy.show_screen("_action_editor")
# else:
# renpy.show_screen("_new_action_editor")
change_time(current_time)
return
def edit_move_scene(scene_num):
v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=scene_keyframes[scene_num][1])
if v:
try:
v = renpy.python.py_eval(v)
if v < 0:
renpy.notify(_("Please type plus value"))
return
move_scene(v, scene_num)
except Exception as e:
message = _("Please type value") + "\n" \
+ format_exc()
renpy.notify(message)
def edit_scene_transition(scene_num):
default, t, w = scene_keyframes[scene_num]
v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=default)
if v:
if v == "None":
v = None
else:
try:
renpy.python.py_eval(v)
except Exception as e:
message = _("Please Input Transition") + "\n" \
+ format_exc()
renpy.notify(message)
return
scene_keyframes[scene_num] = (v, t, w)
change_time(current_time)
return
renpy.notify(_("Please Input Transition"))
def edit_playing_file(channel, time=None):
if time is None:
time = current_time
if time not in sound_keyframes[channel] and is_playing(channel, time, time):
renpy.notify(_("This channel is already used in this time"))
return
default = ""
if time in sound_keyframes[channel]:
default = sound_keyframes[channel][time]
v = renpy.invoke_in_new_context(renpy.call_screen, "_sound_selector", default=default)
if "[" not in v: #]"
v = "[" + v #]"
if "]" not in v:
v += "]"
try:
for f in v[1:-1].split(","):
if "<silence" not in f:
evaled = renpy.python.py_eval(f.strip(), locals=renpy.python.store_dicts["store.audio"])
if not renpy.loadable(evaled):
raise
except Exception as e:
message = _("Please Input filenames") + "\n" \
+ format_exc()
renpy.notify(message)
return
duration = 0
for f in renpy.python.py_eval(v, locals=renpy.python.store_dicts["store.audio"]):
duration += get_file_duration(f)
for t in sound_keyframes[channel].keys():
if t <= time + duration and t > time:
renpy.notify(_("This channel is already used in this time"))
return
sound_keyframes[channel][time] = v
return
def change_scene(scene_num):
global current_scene, current_time
current_scene = scene_num
# if persistent._viewer_legacy_gui:
# renpy.show_screen("_action_editor")
# elif persistent._open_only_one_page:
# renpy.show_screen("_new_action_editor")
change_time(current_time)
def select_default_warper():
v = renpy.invoke_in_new_context(renpy.call_screen, "_warper_selecter")
if v:
persistent._viewer_warper = v
def remove_keyframe(remove_time, key, is_sound=False):
if not isinstance(key, list):
key = [key]
for k in key:
if is_sound:
if remove_time in sound_keyframes[k]:
del sound_keyframes[k][remove_time]
else:
if k in all_keyframes[current_scene]:
for (v, t, w) in all_keyframes[current_scene][k][:]:
if (t == remove_time) and (remove_time != scene_keyframes[current_scene][1] \
or (remove_time == scene_keyframes[current_scene][1] and len(all_keyframes[current_scene][k]) == 1)):
all_keyframes[current_scene][k].remove((v, t, w))
if not all_keyframes[current_scene][k]:
del all_keyframes[current_scene][k]
if t in splines[current_scene][k]:
del splines[current_scene][k][t]
change_time(current_time)
def remove_all_keyframe(time):
keylist = [k for k in all_keyframes[current_scene]]
remove_keyframe(time, keylist)
keylist = list(sound_keyframes.keys())
remove_keyframe(time, keylist, True)
def get_sorted_keyframes(scene_num):
sorted_keyframes = []
for keyframes in all_keyframes[scene_num].values():
for (v, t, w) in keyframes:
if t not in sorted_keyframes:
sorted_keyframes.append(t)
for c, cs in sound_keyframes.items():
for t in cs:
if t not in sorted_keyframes:
sorted_keyframes.append(t)
return sorted(sorted_keyframes)
def move_all_keyframe(new, old):
global moved_time
if new < scene_keyframes[current_scene][1]:
new = scene_keyframes[current_scene][1]
moved_time = round(new, 2)
k_list = [k for k in all_keyframes[current_scene].keys()]
move_keyframe(new, old, k_list)
k_list = list(sound_keyframes.keys())
move_keyframe(new, old, k_list, True)
def move_keyframe(new, old, keys, is_sound=False):
if not is_sound:
if new < scene_keyframes[current_scene][1]:
new = scene_keyframes[current_scene][1]
new = round(float(new), 2)
if new == old:
renpy.restart_interaction()
if persistent._viewer_legacy_gui:
return
else:
return False
if not isinstance(keys, list):
keys = [keys]
if is_sound:
for k in keys:
if is_playing(k, new, old):
renpy.notify(_("This channel is already used in this time"))
if persistent._viewer_legacy_gui:
return
else:
return False
for k in keys:
if keyframes_exist(k, new, is_sound):
if persistent._viewer_legacy_gui:
return
else:
return False
for k in keys:
if is_sound:
if old in sound_keyframes[k]:
files = sound_keyframes[k][old]
sound_keyframes[k][new] = files
del sound_keyframes[k][old]
else:
cs = all_keyframes[current_scene][k]
for i, c in enumerate(cs):
if c[1] == old:
(value, time, warper) = cs.pop(i)
for n, (v, t, w) in enumerate(cs):
if new < t:
cs.insert(n, (value, new, warper))
break
else:
cs.append((value, new, warper))
if old == scene_keyframes[current_scene][1] and new != scene_keyframes[current_scene][1]:
cs.insert(0, (value, scene_keyframes[current_scene][1], persistent._viewer_warper))
if old in splines[current_scene][k]:
knots = splines[current_scene][k][old]
splines[current_scene][k][new] = knots
del splines[current_scene][k][old]
renpy.restart_interaction()
if not persistent._viewer_legacy_gui:
return True
def keyframes_exist(k, time=None, is_sound=False):
if time is None:
time = current_time
if is_sound:
if time in sound_keyframes[k]:
return True
else:
return False
else:
if k not in all_keyframes[current_scene]:
return False
check_points = all_keyframes[current_scene][k]
for c in check_points:
if c[1] == time:
return True
return False
def update_gn_spline(key, time, scene_num=None):
if scene_num is None:
scene_num = current_scene
if isinstance(key, tuple):
tag, layer, prop = key
mkey = (tag, layer)
else:
prop = key
mkey = "camera"
check_result = check_props_group(prop, mkey, scene_num)
if check_result:
gn, ps = check_result
pre_knots = []
for p in ps:
if mkey == "camera":
key2 = p
gn_key = gn
else:
key2 = (tag, layer, p)
gn_key = (tag, layer, gn)
pre_knots.append(splines[scene_num][key2][time])
knots = []
for knot in zip(*pre_knots):
knots.append(tuple(knot))
splines[scene_num][gn_key][time] = knots
def add_knot(key, time, default, knot_number=None, recursion=False):
if not recursion:
if isinstance(key, tuple):
tag, layer, prop = key
mkey = (tag, layer)
else:
prop = key
mkey = "camera"
check_result = check_props_group(prop, mkey, current_scene)
if check_result:
gn, ps = check_result
for p in ps:
if p != prop:
if mkey == "camera":
key2 = p
else:
key2 = (tag, layer, p)
cs = all_keyframes[current_scene][key2]
for i, (v, t, w) in enumerate(cs):
if t == time:
d2 = cs[i-1][0]
add_knot(key2, time, d2, knot_number, recursion=True)
if time in splines[current_scene][key]:
if knot_number is not None:
splines[current_scene][key][time].insert(knot_number, default)
else:
splines[current_scene][key][time].append(default)
else:
splines[current_scene][key][time] = [default]
if not recursion:
update_gn_spline(key, time)
def remove_knot(key, time, i, recursion=False):
if not recursion:
if isinstance(key, tuple):
tag, layer, prop = key
mkey = (tag, layer)
else:
prop = key
mkey = "camera"
check_result = check_props_group(prop, mkey, current_scene)
if check_result:
gn, ps = check_result
for p in ps + [gn]:
if p != prop:
if mkey == "camera":
key2 = p
else:
key2 = (tag, layer, p)
remove_knot(key2, time, i, recursion=True)
if time in splines[current_scene][key]:
splines[current_scene][key][time].pop(i)
if not splines[current_scene][key][time]:
del splines[current_scene][key][time]
def change_time(v):
global current_time
current_time = round(v, 2)
for c in persistent._viewer_channel_list:
renpy.music.stop(c, False)
play(False)
renpy.restart_interaction()
def get_file_duration(filename):
if filename.startswith("<silence "):
return renpy.python.py_eval(filename.split()[1][:-1])
else:
#互換性で残っている未使用のチャンネルで再生
#doesn't work during mute
mute_org = renpy.store._preferences.get_mute("sfx")
renpy.store._preferences.set_mute("sfx", False)
renpy.music.play(filename, channel=1, fadeout=0, loop=False)
duration = None
while duration is None:
renpy.audio.audio.interact()
if renpy.music.is_playing(1) and renpy.music.get_duration(1) != 0:
duration = renpy.music.get_duration(1)
renpy.store._preferences.set_mute("sfx", mute_org)
renpy.music.stop(1)
return duration
def is_playing(channel, new_time, old_time):
times = sorted(list(sound_keyframes[channel].keys()))
if new_time in times:
return True
if old_time in times:
times.remove(old_time)
for t in times:
if t > new_time:
duration = 0
files = renpy.python.py_eval(sound_keyframes[channel][old_time], locals=renpy.python.store_dicts["store.audio"])
for f in files:
duration += get_file_duration(f)
if new_time+duration >= t:
return True
break
times.reverse()
for t in times:
if t < new_time:
duration = 0
files = renpy.python.py_eval(sound_keyframes[channel][t], locals=renpy.python.store_dicts["store.audio"])
for f in files:
duration += get_file_duration(f)
if t+duration >= new_time:
return True
break
return False
def _False():
return False
def open_action_editor():
global current_time, current_scene, scene_keyframes, zorder_list, sound_keyframes, all_keyframes, playing, in_editor, loops, splines
if not config.developer:
return
playing = False
current_time = 0.0 #current_time is always float
current_scene = 0
moved_time = 0
loops = [defaultdict(_False)]
splines = [defaultdict(dict)]
sound_keyframes = {}
all_keyframes = [{}]
zorder_list = [{}]
for l in config.layers:
zorder_list[current_scene][l] = renpy.get_zorder_list(l)
scene_keyframes = [(None, 0, None)]
if persistent._viewer_legacy_gui is None:
persistent._viewer_legacy_gui = default_legacy_gui
if persistent._viewer_transition is None:
persistent._viewer_transition = default_transition
if persistent._viewer_warper is None:
persistent._viewer_warper = default_warper
if persistent._viewer_hide_window is None:
persistent._viewer_hide_window = hide_window_in_animation
if persistent._viewer_allow_skip is None:
persistent._viewer_allow_skip = allow_animation_skip
if persistent._viewer_rot is None:
persistent._viewer_rot = default_rot
if persistent._viewer_focusing is None:
persistent._viewer_focusing = focusing
if persistent._wide_range is None:
persistent._wide_range = wide_range
if persistent._narrow_range is None:
persistent._narrow_range = narrow_range
if persistent._viewers_wide_dragg_speed is None:
persistent._viewers_wide_dragg_speed = wide_drag_speed
if persistent._viewers_narow_dragg_speed is None:
persistent._viewers_narow_dragg_speed = narrow_drag_speed
if persistent._time_range is None:
persistent._time_range = time_range
if persistent._show_camera_icon is None:
persistent._show_camera_icon = default_show_camera_icon
if persistent._one_line_one_prop is None:
persistent._one_line_one_prop = default_one_line_one_prop
if persistent._open_only_one_page is None:
persistent._open_only_one_page = default_open_only_one_page
if persistent._graphic_editor_wide_range is None:
persistent._graphic_editor_wide_range = default_graphic_editor_wide_range
if persistent._graphic_editor_narrow_range is None:
persistent._graphic_editor_narrow_range = default_graphic_editor_narrow_range
if persistent._viewer_channel_list is None:
persistent._viewer_channel_list = default_channel_list
if persistent._viewer_sideview is None:
persistent._viewer_sideview = default_sideview
for c in persistent._viewer_channel_list:
sound_keyframes[c] = {}
for c in renpy.audio.audio.channels:
renpy.music.stop(c)
renpy.store._viewers.at_clauses_flag = False
action_editor_init()
in_editor = True
_window = renpy.store._window
renpy.store._window = False
_skipping_org = renpy.store._skipping
renpy.store._skipping = False
change_time(0)
if persistent._viewer_legacy_gui:
renpy.call_screen("_action_editor")
else:
renpy.call_screen("_new_action_editor")
renpy.store._skipping = _skipping_org
renpy.store._window = _window
def get_transition_delay(tran):
if tran is None or tran == "None":
return 0
if isinstance(tran, str):
tran = renpy.python.py_eval("renpy.store."+tran)
delay = getattr(tran, "delay", None)
if delay is None:
delay = tran().delay
#can't get delay of ATL transition
return delay
def get_animation_delay():
animation_time = 0
for s, (tran, scene_start, _) in enumerate(scene_keyframes):
if scene_start > animation_time:
animation_time = scene_start
delay = get_transition_delay(tran)
if delay + scene_start > animation_time:
animation_time = delay + scene_start
for key, cs in all_keyframes[s].items():
if isinstance(key, tuple):
prop = key[2]
else:
prop = key
for (v, t, w) in cs:
if prop == "child":
delay = get_transition_delay(v[1])
t += delay
if t > animation_time:
animation_time = t
for channel, times in sound_keyframes.items():
if times:
time_list = sorted(list(times.keys()))
start_time = time_list[-1]
files = times[start_time]
try:
for f in renpy.python.py_eval(files, locals=renpy.python.store_dicts["store.audio"]):
start_time += get_file_duration(f)
except:
raise Exception(files)
if start_time > animation_time:
animation_time = start_time
return animation_time
def get_scene_delay(scene_num):
animation_time = 0
(tran, scene_start, _) = scene_keyframes[scene_num]
delay = get_transition_delay(tran)
animation_time = delay + scene_start
for key, cs in all_keyframes[scene_num].items():
if isinstance(key, tuple):
prop = key[2]
else:
prop = key
for (v, t, w) in cs:
if prop == "child":
delay = get_transition_delay(v[1])
t += delay
if t > animation_time:
animation_time = t
return animation_time - scene_start
def set_group_keyframes(keyframes, mkey, scene_num=None):
result = keyframes.copy()
#focusing以外のグループプロパティーはここで纏める
included_gp = {}
for p in result:
check_result = check_props_group(p, mkey, scene_num)
if check_result is not None:
gn, ps = check_result
if gn != "focusing":
args = []
for prop in ps:
args.append(result[prop])
group_cs = []
for cs in zip(*args):
v = tuple(c[0] for c in cs)
if gn in ("matrixtransform", "matrixcolor"):
v = generate_matrix_strings(v, gn, ps)
group_cs.append((v, cs[0][1], cs[0][2]))
included_gp[gn] = (ps, group_cs)
for gn, (ps, group_cs) in included_gp.items():
for prop in ps:
del result[prop]
result[gn] = group_cs
for prop in ("focusing", "dof"):
if prop in result:
del result[prop]
return result
def camera_blur_amount(image_zpos, camera_zpos, dof, focusing):
distance_from_focus = camera_zpos - image_zpos - focusing + config.perspective[1]
if dof == 0:
dof = 0.1
if _camera_blur_warper.startswith("warper_generator"):
warper = renpy.python.py_eval(_camera_blur_warper)
else:
warper = renpy.atl.warpers[_camera_blur_warper]
blur_amount = _camera_blur_amount * warper(distance_from_focus/(float(dof)/2))
if blur_amount < 0:
blur_amount = abs(blur_amount)
if blur_amount < 0.1:
blur_amount = 0
return blur_amount
def get_image_state(layer, scene_num=None):
if scene_num is None:
scene_num = current_scene
result = dict(image_state_org[scene_num][layer])
result.update(image_state[scene_num][layer])
return result
def sort_props(keyframes):
return [(p, keyframes[p]) for p in sort_order_list if p in keyframes]
def put_prop_togetter(keyframes, layer=None, tag=None):
#時間軸とx, yを纏める キーフレームが一つのみのものは含めない
sorted_list = []
for p in sort_order_list:
if p in keyframes:
sorted_list.append((p, keyframes[p]))
result = []
already_added = []
for i, (p, cs) in enumerate(sorted_list):
same_time_set = []
if p in already_added or len(cs) == 1:
continue
else:
same_time_set = [(p, cs)]
already_added.append(p)
if layer is not None and tag is not None:
key = (tag, layer, p)
else:
key = p
for (p2, cs2) in sorted_list[i+1:]:
if p2 not in already_added and len(cs) == len(cs2):
if layer is not None and tag is not None:
key2 = (tag, layer, p2)
else:
key2 = p2
if loops[current_scene][key] != loops[current_scene][key2]:
continue
for c1, c2 in zip(cs, cs2):
if c1[1] != c2[1] or c1[2] != c2[2]:
break
else:
same_time_set.append((p2, cs2))
already_added.append(p2)
result.append(same_time_set)
for ks in result:
ks = x_and_y_to_xy(ks, layer=layer, tag=tag, check_spline=True)
if persistent._one_line_one_prop:
result_dict = {k:v for same_time_set in result for (k, v) in same_time_set}
result.clear()
for p in sort_order_list:
if p in result_dict:
result.append([(p, result_dict[p])])
return result
def x_and_y_to_xy(keyframe_list, layer=None, tag=None, check_spline=False, check_loop=False):
for xy, (x, y) in xygroup.items():
if x in [p for p, cs in keyframe_list] and y in [p for p, cs in keyframe_list]:
if layer is not None and tag is not None:
xkey = (tag, layer, x)
ykey = (tag, layer, y)
else:
xkey = x
ykey = y
if check_spline and (splines[current_scene][xkey] or splines[current_scene][ykey]):
# don't put together when propaerty has spline
continue
if check_loop and (loops[current_scene][xkey] != loops[current_scene][ykey]):
continue
for xi in range(len(keyframe_list)):
if keyframe_list[xi][0] == x:
xcs = keyframe_list[xi][1]
break
for yi in range(len(keyframe_list)):
if keyframe_list[yi][0] == y:
ycs = keyframe_list[yi][1]
break
xcs2 = xcs[:]
ycs2 = ycs[:]
if len(xcs) > len(ycs):
for i in range(len(xcs)-len(ycs)):
ycs2.append(ycs[-1])
if len(ycs) > len(xcs):
for i in range(len(ycs)-len(xcs)):
xcs2.append(xcs[-1])
keyframe_list[xi] = (xy, [((xc[0], yc[0]), xc[1], xc[2]) for xc, yc in zip(xcs2, ycs2)])
keyframe_list.pop(yi)
return keyframe_list
def xy_to_x(prop):
if prop in xygroup:
return xygroup[prop][0]
else:
return prop
def sort_zorder(state, layer, scene_num):
zorder = zorder_list[scene_num][layer]
return [(tag, state[tag]) for tag, _ in zorder]
def check_focusing_used(scene_num = None):
if scene_num is None:
scene_num = current_scene
return (persistent._viewer_focusing and perspective_enabled(scene_num))
def put_clipboard():
string = ""
if (persistent._viewer_hide_window and get_animation_delay() > 0
and len(scene_keyframes) == 1) or len(scene_keyframes) > 1:
if renpy.store._window_auto:
window_mode = "window auto"
else:
window_mode = "window"
string += """
{} hide""".format(window_mode)
for channel, times in sound_keyframes.items():
time = 0
files = "[\n " #]"
sorted_times = sorted(list(times.keys()))
if sorted_times:
for t in sorted_times:
duration = t - time
if duration > 0:
files += "'<silence {}>',\n ".format(duration)
fs = times[t]
files += fs[1:-1] + ",\n "
file = renpy.python.py_eval(fs, locals=renpy.python.store_dicts["store.audio"])
time = t
for f in file:
time += get_file_duration(f)
files = files[:-4] + "]\n"
string += "\n play {} {}".format(channel, files)
for s, (scene_tran, scene_start, _) in enumerate(scene_keyframes):
camera_keyframes = {k:v for k, v in all_keyframes[s].items() if not isinstance(k, tuple)}
camera_keyframes = set_group_keyframes(camera_keyframes, "camera", s)
for k, v in camera_keyframes.items():
if k in any_props:
formated_v = []
for c in v:
if isinstance(c[0], str):
formated_v.append(("'" + c[0] + "'", c[1], c[2]))
else:
formated_v.append(c)
camera_keyframes[k] = formated_v
camera_properties = []
for p in camera_state_org[s]:
check_result = check_props_group(p, "camera", s)
if check_result is not None:
gn, ps = check_result
if gn not in camera_properties:
camera_properties.append(gn)
else:
if p not in special_props:
camera_properties.append(p)
if s > 0:
string += """
scene"""
if camera_keyframes:
string += """
camera:
subpixel True"""
if "crop" in camera_keyframes:
string += " crop_relative True"
if persistent._one_line_one_prop:
string += "\n "
else:
string += " "
#デフォルトと違っても出力しない方が以前の状態の変化に柔軟だが、
#xposのような元がNoneやmatrixtransformのような元のマトリックスの順番が違うとアニメーションしない
#rotateは設定されればキーフレームに入り、されてなければ問題ない
#アニメーションしないなら出力しなくてよいのでここでは不要
for p, cs in x_and_y_to_xy([(p, camera_keyframes[p]) for p in camera_properties if p in camera_keyframes and len(camera_keyframes[p]) == 1]):
string += "{property} {value}".format(property=p, value=cs[0][0])
if persistent._one_line_one_prop:
string += "\n "
else:
string += " "
sorted_list = put_prop_togetter(camera_keyframes)
if len(sorted_list):
for same_time_set in sorted_list:
if len(sorted_list) > 1 or loops[s][xy_to_x(sorted_list[0][0][0])] or "function" in camera_keyframes:
add_tab = " "
string += """
parallel:
"""
else:
add_tab = ""
string += """
"""
for p, cs in same_time_set:
string += "{property} {value} ".format(property=p, value=cs[0][0])
cs = same_time_set[0][1]
for i, c in enumerate(cs[1:]):
if c[2].startswith("warper_generator"):
warper = "warp "+ c[2]
else:
warper = c[2]
string += """
{tab}{warper} {duration:.2f} """.format(tab=add_tab, warper=warper, duration=cs[i+1][1]-cs[i][1])
for p2, cs2 in same_time_set:
string += "{property} {value} ".format(property=p2, value=cs2[i+1][0])
if cs2[i+1][1] in splines[s][xy_to_x(p2)] and splines[s][xy_to_x(p2)][cs2[i+1][1]]:
for knot in splines[s][xy_to_x(p2)][cs2[i+1][1]]:
string += " knot {} ".format(knot)
if loops[s][xy_to_x(p)]:
string += """
repeat"""
if "function" in camera_keyframes:
for p, cs in camera_keyframes.items():
if len(cs) > 1:
string += """
parallel:
"""
break
else:
string += "\n "
string += "function {} ".format(camera_keyframes["function"][0][0][0])
for layer in image_state_org[s]:
state = get_image_state(layer, s)
for tag, _ in zorder_list[s][layer]:
if tag not in state:
continue
image_keyframes = {k[2]:v for k, v in all_keyframes[s].items() if isinstance(k, tuple) and k[0] == tag and k[1] == layer}
image_keyframes = set_group_keyframes(image_keyframes, (tag, layer), s)
for k, v in image_keyframes.items():
if k in any_props:
formated_v = []
for c in v:
if isinstance(c[0], str):
formated_v.append(("'" + c[0] + "'", c[1], c[2]))
else:
formated_v.append(c)
image_keyframes[k] = formated_v
if check_focusing_used(s) and "blur" in image_keyframes:
del image_keyframes["blur"]
image_properties = []
for p in state[tag]:
check_result = check_props_group(p, (tag, layer), s)
if check_result is not None:
gn, ps = check_result
if gn not in image_properties:
image_properties.append(gn)
else:
if p not in special_props:
image_properties.append(p)
if image_keyframes or check_focusing_used(s) or tag in image_state[s][layer]:
image_name = state[tag]["child"][0]
if "child" in image_keyframes:
last_child = image_keyframes["child"][-1][0][0]
if last_child is not None:
last_tag = last_child.split()[0]
if last_tag == image_name.split()[0]:
image_name = last_child
string += """
show {}""".format(image_name)
#at defaultではATLブロックに配置したdisplayableに機能しない
# if tag in image_state[s][layer]:
# string += " at default"
if image_name.split()[0] != tag:
string += " as {}".format(tag)
if layer != "master":
string += " onlayer {}".format(layer)
string += """:
"""
if tag in image_state[s][layer]:
string += "default\n "
string += "subpixel True "
if "crop" in image_keyframes:
string += "crop_relative True "
if persistent._one_line_one_prop:
string += "\n "
for p, cs in x_and_y_to_xy([(p, image_keyframes[p]) for p in image_properties if p in image_keyframes and len(image_keyframes[p]) == 1], layer, tag):
string += "{property} {value}".format(property=p, value=cs[0][0])
if persistent._one_line_one_prop:
string += "\n "
else:
string += " "
sorted_list = put_prop_togetter(image_keyframes, layer, tag)
if "child" in image_keyframes:
if len(sorted_list) >= 1 or loops[s][(tag, layer, "child")] or check_focusing_used(s) or "function" in image_keyframes:
add_tab = " "
string += """
parallel:"""
else:
add_tab = ""
last_time = scene_start
for i in range(0, len(image_keyframes["child"]), 1):
(image, transition), t, w = image_keyframes["child"][i]
widget = None
if i > 0:
old_widget = image_keyframes["child"][i-1][0][0]
if old_widget is not None:
widget = old_widget
if i < len(image_keyframes["child"])-1:
new_widget = image_keyframes["child"][i+1][0][0]
if new_widget is not None:
widget = new_widget
if widget is None:
if image is not None:
widget = image
if widget is None:
null = "Null()"
else:
w, h = renpy.render(renpy.easy.displayable(widget), 0, 0, 0, 0).get_size()
null = "Null({}, {})".format(w, h)
if (t - last_time) > 0:
string += """
{tab}{pause:.2f}""".format(tab=add_tab, pause=t-last_time)
if i == 0 and (image is not None and transition is not None):
string += """
{tab}{child}""".format(tab=add_tab, child=null)
if image is None:
string += """
{tab}{child}""".format(tab=add_tab, child=null)
else:
string += """
{tab}'{child}'""".format(tab=add_tab, child=image)
if transition is not None:
string += " with {}".format(transition)
t += get_transition_delay(transition)
last_time = t
if loops[s][(tag,layer,"child")]:
string += """
repeat"""
if len(sorted_list):
for same_time_set in sorted_list:
if len(sorted_list) > 1 or loops[s][(tag, layer, xy_to_x(sorted_list[0][0][0]))] \
or "child" in image_keyframes or check_focusing_used(s) or "function" in image_keyframes:
add_tab = " "
string += """
parallel:
"""
else:
add_tab = ""
string += """
"""
for p, cs in same_time_set:
string += "{property} {value} ".format(property=p, value=cs[0][0])
cs = same_time_set[0][1]
for i, c in enumerate(cs[1:]):
if c[2].startswith("warper_generator"):
warper = "warp "+ c[2]
else:
warper = c[2]
string += """
{tab}{warper} {duration:.2f} """.format(tab=add_tab, warper=warper, duration=cs[i+1][1]-cs[i][1])
for p2, cs2 in same_time_set:
string += "{property} {value} ".format(property=p2, value=cs2[i+1][0])
if cs2[i+1][1] in splines[s][(tag, layer, xy_to_x(p2))] and splines[s][(tag, layer, xy_to_x(p2))][cs2[i+1][1]]:
for knot in splines[s][(tag, layer, xy_to_x(p2))][cs2[i+1][1]]:
string += " knot {} ".format(knot)
if loops[s][(tag,layer,xy_to_x(p))]:
string += """
repeat"""
if check_focusing_used(s) or "function" in image_keyframes:
for p, cs in image_keyframes.items():
if len(cs) > 1 or "child" in image_keyframes:
string += """
parallel:
"""
break
else:
string += "\n "
if check_focusing_used(s):
focusing_cs = {"focusing":[(get_default("focusing"), 0, None)], "dof":[(get_default("dof"), 0, None)]}
for p in props_groups["focusing"]:
if p in all_keyframes[s]:
focusing_cs[p] = [(v, t-scene_start, w) for (v, t, w) in all_keyframes[s][p]]
if loops[s]["focusing"] or loops[s]["dof"]:
focusing_loop = {}
focusing_loop["focusing_loop"] = loops[s]["focusing"]
focusing_loop["dof_loop"] = loops[s]["dof"]
focusing_func_string = "camera_blur({}, {})".format(focusing_cs, focusing_loop)
else:
focusing_func_string = "camera_blur({})".format(focusing_cs)
if "function" in image_keyframes:
function_string = image_keyframes["function"][0][0][0]
string += "function mfn({}, {}) ".format(function_string, focusing_func_string)
else:
string += "function {} ".format(focusing_func_string)
else:
string += "function {} ".format(image_keyframes["function"][0][0][0])
if s != 0:
string += """
with {}""".format(scene_tran)
if len(scene_keyframes) > 1:
if s < len(scene_keyframes)-1:
pause_time = scene_keyframes[s+1][1] - scene_start
elif (get_scene_delay(s) + scene_start) >= get_animation_delay():
pause_time = get_scene_delay(s)
else:
pause_time = get_animation_delay() - scene_start
pause_time -= get_transition_delay(scene_tran)
pause_time = pause_time + 0.1 #add margin
if pause_time > 0 or s != len(scene_keyframes)-1:
string += """
with Pause({:.2f})""".format(pause_time)
if (persistent._viewer_hide_window and get_animation_delay() > 0) and len(scene_keyframes) == 1:
string += """
with Pause({:.2f})""".format(get_animation_delay()+0.1)
if (persistent._viewer_hide_window and get_animation_delay() > 0 and persistent._viewer_allow_skip) \
or len(scene_keyframes) > 1:
for channel, times in sound_keyframes.items():
if times:
string += "\n stop {}".format(channel)
for i in range(-1, -len(scene_keyframes)-1, -1):
if camera_keyframes_exist(i):
break
last_camera_scene = i
camera_keyframes = {k:v for k, v in all_keyframes[last_camera_scene].items() if not isinstance(k, tuple)}
for p in camera_state_org[last_camera_scene]:
if p not in camera_keyframes:
if camera_state_org[last_camera_scene][p] is not None and camera_state_org[last_camera_scene][p] != camera_state_org[0][p]:
camera_keyframes[p] = [(camera_state_org[last_camera_scene][p], scene_keyframes[last_camera_scene][1], None)]
camera_keyframes = set_group_keyframes(camera_keyframes, "camera", last_camera_scene)
for k, v in camera_keyframes.items():
if k in any_props:
formated_v = []
for c in v:
if isinstance(c[0], str):
formated_v.append(("'" + c[0] + "'", c[1], c[2]))
else:
formated_v.append(c)
camera_keyframes[k] = formated_v
if [cs for cs in camera_keyframes.values() if len(cs) > 1]:
string += """
camera:"""
for p, cs in camera_keyframes.items():
if len(cs) > 1 and loops[last_camera_scene][p]:
string += """
animation"""
break
first = True
for p, cs in x_and_y_to_xy(sort_props(camera_keyframes), check_loop=True):
if p not in special_props:
if len(cs) > 1 and not loops[last_camera_scene][xy_to_x(p)]:
if first:
first = False
string += """
"""
string += "{property} {value}".format(property=p, value=cs[-1][0])
if persistent._one_line_one_prop:
string += "\n "
else:
string += " "
for p, cs in sort_props(camera_keyframes):
if p not in special_props:
if len(cs) > 1 and loops[last_camera_scene][p]:
string += """
parallel:
{property} {value}""".format(property=p, value=cs[0][0])
for i, c in enumerate(cs[1:]):
if c[2].startswith("warper_generator"):
warper = "warp "+ c[2]
else:
warper = c[2]
string += """
{warper} {duration:.2f} {property} {value}""".format(warper=warper, duration=cs[i+1][1]-cs[i][1], property=p, value=c[0])
if c[1] in splines[last_camera_scene][p] and splines[last_camera_scene][p][c[1]]:
for knot in splines[last_camera_scene][p][c[1]]:
string += " knot {}".format(knot)
string += """
repeat"""
# if "function" in camera_keyframes:
# for p, cs in sort_props(camera_keyframes):
# if p not in special_props:
# if len(cs) > 1 and loops[last_camera_scene][p]:
# string += """
# parallel:
# """
# break
# else:
# string += """
# """
# string += "{} {}".format("function", camera_keyframes["function"][0][0][0])
last_scene = len(scene_keyframes)-1
for layer in image_state_org[last_scene]:
state = get_image_state(layer, last_scene)
for tag, _ in zorder_list[last_scene][layer]:
if tag not in state:
continue
image_keyframes = {k[2]:v for k, v in all_keyframes[last_scene].items() if isinstance(k, tuple) and k[0] == tag and k[1] == layer}
image_keyframes = set_group_keyframes(image_keyframes, (tag, layer), last_scene)
for k, v in image_keyframes.items():
if k in any_props:
formated_v = []
for c in v:
if isinstance(c[0], str):
formated_v.append(("'" + c[0] + "'", c[1], c[2]))
else:
formated_v.append(c)
image_keyframes[k] = formated_v
if check_focusing_used(last_scene) and "blur" in image_keyframes:
del image_keyframes["blur"]
if not image_keyframes:
continue
for p, cs in image_keyframes.items():
if len(cs) > 1:
break
else:
continue
image_name = state[tag]["child"][0]
if "child" in image_keyframes:
last_child = image_keyframes["child"][-1][0][0]
if last_child is not None:
last_tag = last_child.split()[0]
if last_tag == tag:
image_name = last_child
string += """
show {}""".format(image_name)
if image_name.split()[0] != tag:
string += " as {}".format(tag)
if layer != "master":
string += " onlayer {}".format(layer)
for p, cs in image_keyframes.items():
if len(cs) > 1 and (p != "child" or loops[last_scene][(tag, layer, "child")]):
break
else:
string += """:
pass"""
continue
string += ":"
for p, cs in image_keyframes.items():
if len(cs) > 1 and loops[last_scene][(tag, layer, p)]:
string += """
animation"""
break
first = True
for p, cs in x_and_y_to_xy(sort_props(image_keyframes), layer, tag, check_loop=True):
if p not in special_props:
if len(cs) > 1 and not loops[last_scene][(tag, layer, xy_to_x(p))]:
if first:
first = False
string += """
"""
string += "{property} {value}".format(property=p, value=cs[-1][0])
if persistent._one_line_one_prop:
string += "\n "
else:
string += " "
for p, cs in sort_props(image_keyframes):
if p not in special_props:
if len(cs) > 1 and loops[last_scene][(tag, layer, p)]:
string += """
parallel:
{property} {value}""".format(property=p, value=cs[0][0])
for i, c in enumerate(cs[1:]):
if c[2].startswith("warper_generator"):
warper = "warp "+ c[2]
else:
warper = c[2]
string += """
{warper} {duration:.2f} {property} {value}""".format(warper=warper, duration=cs[i+1][1]-cs[i][1], property=p, value=c[0])
if c[1] in splines[last_scene][(tag, layer, p)] and splines[last_scene][(tag, layer, p)][c[1]]:
for knot in splines[last_scene][(tag, layer, p)][c[1]]:
string += " knot {}".format(knot)
string += """
repeat"""
if "child" in image_keyframes and loops[last_scene][(tag,layer,"child")]:
last_time = scene_keyframes[last_scene][1]
string += """
parallel:"""
for i in range(0, len(image_keyframes["child"]), 1):
(image, transition), t, w = image_keyframes["child"][i]
widget = None
if i > 0:
old_widget = image_keyframes["child"][i-1][0][0]
if old_widget is not None:
widget = old_widget
if i < len(image_keyframes["child"])-1:
new_widget = image_keyframes["child"][i+1][0][0]
if new_widget is not None:
widget = new_widget
if widget is None:
if image is not None:
widget = image
if widget is None:
null = "Null()"
else:
w, h = renpy.render(renpy.easy.displayable(widget), 0, 0, 0, 0).get_size()
null = "Null({}, {})".format(w, h)
if (t - last_time) > 0:
string += """
{pause:.2f}""".format(pause=t-last_time)
if i == 0 and (image is not None and transition is not None):
string += """
{child}""".format(child=null)
if image is None:
string += """
{child}""".format(child=null)
else:
string += """
'{child}'""".format(child=image)
if transition is not None:
string += " with {}".format(transition)
t += get_transition_delay(transition)
last_time = t
string += """
repeat"""
if check_focusing_used(last_scene):# or "function" in image_keyframes:
# if check_focusing_used(last_scene):
focusing_cs = {"focusing":[(get_default("focusing"), 0, None)], "dof":[(get_default("dof"), 0, None)]}
if "focusing" in all_keyframes[last_scene]:
focusing_cs["focusing"] = all_keyframes[last_scene]["focusing"]
if "dof" in all_keyframes[last_scene]:
focusing_cs["dof"] = all_keyframes[last_scene]["dof"]
if len(focusing_cs["focusing"]) > 1 or len(focusing_cs["dof"]) > 1:
for p, cs in sort_props(image_keyframes):
if p not in special_props:
if len(cs) > 1 and loops[last_scene][(tag, layer, p)]:
string += """
parallel:
{}"""
break
else:
if "child" in image_keyframes and loops[last_scene][(tag,layer,"child")]:
string += """
parallel:
{}"""
else:
string += """
"""
if not loops[last_scene]["focusing"]:
focusing_cs["focusing"] = [focusing_cs["focusing"][-1]]
if not loops[last_scene]["dof"]:
focusing_cs["dof"] = [focusing_cs["dof"][-1]]
if loops[last_scene]["focusing"] or loops[last_scene]["dof"]:
focusing_loop = {}
focusing_loop["focusing_loop"] = loops[last_scene]["focusing"]
focusing_loop["dof_loop"] = loops[last_scene]["dof"]
focusing_func_string = "camera_blur({}, {})".format(focusing_cs, focusing_loop)
else:
focusing_func_string = "camera_blur({})".format(focusing_cs)
# if "function" in image_keyframes:
# function_string = image_keyframes["function"][0][0][0]
# string += "{} mfn({}, {}) ".format("function", function_string, focusing_func_string)
# else:
string += "function {} ".format(focusing_func_string)
# else:
# string += "{} {} ".format("function", image_keyframes["function"][0][0][0])
if (persistent._viewer_hide_window and get_animation_delay() > 0 and len(scene_keyframes) == 1) \
or len(scene_keyframes) > 1:
string += """
{} show""".format(window_mode)
string = '\n'.join(filter(lambda x: x.strip(), string.split('\n')))
string = "\n"+ string + "\n\n"
if string:
string = string.replace("u'", "'", 999)
try:
from pygame import scrap, locals
scrap.put(locals.SCRAP_TEXT, string.encode("utf-8"))
except Exception as e:
message = _("Can't open clip board") + "\n" \
+ format_exc()
renpy.notify(message)
else:
#syntax hilight error in vim
renpy.notify("Placed\n{}\n\non clipboard".format(string).replace("{", "{{").replace("[", "[[")) #]"
else:
renpy.notify(_("Nothing to put"))
init python:
def camera_blur(check_points, loop=None):
if "focusing" not in check_points:
check_points["focusing"] = [(_viewers.get_default("focusing"), 0, None)]
if "dof" not in check_points:
check_points["dof"] = [(_viewers.get_default("dof"), 0, None)]
if loop is None:
loop = {}
if "focusing_loop" not in loop:
loop["focusing_loop"] = False
if "dof_loop" not in loop:
loop["dof_loop"] = False
return renpy.curry(_viewers.transform)(check_points=check_points, loop=loop, subpixel=None, crop_relative=None)
def warper_generator(checkpoints):
#checkpoints = [(x, y, k), ... (1, 1, k)]
checkpoints = [(0, 0, None)] + checkpoints
def f(x, x_0, y_0, x_1, y_1, k):
if k <= 0:
return y_1
elif k == 0.5:
return ((y_1 - y_0) / (x_1 - x_0)) * (x - x_0) + y_0
elif k >= 1:
return 0.
else:
s = -k**2 / (1 - 2*k)
t = (k**2 - 2*k + 1) / (1 - 2*k)
u = -k**2 * (k - 1)**2 / (2*k - 1)**2
x = (x - x_0) / (x_1 - x_0)
y = (u / (x - s) + t) * (y_1 - y_0) + y_0
return y
def warper(x):
if x >= 1:
return 1.
elif x <= 0:
return 0.
for i, (x_1, y_1, k) in enumerate(checkpoints):
if x_1 > x:
x_0, y_0, _ = checkpoints[i-1]
return f(x, x_0, y_0, x_1, y_1, k)
return warper