├── 00camera_statements.rpy ├── 00warper.rpy ├── ActionEditor.rpy ├── README.md ├── camera.png ├── camera.rpy ├── camera_config.rpy ├── image_viewer.rpy ├── keymap.rpy └── spline.rpy /00camera_statements.rpy: -------------------------------------------------------------------------------- 1 | #camera用の追加ステートメント集 2 | # dollyout 移動量 (時間) (warper) 3 | # dollyin 4 | # slideleft 5 | # slideright 6 | # craneup 7 | # cranedown 8 | # 9 | # craneup 100 5 linear #5秒かけてカメラを100上げる 10 | 11 | python early hide: 12 | def parse_camera_statements(lex): 13 | #移動量、時間、ワーパーを返す 14 | amount = eval(lex.simple_expression()) 15 | if not lex.eol(): 16 | second = eval(lex.simple_expression()) 17 | else: 18 | second = 0 19 | if not lex.eol(): 20 | warper = lex.simple_expression() 21 | else: 22 | warper = "power_in_time_warp_real" 23 | return amount, second, warper 24 | ################################################################################################## 25 | def execute_dollyout(o): 26 | amount, second, warper = o 27 | camera_move(_camera_x, _camera_y, _camera_z-amount, _camera_rotate, second, warper=warper) 28 | 29 | renpy.register_statement("dollyout", parse=parse_camera_statements, execute=execute_dollyout) 30 | ################################################################################################## 31 | def execute_dollyin(o): 32 | amount, second, warper = o 33 | camera_move(_camera_x, _camera_y, _camera_z+amount, _camera_rotate, second, warper=warper) 34 | 35 | renpy.register_statement("dollyin", parse=parse_camera_statements, execute=execute_dollyin) 36 | ################################################################################################## 37 | def execute_slideleft(o): 38 | amount, second, warper = o 39 | camera_move(_camera_x-amount, _camera_y, _camera_z, _camera_rotate, second, warper=warper) 40 | 41 | renpy.register_statement("slideleft", parse=parse_camera_statements, execute=execute_slideleft) 42 | ################################################################################################## 43 | def execute_slideright(o): 44 | amount, second, warper = o 45 | camera_move(_camera_x+amount, _camera_y, _camera_z, _camera_rotate, second, warper=warper) 46 | 47 | renpy.register_statement("slideright", parse=parse_camera_statements, execute=execute_slideright) 48 | ################################################################################################## 49 | def execute_craneup(o): 50 | amount, second, warper = o 51 | camera_move(_camera_x, _camera_y-amount, _camera_z, _camera_rotate, second, warper=warper) 52 | 53 | renpy.register_statement("craneup", parse=parse_camera_statements, execute=execute_craneup) 54 | ################################################################################################## 55 | def execute_cranedown(o): 56 | amount, second, warper = o 57 | camera_move(_camera_x, _camera_y+amount, _camera_z, _camera_rotate, second, warper=warper) 58 | 59 | renpy.register_statement("cranedown", parse=parse_camera_statements, execute=execute_cranedown) 60 | -------------------------------------------------------------------------------- /00warper.rpy: -------------------------------------------------------------------------------- 1 | python early hide: 2 | 3 | @renpy.atl_warper 4 | def power_in2(x): 5 | if x >= 1.0: 6 | return 1.0 7 | return 1.0 - (1.0 - x)**2 8 | 9 | @renpy.atl_warper 10 | def power_out2(x): 11 | if x >= 1.0: 12 | return 1.0 13 | return x**2 14 | 15 | @renpy.atl_warper 16 | def power_in3(x): 17 | if x >= 1.0: 18 | return 1.0 19 | return 1.0 - (1.0 - x)**3 20 | 21 | @renpy.atl_warper 22 | def power_out3(x): 23 | if x >= 1.0: 24 | return 1.0 25 | return x**3 26 | 27 | @renpy.atl_warper 28 | def power_in4(x): 29 | if x >= 1.0: 30 | return 1.0 31 | return 1.0 - (1.0 - x)**4 32 | 33 | @renpy.atl_warper 34 | def power_out4(x): 35 | if x >= 1.0: 36 | return 1.0 37 | return x**4 38 | 39 | @renpy.atl_warper 40 | def power_in5(x): 41 | if x >= 1.0: 42 | return 1.0 43 | return 1.0 - (1.0 - x)**5 44 | 45 | @renpy.atl_warper 46 | def power_out5(x): 47 | if x >= 1.0: 48 | return 1.0 49 | return x**5 50 | 51 | @renpy.atl_warper 52 | def power_in6(x): 53 | if x >= 1.0: 54 | return 1.0 55 | return 1.0 - (1.0 - x)**6 56 | 57 | @renpy.atl_warper 58 | def power_out6(x): 59 | if x >= 1.0: 60 | return 1.0 61 | return x**6 62 | 63 | @renpy.atl_warper 64 | def spring1(x): 65 | from math import exp, cos 66 | rho = 5 # 減衰率 67 | mu = 30# 角振動数 68 | return (1.0 - exp(-rho * x) * cos(mu * x)) / (1.0 - exp(-rho) * cos(mu)) 69 | 70 | @renpy.atl_warper 71 | def spring2(x): 72 | from math import exp, cos 73 | rho = 5 # 減衰率 74 | mu = 20# 角振動数 75 | return (1.0 - exp(-rho * x) * cos(mu * x)) / (1.0 - exp(-rho) * cos(mu)) 76 | 77 | @renpy.atl_warper 78 | def spring3(x): 79 | from math import exp, cos 80 | rho = 5 # 減衰率 81 | mu = 10# 角振動数 82 | return (1.0 - exp(-rho * x) * cos(mu * x)) / (1.0 - exp(-rho) * cos(mu)) 83 | 84 | @renpy.atl_warper 85 | def bop_time_warp(x): 86 | return -23.0 * x**5 + 57.5 * x**4 - 55 * x**3 + 25 * x**2 - 3.5 * x 87 | 88 | @renpy.atl_warper 89 | def bop_in_time_warp(x): 90 | return -2.15 * x**2 + 3.15 * x 91 | 92 | @renpy.atl_warper 93 | def bop_out_time_warp(x): 94 | return 2.15 * x**2 - 1.15 * x 95 | 96 | @renpy.atl_warper 97 | def bop_to_time_warp(x): 98 | return -5 * x**5 + 5 * x**4 + x**2 99 | 100 | @renpy.atl_warper 101 | def to_bop_time_warp(x): 102 | return -5 * x**5 + 20 * x**4 - 30 * x**3 + 19 * x**2 - 3 * x 103 | 104 | @renpy.atl_warper 105 | def easeout2(x): 106 | if x >= 1.0: 107 | return 1.0 108 | import math 109 | return 1.0 - math.cos(x * math.pi / 2.0) 110 | 111 | @renpy.atl_warper 112 | def easein2(x): 113 | if x >= 1.0: 114 | return 1.0 115 | import math 116 | return math.cos((1.0 - x) * math.pi / 2.0) 117 | 118 | @renpy.atl_warper 119 | def ease2(x): 120 | if x >= 1.0: 121 | return 1.0 122 | import math 123 | return .5 - math.cos(math.pi * x) / 2.0 124 | @renpy.atl_warper 125 | def power_in_time_warp_real(x): 126 | if x >= 1.0: 127 | return 1.0 128 | return 1.0 - (1.0 - x)**6 129 | 130 | #互換性のために残しておく 131 | @renpy.atl_warper 132 | def power_out_time_warp_real(x): 133 | if x >= 1.0: 134 | return 1.0 135 | return 1.0 - (1.0 - x)**6 136 | 137 | @renpy.atl_warper 138 | def power_in_time_warp_real5(x): 139 | if x >= 1.0: 140 | return 1.0 141 | return 1.0 - (1.0 - x)**5 142 | 143 | @renpy.atl_warper 144 | def power_out_time_warp_real5(x): 145 | if x >= 1.0: 146 | return 1.0 147 | return x**5 148 | 149 | @renpy.atl_warper 150 | def loop_cos(x): 151 | from math import cos, pi 152 | if x >= 1.0: 153 | return 1.0 154 | return (-1*cos(x*2*pi)+1)/2 155 | -------------------------------------------------------------------------------- /ActionEditor.rpy: -------------------------------------------------------------------------------- 1 | screen _action_editor(tab="images", layer="master", name="", time=0): 2 | key "game_menu" action Return() 3 | key "rollback" action _viewers.rollback 4 | key "rollforward" action _viewers.rollforward 5 | if _viewers.sorted_keyframes: 6 | key "K_SPACE" action [SensitiveIf(_viewers.sorted_keyframes), Function(_viewers.camera_viewer.play, play=True), Function(_viewers.transform_viewer.play, play=True), Hide("_action_editor"), Show("_action_editor", tab=tab, layer=layer, name=name, time=_viewers.sorted_keyframes[-1]), renpy.restart_interaction] 7 | else: 8 | key "K_SPACE" action [SensitiveIf(_viewers.sorted_keyframes), Function(_viewers.camera_viewer.play, play=True), Function(_viewers.transform_viewer.play, play=True), Hide("_action_editor"), Show("_action_editor", tab=tab, layer=layer, name=name), renpy.restart_interaction] 9 | if _viewers.fps_keymap: 10 | key "s" action Function(_viewers.camera_viewer.y_changed, _camera_y+100+_viewers.camera_viewer.range_camera_pos) 11 | key "w" action Function(_viewers.camera_viewer.y_changed, _camera_y-100+_viewers.camera_viewer.range_camera_pos) 12 | key "a" action Function(_viewers.camera_viewer.x_changed, _camera_x-100+_viewers.camera_viewer.range_camera_pos) 13 | key "d" action Function(_viewers.camera_viewer.x_changed, _camera_x+100+_viewers.camera_viewer.range_camera_pos) 14 | key "S" action Function(_viewers.camera_viewer.y_changed, _camera_y+1000+_viewers.camera_viewer.range_camera_pos) 15 | key "W" action Function(_viewers.camera_viewer.y_changed, _camera_y-1000+_viewers.camera_viewer.range_camera_pos) 16 | key "A" action Function(_viewers.camera_viewer.x_changed, _camera_x-1000+_viewers.camera_viewer.range_camera_pos) 17 | key "D" action Function(_viewers.camera_viewer.x_changed, _camera_x+1000+_viewers.camera_viewer.range_camera_pos) 18 | else: 19 | key "j" action Function(_viewers.camera_viewer.y_changed, _camera_y+100+_viewers.camera_viewer.range_camera_pos) 20 | key "k" action Function(_viewers.camera_viewer.y_changed, _camera_y-100+_viewers.camera_viewer.range_camera_pos) 21 | key "h" action Function(_viewers.camera_viewer.x_changed, _camera_x-100+_viewers.camera_viewer.range_camera_pos) 22 | key "l" action Function(_viewers.camera_viewer.x_changed, _camera_x+100+_viewers.camera_viewer.range_camera_pos) 23 | key "J" action Function(_viewers.camera_viewer.y_changed, _camera_y+1000+_viewers.camera_viewer.range_camera_pos) 24 | key "K" action Function(_viewers.camera_viewer.y_changed, _camera_y-1000+_viewers.camera_viewer.range_camera_pos) 25 | key "H" action Function(_viewers.camera_viewer.x_changed, _camera_x-1000+_viewers.camera_viewer.range_camera_pos) 26 | key "L" action Function(_viewers.camera_viewer.x_changed, _camera_x+1000+_viewers.camera_viewer.range_camera_pos) 27 | 28 | if time: 29 | timer time+1 action Function(_viewers.change_time, _viewers.time) 30 | $state={k: v for dic in [_viewers.transform_viewer.state_org[layer], _viewers.transform_viewer.state[layer]] for k, v in dic.items()} 31 | 32 | if _viewers.default_rot and store._first_load: 33 | $store._first_load = False 34 | on "show" action Show("_rot") 35 | 36 | frame: 37 | background "#0006" 38 | if time: 39 | at _delay_show(time + 1) 40 | vbox: 41 | 42 | hbox: 43 | style_group "action_editor_a" 44 | textbutton _("time: [_viewers.time:>.2f] s") action Function(_viewers.edit_time) 45 | textbutton _("<") action Function(_viewers.prev_time) 46 | textbutton _(">") action Function(_viewers.next_time) 47 | bar adjustment ui.adjustment(range=7.0, value=_viewers.time, changed=_viewers.change_time) xalign 1. yalign .5 48 | hbox: 49 | style_group "action_editor_a" 50 | hbox: 51 | textbutton _("default warper") action _viewers.select_default_warper 52 | textbutton _("rot") action [SelectedIf(renpy.get_screen("_rot")), If(renpy.get_screen("_rot"), true=Hide("_rot"), false=Show("_rot"))] 53 | textbutton _("hide") action HideInterface() 54 | # textbutton _("window") action _viewers.AddWindow() #renpy.config.empty_window 55 | if _viewers.sorted_keyframes: 56 | textbutton _("play") action [SensitiveIf(_viewers.sorted_keyframes), Function(_viewers.camera_viewer.play, play=True), Function(_viewers.transform_viewer.play, play=True), Hide("_action_editor"), Show("_action_editor", tab=tab, layer=layer, name=name, time=_viewers.sorted_keyframes[-1]), renpy.restart_interaction] 57 | else: 58 | textbutton _("play") action [SensitiveIf(_viewers.sorted_keyframes), Function(_viewers.camera_viewer.play, play=True), Function(_viewers.transform_viewer.play, play=True), Hide("_action_editor"), Show("_action_editor", tab=tab, layer=layer, name=name), renpy.restart_interaction] 59 | textbutton _("clipboard") action Function(_viewers.put_clipboard) 60 | hbox: 61 | xalign 1. 62 | textbutton _("close") action Return() 63 | hbox: 64 | style_group "action_editor_a" 65 | textbutton _("clear keyframes") action [SensitiveIf(_viewers.sorted_keyframes), Function(_viewers.clear_keyframes), renpy.restart_interaction] 66 | textbutton _("remove keyframes") action [SensitiveIf(_viewers.time in _viewers.sorted_keyframes), Function(_viewers.remove_keyframes, _viewers.time), renpy.restart_interaction] 67 | textbutton _("move keyframes") action [SensitiveIf(_viewers.time in _viewers.sorted_keyframes), SetField(_viewers, "moved_time", _viewers.time), Show("_move_keyframes")] 68 | textbutton _("last moves") action [SensitiveIf(_last_camera_arguments), Function(_viewers.last_moves), renpy.restart_interaction] 69 | null height 10 70 | hbox: 71 | style_group "action_editor_a" 72 | xfill False 73 | textbutton _("Images") action [SelectedIf(tab == "images"), Show("_action_editor", tab="images")] 74 | textbutton _("2D Camera") action [SensitiveIf(list(_3d_layers.keys()) == ["master"]), SelectedIf(tab == "2D Camera"), Show("_action_editor", tab="2D Camera")] 75 | textbutton _("3D Layers") action [SelectedIf(tab == "3D Layers"), Show("_action_editor", tab="3D Layers")] 76 | textbutton _("3D Camera") action [SelectedIf(tab == "3D Camera"), Show("_action_editor", tab="3D Camera")] 77 | if tab == "images": 78 | hbox: 79 | style_group "action_editor_a" 80 | for l in config.layers: 81 | if l not in ["screens", "transient", "overlay"]: 82 | textbutton "[l]" action [SelectedIf(l == layer), Show("_action_editor", tab=tab, layer=l)] 83 | hbox: 84 | style_group "action_editor_a" 85 | textbutton _("+") action Function(_viewers.transform_viewer.add_image, layer) 86 | for n in state: 87 | textbutton "{}".format(n.split()[0]) action [SelectedIf(n == name), Show("_action_editor", tab=tab, layer=layer, name=n)] 88 | 89 | if name in state: 90 | for p, d in _viewers.transform_viewer.props: 91 | $prop = _viewers.transform_viewer.get_property(layer, name.split()[0], p) 92 | $ f = _viewers.transform_viewer.generate_changed(layer, name, p) 93 | if p not in _viewers.transform_viewer.force_float and ((state[name][p] is None and isinstance(d, int)) or isinstance(state[name][p], int)): 94 | hbox: 95 | style_group "action_editor" 96 | textbutton "[p]" action [SensitiveIf((name, layer, p) in _viewers.all_keyframes), SelectedIf(_viewers.keyframes_exist((name, layer, p))), Show("_edit_keyframe", k=(name, layer, p), int=True)] 97 | textbutton "[prop]" action Function(_viewers.transform_viewer.edit_value, f, True, default=prop) alternate Function(_viewers.transform_viewer.reset, name, layer, p) 98 | bar adjustment ui.adjustment(range=_viewers.transform_viewer.int_range*2, value=prop+_viewers.transform_viewer.int_range, page=1, changed=f) xalign 1. yalign .5 99 | else: 100 | hbox: 101 | style_group "action_editor" 102 | textbutton "[p]" action [SensitiveIf((name, layer, p) in _viewers.all_keyframes), SelectedIf(_viewers.keyframes_exist((name, layer, p))), Show("_edit_keyframe", k=(name, layer, p))] 103 | textbutton "[prop:>.2f]" action Function(_viewers.transform_viewer.edit_value, f, False, default=prop) alternate Function(_viewers.transform_viewer.reset, name, layer, p) 104 | bar adjustment ui.adjustment(range=_viewers.transform_viewer.float_range*2, value=prop+_viewers.transform_viewer.float_range, page=.05, changed=f) xalign 1. yalign .5 105 | elif tab == "3D Camera" or tab == "2D Camera": 106 | if list(_3d_layers.keys()) == ["master"] and tab == "3D Camera": 107 | label _("Please register 3D layers") 108 | else: 109 | hbox: 110 | style_group "action_editor" 111 | textbutton "x" action [SensitiveIf("_camera_x" in _viewers.all_keyframes), SelectedIf(_viewers.keyframes_exist("_camera_x")), Show("_edit_keyframe", k="_camera_x")] 112 | textbutton "[_camera_x: >5]" action Function(_viewers.camera_viewer.edit_value, _viewers.camera_viewer.x_changed, _viewers.camera_viewer.range_camera_pos, default=_camera_x) alternate [Function(camera_move, _viewers.camera_viewer._camera_x, _camera_y, _camera_z, _camera_rotate), renpy.restart_interaction] 113 | bar adjustment ui.adjustment(range=_viewers.camera_viewer.range_camera_pos*2, value=_camera_x+_viewers.camera_viewer.range_camera_pos, page=1, changed=_viewers.camera_viewer.x_changed) xalign 1. yalign .5 114 | hbox: 115 | style_group "action_editor" 116 | textbutton "y" action [SensitiveIf("_camera_y" in _viewers.all_keyframes), SelectedIf(_viewers.keyframes_exist("_camera_y")), Show("_edit_keyframe", k="_camera_y")] 117 | textbutton "[_camera_y: >5]" action Function(_viewers.camera_viewer.edit_value, _viewers.camera_viewer.y_changed, _viewers.camera_viewer.range_camera_pos, default=_camera_y) alternate [Function(camera_move, _camera_x, _viewers.camera_viewer._camera_y, _camera_z, _camera_rotate), renpy.restart_interaction] 118 | bar adjustment ui.adjustment(range=_viewers.camera_viewer.range_camera_pos*2, value=_camera_y+_viewers.camera_viewer.range_camera_pos, page=1, changed=_viewers.camera_viewer.y_changed) xalign 1. yalign .5 119 | hbox: 120 | style_group "action_editor" 121 | textbutton "z" action [SensitiveIf("_camera_z" in _viewers.all_keyframes), SelectedIf(_viewers.keyframes_exist("_camera_z")), Show("_edit_keyframe", k="_camera_z")] 122 | textbutton "[_camera_z: >5]" action Function(_viewers.camera_viewer.edit_value, _viewers.camera_viewer.z_changed, _viewers.camera_viewer.range_camera_pos, default=_camera_z) alternate [Function(camera_move, _camera_x, _camera_y, _viewers.camera_viewer._camera_z, _camera_rotate), renpy.restart_interaction] 123 | bar adjustment ui.adjustment(range=_viewers.camera_viewer.range_camera_pos*2, value=_camera_z+_viewers.camera_viewer.range_camera_pos, page=1, changed=_viewers.camera_viewer.z_changed) xalign 1. yalign .5 124 | hbox: 125 | style_group "action_editor" 126 | textbutton "rotate" action [SensitiveIf("_camera_rotate" in _viewers.all_keyframes), SelectedIf(_viewers.keyframes_exist("_camera_rotate")), Show("_edit_keyframe", k="_camera_rotate")] 127 | textbutton "[_camera_rotate: >5]" action Function(_viewers.camera_viewer.edit_value, _viewers.camera_viewer.r_changed, _viewers.camera_viewer.range_rotate, default=_camera_rotate) alternate [Function(camera_move, _camera_x, _camera_y, _camera_z, _viewers.camera_viewer._camera_rotate), renpy.restart_interaction] 128 | bar adjustment ui.adjustment(range=_viewers.camera_viewer.range_rotate*2, value=_camera_rotate+_viewers.camera_viewer.range_rotate, page=1, changed=_viewers.camera_viewer.r_changed) xalign 1. yalign .5 129 | if tab == "3D Camera": 130 | hbox: 131 | style_group "action_editor" 132 | textbutton "focus" 133 | textbutton "[_camera_focus: >5]" action Function(_viewers.camera_viewer.edit_value, _viewers.camera_viewer.focus_changed, 0, default=_camera_focus) alternate [Function(focus_set, _viewers.camera_viewer._camera_focus), renpy.restart_interaction] 134 | bar adjustment ui.adjustment(range=_viewers.camera_viewer.range_focus, value=_camera_focus, page=1, changed=_viewers.camera_viewer.focus_changed) xalign 1. yalign .5 135 | hbox: 136 | style_group "action_editor" 137 | textbutton "dof" 138 | textbutton "[_camera_dof: >5]" action Function(_viewers.camera_viewer.edit_value, _viewers.camera_viewer.dof_changed, 0, default=_camera_dof) alternate [Function(dof_set, _viewers.camera_viewer._camera_dof), renpy.restart_interaction] 139 | bar adjustment ui.adjustment(range=_viewers.camera_viewer.range_dof, value=_camera_dof, page=1, changed=_viewers.camera_viewer.dof_changed) xalign 1. yalign .5 140 | elif tab == "3D Layers": 141 | if list(_3d_layers.keys()) == ["master"]: 142 | label _("Please register 3D layers") 143 | else: 144 | for layer in sorted(_3d_layers.keys()): 145 | hbox: 146 | style_group "action_editor" 147 | textbutton "[layer]" action [SensitiveIf(layer in _viewers.all_keyframes), SelectedIf(_viewers.keyframes_exist(layer)), SetField(_viewers, "moved_time", _viewers.time), Show("_edit_keyframe", k=layer)] 148 | textbutton "{}".format(_3d_layers[layer]) action Function(_viewers.camera_viewer.edit_value, _viewers.camera_viewer.generate_layer_z_changed(layer), 0, default=_3d_layers[layer]) alternate [Function(layer_move, layer, _viewers.camera_viewer._3d_layers[layer]), renpy.restart_interaction] 149 | bar adjustment ui.adjustment(range=_viewers.camera_viewer.range_layer_z, value=_3d_layers[layer], page=1, changed=_viewers.camera_viewer.generate_layer_z_changed(layer)) xalign 1. yalign .5 150 | hbox: 151 | style_group "action_editor" 152 | xfill False 153 | xalign 1. 154 | if tab == "images": 155 | if name: 156 | textbutton _("remove") action [SensitiveIf(name in _viewers.transform_viewer.state[layer]), Show("_action_editor", tab=tab, layer=layer), Function(renpy.hide, name, layer), Function(_viewers.transform_viewer.state[layer].pop, name, layer), Function(_viewers.transform_viewer.remove_keyframes, name=name, layer=layer), _viewers.sort_keyframes] 157 | textbutton _("clipboard") action Function(_viewers.transform_viewer.put_show_clipboard, name, layer) 158 | textbutton _("reset") action [_viewers.transform_viewer.image_reset, renpy.restart_interaction] 159 | elif tab == "2D Camera": 160 | textbutton _("clipboard") action Function(_viewers.camera_viewer.put_clipboard, True) 161 | textbutton _("reset") action [_viewers.camera_viewer.camera_reset, renpy.restart_interaction] 162 | elif tab == "3D Layers": 163 | textbutton _("clipboard") action Function(_viewers.camera_viewer.put_clipboard, False) 164 | textbutton _("reset") action [_viewers.camera_viewer.layer_reset, renpy.restart_interaction] 165 | elif tab == "3D Camera": 166 | textbutton _("clipboard") action Function(_viewers.camera_viewer.put_clipboard, True) 167 | textbutton _("reset") action [_viewers.camera_viewer.camera_reset, renpy.restart_interaction] 168 | 169 | if time: 170 | add _viewers.dragged at _delay_show(time + 1) 171 | else: 172 | add _viewers.dragged 173 | 174 | init -1598: 175 | style action_editor_button: 176 | size_group "action_editor" 177 | outlines [ (absolute(1), "#000", absolute(0), absolute(0)) ] 178 | idle_background None 179 | insensitive_background None 180 | style action_editor_button_text: 181 | color "#aaa" 182 | selected_color "#fff" 183 | insensitive_color "#777" 184 | outlines [ (absolute(1), "#000", absolute(0), absolute(0)) ] 185 | style action_editor_a_button: 186 | take action_editor_button 187 | size_group None 188 | style action_editor_a_button_text take action_editor_button_text 189 | 190 | style action_editor_label: 191 | xminimum 110 192 | style action_editor_vbox xfill True 193 | 194 | screen _input_screen(message="type value", default=""): 195 | modal True 196 | key "game_menu" action Return("") 197 | 198 | frame: 199 | background "#0006" 200 | style_group "input_screen" 201 | 202 | has vbox 203 | 204 | label message 205 | 206 | hbox: 207 | input default default 208 | 209 | init -1598: 210 | style input_screen_frame xfill True ypos .1 xmargin .05 ymargin .05 211 | style input_screen_vbox xfill True spacing 30 212 | style input_screen_label xalign .5 213 | style input_screen_hbox xalign .5 214 | 215 | transform _delay_show(time): 216 | alpha 0 217 | pause time 218 | alpha 1 219 | 220 | screen _rot(): #show rule of thirds 221 | for i in range(1, 3): 222 | add Solid("#F00", xsize=config.screen_width, ysize=1, ypos=config.screen_height*i//3) 223 | add Solid("#F00", xsize=1, ysize=config.screen_height, xpos=config.screen_width*i//3) 224 | 225 | screen _warper_selecter(current_warper=""): 226 | modal True 227 | key "game_menu" action Return("") 228 | 229 | frame: 230 | background "#0006" 231 | style_group "warper_selecter" 232 | 233 | has vbox 234 | 235 | label _("Select a warper function") 236 | viewport: 237 | mousewheel True 238 | edgescroll (100, 100) 239 | xsize config.screen_width-500 240 | ysize config.screen_height-200 241 | scrollbars "vertical" 242 | vbox: 243 | for warper in sorted(renpy.atl.warpers.keys()): 244 | textbutton warper action [SelectedIf((_viewers.warper == warper and not current_warper) or warper == current_warper), Return(warper)] hovered Show("_warper_graph", warper=warper) unhovered Hide("_warper") 245 | hbox: 246 | textbutton _("add") action OpenURL("http://renpy.org/wiki/renpy/doc/cookbook/Additional_basic_move_profiles") 247 | textbutton _("close") action Return("") 248 | 249 | screen _warper_graph(warper): 250 | $ t=120 251 | $ length=300 252 | $ xpos=config.screen_width-400 253 | $ ypos=100 254 | # add Solid("#000", xsize=3, ysize=1.236*length, xpos=xpos+length/2, ypos=length/2+xpos, rotate=45, anchor=(.5, .5)) 255 | add Solid("#CCC", xsize=length, ysize=length, xpos=xpos, ypos=ypos ) 256 | add Solid("#000", xsize=length, ysize=3, xpos=xpos, ypos=length+ypos ) 257 | add Solid("#000", xsize=length, ysize=3, xpos=xpos, ypos=ypos ) 258 | add Solid("#000", xsize=3, ysize=length, xpos=xpos+length, ypos=ypos) 259 | add Solid("#000", xsize=3, ysize=length, xpos=xpos, ypos=ypos) 260 | for i in range(1, t): 261 | $ysize=int(length*renpy.atl.warpers[warper](i/float(t))) 262 | if ysize >= 0: 263 | add Solid("#000", xsize=length//t, ysize=ysize, xpos=xpos+i*length//t, ypos=length+ypos, yanchor=1.) 264 | else: 265 | add Solid("#000", xsize=length//t, ysize=-ysize, xpos=xpos+i*length//t, ypos=length+ypos-ysize, yanchor=1.) 266 | 267 | screen _move_keyframes: 268 | modal True 269 | key "game_menu" action Hide("_move_keyframes") 270 | frame: 271 | background "#0006" 272 | has vbox 273 | textbutton _("time: [_viewers.moved_time:>.2f] s") action Function(_viewers.edit_move_all_keyframes) 274 | bar adjustment ui.adjustment(range=7.0, value=_viewers.moved_time, changed=renpy.curry(_viewers.move_keyframes)(old=_viewers.moved_time)) xalign 1. yalign .5 275 | textbutton _("close") action Hide("_move_keyframes") xalign .98 276 | 277 | # _edit_keyframe((name, layer), "xpos") 278 | # _edit_keyframe(_camera_x) 279 | screen _edit_keyframe(k, int=False): 280 | $check_points = _viewers.all_keyframes[k] 281 | modal True 282 | key "game_menu" action Hide("_edit_keyframe") 283 | frame: 284 | background "#0009" 285 | xfill True 286 | has vbox 287 | label _("KeyFrames") xalign .5 288 | for v, t, w in check_points: 289 | if t != 0: 290 | hbox: 291 | textbutton _("x") action [Function(_viewers.remove_keyframe, remove_time=t, k=k), renpy.restart_interaction] background None 292 | textbutton _("{}".format(v)) action Function(_viewers.edit_the_value, check_points=check_points, old=t, value_org=v, int=int) 293 | textbutton _("{}".format(w)) action Function(_viewers.edit_the_warper, check_points=check_points, old=t, value_org=w) 294 | textbutton _("[t:>.2f] s") action Function(_viewers.edit_move_keyframes, check_points=check_points, old=t) 295 | bar adjustment ui.adjustment(range=7.0, value=t, changed=renpy.curry(_viewers.move_keyframe)(old=t, check_points=check_points)) xalign 1. yalign .5 296 | hbox: 297 | textbutton _("loop") action ToggleDict(_viewers.loops, k) 298 | if k[:8] == "_camera_": 299 | textbutton _("expression") action Function(_viewers.edit_expression, k) 300 | textbutton _("spline") action ToggleDict(_viewers.splines, "camera") 301 | elif not isinstance(k, tuple): 302 | textbutton _("expression") action Function(_viewers.edit_expression, k) 303 | textbutton _("spline") action ToggleDict(_viewers.splines, k) 304 | textbutton _("close") action Hide("_edit_keyframe") xalign .98 305 | 306 | init -1098 python: 307 | # Added keymap 308 | config.underlay.append(renpy.Keymap( 309 | # self_voicing = Preference("self voicing", "toggle"), #TODO ??? 310 | action_editor = _viewers.action_editor, 311 | image_viewer = _open_image_viewer, 312 | )) 313 | 314 | init -1598 python in _viewers: 315 | # TransformViewer 316 | class TransformViewer(object): 317 | def __init__(self): 318 | 319 | self.int_range = 1500 320 | self.float_range = 7.0 321 | # layer->tag->property->value 322 | self.state_org = {} 323 | self.state = {} 324 | # ((property, default)...), default is used when property can't be got. 325 | self.props = ( 326 | ("xpos", 0.), 327 | ("ypos", 0.), 328 | ("xanchor", 0.), 329 | ("yanchor", 0.), 330 | # ("xoffset", 0.), 331 | # ("yoffset", 0.), 332 | ("xzoom", 1.), 333 | ("yzoom", 1.), 334 | ("zoom", 1.), 335 | ("rotate", 0,), 336 | ("alpha", 1.), 337 | ("additive", 0.), 338 | ) 339 | self.force_float = ["zoom", "xzoom", "yzoom", "alpha", "additive"] 340 | 341 | def init(self): 342 | if not renpy.config.developer: 343 | return 344 | sle = renpy.game.context().scene_lists 345 | # back up for reset() 346 | for layer in renpy.config.layers: 347 | self.state_org[layer] = {} 348 | self.state[layer] = {} 349 | for tag in sle.layers[layer]: 350 | if not tag[0]: 351 | continue 352 | d = sle.get_displayable_by_tag(layer, tag[0]) 353 | if isinstance(d, renpy.display.screen.ScreenDisplayable): 354 | continue 355 | pos = renpy.get_placement(d) 356 | state = getattr(d, "state", None) 357 | 358 | 359 | string = "" 360 | for e in tag.name: 361 | string += str(e) + " " 362 | name = string[:-1] 363 | self.state_org[layer][name] = {} 364 | for p in ["xpos", "ypos", "xanchor", "yanchor"]: 365 | self.state_org[layer][name][p] = getattr(pos, p, None) 366 | for p, d in self.props: 367 | if p not in self.state_org[layer][name]: 368 | self.state_org[layer][name][p] = getattr(state, p, None) 369 | 370 | def reset(self, name, layer, prop): 371 | state={k: v for dic in [self.state_org[layer], self.state[layer]] for k, v in dic.items()}[name][prop] 372 | kwargs = {} 373 | for p, d in self.props: 374 | value = self.get_property(layer, name.split()[0], p, False) 375 | if value is not None: 376 | kwargs[p] = value 377 | elif p != "rotate": 378 | kwargs[p] = d 379 | kwargs[prop] = state 380 | renpy.show(name, [renpy.store.Transform(**kwargs)], layer=layer) 381 | renpy.restart_interaction() 382 | 383 | def image_reset(self): 384 | for layer in renpy.config.layers: 385 | for name, props in {k: v for dic in [self.state_org[layer], self.state[layer]] for k, v in dic.items()}.iteritems(): 386 | for prop in props: 387 | self.reset(name, layer, prop) 388 | 389 | def set_keyframe(self, layer, name, prop, value): 390 | 391 | keyframes = all_keyframes.get((name, layer, prop), []) 392 | if keyframes: 393 | for i, (v, t, w) in enumerate(keyframes): 394 | if time < t: 395 | keyframes.insert(i, (value, time, warper)) 396 | break 397 | elif time == t: 398 | keyframes[i] = ( value, time, warper) 399 | break 400 | else: 401 | keyframes.append((value, time, warper)) 402 | else: 403 | if time == 0: 404 | all_keyframes[(name, layer, prop)] = [(value, time, warper)] 405 | else: 406 | org = {k: v for dic in [self.state_org[layer], self.state[layer]] for k, v in dic.items()}[name][prop] 407 | all_keyframes[(name, layer, prop)] = [(org, 0, None), (value, time, warper)] 408 | sort_keyframes() 409 | 410 | def play(self, play): 411 | for layer in renpy.config.layers: 412 | for name in {k: v for dic in [self.state_org[layer], self.state[layer]] for k, v in dic.items()}: 413 | check_points = {} 414 | for prop, d in self.props: 415 | if (name, layer, prop) in all_keyframes: 416 | check_points[prop] = all_keyframes[(name, layer, prop)] 417 | if not check_points: # ビューワー上でのアニメーション(フラッシュ等)の誤動作を抑制 418 | continue 419 | loop = {prop+"_loop": loops[(name, layer, prop)] for prop, d in self.props} 420 | if play: 421 | renpy.show(name, [renpy.store.Transform(function=renpy.curry(self.transform)(check_points=check_points, loop=loop))], layer=layer) 422 | else: 423 | # check_points = { prop: ( (value, time, warper).. ) } 424 | kwargs = {} 425 | kwargs.subpixel = True 426 | # kwargs.transform_anchor = True 427 | st = renpy.store._viewers.time 428 | 429 | for p, cs in check_points.items(): 430 | time = st 431 | if loop[p+"_loop"] and cs[-1][1]: 432 | time = time % cs[-1][1] 433 | 434 | for i in xrange(1, len(cs)): 435 | checkpoint = cs[i][1] 436 | pre_checkpoint = cs[i-1][1] 437 | if time < checkpoint: 438 | start = cs[i-1] 439 | goal = cs[i] 440 | if checkpoint != pre_checkpoint: 441 | g = renpy.atl.warpers[goal[2]]((time - pre_checkpoint) / float(checkpoint - pre_checkpoint)) 442 | else: 443 | g = 1. 444 | for p2, d in self.props: 445 | if p2 == p: 446 | default = d 447 | if goal[0] is not None: 448 | if isinstance(goal[0], int) and p not in self.force_float: 449 | if start[0] is None: 450 | v = g*(goal[0]-default)+default 451 | else: 452 | v = g*(goal[0]-start[0])+start[0] 453 | v = int(v) 454 | else: 455 | if start[0] is None: 456 | v = g*(goal[0]-default)+default 457 | else: 458 | v = g*(goal[0]-start[0])+start[0] 459 | kwargs[p] = v 460 | break 461 | else: 462 | kwargs[p] = cs[-1][0] 463 | 464 | renpy.show(name, [renpy.store.Transform(**kwargs)], layer=layer) 465 | 466 | def transform(self, tran, st, at, check_points, loop, subpixel=True): 467 | # check_points = { prop: [ (value, time, warper).. ] } 468 | tran.subpixel = subpixel 469 | # tran.transform_anchor = True 470 | 471 | for p, cs in check_points.items(): 472 | time = st 473 | if loop[p+"_loop"] and cs[-1][1]: 474 | time = st % cs[-1][1] 475 | 476 | for i in xrange(1, len(cs)): 477 | checkpoint = cs[i][1] 478 | pre_checkpoint = cs[i-1][1] 479 | if time < checkpoint: 480 | start = cs[i-1] 481 | goal = cs[i] 482 | if checkpoint != pre_checkpoint: 483 | g = renpy.atl.warpers[goal[2]]((time - pre_checkpoint) / float(checkpoint - pre_checkpoint)) 484 | else: 485 | g = 1. 486 | for p2, d in self.props: 487 | if p2 == p: 488 | default = d 489 | if goal[0] is not None: 490 | if isinstance(goal[0], int) and p not in self.force_float: 491 | if start[0] is None: 492 | v = g*(goal[0]-default)+default 493 | else: 494 | v = g*(goal[0]-start[0])+start[0] 495 | v = int(v) 496 | else: 497 | if start[0] is None: 498 | v = g*(goal[0]-default)+default 499 | else: 500 | v = g*(goal[0]-start[0])+start[0] 501 | setattr(tran, p, v) 502 | break 503 | else: 504 | setattr(tran, p, cs[-1][0]) 505 | return .005 506 | 507 | 508 | def generate_changed(self, layer, name, prop): 509 | state={k: v for dic in [self.state_org[layer], self.state[layer]] for k, v in dic.items()}[name][prop] 510 | def changed(v): 511 | kwargs = {} 512 | for p, d in self.props: 513 | value = self.get_property(layer, name.split()[0], p, False) 514 | if value is not None: 515 | kwargs[p] = value 516 | elif p != "rotate": 517 | kwargs[p] = d 518 | if p == prop: 519 | default = d 520 | if prop not in self.force_float and ( (state is None and isinstance(default, int)) or isinstance(state, int) ): 521 | kwargs[prop] = v - self.int_range 522 | else: 523 | kwargs[prop] = round(v -self.float_range, 2) 524 | 525 | self.set_keyframe(layer, name, prop, kwargs[prop]) 526 | renpy.show(name, [renpy.store.Transform(**kwargs)], layer=layer) 527 | renpy.restart_interaction() 528 | return changed 529 | 530 | def get_property(self, layer, tag, prop, default=True): 531 | sle = renpy.game.context().scene_lists 532 | # if tag in self.state[layer]: 533 | # #TODO 534 | # default = True 535 | if tag: 536 | d = sle.get_displayable_by_tag(layer, tag) 537 | pos = renpy.get_placement(d) 538 | state = getattr(pos, prop, None) 539 | if state is None: 540 | state = getattr(getattr(d, "state", None), prop, None) 541 | if state is None and default: 542 | for p, value in self.props: 543 | if p == prop: 544 | state = value 545 | return state 546 | return None 547 | 548 | def put_show_clipboard(self, name, layer): 549 | string = """ 550 | show %s onlayer %s""" % (name, layer) 551 | for p, d in self.props: 552 | value = self.get_property(layer, name.split()[0], p) 553 | if value != d: 554 | if string.find(":") < 0: 555 | string += ":\n " 556 | string += "%s %s " % (p, value) 557 | try: 558 | from pygame import scrap, locals 559 | scrap.put(locals.SCRAP_TEXT, string) 560 | except: 561 | renpy.notify(_("Can't open clipboard")) 562 | else: 563 | renpy.notify(__('Placed \n"%s"\n on clipboard') % string) 564 | 565 | def edit_value(self, function, int=False, default=""): 566 | v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=default) 567 | if v: 568 | try: 569 | if int: 570 | v = renpy.python.py_eval(v) + self.int_range 571 | else: 572 | v = renpy.python.py_eval(v) + self.float_range 573 | function(v) 574 | except: 575 | renpy.notify(_("Please type value")) 576 | 577 | def add_image(self, layer): 578 | default = () 579 | while True: 580 | name = renpy.invoke_in_new_context(renpy.call_screen, "_image_selecter", default=default) 581 | if isinstance(name, tuple): #press button 582 | for n in renpy.display.image.images: 583 | if set(n) == set(name): 584 | string="" 585 | for e in n: 586 | string += e + " " 587 | self.state[layer][string] = {} 588 | renpy.show(string, layer=layer) 589 | for p, d in self.props: 590 | self.state[layer][string][p] = self.get_property(layer, string.split()[0], p, False) 591 | all_keyframes[(string, layer, "xpos")] = [(self.state[layer][string]["xpos"], 0, None)] 592 | remove_list = [n_org for n_org in self.state_org[layer] if n_org.split()[0] == n[0]] 593 | for n_org in remove_list: 594 | del self.state_org[layer][n_org] 595 | for k in [k for k in all_keyframes if isinstance(k, tuple) and k[0] == n_org and k[1] == layer]: 596 | del all_keyframes[k] 597 | sort_keyframes() 598 | renpy.show_screen("_action_editor", tab="images", layer=layer, name=string) 599 | return 600 | else: 601 | default = name 602 | elif name: #from input text 603 | # for n in renpy.display.image.images: #テキスト入力からはいきなり表示しないようにする。 604 | # if set(n) == set(name.split()): 605 | # self.state[layer][name] = {} 606 | # renpy.show(name, layer=layer) 607 | # for p, d in self.props: 608 | # self.state[layer][name][p] = self.get_property(layer, name.split()[0], p, False) 609 | # all_keyframes[(name, layer, "xpos")] = [(self.state[layer][name]["xpos"], 0, None)] 610 | # remove_list = [n_org for n_org in self.state_org[layer] if n_org.split()[0] == n[0]] 611 | # for n_org in remove_list: 612 | # del self.state_org[layer][n_org] 613 | # transform_viewer.remove_keyframes(n_org, layer) 614 | # sort_keyframes() 615 | # renpy.show_screen("_action_editor", tab="images", layer=layer, name=name) 616 | # return 617 | default = tuple(name.split()) 618 | else: 619 | renpy.notify(_("Please type image name")) 620 | return 621 | 622 | def remove_keyframes(self, name, layer): 623 | for k in [k for k in all_keyframes if isinstance(k, tuple) and k[0] == name and k[1] == layer]: 624 | del all_keyframes[k] 625 | transform_viewer = TransformViewer() 626 | 627 | ########################################################################## 628 | # CameraViewer 629 | class CameraViewer(object): 630 | 631 | def __init__(self): 632 | self.range_camera_pos = 6000 633 | self.range_rotate = 360 634 | self.range_layer_z = 10000 635 | self.range_focus = 10000 636 | self.range_dof = 2000 637 | 638 | def init(self): 639 | if not renpy.config.developer: 640 | return 641 | self._camera_x = renpy.store._camera_x 642 | self._camera_y = renpy.store._camera_y 643 | self._camera_z = renpy.store._camera_z 644 | self._camera_rotate = renpy.store._camera_rotate 645 | self._camera_focus = renpy.store._camera_focus 646 | self._camera_dof = renpy.store._camera_dof 647 | self._3d_layers = renpy.store._3d_layers.copy() 648 | 649 | def camera_reset(self): 650 | renpy.store.camera_move(self._camera_x, self._camera_y, self._camera_z, self._camera_rotate) 651 | renpy.store.focus_set(self._camera_focus) 652 | renpy.store.dof_set(self._camera_dof) 653 | renpy.restart_interaction() 654 | 655 | def layer_reset(self): 656 | for layer in renpy.store._3d_layers: 657 | renpy.store.layer_move(layer, self._3d_layers[layer]) 658 | renpy.restart_interaction() 659 | 660 | def x_changed(self, v): 661 | v=int(v) 662 | renpy.store.camera_move(v - self.range_camera_pos, renpy.store._camera_y, renpy.store._camera_z, renpy.store._camera_rotate) 663 | self.set_camera_keyframe("_camera_x", v-self.range_camera_pos) 664 | renpy.restart_interaction() 665 | 666 | def y_changed(self, v): 667 | v=int(v) 668 | renpy.store.camera_move(renpy.store._camera_x, v - self.range_camera_pos, renpy.store._camera_z, renpy.store._camera_rotate) 669 | self.set_camera_keyframe("_camera_y", v-self.range_camera_pos) 670 | renpy.restart_interaction() 671 | 672 | def z_changed(self, v): 673 | v=int(v) 674 | renpy.store.camera_move(renpy.store._camera_x, renpy.store._camera_y, v - self.range_camera_pos, renpy.store._camera_rotate) 675 | self.set_camera_keyframe("_camera_z", v-self.range_camera_pos) 676 | renpy.restart_interaction() 677 | 678 | def r_changed(self, v): 679 | v=int(v) 680 | renpy.store.camera_move(renpy.store._camera_x, renpy.store._camera_y, renpy.store._camera_z, v - self.range_rotate) 681 | self.set_camera_keyframe("_camera_rotate", v-self.range_rotate) 682 | renpy.restart_interaction() 683 | 684 | def focus_changed(self, v): 685 | v=int(v) 686 | renpy.store.focus_set(v) 687 | self.set_camera_keyframe("_camera_focus", v) 688 | renpy.restart_interaction() 689 | 690 | def dof_changed(self, v): 691 | v=int(v) 692 | renpy.store.dof_set(v) 693 | self.set_camera_keyframe("_camera_dof", v) 694 | renpy.restart_interaction() 695 | 696 | def generate_layer_z_changed(self, l): 697 | def layer_z_changed(v): 698 | renpy.store.layer_move(l, int(v)) 699 | self.set_layer_keyframe(l) 700 | renpy.restart_interaction() 701 | return layer_z_changed 702 | 703 | def put_clipboard(self, camera_tab): 704 | string = "" 705 | if camera_tab: 706 | string = """ 707 | $camera_move(%s, %s, %s, %s, duration=0)""" % (renpy.store._camera_x, renpy.store._camera_y, renpy.store._camera_z, renpy.store._camera_rotate) 708 | string += """ 709 | $focus_set(%s, duration=0)""" % (renpy.store._camera_focus) 710 | string += """ 711 | $dof_set(%s, duration=0)""" % (renpy.store._camera_dof) 712 | else: 713 | for layer in renpy.store._3d_layers: 714 | string += """ 715 | $layer_move("%s", %s, duration=0)""" % (layer, renpy.store._3d_layers[layer]) 716 | try: 717 | from pygame import scrap, locals 718 | scrap.put(locals.SCRAP_TEXT, string) 719 | except: 720 | renpy.notify(_("Can't open clipboard")) 721 | else: 722 | renpy.notify(__("Placed \n'%s'\n on clipboard") % string) 723 | 724 | def edit_value(self, function, range, default=""): 725 | v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=default) 726 | if v: 727 | try: 728 | function(renpy.python.py_eval(v) + range) 729 | except: 730 | renpy.notify(_("Please type value")) 731 | 732 | def set_camera_keyframe(self, coordinate, value): 733 | keyframes = all_keyframes.get(coordinate, []) 734 | if keyframes: 735 | for i, (v, t, w) in enumerate(keyframes): 736 | if time < t: 737 | keyframes.insert(i, (value, time, warper)) 738 | break 739 | elif time == t: 740 | keyframes[i] = (value, time, warper) 741 | break 742 | else: 743 | keyframes.append((value, time, warper)) 744 | else: 745 | if time == 0: 746 | all_keyframes[coordinate] = [(value, time, warper)] 747 | else: 748 | all_keyframes[coordinate] = [(getattr(self, coordinate), 0, None), (value, time, warper)] 749 | sort_keyframes() 750 | 751 | def set_layer_keyframe(self, layer): 752 | keyframes = all_keyframes.get(layer, []) 753 | if keyframes: 754 | for i, (v, t, w) in enumerate(keyframes): 755 | if time < t: 756 | keyframes.insert(i, (renpy.store._3d_layers[layer], time, warper)) 757 | break 758 | elif time == t: 759 | keyframes[i] = (renpy.store._3d_layers[layer], time, warper) 760 | break 761 | else: 762 | keyframes.append((renpy.store._3d_layers[layer], time, warper)) 763 | else: 764 | if time == 0: 765 | all_keyframes[layer] = [(renpy.store._3d_layers[layer], time, warper)] 766 | else: 767 | all_keyframes[layer] = [(self._3d_layers[layer], 0, None), (renpy.store._3d_layers[layer], time, warper)] 768 | sort_keyframes() 769 | 770 | def play(self, play): 771 | camera_check_points = {} 772 | for coordinate in ["_camera_x", "_camera_y", "_camera_z", "_camera_rotate"]: 773 | if coordinate in all_keyframes: 774 | camera_check_points[coordinate[8:]] = all_keyframes[coordinate] 775 | 776 | layer_check_points = {} 777 | kwargs = {} 778 | for layer in renpy.store._3d_layers: 779 | if layer in all_keyframes: 780 | layer_check_points[layer] = all_keyframes[layer] 781 | kwargs[layer+"_loop"] = loops[layer] 782 | kwargs[layer+"_spline"] = splines[layer] 783 | 784 | focus_check_points = {} 785 | for i in ["_camera_focus", "_camera_dof"]: 786 | if i in all_keyframes: 787 | focus_check_points[i[8:]] = all_keyframes[i] 788 | 789 | for coordinate in ["_camera_x", "_camera_y", "_camera_z", "_camera_rotate"]: 790 | kwargs[coordinate[8:]+"_loop"] = loops[coordinate] 791 | for coordinate in ["_camera_x", "_camera_y", "_camera_z", "_camera_rotate"]: 792 | if expressions[coordinate]: 793 | kwargs[coordinate[8:]+"_express"] = renpy.python.py_eval(expressions[coordinate]) 794 | if camera_check_points or layer_check_points or focus_check_points: 795 | renpy.store.all_moves(camera_check_points=camera_check_points, layer_check_points=layer_check_points, focus_check_points=focus_check_points, play=play, camera_spline=splines["camera"], **kwargs) 796 | 797 | camera_viewer = CameraViewer() 798 | 799 | class Dragged(renpy.Displayable): 800 | 801 | def __init__(self, child, **properties): 802 | super(Dragged, self).__init__(**properties) 803 | # The child. 804 | self.child = renpy.displayable(child) 805 | self.cx = self.x = (0.5 + renpy.store._camera_x/(2.*camera_viewer.range_camera_pos))*renpy.config.screen_width 806 | self.cy = self.y = (0.5 + renpy.store._camera_y/(2.*camera_viewer.range_camera_pos))*renpy.config.screen_height 807 | self.dragging = False 808 | 809 | def render(self, width, height, st, at): 810 | 811 | # Create a render from the child. 812 | child_render = renpy.render(self.child, width, height, st, at) 813 | 814 | # Get the size of the child. 815 | self.width, self.height = child_render.get_size() 816 | 817 | # Create the render we will return. 818 | render = renpy.Render(renpy.config.screen_width, renpy.config.screen_height) 819 | 820 | # Blit (draw) the child's render to our render. 821 | render.blit(child_render, (self.x-self.width/2., self.y-self.height/2.)) 822 | 823 | # Return the render. 824 | return render 825 | 826 | def event(self, ev, x, y, st): 827 | 828 | if renpy.map_event(ev, "mousedown_1"): 829 | if self.x-self.width/2. <= x and x <= self.x+self.width/2. and self.y-self.height/2. <= y and y <= self.y+self.height/2.: 830 | self.dragging = True 831 | elif renpy.map_event(ev, "mouseup_1"): 832 | self.dragging = False 833 | 834 | # if x <= 0: 835 | # x = 0 836 | # if renpy.config.screen_width <= x: 837 | # x = renpy.config.screen_width 838 | # if y <= 0: 839 | # y = 0 840 | # if renpy.config.screen_height <= y: 841 | # y = renpy.config.screen_height 842 | 843 | if renpy.store._camera_x != int(self.cx) or renpy.store._camera_y != int(self.cy): 844 | self.x = (0.5 + renpy.store._camera_x/(2.*camera_viewer.range_camera_pos))*renpy.config.screen_width 845 | self.y = (0.5 + renpy.store._camera_y/(2.*camera_viewer.range_camera_pos))*renpy.config.screen_height 846 | renpy.redraw(self, 0) 847 | 848 | if self.dragging: 849 | if self.x != x or self.y != y: 850 | self.cx = int(2*camera_viewer.range_camera_pos*( float(x)/renpy.config.screen_width - 0.5)) 851 | self.cy = int(2*camera_viewer.range_camera_pos*( float(y)/renpy.config.screen_height - 0.5)) 852 | if self.cx != renpy.store._camera_x: 853 | camera_viewer.set_camera_keyframe("_camera_x", self.cx) 854 | if self.cy != renpy.store._camera_y: 855 | camera_viewer.set_camera_keyframe("_camera_y", self.cy) 856 | renpy.store.camera_move(self.cx, self.cy, renpy.store._camera_z, renpy.store._camera_rotate) 857 | self.x, self.y = x, y 858 | renpy.restart_interaction() 859 | renpy.redraw(self, 0) 860 | 861 | # Pass the event to our child. 862 | # return self.child.event(ev, x, y, st) 863 | 864 | def per_interact(self): 865 | renpy.redraw(self, 0) 866 | 867 | def visit(self): 868 | return [ self.child ] 869 | dragged = Dragged("camera.png") 870 | 871 | ########################################################################## 872 | from collections import defaultdict 873 | loops = defaultdict(lambda:False) 874 | expressions = defaultdict(lambda:None) 875 | splines = defaultdict(lambda:False) 876 | all_keyframes = {} 877 | time = 0 878 | moved_time = 0 879 | sorted_keyframes = [] 880 | warper = default_warper 881 | 882 | def edit_expression(k): 883 | value = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=expressions[k]) 884 | try: 885 | result = renpy.python.py_eval(value)(0, 0) 886 | if isinstance(result, float) or isinstance(result, int): 887 | expressions[k] = value 888 | else: 889 | raise 890 | except: 891 | renpy.notify(_("This isn't a valid expression")) 892 | renpy.restart_interaction() 893 | 894 | def edit_the_value(check_points, old, value_org, int=False): 895 | value = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=value_org) 896 | try: 897 | value = renpy.python.py_eval(value) 898 | if int: 899 | value = int(value) 900 | else: 901 | value = float(value) 902 | for i, (v, t, w) in enumerate(check_points): 903 | if t == old: 904 | check_points[i] = (value, t, w) 905 | break 906 | except: 907 | renpy.notify(_("Please type value")) 908 | renpy.restart_interaction() 909 | 910 | def edit_the_warper(check_points, old, value_org): 911 | warper = renpy.invoke_in_new_context(renpy.call_screen, "_warper_selecter", current_warper=value_org) 912 | if warper: 913 | for i, (v, t, w) in enumerate(check_points): 914 | if t == old: 915 | check_points[i] = (v, t, warper) 916 | break 917 | renpy.restart_interaction() 918 | 919 | def edit_move_keyframes(check_points, old): 920 | v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=old) 921 | if v: 922 | try: 923 | v = renpy.python.py_eval(v) 924 | if v < 0: 925 | return 926 | move_keyframe(v, old, check_points) 927 | except: 928 | renpy.notify(_("Please type value")) 929 | 930 | def edit_move_all_keyframes(): 931 | v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=moved_time) 932 | if v: 933 | try: 934 | v = renpy.python.py_eval(v) 935 | if v < 0: 936 | return 937 | move_keyframes(v, moved_time) 938 | except: 939 | renpy.notify(_("Please type value")) 940 | 941 | def edit_time(): 942 | global time 943 | v = renpy.invoke_in_new_context(renpy.call_screen, "_input_screen", default=time) 944 | if v: 945 | try: 946 | v = renpy.python.py_eval(v) 947 | if v < 0: 948 | return 949 | change_time(v) 950 | except: 951 | renpy.notify(_("Please type value")) 952 | 953 | def next_time(): 954 | if not sorted_keyframes: 955 | change_time(0) 956 | return 957 | else: 958 | for i, t in enumerate(sorted_keyframes): 959 | if time < t: 960 | change_time(sorted_keyframes[i]) 961 | return 962 | change_time(sorted_keyframes[0]) 963 | 964 | def prev_time(): 965 | if not sorted_keyframes: 966 | change_time(0) 967 | return 968 | else: 969 | for i, t in enumerate(sorted_keyframes): 970 | if time <= t: 971 | change_time(sorted_keyframes[i-1]) 972 | break 973 | else: 974 | change_time(sorted_keyframes[-1]) 975 | 976 | def select_default_warper(): 977 | global warper 978 | v = renpy.invoke_in_new_context(renpy.call_screen, "_warper_selecter") 979 | if v: 980 | warper = v 981 | 982 | # @renpy.pure 983 | # class AddWindow(renpy.store.Action, renpy.store.DictEquality): 984 | # def __init__(self): 985 | # pass 986 | # def __call__(self): 987 | # if renpy.shown_window(): 988 | # renpy.scene("window") 989 | # else: 990 | # renpy.add_layer("window", below="screens") 991 | # renpy.config.empty_window() 992 | # renpy.restart_interaction() 993 | # def get_selected(self): 994 | # if renpy.shown_window(): 995 | # return True 996 | # return False 997 | 998 | def clear_keyframes(): 999 | all_keyframes.clear() 1000 | sorted_keyframes[:]=[] 1001 | 1002 | def remove_keyframe(remove_time, k): 1003 | remove_list = [] 1004 | for (v, t, w) in all_keyframes[k]: 1005 | if t == remove_time: 1006 | if remove_time != 0 or (remove_time == 0 and len(all_keyframes[k]) == 1): 1007 | remove_list.append((v, t, w)) 1008 | for c in remove_list: 1009 | all_keyframes[k].remove(c) 1010 | if not all_keyframes[k]: 1011 | del all_keyframes[k] 1012 | sort_keyframes() 1013 | change_time(time) 1014 | 1015 | def remove_keyframes(time): 1016 | keylist = [k for k in all_keyframes] 1017 | for k in keylist: 1018 | remove_keyframe(time, k) 1019 | 1020 | def sort_keyframes(): 1021 | global sorted_keyframes 1022 | sorted_keyframes[:] = [] 1023 | for keyframes in all_keyframes.values(): 1024 | for (v, t, w) in keyframes: 1025 | if t not in sorted_keyframes: 1026 | sorted_keyframes.append(t) 1027 | sorted_keyframes.sort() 1028 | 1029 | def move_keyframes(new, old): 1030 | global moved_time 1031 | moved_time = round(new, 2) 1032 | for k, v in all_keyframes.items(): 1033 | move_keyframe(new, old, v) 1034 | renpy.restart_interaction() 1035 | 1036 | def move_keyframe(new, old, check_points): 1037 | new = round(new, 2) 1038 | for i, c in enumerate(check_points): 1039 | if c[1] == old: 1040 | (value, time, warper) = check_points.pop(i) 1041 | for n, (v, t, w) in enumerate(check_points): 1042 | if new < t: 1043 | check_points.insert(n, (value, new, warper)) 1044 | break 1045 | elif new == t: 1046 | # check_points[n] = (new, (value, new, w)) 1047 | check_points.insert(n, (value, new, warper)) 1048 | break 1049 | else: 1050 | check_points.append((value, new, warper)) 1051 | if old == 0 and new != 0: 1052 | check_points.insert(0, (value, 0, None)) 1053 | sort_keyframes() 1054 | renpy.restart_interaction() 1055 | 1056 | def keyframes_exist(k): 1057 | if k not in all_keyframes: 1058 | return False 1059 | check_points = all_keyframes[k] 1060 | for c in check_points: 1061 | if c[1] == time: 1062 | return True 1063 | return False 1064 | 1065 | def change_time(v): 1066 | global time 1067 | time = round(v, 2) 1068 | transform_viewer.play(False) 1069 | camera_viewer.play(False) 1070 | renpy.restart_interaction() 1071 | 1072 | def rollback(): 1073 | renpy.store.camera_move(renpy.store._camera_x, renpy.store._camera_y, renpy.store._camera_z-100, renpy.store._camera_rotate) 1074 | camera_viewer.set_camera_keyframe("_camera_z", renpy.store._camera_z) 1075 | renpy.restart_interaction() 1076 | 1077 | def rollforward(): 1078 | renpy.store.camera_move(renpy.store._camera_x, renpy.store._camera_y, renpy.store._camera_z+100, renpy.store._camera_rotate) 1079 | camera_viewer.set_camera_keyframe("_camera_z", renpy.store._camera_z) 1080 | renpy.restart_interaction() 1081 | 1082 | def action_editor(): 1083 | global time 1084 | if not renpy.config.developer: 1085 | return 1086 | transform_viewer.init() 1087 | camera_viewer.init() 1088 | loops.clear() 1089 | expressions.clear() 1090 | renpy.store._first_load = True 1091 | renpy.invoke_in_new_context(renpy.call_screen, "_action_editor") 1092 | clear_keyframes() 1093 | time = 0 1094 | camera_viewer.layer_reset() 1095 | camera_viewer.camera_reset() 1096 | 1097 | def last_moves(): 1098 | all_keyframes["_camera_x"] = renpy.store._last_camera_arguments[0]["x"] 1099 | all_keyframes["_camera_y"] = renpy.store._last_camera_arguments[0]["y"] 1100 | all_keyframes["_camera_z"] = renpy.store._last_camera_arguments[0]["z"] 1101 | all_keyframes["_camera_rotate"] = renpy.store._last_camera_arguments[0]["rotate"] 1102 | all_keyframes["_camera_z"] = renpy.store._last_camera_arguments[0]["z"] 1103 | for k in renpy.store._last_camera_arguments[1]: 1104 | all_keyframes[k] = renpy.store._last_camera_arguments[1][k] 1105 | all_keyframes["_camera_focus"] = renpy.store._last_camera_arguments[2]["focus"] 1106 | all_keyframes["_camera_dof"] = renpy.store._last_camera_arguments[2]["dof"] 1107 | loops["_camera_x"] = renpy.store._last_camera_arguments[3] 1108 | loops["_camera_y"] = renpy.store._last_camera_arguments[4] 1109 | loops["_camera_z"] = renpy.store._last_camera_arguments[5] 1110 | loops["_camera_rotate"] = renpy.store._last_camera_arguments[6] 1111 | expressions["_camera_x"] = renpy.store._last_camera_arguments[7] 1112 | expressions["_camera_y"] = renpy.store._last_camera_arguments[8] 1113 | expressions["_camera_z"] = renpy.store._last_camera_arguments[9] 1114 | expressions["_camera_rotate"] = renpy.store._last_camera_arguments[10] 1115 | for k in renpy.store._last_camera_arguments[11]: 1116 | if k.find("loop"): 1117 | loops[k[:-5]] = renpy.store._last_camera_arguments[11][k] 1118 | elif k.find("express"): 1119 | expressions[k[:-8]] = renpy.store._last_camera_arguments[11][k] 1120 | splines["camera"] = renpy.store._last_camera_arguments[17] 1121 | all_keyframes["_camera_x"].insert(0, (renpy.store._last_camera_arguments[12], 0, None)) 1122 | all_keyframes["_camera_y"].insert(0, (renpy.store._last_camera_arguments[13], 0, None)) 1123 | all_keyframes["_camera_z"].insert(0, (renpy.store._last_camera_arguments[14], 0, None)) 1124 | all_keyframes["_camera_rotate"].insert(0, (renpy.store._last_camera_arguments[15], 0, None)) 1125 | for k in renpy.store._last_camera_arguments[1]: 1126 | all_keyframes[k].insert(0, (renpy.store._last_camera_arguments[16][k], 0, None)) 1127 | all_keyframes["_camera_focus"].insert(0, (renpy.store._last_camera_arguments[17], 0, None)) 1128 | all_keyframes["_camera_dof"].insert(0, (renpy.store._last_camera_arguments[18], 0, None)) 1129 | sort_keyframes() 1130 | change_time(0) 1131 | 1132 | def put_clipboard(): 1133 | camera_check_points = {} 1134 | for coordinate in ["_camera_x", "_camera_y", "_camera_z", "_camera_rotate"]: 1135 | if coordinate in all_keyframes: 1136 | camera_check_points[coordinate[8:]] = all_keyframes[coordinate] 1137 | if len(camera_check_points[coordinate[8:]]) == 1 and camera_check_points[coordinate[8:]][0][0] == getattr(renpy.store._viewers.camera_viewer, coordinate): 1138 | del camera_check_points[coordinate[8:]] 1139 | 1140 | layer_check_points = {} 1141 | loop = "" 1142 | spline = "" 1143 | expression = "" 1144 | argments = "" 1145 | for layer in renpy.store._3d_layers: 1146 | if layer in all_keyframes: 1147 | layer_check_points[layer] = all_keyframes[layer] 1148 | if len(layer_check_points[layer]) == 1 and layer_check_points[layer][0][0] == camera_viewer._3d_layers[layer]: 1149 | del layer_check_points[layer] 1150 | if loops[layer]: 1151 | loop += layer+"_loop=True, " 1152 | if splines[layer]: 1153 | spline += layer+"_spline=True, " 1154 | 1155 | focus_check_points = {} 1156 | for i in ["_camera_focus", "_camera_dof"]: 1157 | if i in all_keyframes: 1158 | focus_check_points[i[8:]] = all_keyframes[i] 1159 | if len(focus_check_points[i[8:]]) == 1 and focus_check_points[i[8:]][0][0] == getattr(renpy.store._viewers.camera_viewer, i): 1160 | del focus_check_points[i[8:]] 1161 | 1162 | for coordinate in ["_camera_x", "_camera_y", "_camera_z", "_camera_rotate"]: 1163 | if loops[coordinate]: 1164 | loop += coordinate[8:]+"_loop=True, " 1165 | if expressions[coordinate]: 1166 | expression += coordinate[8:]+"_express="+expressions[coordinate]+", " 1167 | if splines["camera"]: 1168 | spline += "camera_spline=True, " 1169 | string = "" 1170 | 1171 | if camera_check_points: 1172 | argments += "camera_check_points={}, ".format(camera_check_points) 1173 | if layer_check_points: 1174 | argments += "layer_check_points={}, ".format(layer_check_points) 1175 | if focus_check_points: 1176 | argments += "focus_check_points={}, ".format(focus_check_points) 1177 | if expression: 1178 | argments += expression 1179 | if loop: 1180 | argments += loop 1181 | if spline: 1182 | argments += spline 1183 | 1184 | if argments: 1185 | string += """ 1186 | $all_moves({})""".format(argments[:-2]) 1187 | 1188 | for layer in transform_viewer.state_org: 1189 | for name, kwargs_org in {k: v for dic in [transform_viewer.state_org[layer], transform_viewer.state[layer]] for k, v in dic.items()}.items(): 1190 | kwargs = {k[2]:v for k, v in all_keyframes.items() if isinstance(k, tuple) and k[0] == name and k[1] == layer} 1191 | if kwargs: 1192 | string += """ 1193 | show {} onlayer {}: 1194 | subpixel True """.format(name, layer) 1195 | for p, d in transform_viewer.props: 1196 | if p in kwargs and len(kwargs[p]) == 1: 1197 | string += "{} {} ".format(p, kwargs[p][0][0]) 1198 | elif d != {k2: v2 for dic in [transform_viewer.state_org[layer], transform_viewer.state[layer]] for k2, v2 in dic.items()}[name][p]: 1199 | string += "{} {} ".format(p, {k2: v2 for dic in [transform_viewer.state_org[layer], transform_viewer.state[layer]] for k2, v2 in dic.items()}[name][p]) 1200 | for p, check_points in kwargs.items(): 1201 | if len(check_points) > 1: 1202 | string += """ 1203 | parallel:""" 1204 | string += """ 1205 | {} {}""".format(p, check_points[0][0]) 1206 | for i, check_point in enumerate(check_points[1:]): 1207 | string += """ 1208 | {} {} {} {}""".format(check_point[2], check_points[i+1][1]-check_points[i][1], p, check_point[0]) 1209 | if loops[(name,layer,p)]: 1210 | string += """ 1211 | repeat""" 1212 | 1213 | if string: 1214 | string = string.replace("u'", "'", 999) 1215 | try: 1216 | from pygame import scrap, locals 1217 | scrap.put(locals.SCRAP_TEXT, string) 1218 | except: 1219 | renpy.notify(_("Can't open clipboard")) 1220 | else: 1221 | #syntax hilight error in vim 1222 | renpy.notify("Placed\n{}\n\non clipboard".format(string).replace("{", "{{").replace("[", "[[")) 1223 | else: 1224 | renpy.notify(_("Nothing to put")) 1225 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | With the introduction of 3Dstage in Ren'Py v7.46, this version has been discontinued. 2 | Now, ActionEditor3 is available 3 | https://github.com/kyouryuukunn/renpy-ActionEditor3 4 | 5 | Ren'Py v7.4.6で導入された3Dstageに合せて本バージョンは開発停止しました。 6 | 以後のバージョンではActionEditor3をご利用ください。 7 | https://github.com/kyouryuukunn/renpy-ActionEditor3 8 | 9 | youtube sample 10 | Introduction 11 | 12 | Sample 13 | 14 | 15 | 日本語マニュアルはドキュメント後半にあります。 16 | 17 | This script adds the ability to simulate a 3D camera within Ren'Py, along with an 18 | in-game Action Editor and Image Viewer GUI to assist in animating the camera. 19 | To install, copy all files in the camera directory to your game directory. 20 | 21 | Ren'Py 22 | 23 | Action Editor 24 | ================ 25 | 26 | This allows you to adjusts coordinates of the simulated camera, 3D layers, and transform properties 27 | of images in real-time with a GUI. It can then generate a script based on these changes and 28 | place it on the clipboard for later pasting into Ren'Py scripts. 29 | 30 | When `config.developer` is True, pressing action_editor (by default, 31 | "shift+P") will open the Action editor. 32 | 33 | The Action Editor has the following features: 34 | 35 | * View and adjust the transform properties of images, camera coordinates, and 3D layer depth with bars 36 | * View and adjust the x and y coordinates of the camera with a mouse-positionable camera 37 | * Adjust the z coordinate of the camera with the mouse wheel. 38 | * Adjust the x,y coordinate of the camera with the keyboard(hjkl, HJKL). 39 | * Alternatively, each value can be adjusted with the keyboard without going back to the original script. 40 | * Add, delete, and edit keyframes on a timeline. 41 | * After setting up a scene with the desired look and animations, the Action 42 | Editor will generate a script and place it on your clipboard for pasting 43 | into your Ren'Py scripts. (v6.99 and later only) 44 | * Supported the concept of depth of field using blur after v7.40(gl2 or ANGLE2 is required). 45 | 1pixel blur is used where the distance from the focus position is dof. 46 | DOF is used to adjust the sharp range. Focus is used to adjust the focus position. 47 | You can adjust dof config in camera_config.rpy 48 | 49 | Image Viewer 50 | ================ 51 | 52 | Press Shift+U to open Image Viewer and view all currently generated displayables. 53 | 54 | 55 | Camera 56 | ================ 57 | 58 | With some limitations, Ren'Py can simulate 3D camera motion. This will 59 | let you achieve a parallax effect by placing sprites and assets on a 3D field. 60 | This script works by applying ATL transforms to all displayables on 3D layers 61 | in a manner that respects distance from a virtual camera. 62 | 63 | To start using the 3D camera, set additional layers to be registered 64 | as 3D layers. If no layers are registered as 3D layers, this script will 65 | register the default `master` layer as a 3D layer. 66 | 67 | To get started, add the layers you need. For example, add the following to 68 | options.rpy to add `background`, `middle`, and `forward` as regular 2D layers: 69 | 70 | config.layers = ['master', 'background', 'middle', 'forward', 'transient', 'screens', 'overlay'] 71 | 72 | Second, register any layers that you want to respect 3D motion as 3d layers by using 73 | :func:`register_3d_layer`. The z coordinates of these layers can be moved and 74 | can have their positions and transforms affected by the camera. If no layers 75 | are registered as 3D layers, the default `master` layer becomes the sole 3D 76 | layer: 77 | 78 | init python: 79 | register_3d_layer('background', 'middle', 'forward') 80 | 81 | This sample script should give an idea of how the system works: 82 | 83 | label start: 84 | # Resets the camera and layers positions 85 | $ camera_reset() 86 | # Instantly sets layer distances from the camera 87 | $ layer_move("background", 2000) 88 | $ layer_move("middle", 1500) 89 | $ layer_move("forward", 1000) 90 | scene bg onlayer background 91 | # WARNING: The 'scene' command will reset the depth of whatever layer the image 92 | # is displayed on. Make sure you reset the depth after you call the 'scene' command. 93 | $ layer_move("background", 2000) 94 | show A onlayer middle 95 | show B onlayer forward 96 | with dissolve 97 | "Moves the camera to (1800, 0, 0) in 1 second." 98 | $ camera_move(1800, 0, 0, 0, 1) 99 | "Moves the camera to (0, 0, 1600) in 5 seconds." 100 | $ camera_move(0, 0, 1600, 0, 5) 101 | "Moves the camera to (0, 0, 0) instantaneously." 102 | $ camera_move(0, 0, 0) 103 | "Rotates the camera 180 degrees in 1 second."" 104 | $ camera_move(0, 0, 0, 180, 1) 105 | 'Rotates the camera -180 degrees in 1 second and subsequently moves the camera to (-1800, 0, 500) in 1.5 seconds' 106 | $ camera_moves( ( (0, 0, 0, 0, 1, 'linear'), (-1800, 0, 500, 0, 1.5, 'linear') ) ) 107 | 'Continually moves the camera between (-1800, 0, 500) and (0, 0, 0), taking 0.5 seconds for the first move and 1 second for the second until the action is interrupted.' 108 | $ camera_moves( ( (0, 0, 0, 0, .5, 'linear'), (-1800, 0, 500, 0, 1, 'linear') ), loop=True) 109 | 110 | There are some limitations to the 3D camera: 111 | 112 | * Only rotations perpindicular to the camera (Z rotations) can be performed due to the 3D camera relying 113 | on Ren'Py's existing transform system. 114 | 115 | * 3D camera motion applies its own transforms to 3D layers, so the `show layer` statement or 116 | :func:`renpy.show_layer_at` can't be used with registered 3D layers. 117 | 118 | * Layers still stack in the order they are registered, regardless of what their z coordinates are. In our above example, `background` will always be below the other layers because it was registered first, even if its z coordinate was at `0` and the `forward` layer's z coordinate was at `1000`. 119 | 120 | * `camera_move`, `camera_moves`, `layer_move`, `layer_moves`, and `all_moves` can't play 121 | simultaneously within the same interaction. If multiple camera actions are called in the same interaction, 122 | only the last one will play out and earlier actions will be done instantenously before the last action is played. 123 | 124 | * DOF is simulated using blur for layers, so note the back layer is often seen through the front layer. 125 | 126 | * By default, the `scene` and `hide` statements use the `master` layer or a specified layer. 127 | If you use 3D layers preferentially, write code like below: 128 | 129 | 130 | init -1 python hide: 131 | def hide(name, layer='master'): 132 | for l in _3d_layers: 133 | if renpy.showing(name, l): 134 | renpy.hide(name, l) 135 | break 136 | else: 137 | renpy.hide(name, layer) 138 | 139 | config.hide = hide 140 | 141 | def scene(layer='master'): 142 | 143 | renpy.scene(layer) 144 | for l in _3d_layers: 145 | renpy.scene(l) 146 | 147 | config.scene = scene 148 | 149 | Camera Functions 150 | ---------------- 151 | 152 | def register_3d_layer(*layers): 153 | """ 154 | :doc: camera 155 | 156 | Register layers as 3D layers. Only 3D layers will be affected by camera 157 | movement and 3D layer transforms. This should be called in an init 158 | block. If no layers are registered as 3D layers, the 'master' layer 159 | will become a 3D layer by default. 160 | 161 | `layers` 162 | This should be a string or a group of strings naming registered layers. 163 | """ 164 | 165 | def camera_reset(): 166 | """ 167 | :doc: camera 168 | 169 | Resets the camera, 3D layers positions and the focus position, the depth of field. 170 | """ 171 | 172 | def camera_restore(): 173 | """ 174 | :doc: camera 175 | 176 | Safety method used internally to deal with unexpected camera behavior. 177 | 178 | """ 179 | 180 | def camera_move(x, y, z, rotate=0, duration=0, warper='linear', subpixel=True, loop=False, x_express=None, y_express=None, z_express=None, rotate_express=None, **kwargs): 181 | """ 182 | :doc: camera 183 | 184 | Moves the camera to a given coordinate and rotation. 185 | 186 | `x` 187 | The x coordinate to move the camera to. 188 | `y` 189 | The y coordinate to move the camera to. 190 | `z` 191 | The z coordinate to move the camera to. 192 | `rotate` 193 | Rotation of the camera, perpindicular to the scene, in degrees. 194 | `duration` 195 | The time, in seconds, to complete the camera move. If no time is given, 196 | the move will happen instantaneously. 197 | `warper` 198 | A string that points to a registered ATL warper, like \'ease\'. 199 | If no warper is given, this will default to \'linear\'. 200 | `subpixel` 201 | If True, transforms caused by the 3D camera will be rendered with 202 | subpixel precision. This defaults to True. 203 | `loop` 204 | If true, the camera move will continually loop until another camera 205 | action interrupts. This defaults to False. 206 | `x_express` 207 | This should be a callable function that is called with the shown 208 | timebase and is given an animation timebase in seconds. The 209 | result of this function is added to the x coordinate of the camera. 210 | `y_express` 211 | This should be a callable function that is called with the shown 212 | timebase and is given an animation timebase in seconds. The 213 | result of this function is added to the y coordinate of the camera. 214 | `z_express` 215 | This should be a callable function that is called with the shown 216 | timebase and is given an animation timebase in seconds. The 217 | result of this function is added to the z coordinate of the camera. 218 | `rotate_express` 219 | This should be a callable function that is called with the shown 220 | timebase and is given an animation timebase in seconds. The 221 | result of this function is added to the rotation value of the camera. 222 | `_express` 223 | This should be a callable function that is called with the shown 224 | timebase and is given an animation timebase in seconds. The 225 | result of this function is added to the coordinate of the given layer. 226 | """ 227 | 228 | def camera_relative_move(x, y, z, rotate=0, duration=0, warper='linear', subpixel=True, loop=False, x_express=None, y_express=None, z_express=None, rotate_express=None, **kwargs): 229 | """ 230 | :doc: camera 231 | 232 | Move the coordinate and rotate of a camera relatively and apply transforms to all 3D layers. 233 | 234 | `x` 235 | the x coordinate of a camera relative to the current one. 236 | `y` 237 | the y coordinate of a camera relative to the current one. 238 | `z` 239 | the z coordinate of a camera relative to the current one. 240 | `rotate` 241 | Defaul 0, the rotate of a camera relative to the current one. 242 | `duration` 243 | Default 0, this is the second times taken to move a camera. 244 | `warper` 245 | Default 'linear', this should be string and the name of a warper 246 | registered with ATL. 247 | `subpixel` 248 | Default True, if True, causes things to be drawn on the screen 249 | using subpixel positioning 250 | `loop` 251 | Default False, if True, this motion repeats. 252 | 'x_express' 253 | This should be callable, which is called with the shown timebase 254 | and the animation timebase, in seconds and return a number. The 255 | result of this is added to the x coordinate of the camera. 256 | 'y_express' 257 | This should be callable, which is called with the shown timebase 258 | and the animation timebase, in seconds and return a number. The 259 | result of this is added to the y coordinate of the camera. 260 | 'z_express' 261 | This should be callable, which is called with the shown timebase 262 | and the animation timebase, in seconds and return a number. The 263 | result of this is added to the z coordinate of the camera. 264 | 'rotate_express' 265 | This should be callable, which is called with the shown timebase 266 | and the animation timebase, in seconds and return a number. The 267 | result of this is added to the rotate coordinate of the camera. 268 | `_express` 269 | This should be a callable function that is called with the shown 270 | timebase and is given an animation timebase in seconds. The 271 | result of this function is added to the coordinate of the given layer. 272 | """ 273 | 274 | def layer_move(layer, z, duration=0, warper='linear', subpixel=True, loop=False, x_express=None, y_express=None, z_express=None, rotate_express=None, layer_express=None): 275 | """ 276 | :doc: camera 277 | 278 | Moves the z coordinate of a layer and applies a transform to the layer. 279 | 280 | `layer` 281 | A string that names a registered 3D layer to be moved. 282 | `z` 283 | The z coordinate to move the 3D layer to. 284 | `duration` 285 | The time, in seconds, to complete the layer move. If no time is given, 286 | the move will happen instantaneously. 287 | `warper` 288 | A string that points to a registered ATL warper, like \'ease\'. 289 | If no warper is given, this will default to \'linear\'. 290 | `subpixel` 291 | If True, the resulting layer move will be rendered with 292 | subpixel precision. This defaults to True. 293 | `loop` 294 | If true, the layer move will continually loop until another camera 295 | action interrupts. This defaults to False. 296 | `x_express` 297 | This should be a callable function that is called with the shown 298 | timebase and is given an animation timebase in seconds. The 299 | result of this function is added to the x coordinate of the camera. 300 | `y_express` 301 | This should be a callable function that is called with the shown 302 | timebase and is given an animation timebase in seconds. The 303 | result of this function is added to the y coordinate of the camera. 304 | `z_express` 305 | This should be a callable function that is called with the shown 306 | timebase and is given an animation timebase in seconds. The 307 | result of this function is added to the z coordinate of the camera. 308 | `rotate_express` 309 | This should be a callable function that is called with the shown 310 | timebase and is given an animation timebase in seconds. The 311 | result of this function is added to the rotation value of the camera. 312 | `layer_express` 313 | This should be a callable function that is called with the shown 314 | timebase and is given an animation timebase in seconds. The 315 | result of this function is added to the coordinate of the layer. 316 | """ 317 | 318 | def camera_moves(check_points, loop=False, subpixel=True, x_express=None, y_express=None, z_express=None, rotate_express=None, spline=False, **kwargs): 319 | """ 320 | :doc: camera 321 | 322 | Allows multiple camera moves to happen in succession. 323 | 324 | `check_points` 325 | A list of camera moves, in the format of (x, y, z, rotate, duration, warper) 326 | `loop` 327 | If true, the camera moves will continually loop until another camera 328 | action interrupts. This defaults to False. 329 | `subpixel` 330 | If True, transforms caused by the 3D camera will be rendered with 331 | subpixel precision. This defaults to True. 332 | `x_express` 333 | This should be a callable function that is called with the shown 334 | timebase and is given an animation timebase in seconds. The 335 | result of this function is added to the x coordinate of the camera. 336 | `y_express` 337 | This should be a callable function that is called with the shown 338 | timebase and is given an animation timebase in seconds. The 339 | result of this function is added to the y coordinate of the camera. 340 | `z_express` 341 | This should be a callable function that is called with the shown 342 | timebase and is given an animation timebase in seconds. The 343 | result of this function is added to the z coordinate of the camera. 344 | `rotate_express` 345 | This should be a callable function that is called with the shown 346 | timebase and is given an animation timebase in seconds. The 347 | result of this function is added to the rotation value of the camera. 348 | `_express` 349 | This should be a callable function that is called with the shown 350 | timebase and is given an animation timebase in seconds. The 351 | result of this function is added to the coordinate of the given layer. 352 | `spline` 353 | Enable spline interpolation for the coordinates of the camera. If this is True, warpers are ignored. This defaults to False. 354 | """ 355 | 356 | def camera_relative_moves(relative_check_points, loop=False, subpixel=True, x_express=None, y_express=None, z_express=None, rotate_express=None, spline=False, **kwargs): 357 | """ 358 | :doc: camera 359 | 360 | Allows relative multiple camera moves to happen in succession. 361 | 362 | `relative_check_points` 363 | A list of camera moves, in the format of (x, y, z, rotate, duration, warper) 364 | `loop` 365 | If true, the camera moves will continually loop until another camera 366 | action interrupts. This defaults to False. 367 | `subpixel` 368 | If True, transforms caused by the 3D camera will be rendered with 369 | subpixel precision. This defaults to True. 370 | `x_express` 371 | This should be a callable function that is called with the shown 372 | timebase and is given an animation timebase in seconds. The 373 | result of this function is added to the x coordinate of the camera. 374 | `y_express` 375 | This should be a callable function that is called with the shown 376 | timebase and is given an animation timebase in seconds. The 377 | result of this function is added to the y coordinate of the camera. 378 | `z_express` 379 | This should be a callable function that is called with the shown 380 | timebase and is given an animation timebase in seconds. The 381 | result of this function is added to the z coordinate of the camera. 382 | `rotate_express` 383 | This should be a callable function that is called with the shown 384 | timebase and is given an animation timebase in seconds. The 385 | result of this function is added to the rotation value of the camera. 386 | `_express` 387 | This should be a callable function that is called with the shown 388 | timebase and is given an animation timebase in seconds. The 389 | result of this function is added to the coordinate of the given layer. 390 | `spline` 391 | Enable spline interpolation for the coordinates of the camera. If this is True, warpers are ignored. This defaults to False. 392 | """ 393 | 394 | def layer_moves(layer, check_points, loop=False, subpixel=True, x_express=None, y_express=None, z_express=None, rotate_express=None, layer_express=None, spline=False): 395 | """ 396 | :doc: camera 397 | 398 | Move a layer through check points and apply transform to the layer. 399 | 400 | `layer` 401 | A string that names a registered 3D layer to be moved. 402 | `check_points` 403 | A list of layer moves, in the format of (z, duration, warper) 404 | `loop` 405 | If true, the layer moves will continually loop until another camera 406 | action interrupts. This defaults to False. 407 | `subpixel` 408 | If True, the resulting layer moves will be rendered with 409 | subpixel precision. This defaults to True. 410 | `layer_express` 411 | This should be a callable function that is called with the shown 412 | timebase and is given an animation timebase in seconds. The 413 | result of this function is added to the coordinate of the layer. 414 | `x_express` 415 | This should be a callable function that is called with the shown 416 | timebase and is given an animation timebase in seconds. The 417 | result of this function is added to the x coordinate of the camera. 418 | `y_express` 419 | This should be a callable function that is called with the shown 420 | timebase and is given an animation timebase in seconds. The 421 | result of this function is added to the y coordinate of the camera. 422 | `z_express` 423 | This should be a callable function that is called with the shown 424 | timebase and is given an animation timebase in seconds. The 425 | result of this function is added to the z coordinate of the camera. 426 | `rotate_express` 427 | This should be a callable function that is called with the shown 428 | timebase and is given an animation timebase in seconds. The 429 | result of this function is added to the rotation value of the camera. 430 | `spline` 431 | Enable spline interpolation for the coordinates of the layer. If this is True, warpers are ignored. This defaults to False. 432 | """ 433 | 434 | def focus_set(focus, duration=0, warper='linear', **kwargs): 435 | """ 436 | :doc: camera 437 | 438 | Set the focus position. 439 | 440 | `focus` 441 | `focus` decides the focus position. It is the z coordinate which is sum of this value and 442 | the z coordinate of camera. 443 | `duration` 444 | The time, in seconds, to complete the focus change. If no time is given, 445 | the change will happen instantaneously. 446 | `warper` 447 | A string that points to a registered ATL warper, like \'ease\'. 448 | If no warper is given, this will default to \'linear\'. 449 | """ 450 | 451 | def dof_set(dof, duration=0, warper='linear', **kwargs): 452 | """ 453 | :doc: camera 454 | 455 | Set the depth of field. 456 | 457 | `dof` 458 | `dof` is the z range where layers aren't blured. it defaults to 9999999. 459 | `duration` 460 | The time, in seconds, to complete the dof change. If no time is given, 461 | the change will happen instantaneously. 462 | `warper` 463 | A string that points to a registered ATL warper, like \'ease\'. 464 | If no warper is given, this will default to \'linear\'. 465 | """ 466 | 467 | def all_moves(camera_check_points=None, layer_check_points=None, focus_check_points=None, subpixel=True, play=True, x_loop=False, y_loop=False, z_loop=False, rotate_loop=False, x_express=None, y_express=None, z_express=None, rotate_express=None, camera_spline=False, **kwargs): 468 | """ 469 | :doc: camera 470 | 471 | Allows for both camera moves and layer moves to happen within the same interaction, in any given combination. The Action Editor will usually generate these. 472 | 473 | `camera_check_points` 474 | A list of check points for the camera to go through, split by coordinate in the following format: 475 | { 476 | 'x':[(x, duration, warper)...] 477 | 'y':[(y, duration, warper)...] 478 | 'z':[(z, duration, warper)...] 479 | 'rotate':[(rotate, duration, warper)...] 480 | } 481 | `layer_check_points` 482 | A list of check points for layers to go through, in the following format: 483 | { 484 | 'layer name':[(z, duration, warper)...] 485 | } 486 | `focus_check_points` 487 | A list of check points for the depth of field & the focus position, 488 | in the following format: 489 | { 490 | 'focus':[(z, duration, warper)...] 491 | 'dof':[(dof, duration, warper)...] 492 | } 493 | `dof` is the z range where layers aren't blured. it defaults to 9999999. 494 | `focus` decides the focus position. It is the z coordinate which is sum of this value and 495 | the z coordinate of camera. 496 | `x_loop` 497 | If True, all x coordinate check points will loop continuously. This defaults to False. 498 | `y_loop` 499 | If True, all y coordinate check points will loop continuously. This defaults to False. 500 | `z_loop` 501 | If True, all z coordinate check points will loop continuously. This defaults to False. 502 | `rotate_loop` 503 | If True, all rotation check points will loop continuously. This defaults to False. 504 | `subpixel` 505 | If True, all transforms caused by this function will be drawn with subpixel precision. This defaults to True. 506 | `_loop` 507 | If True, all layer move check points for the given layer will loop continuously. This defaults to False. 508 | `x_express` 509 | This should be a callable function that is called with the shown 510 | timebase and is given an animation timebase in seconds. The 511 | result of this function is added to the x coordinate of the camera. 512 | `y_express` 513 | This should be a callable function that is called with the shown 514 | timebase and is given an animation timebase in seconds. The 515 | result of this function is added to the y coordinate of the camera. 516 | `z_express` 517 | This should be a callable function that is called with the shown 518 | timebase and is given an animation timebase in seconds. The 519 | result of this function is added to the z coordinate of the camera. 520 | `rotate_express` 521 | This should be a callable function that is called with the shown 522 | timebase and is given an animation timebase in seconds. The 523 | result of this function is added to the rotation value of the camera. 524 | `_express` 525 | This should be a callable function that is called with the shown 526 | timebase and is given an animation timebase in seconds. The 527 | result of this function is added to the coordinate of the given layer. 528 | `camera_spline` 529 | Enable spline interpolation for the coordinates of the camera. If this is True, warpers are ignored. This defaults to False. 530 | `_spline` 531 | Enable spline interpolation for the coordinates of the given layer. If this is True, warpers are ignored. This defaults to False. 532 | """ 533 | 534 | 535 | このスクリプトはRen'Pyに擬似的な3Dカメラ機能及びとそれをGUI上で設定する演出エディター、さらに画像ビューワー、便利なワーパー関数を追加します。フォルダ内のファイルをgameフォルダにコピーしてください。 536 | 537 | 538 | 演出エディター 539 | ================ 540 | 541 | 演出エディターでは変換プロパティーやカメラ、レイヤーの座標設定をGUI上で変更し、 542 | 結果を確認できます。さらにそれらの値を時間軸に沿って変更可能なので、スクリプト 543 | を変更するたびに、リロードで結果を確認する従来の方法より遥かに短時間で動的演出 544 | を作成可能です。設定した値はクリップボードに送られ、スクリプトに貼り付けられま 545 | す。 546 | 547 | config.developer が True なら、Shift+Pで演出エディターが起動します。 548 | 549 | 演出エディターでは以下の機能が利用可能です。: 550 | 551 | * 各画像の変換プロパティーやカメラ、レイヤー座標を直接入力またはバーの操作により変更 552 | * 数値を右クリックでリセット 553 | * カメラアイコンのドラッグまたはマウスホイール、キーボード(hjkl,HJKL)によるカメラ移動 554 | * 動画編集ソフトの様にキーフレームを設定して時間軸にそった演出を作成 555 | * 作成した演出のコードをクリップボードに送る(v6.99以上, Windows限定) 556 | * v7.40以降ではブラー機能を流用して擬似的に被写界深度(dof)の概念を導入しています 557 | (gl2またはAngle2の有効化が必要です) 558 | カメラからフォーカス分前方の位置からDOF離れた位置で1ピクセルのブラーが発生します。 559 | DOFの数値でピントの合う範囲、Focusでピント位置を調整できます。 560 | camera_config.rpyで細かい挙動を調整できます。 561 | 562 | 563 | イメージビューワー 564 | ================ 565 | 定義された画像を画像タグ、属性から縛り込んで表示します。 566 | 567 | config.developer が True なら、Shift+Uで起動します。 568 | 569 | カメラ 570 | ================ 571 | 572 | 三次元を再現する関数群をRen'Py に追加します。これらは3Dレイヤーに登録された各レ 573 | イヤーにz座標を与え、カメラとの位置関係により拡大縮小移動させて三次元をシ 574 | ミュレートします。これにより奥行きの表現が簡単に可能になります。この機能を 575 | 利用するには、先ず3Dレイヤーに登録するレイヤーを追加しなければなりません。3Dレ 576 | イヤーに何も登録されていない場合、デフォルトで"master"レイヤーのみが3Dレイ 577 | ヤーに登録されます。 578 | 579 | 例 580 | 581 | options.rpy に3Dレイヤーにしたいレイヤーを追加します。例えば 'background', 'middle', 'forward' レイヤーを以下のように設定に追加します。 582 | 583 | config.layers = [ 'master', 'background', 'middle', 'forward', 'transient', 'screens', 'overlay'] 584 | 585 | 次に register_3d_layer 関数で3Dレイヤーを登録します。登録したレイヤーはz座標を移動出来、カメラの影響を受けます。register_3d_layerが使用されないと、デフォルトで"master"レイヤーが登録されます。 586 | 587 | init python: 588 | register_3d_layer( 'background', 'middle', 'forward',) 589 | 590 | 以上の設定で、ゲーム中でカメラを動かすと3Dレイヤーが三次元を再現するように動作します。 591 | 592 | label start: 593 | # カメラ、レイヤー位置をリセット 594 | $ camera_reset() 595 | # 0秒でレイヤーz座標を変更します。 596 | $ layer_move("background", 2000) 597 | $ layer_move("middle", 1500) 598 | $ layer_move("forward", 1000) 599 | scene bg onlayer background 600 | # 注意: 'scene' ステートメントは画像が表示されるだけでなく、その画像が表示されるレイヤーの状態もリセットします。 601 | # 問題が発生する場合はsceneステートメント後にlayer_move関数でレイヤー位置を再設定してください。 602 | show A onlayer middle 603 | show B onlayer forward 604 | with dissolve 605 | '1秒でカメラを(0, 130, 0)まで移動させます。' 606 | $ camera_move(0, 130, 0, 0, 1) 607 | '5秒でカメラを(-70, 130, 1000)まで移動させます。' 608 | $ camera_move(-70, 130, 1000, 0, 5) 609 | '0秒かけてカメラを(0, 0, 0)まで移動させます。' 610 | $ camera_move(0, 0, 0) 611 | '1秒かけてカメラを時計回りに180度回転します。' 612 | $ camera_move(0, 0, 0, 180, 1) 613 | '1秒かけてカメラを反時計回りに180度回転させ、4秒かけてカメラを(100, 100, 100)まで移動させます。' 614 | $ camera_moves( ( (0, 0, 0, 0, 1, 'linear'), (100, 100, 100, 0, 5, 'linear') ) ) 615 | 'カメラが(100, 100, 100)から(0, 0, 0)までを繰り返し往復します' 616 | $ camera_moves( ( (0, 0, 0, 0, 1, 'linear'), (100, 100, 100, 0, 2, 'linear') ), loop=True) 617 | 618 | カメラ機能にはいくつかの制限があることに注意してください。 619 | 620 | * カメラモーションは3Dレイヤーに対して変換を適用して再現しているため、3Dレイヤーに対して show layer ステートメントや renpy.show_layer_at 関数は使用出来ません。 621 | * レイヤーの重なり順はレイヤーのz座標を反映しません。 622 | * camera_move, camera_moves, layer_move, layer_moves, all_moves はそれぞれ排他的です。ひとつのインタラクション中に複数回呼び出されると、最後に呼び出されたもののみが正常に動作し、それ以外は瞬時に移動します。 623 | * 被写界深度はレイヤー毎のブラーを流用しているため、本物のブラーと違い裏側が透けて見えることがあります。 624 | 625 | * デフォルトではRen'Pyの scene, show, hide ステートメントは master レイヤー又は指定されたレイヤーにのみ作用します。3Dレイヤーに対して優先的に作用させたい場合は以下のようにしてRen'Pyの設定を変更してください。 626 | 627 | init -1 python hide: 628 | 629 | def hide(name, layer='master'): 630 | for l in _3d_layers: 631 | if renpy.showing(name, l): 632 | renpy.hide(name, l) 633 | else: 634 | renpy.hide(name, layer) 635 | 636 | config.hide = hide 637 | 638 | def scene(layer='master'): 639 | 640 | renpy.scene(layer) 641 | for l in _3d_layers: 642 | renpy.scene(l) 643 | 644 | config.scene = scene 645 | 646 | カメラ関数 647 | ---------------- 648 | 649 | def register_3d_layer(*layers): 650 | """ 651 | :doc: camera 652 | 653 | レイヤーを3Dレイヤーとして登録します。3Dレイヤーに登録されたレイヤー 654 | には、そのz座標とカメラの位置に基づいた変換が適用されます。initブ 655 | ロックで一度だけ呼び出してください。3Dレイヤーになにも登録されていな 656 | い場合、"master"レイヤーを3Dレイヤーに登録します。 657 | 658 | `layers` 659 | 3Dレイヤーに登録する、一つ以上のレイヤー名の文字列です。 660 | """ 661 | 662 | def camera_reset(): 663 | """ 664 | :doc: camera 665 | 666 | カメラとレイヤー,フォーカス位置、被写界深度を初期値に戻します。 667 | """ 668 | 669 | def camera_restore(): 670 | """ 671 | :doc: camera 672 | 673 | カメラとレイヤーを現在設定されている位置に戻します。 674 | sceneステートメントや、show layerステートメントで画像位置が狂ったときの修正ようです。 675 | """ 676 | 677 | def camera_move(x, y, z, rotate=0, duration=0, warper='linear', subpixel=True, loop=False, x_express=None, y_express=None, z_express=None, rotate_express=None, **kwargs): 678 | """ 679 | :doc: camera 680 | 681 | カメラの座標と角度を指定の時間かけて変更します。 682 | 683 | `x` 684 | カメラのx座標の数字です。 685 | `y` 686 | カメラのy座標の数字です。 687 | `z` 688 | カメラのy座標の数字です。 689 | `rotate` 690 | デフォルトは0で、カメラの傾きの数字です。 691 | `duration` 692 | デフォルトは0で、カメラ移動にかかる時間の秒数です。 693 | `loop` 694 | デフォルトは Falseで、True ならこのモーションが繰り替えされます。 695 | `warper` 696 | デフォルトは'linear'で, 時間補間に使用する関数名の文字列です。こ 697 | れにはATLに登録された時間補間関数が指定出来ます。 698 | `subpixel` 699 | デフォルトは Trueで、 True なら、1 pixel 以下の値を使用して画面 700 | に描画します。 701 | 'x_express' 702 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 703 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 704 | x座標に加えられます。 705 | 'y_express' 706 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 707 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 708 | y座標に加えられます。 709 | 'z_express' 710 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 711 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 712 | z座標に加えられます。 713 | 'rotate_express' 714 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 715 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 716 | rotate座標に加えられます。 717 | `_express` 718 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時 719 | 間軸の秒数を引数に呼び出され、数字を返します。この結果は指定 720 | したレイヤーの座標に加えられます。 721 | """ 722 | 723 | def camera_relative_move(x, y, z, rotate=0, duration=0, warper='linear', subpixel=True, loop=False, x_express=None, y_express=None, z_express=None, rotate_express=None, **kwargs): 724 | """ 725 | :doc: camera 726 | 727 | カメラの座標と角度を指定の時間かけて変更します。 728 | 729 | `x` 730 | 現在の座標に対して相対的なカメラのx座標の数字です。 731 | `y` 732 | 現在の座標に対して相対的なカメラのy座標の数字です。 733 | `z` 734 | 現在の座標に対して相対的なカメラのy座標の数字です。 735 | `rotate` 736 | デフォルトは0で、現在の角度に対して相対的なカメラの傾きの数字です。 737 | `duration` 738 | デフォルトは0で、カメラ移動にかかる時間の秒数です。 739 | `loop` 740 | デフォルトは Falseで、True ならこのモーションが繰り替えされます。 741 | `warper` 742 | デフォルトは'linear'で, 時間補間に使用する関数名の文字列です。こ 743 | れにはATLに登録された時間補間関数が指定出来ます。 744 | `subpixel` 745 | デフォルトは Trueで、 True なら、1 pixel 以下の値を使用して画面 746 | に描画します。 747 | 'x_express' 748 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 749 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 750 | x座標に加えられます。 751 | 'y_express' 752 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 753 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 754 | y座標に加えられます。 755 | 'z_express' 756 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 757 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 758 | z座標に加えられます。 759 | 'rotate_express' 760 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 761 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 762 | rotate座標に加えられます。 763 | `_express` 764 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時 765 | 間軸の秒数を引数に呼び出され、数字を返します。この結果は指定 766 | したレイヤーの座標に加えられます。 767 | """ 768 | 769 | def camera_moves(check_points, loop=False, subpixel=True, x_express=None, y_express=None, z_express=None, rotate_express=None, spline=False, **kwargs): 770 | """ 771 | :doc: camera 772 | 773 | 1つ以上のチェックポイントを通ってカメラを動かします。 774 | 775 | `check_points` 776 | カメラのx,y,z座標、傾き、カメラの移動開始からその位置に到達 777 | するまでの秒数、その間の時間補間関数名の文字列からなるタプル 778 | のリストです。カメラはここで指定された各タプルを順番に移動す 779 | るので、タプルは時系列に沿って並べてください。 780 | `loop` 781 | デフォルトは Falseで、True ならこのモーションが繰り替えされます。 782 | `subpixel` 783 | デフォルトは Trueで、 True なら、1 pixel 以下の値を使用して画面 784 | に描画します。 785 | 'x_express' 786 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 787 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 788 | x座標に加えられます。 789 | 'y_express' 790 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 791 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 792 | y座標に加えられます。 793 | 'z_express' 794 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 795 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 796 | z座標に加えられます。 797 | 'rotate_express' 798 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 799 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 800 | rotate座標に加えられます。 801 | `_express` 802 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時 803 | 間軸の秒数を引数に呼び出され、数字を返します。この結果は指定 804 | したレイヤーの座標に加えられます。 805 | `spline` 806 | カメラの座標に対してスプライン補間を有効にします。True ならワーパーは無視されます。これはデフォルトでFalseです。 807 | """ 808 | 809 | def camera_relative_move(relative_check_points, loop=False, subpixel=True, x_express=None, y_express=None, z_express=None, rotate_express=None, spline=False, **kwargs): 810 | """ 811 | :doc: camera 812 | 813 | 1つ以上のチェックポイントを通ってカメラを動かします。 814 | 815 | `relative_check_points` 816 | 現在地に対する相対的なカメラのx,y,z座標、傾きおよびカメラの 817 | 移動開始からその位置に到達するまでの秒数、その間の時間補間関 818 | 数名の文字列からなるタプルのリストです。カメラはここで指定さ 819 | れた各タプルを順番に移動するので、タプルは時系列に沿って並べ 820 | てください。 821 | `loop` 822 | デフォルトは Falseで、True ならこのモーションが繰り替えされます。 823 | `subpixel` 824 | デフォルトは Trueで、 True なら、1 pixel 以下の値を使用して画面 825 | に描画します。 826 | 'x_express' 827 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 828 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 829 | x座標に加えられます。 830 | 'y_express' 831 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 832 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 833 | y座標に加えられます。 834 | 'z_express' 835 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 836 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 837 | z座標に加えられます。 838 | 'rotate_express' 839 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 840 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 841 | rotate座標に加えられます。 842 | `_express` 843 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時 844 | 間軸の秒数を引数に呼び出され、数字を返します。この結果は指定 845 | したレイヤーの座標に加えられます。 846 | `spline` 847 | カメラの座標に対してスプライン補間を有効にします。True ならワーパーは無視されます。これはデフォルトでFalseです。 848 | """ 849 | 850 | def layer_move(layer, z, duration=0, warper='linear', subpixel=True, loop=False, x_express=None, y_express=None, z_express=None, rotate_express=None, layer_express=None): 851 | """ 852 | :doc: camera 853 | 854 | 3Dレイヤーのz座標を指定の時間かけて変更します。 855 | 856 | `layer` 857 | 移動するレイヤー名の文字列です。 858 | `z` 859 | レイヤーのz座標の数字です。 860 | `duration` 861 | デフォルトは0で、レイヤー移動にかかる時間の秒数です。 862 | `warper` 863 | デフォルトは'linear'で, 時間補間に使用する関数名の文字列です。こ 864 | れにはATLに登録された時間補間関数が指定出来ます。 865 | `subpixel` 866 | デフォルトは Trueで、 True なら、1 pixel 以下の値を使用して画面 867 | に描画します。 868 | `loop` 869 | デフォルトは Falseで、True ならこのモーションが繰り替えされます。 870 | `layer_express` 871 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時 872 | 間軸の秒数を引数に呼び出され、数字を返します。この結果はレイ 873 | ヤーの座標に加えられます。 874 | 'x_express' 875 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 876 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 877 | x座標に加えられます。 878 | 'y_express' 879 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 880 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 881 | y座標に加えられます。 882 | 'z_express' 883 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 884 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 885 | z座標に加えられます。 886 | 'rotate_express' 887 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 888 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 889 | rotate座標に加えられます。 890 | `_express` 891 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時 892 | 間軸の秒数を引数に呼び出され、数字を返します。この結果は指定 893 | したレイヤーの座標に加えられます。 894 | `spline` 895 | レイヤーの座標に対してスプライン補間を有効にします。True ならワーパーは無視されます。これはデフォルトでFalseです。 896 | """ 897 | 898 | def layer_moves(layer, check_points, loop=False, subpixel=True, x_express=None, y_express=None, z_express=None, rotate_express=None, layer_express=None, spline=False): 899 | """ 900 | :doc: camera 901 | 902 | 1つ以上のチェックポイントを通って3Dレイヤーを動かします。 903 | 904 | `layer` 905 | 移動するレイヤー名の文字列です。 906 | `check_points` 907 | レイヤーのz座標の数字、レイヤーの移動開始からその位置に到達するまでの 908 | 秒数の数字、その間の時間補間関数の文字列からなるタプルのlistです。 909 | レイヤーはここで指定された各タプルを順番に移動するので、タプル 910 | は時系列に沿って並べてください。 911 | `loop` 912 | デフォルトは Falseで、True ならこのモーションが繰り替えされます。 913 | `subpixel` 914 | デフォルトは Trueで、 True なら、1 pixel 以下の値を使用して画面 915 | に描画します。 916 | `layer_express` 917 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時 918 | 間軸の秒数を引数に呼び出され、数字を返します。この結果はレイ 919 | ヤーの座標に加えられます。 920 | 'x_express' 921 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 922 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 923 | x座標に加えられます。 924 | 'y_express' 925 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 926 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 927 | y座標に加えられます。 928 | 'z_express' 929 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 930 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 931 | z座標に加えられます。 932 | 'rotate_express' 933 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 934 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 935 | rotate座標に加えられます。 936 | `spline` 937 | レイヤーの座標に対してスプライン補間を有効にします。True ならワーパーは無視されます。これはデフォルトでFalseです。 938 | """ 939 | 940 | def dof_set(dof, duration=0, warper='linear', **kwargs): 941 | """ 942 | :doc: camera 943 | 944 | 被写界深度を設定します。 945 | 946 | `dof` 947 | `dof` はlayerにブラーがかからないz値の範囲で、デフォルトで9999999です 948 | `duration` 949 | dof の変化が完了するのにかかる秒数です。時間を指定しなけれあば、 950 | 瞬時に変化します。 951 | `warper` 952 | \'ease\' のような登録された ATL warper も文字列です。 953 | 指定されなければデフォルトで \'linear\' です。 954 | """ 955 | 956 | def all_moves(camera_check_points=None, layer_check_points=None, subpixel=True, play=True, x_loop=False, y_loop=False, z_loop=False, rotate_loop=False, x_express=None, y_express=None, z_express=None, rotate_express=None, camera_spline=False, **kwargs): 957 | """ 958 | :doc: camera 959 | 960 | 1つ以上のチェックポイントを通ってカメラと3Dレイヤーを同時に動かします。 961 | 962 | `camera_check_points` 963 | カメラの各パラメーター名の文字列をキーとし、その値、その値に 964 | なるまでの秒数、その間の時間補間関数名の文字列からなるタプル 965 | のリストを値に持つ辞書です。カメラはここで指定された各タプル 966 | を順番に移動するので、タプルは時系列に沿って並べてください。 967 | { 968 | 'x':[(x, duration, warper)...], 969 | 'y':[(y, duration, warper)...], 970 | 'z':[(z, duration, warper)...], 971 | 'rotate':[(rotate, duration, warper)...], 972 | } 973 | `layer_check_points` 974 | 移動するレイヤー名の文字列をキーとし、レイヤーのz座標の数字、レ 975 | イヤーの移動開始からその位置に到達するまでの秒数の数字、その間 976 | の時間補間関数の文字列からなるタプルのリストを値に持つ辞書で 977 | す。レイヤーはここで指定された各タプルを順番に移動するので、タ 978 | プルは時系列に沿って並べてください。 979 | `focus_check_points` 980 | 被写界深度とフォーカス位置の辞書で、その値、その値になるまでの 981 | 秒その間の時間補間関数名の文字列からなるタプルのリストを値とします。 982 | { 983 | 'focus':[(z, duration, warper)...] 984 | 'dof':[(dof, duration, warper)...] 985 | } 986 | `dof` はレイヤーにブラーの掛らないフォーカス位置からのZ値の範囲で、 987 | デフォルトでは9999999です。 988 | `focus` の値にカメラのZ座標を足したものがカメラのフォーカス位置となります。 989 | `x_loop` 990 | デフォルトは Falseで、True ならカメラのモーションが繰り替えされます。 991 | `y_loop` 992 | デフォルトは Falseで、True ならカメラのモーションが繰り替えされます。 993 | `z_loop` 994 | デフォルトは Falseで、True ならカメラのモーションが繰り替えされます。 995 | `rotate_loop` 996 | デフォルトは Falseで、True ならカメラのモーションが繰り替えされます。 997 | `subpixel` 998 | デフォルトは Trueで、 True なら、1 pixel 以下の値を使用して画面 999 | に描画します。 1000 | 'x_express' 1001 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 1002 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 1003 | x座標に加えられます。 1004 | 'y_express' 1005 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 1006 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 1007 | y座標に加えられます。 1008 | 'z_express' 1009 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 1010 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 1011 | z座標に加えられます。 1012 | 'rotate_express' 1013 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時間 1014 | 軸の秒数を引数に呼び出され、数字を返します。この結果はカメラの 1015 | rotate座標に加えられます。 1016 | `_express` 1017 | これは呼出可能なオブジェクトで、出現時間軸とアニメーション時 1018 | 間軸の秒数を引数に呼び出され、数字を返します。この結果は指定 1019 | したレイヤーの座標に加えられます。 1020 | `camera_spline` 1021 | カメラの座標に対してスプライン補間を有効にします。True ならワーパーは無視されます。これはデフォルトでFalseです。 1022 | `spline` 1023 | レイヤーの座標に対してスプライン補間を有効にします。True ならワーパーは無視されます。これはデフォルトでFalseです。 1024 | 1025 | キーワード引数として <レイヤー名>_loop をとります。デフォルトは Falseで、True ならそのレイヤーのモーションが繰り替えされます。 1026 | """ 1027 | -------------------------------------------------------------------------------- /camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyouryuukunn/renpy-ActionEditor/97fa16aa80da66088dafbad9d1cd59cb1c9775c6/camera.png -------------------------------------------------------------------------------- /camera.rpy: -------------------------------------------------------------------------------- 1 | 2 | init 1600: 3 | if getattr(store, "_3d_layers", None): 4 | default _3d_layers = _3d_layers 5 | else: 6 | default _3d_layers = {"master":_LAYER_Z} 7 | init -1599 python: 8 | 9 | ########################################################################## 10 | # Camera functions 11 | _camera_x = 0 12 | _camera_y = 0 13 | _camera_z = 0 14 | _camera_rotate = 0 15 | _last_camera_arguments = None 16 | 17 | def register_3d_layer(*layers): 18 | """ 19 | :doc: camera 20 | 21 | Register layers as 3D layers. Only 3D layers will be affected by camera 22 | movement and 3D layer transforms. This should be called in an init 23 | block. If no layers are registered as 3D layers, the 'master' layer 24 | will become a 3D layer by default. 25 | 26 | `layers` 27 | This should be a string or a group of strings naming registered layers. 28 | """ 29 | global _3d_layers 30 | _3d_layers = {layer:_LAYER_Z for layer in layers} 31 | 32 | def camera_reset(): 33 | """ 34 | :doc: camera 35 | 36 | Resets the camera, 3D layers positions and the focus position, the depth of field. 37 | """ 38 | for layer in _3d_layers: 39 | layer_move(layer, _LAYER_Z) 40 | camera_move(0, 0, 0) 41 | focus_set(1000) 42 | dof_set(9999999) 43 | 44 | def camera_restore(): 45 | """ 46 | :doc: camera 47 | 48 | Safety method used internally to deal with unexpected behavior. 49 | 50 | """ 51 | camera_move(_camera_x, _camera_y, _camera_z) 52 | 53 | def camera_move(x, y, z, rotate=0, duration=0, warper='linear', subpixel=True, loop=False, x_express=None, y_express=None, z_express=None, rotate_express=None, **kwargs): 54 | """ 55 | :doc: camera 56 | 57 | Moves the camera to a given coordinate and rotation. 58 | 59 | `x` 60 | The x coordinate to move the camera to. 61 | `y` 62 | The y coordinate to move the camera to. 63 | `z` 64 | The z coordinate to move the camera to. 65 | `rotate` 66 | Rotation of the camera, perpindicular to the scene, in degrees. 67 | `duration` 68 | The time, in seconds, to complete the camera move. If no time is given, 69 | the move will happen instantaneously. 70 | `warper` 71 | A string that points to a registered ATL warper, like \'ease\'. 72 | If no warper is given, this will default to \'linear\'. 73 | `subpixel` 74 | If True, transforms caused by the 3D camera will be rendered with 75 | subpixel precision. This defaults to True. 76 | `loop` 77 | If true, the camera move will continually loop until another camera 78 | action interrupts. This defaults to False. 79 | `x_express` 80 | This should be a callable function that is called with the shown 81 | timebase and is given an animation timebase in seconds. The 82 | result of this function is added to the x coordinate of the camera. 83 | `y_express` 84 | This should be a callable function that is called with the shown 85 | timebase and is given an animation timebase in seconds. The 86 | result of this function is added to the y coordinate of the camera. 87 | `z_express` 88 | This should be a callable function that is called with the shown 89 | timebase and is given an animation timebase in seconds. The 90 | result of this function is added to the z coordinate of the camera. 91 | `rotate_express` 92 | This should be a callable function that is called with the shown 93 | timebase and is given an animation timebase in seconds. The 94 | result of this function is added to the rotation value of the camera. 95 | `_express` 96 | This should be a callable function that is called with the shown 97 | timebase and is given an animation timebase in seconds. The 98 | result of this function is added to the coordinate of the given layer. 99 | """ 100 | 101 | camera_moves([(x, y, z, rotate, duration, warper, ),], subpixel=subpixel, loop=loop, x_express=x_express, y_express=y_express, z_express=z_express, rotate_express=rotate_express, **kwargs) 102 | 103 | def camera_relative_move(x, y, z, rotate=0, duration=0, warper='linear', subpixel=True, loop=False, x_express=None, y_express=None, z_express=None, rotate_express=None, **kwargs): 104 | """ 105 | :doc: camera 106 | 107 | Move the coordinate and rotate of a camera relatively and apply transforms to all 3D layers. 108 | 109 | `x` 110 | the x coordinate of a camera relative to the current one. 111 | `y` 112 | the y coordinate of a camera relative to the current one. 113 | `z` 114 | the z coordinate of a camera relative to the current one. 115 | `rotate` 116 | Defaul 0, the rotate of a camera relative to the current one. 117 | `duration` 118 | Default 0, this is the second times taken to move a camera. 119 | `warper` 120 | Default 'linear', this should be string and the name of a warper 121 | registered with ATL. 122 | `subpixel` 123 | Default True, if True, causes things to be drawn on the screen 124 | using subpixel positioning 125 | `loop` 126 | Default False, if True, this motion repeats. 127 | 'x_express' 128 | This should be callable, which is called with the shown timebase 129 | and the animation timebase, in seconds and return a number. The 130 | result of this is added to the x coordinate of the camera. 131 | 'y_express' 132 | This should be callable, which is called with the shown timebase 133 | and the animation timebase, in seconds and return a number. The 134 | result of this is added to the y coordinate of the camera. 135 | 'z_express' 136 | This should be callable, which is called with the shown timebase 137 | and the animation timebase, in seconds and return a number. The 138 | result of this is added to the z coordinate of the camera. 139 | 'rotate_express' 140 | This should be callable, which is called with the shown timebase 141 | and the animation timebase, in seconds and return a number. The 142 | result of this is added to the rotate coordinate of the camera. 143 | `_express` 144 | This should be a callable function that is called with the shown 145 | timebase and is given an animation timebase in seconds. The 146 | result of this function is added to the coordinate of the given layer. 147 | """ 148 | camera_move(x+_camera_x, y+_camera_y, z+_camera_z, rotate+_camera_rotate, duration, warper, subpixel, loop, x_express, y_express, z_express, rotate_express, **kwargs) 149 | 150 | 151 | def camera_moves(check_points, loop=False, subpixel=True, x_express=None, y_express=None, z_express=None, rotate_express=None, spline=False, **kwargs): 152 | """ 153 | :doc: camera 154 | 155 | Allows multiple camera moves to happen in succession. 156 | 157 | `check_points` 158 | A list of camera moves, in the format of (x, y, z, rotate, duration, warper) 159 | `loop` 160 | If true, the camera moves will continually loop until another camera 161 | action interrupts. This defaults to False. 162 | `subpixel` 163 | If True, transforms caused by the 3D camera will be rendered with 164 | subpixel precision. This defaults to True. 165 | `x_express` 166 | This should be a callable function that is called with the shown 167 | timebase and is given an animation timebase in seconds. The 168 | result of this function is added to the x coordinate of the camera. 169 | `y_express` 170 | This should be a callable function that is called with the shown 171 | timebase and is given an animation timebase in seconds. The 172 | result of this function is added to the y coordinate of the camera. 173 | `z_express` 174 | This should be a callable function that is called with the shown 175 | timebase and is given an animation timebase in seconds. The 176 | result of this function is added to the z coordinate of the camera. 177 | `rotate_express` 178 | This should be a callable function that is called with the shown 179 | timebase and is given an animation timebase in seconds. The 180 | result of this function is added to the rotation value of the camera. 181 | `_express` 182 | This should be a callable function that is called with the shown 183 | timebase and is given an animation timebase in seconds. The 184 | result of this function is added to the coordinate of the given layer. 185 | `spline` 186 | Enable spline interpolation for the coordinates of the camera. If this is True, warpers are ignored. This defaults to False. 187 | """ 188 | camera_check_points = {} 189 | camera_check_points["x"] = [] 190 | camera_check_points["y"] = [] 191 | camera_check_points["z"] = [] 192 | camera_check_points["rotate"] = [] 193 | for x, y, z, rotate, duration, warper in check_points: 194 | camera_check_points["x"].append((x, duration, warper)) 195 | camera_check_points["y"].append((y, duration, warper)) 196 | camera_check_points["z"].append((z, duration, warper)) 197 | camera_check_points["rotate"].append((rotate, duration, warper)) 198 | kwargs["x_loop"]=loop 199 | kwargs["y_loop"]=loop 200 | kwargs["z_loop"]=loop 201 | kwargs["rotate_loop"]=loop 202 | all_moves(camera_check_points=camera_check_points, loop=loop, subpixel=subpixel, x_express=x_express, y_express=y_express, z_express=z_express, rotate_express=rotate_express, camera_spline=spline, **kwargs) 203 | 204 | def camera_relative_moves(relative_check_points, loop=False, subpixel=True, x_express=None, y_express=None, z_express=None, rotate_express=None, spline=False, **kwargs): 205 | """ 206 | :doc: camera 207 | 208 | Allows relative multiple camera moves to happen in succession. 209 | 210 | `relative_check_points` 211 | A list of camera moves, in the format of (x, y, z, rotate, duration, warper) 212 | `loop` 213 | If true, the camera moves will continually loop until another camera 214 | action interrupts. This defaults to False. 215 | `subpixel` 216 | If True, transforms caused by the 3D camera will be rendered with 217 | subpixel precision. This defaults to True. 218 | `x_express` 219 | This should be a callable function that is called with the shown 220 | timebase and is given an animation timebase in seconds. The 221 | result of this function is added to the x coordinate of the camera. 222 | `y_express` 223 | This should be a callable function that is called with the shown 224 | timebase and is given an animation timebase in seconds. The 225 | result of this function is added to the y coordinate of the camera. 226 | `z_express` 227 | This should be a callable function that is called with the shown 228 | timebase and is given an animation timebase in seconds. The 229 | result of this function is added to the z coordinate of the camera. 230 | `rotate_express` 231 | This should be a callable function that is called with the shown 232 | timebase and is given an animation timebase in seconds. The 233 | result of this function is added to the rotation value of the camera. 234 | `_express` 235 | This should be a callable function that is called with the shown 236 | timebase and is given an animation timebase in seconds. The 237 | result of this function is added to the coordinate of the given layer. 238 | `spline` 239 | Enable spline interpolation for the coordinates of the camera. If this is True, warpers are ignored. This defaults to False. 240 | """ 241 | for i in len(relative_check_points): 242 | relative_check_points[i] = ( 243 | relative_check_points[i][0]+_camera_x, 244 | relative_check_points[i][1]+_camera_y, 245 | relative_check_points[i][2]+_camera_z, 246 | relative_check_points[i][3]+_camera_rotate, 247 | relative_check_points[i][4], 248 | relative_check_points[i][5] 249 | ) 250 | camera_moves(relative_check_points, loop=loop, subpixel=subpixel, x_express=x_express, y_express=y_express, z_express=z_express, rotate_express=rotate_express, spline=spline, **kwargs) 251 | 252 | 253 | def layer_move(layer, z, duration=0, warper='linear', subpixel=True, loop=False, x_express=None, y_express=None, z_express=None, rotate_express=None, layer_express=None): 254 | """ 255 | :doc: camera 256 | 257 | Moves the z coordinate of a layer and applies a transform to the layer. 258 | 259 | `layer` 260 | A string that names a registered 3D layer to be moved. 261 | `z` 262 | The z coordinate to move the 3D layer to. 263 | `duration` 264 | The time, in seconds, to complete the layer move. If no time is given, 265 | the move will happen instantaneously. 266 | `warper` 267 | A string that points to a registered ATL warper, like \'ease\'. 268 | If no warper is given, this will default to \'linear\'. 269 | `subpixel` 270 | If True, the resulting layer move will be rendered with 271 | subpixel precision. This defaults to True. 272 | `loop` 273 | If true, the layer move will continually loop until another camera 274 | action interrupts. This defaults to False. 275 | `x_express` 276 | This should be a callable function that is called with the shown 277 | timebase and is given an animation timebase in seconds. The 278 | result of this function is added to the x coordinate of the camera. 279 | `y_express` 280 | This should be a callable function that is called with the shown 281 | timebase and is given an animation timebase in seconds. The 282 | result of this function is added to the y coordinate of the camera. 283 | `z_express` 284 | This should be a callable function that is called with the shown 285 | timebase and is given an animation timebase in seconds. The 286 | result of this function is added to the z coordinate of the camera. 287 | `rotate_express` 288 | This should be a callable function that is called with the shown 289 | timebase and is given an animation timebase in seconds. The 290 | result of this function is added to the rotation value of the camera. 291 | `layer_express` 292 | This should be a callable function that is called with the shown 293 | timebase and is given an animation timebase in seconds. The 294 | result of this function is added to the coordinate of the layer. 295 | """ 296 | 297 | layer_moves(layer, [(z, duration, warper, ),], subpixel=subpixel, loop=loop, x_express=x_express, y_express=y_express, z_express=z_express, rotate_express=rotate_express, layer_express=layer_express) 298 | 299 | 300 | def layer_moves(layer, check_points, loop=False, subpixel=True, x_express=None, y_express=None, z_express=None, rotate_express=None, layer_express=None, spline=False): 301 | """ 302 | :doc: camera 303 | 304 | Move a layer through check points and apply transform to the layer. 305 | 306 | `layer` 307 | A string that names a registered 3D layer to be moved. 308 | `check_points` 309 | A list of layer moves, in the format of (z, duration, warper) 310 | `loop` 311 | If true, the layer moves will continually loop until another camera 312 | action interrupts. This defaults to False. 313 | `subpixel` 314 | If True, the resulting layer moves will be rendered with 315 | subpixel precision. This defaults to True. 316 | `layer_express` 317 | This should be a callable function that is called with the shown 318 | timebase and is given an animation timebase in seconds. The 319 | result of this function is added to the coordinate of the layer. 320 | `x_express` 321 | This should be a callable function that is called with the shown 322 | timebase and is given an animation timebase in seconds. The 323 | result of this function is added to the x coordinate of the camera. 324 | `y_express` 325 | This should be a callable function that is called with the shown 326 | timebase and is given an animation timebase in seconds. The 327 | result of this function is added to the y coordinate of the camera. 328 | `z_express` 329 | This should be a callable function that is called with the shown 330 | timebase and is given an animation timebase in seconds. The 331 | result of this function is added to the z coordinate of the camera. 332 | `rotate_express` 333 | This should be a callable function that is called with the shown 334 | timebase and is given an animation timebase in seconds. The 335 | result of this function is added to the rotation value of the camera. 336 | `spline` 337 | Enable spline interpolation for the coordinates of the layer. If this is True, warpers are ignored. This defaults to False. 338 | """ 339 | all_moves(layer_check_points={layer:check_points}, subpixel=subpixel, x_express=x_express, y_express=y_express, z_express=z_express, rotate_express=rotate_express, **{layer+"_loop":loop, layer+"_spline":spline, layer+"_express":layer_express}) 340 | 341 | 342 | def focus_set(focus, duration=0, warper='linear', **kwargs): 343 | """ 344 | :doc: camera 345 | 346 | Set the focus position. 347 | 348 | `focus` 349 | `focus` decides the focus position. It is the z coordinate which is sum of this value and 350 | the z coordinate of camera. 351 | `duration` 352 | The time, in seconds, to complete the focus change. If no time is given, 353 | the change will happen instantaneously. 354 | `warper` 355 | A string that points to a registered ATL warper, like \'ease\'. 356 | If no warper is given, this will default to \'linear\'. 357 | """ 358 | 359 | all_moves(focus_check_points={"focus": [(focus, duration, warper, ), ]}, **kwargs) 360 | 361 | def dof_set(dof, duration=0, warper='linear', **kwargs): 362 | """ 363 | :doc: camera 364 | 365 | Set the depth of field. 366 | 367 | `dof` 368 | `dof` is the z range where layers aren't blured. it defaults to 9999999. 369 | `duration` 370 | The time, in seconds, to complete the dof change. If no time is given, 371 | the change will happen instantaneously. 372 | `warper` 373 | A string that points to a registered ATL warper, like \'ease\'. 374 | If no warper is given, this will default to \'linear\'. 375 | """ 376 | 377 | all_moves(focus_check_points={"dof": [(dof, duration, warper, ), ]}, **kwargs) 378 | 379 | def all_moves(camera_check_points=None, layer_check_points=None, focus_check_points=None, subpixel=True, play=True, x_loop=False, y_loop=False, z_loop=False, rotate_loop=False, x_express=None, y_express=None, z_express=None, rotate_express=None, camera_spline=False, **kwargs): 380 | """ 381 | :doc: camera 382 | 383 | Allows for both camera moves and layer moves to happen within the same interaction, in any given combination. The Action Editor will usually generate these. 384 | 385 | `camera_check_points` 386 | A list of check points for the camera to go through, split by coordinate in the following format: 387 | { 388 | 'x':[(x, duration, warper)...] 389 | 'y':[(y, duration, warper)...] 390 | 'z':[(z, duration, warper)...] 391 | 'rotate':[(rotate, duration, warper)...] 392 | } 393 | `layer_check_points` 394 | A list of check points for layers to go through, in the following format: 395 | { 396 | 'layer name':[(z, duration, warper)...] 397 | } 398 | `focus_check_points` 399 | A list of check points for the depth of field & the focus position, 400 | in the following format: 401 | { 402 | 'focus':[(z, duration, warper)...] 403 | 'dof':[(dof, duration, warper)...] 404 | } 405 | `dof` is the z range where layers aren't blured. it defaults to 9999999. 406 | `focus` decides the focus position. It is the z coordinate which is sum of this value and 407 | the z coordinate of camera. 408 | `x_loop` 409 | If True, all x coordinate check points will loop continuously. This defaults to False. 410 | `y_loop` 411 | If True, all y coordinate check points will loop continuously. This defaults to False. 412 | `z_loop` 413 | If True, all z coordinate check points will loop continuously. This defaults to False. 414 | `rotate_loop` 415 | If True, all rotation check points will loop continuously. This defaults to False. 416 | `subpixel` 417 | If True, all transforms caused by this function will be drawn with subpixel precision. This defaults to True. 418 | `_loop` 419 | If True, all layer move check points for the given layer will loop continuously. This defaults to False. 420 | `x_express` 421 | This should be a callable function that is called with the shown 422 | timebase and is given an animation timebase in seconds. The 423 | result of this function is added to the x coordinate of the camera. 424 | `y_express` 425 | This should be a callable function that is called with the shown 426 | timebase and is given an animation timebase in seconds. The 427 | result of this function is added to the y coordinate of the camera. 428 | `z_express` 429 | This should be a callable function that is called with the shown 430 | timebase and is given an animation timebase in seconds. The 431 | result of this function is added to the z coordinate of the camera. 432 | `rotate_express` 433 | This should be a callable function that is called with the shown 434 | timebase and is given an animation timebase in seconds. The 435 | result of this function is added to the rotation value of the camera. 436 | `_express` 437 | This should be a callable function that is called with the shown 438 | timebase and is given an animation timebase in seconds. The 439 | result of this function is added to the coordinate of the given layer. 440 | `camera_spline` 441 | Enable spline interpolation for the coordinates of the camera. If this is True, warpers are ignored. This defaults to False. 442 | `_spline` 443 | Enable spline interpolation for the coordinates of the given layer. If this is True, warpers are ignored. This defaults to False. 444 | """ 445 | global _camera_x, _camera_y, _camera_z, _camera_rotate, _camera_focus, _camera_dof, _3d_layers, _last_camera_arguments 446 | from math import sin, pi 447 | from random import random 448 | 449 | if camera_check_points is None: 450 | camera_check_points = {} 451 | if layer_check_points is None: 452 | layer_check_points = {} 453 | if focus_check_points is None: 454 | focus_check_points = {} 455 | if config.developer: 456 | _last_camera_arguments = (camera_check_points, layer_check_points, focus_check_points, x_loop, y_loop, z_loop, rotate_loop, x_express, y_express, z_express, rotate_express, kwargs, _camera_x, _camera_y, _camera_z, _camera_rotate, _3d_layers.copy(), camera_spline, _camera_focus, _camera_dof) 457 | start_xanchor = _FOCAL_LENGTH*_camera_x/(renpy.config.screen_width *_LAYER_Z) + .5 458 | start_yanchor = _FOCAL_LENGTH*_camera_y/(renpy.config.screen_height*_LAYER_Z) + .5 459 | camera_check_points2 = { 'xanchor':[(start_xanchor, 0, None, )], 'yanchor':[(start_yanchor, 0, None, )], 'z': [(_camera_z, 0, None, )], 'rotate':[(_camera_rotate, 0, None, )] } 460 | 461 | for coordinate in ["x", "y", "z", "rotate"]: 462 | if coordinate not in camera_check_points: 463 | camera_check_points[coordinate] = [(getattr(renpy.store, "_camera_"+coordinate), 0, None, )] 464 | for c in camera_check_points['x']: 465 | camera_check_points2['xanchor'].append((_FOCAL_LENGTH*c[0]/(renpy.config.screen_width *_LAYER_Z) + .5, c[1], c[2], )) 466 | for c in camera_check_points['y']: 467 | camera_check_points2['yanchor'].append((_FOCAL_LENGTH*c[0]/(renpy.config.screen_height *_LAYER_Z) + .5, c[1], c[2], )) 468 | camera_check_points2['z'].extend(camera_check_points['z']) 469 | camera_check_points2['rotate'].extend(camera_check_points['rotate']) 470 | for i in ["focus", "dof"]: 471 | if i not in focus_check_points: 472 | focus_check_points[i] = [(getattr(renpy.store, "_camera_"+i), 0, None, )] 473 | if camera_spline: 474 | camera_check_points2 = _ready_spline_camera_interpolation(camera_check_points2) 475 | for layer in _3d_layers: 476 | 477 | if layer not in layer_check_points: 478 | layer_check_points[layer] = [(_3d_layers[layer], 0, None), ] 479 | layer_check_points2 = [(_3d_layers[layer], 0, None), ] 480 | for c in layer_check_points[layer]: 481 | layer_check_points2.append((c[0], float(c[1]), c[2])) 482 | layer_loop = kwargs.get(layer+"_loop", False) 483 | layer_express = kwargs.get(layer+"_express", None) 484 | if kwargs.get(layer+"_spline", False): 485 | layer_check_points2 = _ready_spline_layer_interpolation(layer_check_points2) 486 | 487 | if play: 488 | renpy.game.context().scene_lists.set_layer_at_list(layer, [Transform(function=renpy.curry(_camera_trans)(camera_check_points=camera_check_points2, layer_check_points=layer_check_points2, focus_check_points=focus_check_points, subpixel=subpixel, layer_loop=layer_loop, x_loop=x_loop, y_loop=y_loop, z_loop=z_loop, rotate_loop=rotate_loop, x_express=x_express, y_express=y_express, z_express=z_express, rotate_express=rotate_express, layer_express=layer_express))]) 489 | layer_z = layer_check_points2[-1][0] 490 | else: 491 | # This is used when the time bar is changed by Action Editor 492 | st = _viewers.time 493 | xanchor = get_at_time(camera_check_points2['xanchor'], st, x_loop) 494 | yanchor = get_at_time(camera_check_points2['yanchor'], st, y_loop) 495 | z = get_at_time(camera_check_points2['z'], st, z_loop) 496 | rotate = get_at_time(camera_check_points2['rotate'], st, rotate_loop) 497 | focus = get_at_time(focus_check_points['focus'], st, False) 498 | dof = get_at_time(focus_check_points['dof'], st, False) 499 | layer_z = get_at_time(layer_check_points2, st, layer_loop) 500 | if x_express: 501 | xanchor += _FOCAL_LENGTH*x_express(st, st)/(renpy.config.screen_width *_LAYER_Z) 502 | if y_express: 503 | yanchor += _FOCAL_LENGTH*y_express(st, st)/(renpy.config.screen_height *_LAYER_Z) 504 | if z_express: 505 | z += z_express(st, st) 506 | if rotate_express: 507 | rotate += rotate_express(st, st) 508 | if layer_express: 509 | layer_z += layer_express(st, st) 510 | distance = float(layer_z - z) 511 | if distance == 0: 512 | distance = .1 513 | if distance >= 0: 514 | alpha = 1 515 | zoom = _LAYER_Z / distance 516 | focus_distance = abs(layer_z - focus - z) 517 | if dof == 0: 518 | _dof = 0.1 519 | else: 520 | _dof = dof 521 | blur_amount = _camera_blur_amount * renpy.atl.warpers[_camera_blur_warper](focus_distance/(_dof)) 522 | if blur_amount <= 1.0: 523 | blur_amount = None 524 | renpy.game.context().scene_lists.set_layer_at_list(layer, [Transform(xpos=.5, ypos=.5, alpha=alpha, transform_anchor=True, xanchor=xanchor, yanchor=yanchor, zoom=zoom, rotate=rotate, blur=blur_amount)]) 525 | else: 526 | alpha = 0 527 | renpy.game.context().scene_lists.set_layer_at_list(layer, [Transform(xpos=.5, ypos=.5, alpha=alpha, transform_anchor=True, xanchor=xanchor, yanchor=yanchor, rotate=rotate, rotate_pad=False, blur=None)]) 528 | 529 | _3d_layers[layer] = int(layer_z) 530 | if play: 531 | _camera_x = camera_check_points['x'][-1][0] 532 | _camera_y = camera_check_points['y'][-1][0] 533 | _camera_z = camera_check_points['z'][-1][0] 534 | _camera_rotate = camera_check_points['rotate'][-1][0] 535 | _camera_focus = focus_check_points['focus'][-1][0] 536 | _camera_dof = focus_check_points['dof'][-1][0] 537 | else: 538 | _camera_x = int(((xanchor-.5)*renpy.config.screen_width*_LAYER_Z)/_FOCAL_LENGTH) 539 | _camera_y = int(((yanchor-.5)*renpy.config.screen_height*_LAYER_Z)/_FOCAL_LENGTH) 540 | _camera_z = int(z) 541 | _camera_rotate = int(rotate) 542 | _camera_focus = int(focus) 543 | _camera_dof = int(dof) 544 | 545 | def _camera_trans(tran, st, at, camera_check_points, layer_check_points, focus_check_points, layer_loop, x_loop, y_loop, z_loop, rotate_loop, subpixel, x_express, y_express, z_express, rotate_express, layer_express): 546 | if not (layer_loop or x_loop or y_loop or z_loop or rotate_loop or x_express or y_express or z_express or rotate_express or layer_express): 547 | for check_point in camera_check_points.items(): 548 | if check_point[-1][1] and check_point[-1][1] >= st: 549 | break 550 | else: 551 | for check_point in layer_check_points.items(): 552 | if check_point[-1][1] and check_point[-1][1] >= st: 553 | break 554 | else: 555 | for check_point in focus_check_points.items(): 556 | if check_point[-1][1] and check_point[-1][1] >= st: 557 | break 558 | else: 559 | return 560 | # camera_check_points = {xanchor:(value, duration, warper), yanchor, z, rotate} 561 | # layer_check_points = (layer_z, duration, warper) 562 | # focus_check_points = {focus: (value, duration, warper), dof: (value, duration, warper)} 563 | from math import sin, pi 564 | from random import random 565 | tran.xpos = .5 566 | tran.ypos = .5 567 | tran.subpixel = subpixel 568 | tran.transform_anchor = True 569 | tran.xanchor = get_at_time(camera_check_points['xanchor'], st, x_loop) 570 | tran.yanchor = get_at_time(camera_check_points['yanchor'], st, y_loop) 571 | z = get_at_time(camera_check_points['z'], st, z_loop) 572 | focus = get_at_time(focus_check_points['focus'], st, False) 573 | dof = get_at_time(focus_check_points['dof'], st, False) 574 | tran.rotate = get_at_time(camera_check_points['rotate'], st, rotate_loop) 575 | layer_z = get_at_time(layer_check_points, st, layer_loop) 576 | if x_express: 577 | tran.xanchor += _FOCAL_LENGTH*x_express(st, at)/(renpy.config.screen_width *_LAYER_Z) 578 | if y_express: 579 | tran.yanchor += _FOCAL_LENGTH*y_express(st, at)/(renpy.config.screen_height *_LAYER_Z) 580 | if z_express: 581 | z += z_express(st, at) 582 | if rotate_express: 583 | tran.rotate += rotate_express(st, at) 584 | if layer_express: 585 | layer_z += layer_express(st, st) 586 | distance = float(layer_z - z) 587 | if distance == 0: 588 | distance = .1 589 | if distance >= 0: 590 | tran.alpha = 1 591 | tran.zoom = _LAYER_Z / distance 592 | focus_distance = abs(layer_z - focus - z) 593 | if dof == 0: 594 | _dof = 0.1 595 | else: 596 | _dof = dof 597 | blur_amount=_camera_blur_amount * renpy.atl.warpers[_camera_blur_warper](focus_distance/(_dof)) 598 | if blur_amount <= 1.0: 599 | tran.blur = None 600 | else: 601 | tran.blur = _camera_blur_amount * renpy.atl.warpers[_camera_blur_warper](focus_distance/(_dof)) 602 | else: 603 | tran.alpha = 0 604 | return .005 605 | 606 | def get_at_time(check_points, time, loop): 607 | # check_points = ((value, time, warper)...) 608 | if loop and check_points[-1][1]: 609 | time %= check_points[-1][1] 610 | 611 | for i in xrange(1, len(check_points)): 612 | checkpoint = check_points[i][1] 613 | pre_checkpoint = check_points[i-1][1] 614 | if time < checkpoint: 615 | start = check_points[i-1] 616 | goal = check_points[i] 617 | if checkpoint != pre_checkpoint: 618 | g = renpy.atl.warpers[goal[2]]((time - pre_checkpoint) / float(checkpoint - pre_checkpoint)) 619 | else: 620 | g = 1. 621 | 622 | return g*(goal[0]-start[0])+start[0] 623 | else: 624 | return check_points[-1][0] 625 | 626 | # def get_camera_coordinate(tran, z, layer, layer_z): #_3d_layers can't rollback? 627 | # global _camera_x, _camera_y, _camera_z, _camera_rotate 628 | # _camera_x = int(((tran.xanchor-.5)*renpy.config.screen_width*_LAYER_Z)/_FOCAL_LENGTH) 629 | # _camera_y = int(((tran.yanchor-.5)*renpy.config.screen_height*_LAYER_Z)/_FOCAL_LENGTH) 630 | # _camera_z = int(z) 631 | # _camera_rotate = int(tran.rotate) 632 | # _3d_layers[layer] = int(layer_z) 633 | 634 | def _ready_spline_camera_interpolation(camera_check_points): 635 | new_camera_check_points = {} 636 | new_camera_check_points["rotate"] = camera_check_points["rotate"] 637 | MINTIME = 0.1 638 | for coordinate in ["xanchor", "yanchor", "z"]: 639 | sv = [(t, v) for i, (v, t, w) in enumerate(camera_check_points[coordinate]) if i+1 == len(camera_check_points[coordinate]) or t != camera_check_points[coordinate][i+1][1]] 640 | if len(sv) > 2: 641 | new_camera_check_points[coordinate] = [] 642 | for i in _drange(0, camera_check_points[coordinate][-1][1], MINTIME): 643 | new_camera_check_points[coordinate].append((_spline(sv, i), i, "linear")) 644 | else: 645 | new_camera_check_points[coordinate] = camera_check_points[coordinate] 646 | 647 | return new_camera_check_points 648 | 649 | def _ready_spline_layer_interpolation(layer_check_points): 650 | MINTIME = 0.1 651 | sz = [(t, v) for i, (v, t, w) in enumerate(layer_check_points) if i+1 == len(layer_check_points) or t != layer_check_points[i+1][1]] 652 | if len(sz) > 2: 653 | new_layer_check_points = [] 654 | for i in _drange(0, layer_check_points[-1][1], MINTIME): 655 | new_layer_check_points.append((_spline(sz, i), i, "linear")) 656 | else: 657 | new_layer_check_points = layer_check_points 658 | return new_layer_check_points 659 | 660 | def _drange(begin, end, step): 661 | n = begin 662 | while n < end: 663 | yield n 664 | n += step 665 | yield end 666 | 667 | -------------------------------------------------------------------------------- /camera_config.rpy: -------------------------------------------------------------------------------- 1 | init -1600 python: 2 | 3 | ########################################################################## 4 | # Camera functions 5 | _camera_focus = 1848.9 #default camera WD 6 | _camera_dof = 9999999 #default dof value 7 | _camera_blur_amount = 1.0 #The blur value where the distance from focus position is dof. 8 | _camera_blur_warper = "linear" #warper function name which is used for the distance from focus position and blur amount. 9 | _FOCAL_LENGTH = 147.40 #default focus position 10 | _LAYER_Z = 1848.9 #default z value of 3D layer 11 | 12 | init -1600 python in _viewers: 13 | # If True, show rot default. 14 | default_rot = False 15 | # If True, set camera keymap FPS(wasd), otherwise vim(hjkl) 16 | fps_keymap = False 17 | default_warper = "linear" 18 | -------------------------------------------------------------------------------- /image_viewer.rpy: -------------------------------------------------------------------------------- 1 | #Shift+U: Open Image Viewer 2 | #2016 1/22 v6.99 3 | 4 | # screen _image_tag_input(default, string=""): 5 | # key "game_menu" action Return("") 6 | # on "show" action Show("_image_selecter", default=default) 7 | # for e in default: 8 | # $string += e + " " 9 | # vbox: 10 | # button: 11 | # id "tag_input" 12 | # action NullAction() 13 | # add Input(default=string, changed=_tag_input, button=renpy.get_widget("_image_tag_input","tag_input")) 14 | # 15 | # init python: 16 | # def _tag_input(input): 17 | # if len(input) and input[-1] == " ": 18 | # renpy.show_screen("_image_selecter", default=tuple(input.split())) 19 | # renpy.restart_interaction() 20 | 21 | screen _image_selecter(default, string=""): 22 | key "game_menu" action Return("") 23 | zorder 20 24 | for e in default: 25 | $string += e + " " 26 | $default_set = set(default) 27 | frame: 28 | background "#0006" 29 | xalign 1. 30 | has vbox 31 | label _("Type a image name") style "image_selecter_input" 32 | # input value ScreenVariableInputValue("string") #自動絞り込み 謎バグにより使用不可 33 | input default string style "image_selecter_input" #changed _tag_input 34 | if default: 35 | $s = set() 36 | for name in renpy.display.image.images: 37 | $name_set = set(name) 38 | if default_set < name_set: 39 | $s.update(name_set-default_set) 40 | elif default_set == name_set: 41 | $s.update(default_set) 42 | else: 43 | $s = {name[0] for name in renpy.display.image.images} 44 | viewport: 45 | mousewheel True 46 | xmaximum 400 47 | # ymaximum 300 48 | # edgescroll (100, 100) 49 | scrollbars "both" 50 | vbox: 51 | style_group "image_selecter" 52 | for tag in tuple(s): 53 | textbutton tag action Return(default + (tag, )) hovered ShowImage(default, tag) unhovered Function(renpy.hide, "preview", layer="screens") 54 | # $s=tuple(s) 55 | # for x in range(0, len(s), 4): 56 | # if x+5 < len(s): 57 | # hbox: 58 | # for tag in s[x:x+4]: 59 | # textbutton tag action Return(default + (tag, )) hovered _viewers.ShowImage(default, tag) unhovered Function(renpy.hide, "preview", layer="screens") 60 | # else: 61 | # hbox: 62 | # for tag in s[x:]: 63 | # textbutton tag action Return(default + (tag, )) hovered _viewers.ShowImage(default, tag) unhovered Function(renpy.hide, "preview", layer="screens") 64 | init: 65 | style image_selecter_input: 66 | outlines [ (absolute(1), "#000", absolute(0), absolute(0)) ] 67 | style image_selecter_button: 68 | size_group "image_selecter" 69 | idle_background None 70 | style image_selecter_button_text: 71 | xalign .0 72 | outlines [ (absolute(1), "#000", absolute(0), absolute(0)) ] 73 | init -2000 python: 74 | def _open_image_viewer(): 75 | if not renpy.config.developer: 76 | return 77 | default = () 78 | while True: 79 | name = renpy.invoke_in_new_context(renpy.call_screen, "_image_selecter", default=default) 80 | if isinstance(name, tuple): #press button 81 | default = tuple(name) 82 | elif name: #from input text 83 | default = tuple(name.split()) 84 | else: 85 | renpy.notify(_("Please type image name")) 86 | return 87 | 88 | init -1 python: 89 | @renpy.pure 90 | class ShowImage(renpy.store.Action, renpy.store.DictEquality): 91 | def __init__(self, default, tag): 92 | self.string="" 93 | for e in default: 94 | self.string += e + " " 95 | self.string += tag 96 | self.check = None 97 | 98 | def __call__(self): 99 | if self.check is None: 100 | for n in renpy.display.image.images: 101 | if set(n) == set(self.string.split()): 102 | self.string="" 103 | for e in n: 104 | self.string += e + " " 105 | try: 106 | for fn in renpy.display.image.images[n].predict_files(): 107 | if not renpy.loader.loadable(fn): 108 | self.check = False 109 | break 110 | else: 111 | self.check = True 112 | except: 113 | self.check = True #text displayable 114 | if self.check: 115 | renpy.show(self.string, at_list=[renpy.store.truecenter], layer="screens", tag="preview") 116 | else: 117 | renpy.show("preview", what=renpy.text.text.Text("No files", color="#F00"), at_list=[renpy.store.truecenter], layer="screens") 118 | renpy.restart_interaction() 119 | 120 | # def get_sensitive(self): 121 | # for n in renpy.display.image.images: 122 | # if set(n) == set(self.string.split()): 123 | # return True 124 | # else: 125 | # return False 126 | 127 | # init python: 128 | # @renpy.pure 129 | # class _ImageInputValue(ScreenVariableInputValue, FieldEquality): 130 | # 131 | # def __init__(self, variable, default=True): 132 | # super(_ImageInputValue, self).__init__(variable, default, returnable=True) 133 | # 134 | # def set_text(self, s): 135 | # if s and s[-1] == " ": 136 | # for n in renpy.display.image.images: 137 | # if set(n) == set(name.split()): 138 | # self.state[layer][name] = {} 139 | # renpy.show(name, layer=layer) 140 | # for p, d in self.props: 141 | # self.state[layer][name][p] = self.get_property(layer, name.split()[0], p, False) 142 | # all_keyframes[(name, layer, "xpos")] = [(self.state[layer][name]["xpos"], 0, None)] 143 | # remove_list = [n_org for n_org in self.state_org[layer] if n_org.split()[0] == n[0]] 144 | # for n_org in remove_list: 145 | # del self.state_org[layer][n_org] 146 | # transform_viewer.remove_keyframes(n_org, layer) 147 | # sort_keyframes() 148 | # renpy.show_screen("_action_editor", tab="images", layer=layer, name=name) 149 | # return 150 | # default = tuple(s.split()) 151 | # renpy.show_screen("_image_selecter", default=default) 152 | # super(_ImageInputValue, self).set_text(s) 153 | # 154 | -------------------------------------------------------------------------------- /keymap.rpy: -------------------------------------------------------------------------------- 1 | init 1100 python: 2 | config.locked = False 3 | config.keymap["action_editor"] = ['P'] 4 | config.keymap["image_viewer"] = ['U'] 5 | config.locked = True 6 | 7 | 8 | -------------------------------------------------------------------------------- /spline.rpy: -------------------------------------------------------------------------------- 1 | #スプライン補間用の関数を追加します。 2 | # Add the function for spline interpolation. 3 | # _spline(sp, x) 4 | # タプル(x, y)のリストからスプライン補間を用いてxに対応する値を返します。 5 | # sp: タプル(x, y)のリスト 6 | # x: 求めるxの値 7 | 8 | 9 | 10 | 11 | # init -1 python: 12 | # class _Spline(): 13 | # def __init__(self, sp): 14 | # self.sp = sp 15 | # self.num = len(sp)-1 16 | # MaxSplineSize = self.num + 1 17 | # self.a = [0]*MaxSplineSize 18 | # self.b = [0]*MaxSplineSize 19 | # self.c = [0]*MaxSplineSize 20 | # self.d = [0]*MaxSplineSize 21 | # 22 | # w = [0]*MaxSplineSize 23 | # for i in range(0, self.num+1): 24 | # self.a[i] = sp[i][0] 25 | # 26 | # self.c[0] = self.c[self.num] = 0.0 27 | # for i in range(1, self.num): 28 | # self.c[i] = 3.0 * (self.a[i+1] - self.a[i])/float(sp[i+1][1]-sp[i][1]) - 3.0 * (self.a[i]-self.a[i-1])/float(sp[i][1]-sp[i-1][1]) 29 | # w[0]=0.0 30 | # for i in range(1, self.num): 31 | # tmp = 2*(sp[i+1][1]-sp[i-1][1]) - w[i-1] 32 | # self.c[i] = (self.c[i] - (sp[i][1]-sp[i-1][1])*self.c[i-1])/float(tmp) 33 | # w[i] = (sp[i+1][1]-sp[i][1]) / float(tmp) 34 | # for i in range(self.num-1, 0, -1): 35 | # self.c[i] = self.c[i] - self.c[i+1] * w[i] 36 | # 37 | # self.b[self.num] = self.d[self.num] =0.0 38 | # for i in range(0, self.num): 39 | # self.d[i] = ( self.c[i+1] - self.c[i]) / (3.0*(sp[i+1][1]-sp[i][1])) 40 | # self.b[i] = (self.a[i+1] - self.a[i])/float(sp[i+1][1]-sp[i][1]) - (sp[i+1][1]-sp[i][1])*(self.c[i+1]+2.0*self.c[i])/3.0 41 | # 42 | # def culc(self, t): 43 | # for i in range(0, len(self.sp)): 44 | # if t < self.sp[i][1]: 45 | # j = i - 1 46 | # break 47 | # else: 48 | # j = len(self.sp) - 2 49 | # 50 | # dt = float(t) - float(j); 51 | # return self.a[j] + ( self.b[j] + (self.c[j] + self.d[j] * dt) * dt ) * dt 52 | init python: 53 | def _spline(sp, x): 54 | 55 | # スプライン補間関数 56 | # sp : [(x, y)]既知の点群 57 | # x : xの値 58 | # 戻り値 : xに対応する関数の値 59 | N = len(sp) 60 | idx = -1 61 | h = [0]*(N-1) 62 | b = [0]*(N-1) 63 | d = [0]*(N-1) 64 | g = [0]*(N-1) 65 | u = [0]*(N-1) 66 | r = [0]*(N) 67 | 68 | i = 1 69 | while(i 1: 95 | k = idx 96 | else: 97 | k = 1 98 | 99 | r[0] = 0.0 100 | r[N-1] = 0.0 101 | r[N-2] = u[N-2] 102 | 103 | for i in range(N-3, k, -1): 104 | r[i] = u[i] - g[i] * r[i+1] 105 | 106 | dx = x - sp[idx][0]; 107 | q = (sp[idx+1][1] - sp[idx][1]) / h[idx] - h[idx] * (r[idx+1] + 2.0 * r[idx]) / 3.0 108 | s = (r[idx+1] - r[idx]) / (3.0 * h[idx]) 109 | 110 | return sp[idx][1] + dx * (q + dx * (r[idx] + s * dx)) 111 | --------------------------------------------------------------------------------