Skip to content

Commit 623a028

Browse files
committed
move animation to its own file
1 parent 4f448d9 commit 623a028

File tree

3 files changed

+175
-169
lines changed

3 files changed

+175
-169
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ There are three scripts:
1010
- `dmodels_main.dsc` is the 'main' file - it contains a detailed informational header with usage details, and a configuration section.
1111
- Look through that file to learn how to use dModels.
1212
- `dmodels_loader.dsc` is the script that handles loading in `.bbmodel` files to Denizen and building the resource pack.
13-
- `dmodels_spawning.dsc` is the API script that actually handles the spawning/moving/animating/etc of models in-game.
13+
- `dmodels_spawning.dsc` is the coremost API script that handles the spawning/deleting/positioning of models in-game.
14+
- `dmodels_animating.dsc` is the script that handles animation playback for models.
1415

1516
### Related Links
1617

scripts/dmodels_animating.dsc

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
###########################
2+
# This file is part of dModels / Denizen Models.
3+
# Refer to the header of "dmodels_main.dsc" for more information.
4+
###########################
5+
6+
7+
dmodels_end_animation:
8+
type: task
9+
debug: false
10+
definitions: root_entity
11+
script:
12+
- flag <[root_entity]> dmodels_animation_id:!
13+
- flag <[root_entity]> dmodels_anim_time:0
14+
- flag server dmodels_anim_active.<[root_entity].uuid>:!
15+
- run dmodels_reset_model_position def.root_entity:<[root_entity]>
16+
17+
dmodels_animate:
18+
type: task
19+
debug: false
20+
definitions: root_entity|animation
21+
script:
22+
- run dmodels_reset_model_position def.root_entity:<[root_entity]>
23+
- define animation_data <server.flag[dmodels_data.animations_<[root_entity].flag[dmodel_model_id]>.<[animation]>]||null>
24+
- if <[animation_data]> == null:
25+
- debug error "[DModels] Cannot animate entity <[root_entity].uuid> due to model <[root_entity].flag[dmodel_model_id]> not having an animation named <[animation]>"
26+
- stop
27+
- flag <[root_entity]> dmodels_animation_id:<[animation]>
28+
- flag <[root_entity]> dmodels_anim_time:0
29+
- flag server dmodels_anim_active.<[root_entity].uuid>:<[root_entity]>
30+
31+
dmodels_move_to_frame:
32+
type: task
33+
debug: false
34+
definitions: root_entity|animation|timespot|delay_pose
35+
script:
36+
- define model_data <server.flag[dmodels_data.model_<[root_entity].flag[dmodel_model_id]>]>
37+
- define animation_data <server.flag[dmodels_data.animations_<[root_entity].flag[dmodel_model_id]>.<[animation]>]>
38+
- if <[timespot]> > <[animation_data.length]>:
39+
- choose <[animation_data.loop]>:
40+
- case loop:
41+
- define timespot <[timespot].mod[<[animation_data.length]>]>
42+
- case once:
43+
- flag server dmodels_anim_active.<[root_entity].uuid>:!
44+
- if <[root_entity].has_flag[dmodels_default_animation]>:
45+
- run dmodels_animate def.root_entity:<[root_entity]> def.animation:<[root_entity].flag[dmodels_default_animation]>
46+
- else:
47+
- run dmodels_reset_model_position def.root_entity:<[root_entity]>
48+
- stop
49+
- case hold:
50+
- define timespot <[animation_data.length]>
51+
- flag server dmodels_anim_active.<[root_entity].uuid>:!
52+
- define center <[root_entity].location.with_pitch[0].below[0.72]>
53+
- define yaw_mod <[root_entity].location.yaw.add[180].to_radians>
54+
- define parentage <map>
55+
- foreach <[animation_data.animators]> key:part_id as:animator:
56+
- define framedata.position 0,0,0
57+
- define framedata.rotation 0,0,0
58+
- foreach position|rotation as:channel:
59+
- define relevant_frames <[animator.frames].filter[get[channel].equals[<[channel]>]]>
60+
- define before_frame <[relevant_frames].filter[get[time].is_less_than_or_equal_to[<[timespot]>]].last||null>
61+
- define after_frame <[relevant_frames].filter[get[time].is_more_than_or_equal_to[<[timespot]>]].first||null>
62+
- if <[before_frame]> == null:
63+
- define before_frame <[after_frame]>
64+
- if <[after_frame]> == null:
65+
- define after_frame <[before_frame]>
66+
- if <[before_frame]> == null:
67+
- define data 0,0,0
68+
- else:
69+
- define time_range <[after_frame.time].sub[<[before_frame.time]>]>
70+
- if <[time_range]> == 0:
71+
- define time_percent 0
72+
- else:
73+
- define time_percent <[timespot].sub[<[before_frame.time]>].div[<[time_range]>]>
74+
- choose <[before_frame.interpolation]>:
75+
- case catmullrom:
76+
- define before_extra <[relevant_frames].filter[get[time].is_less_than[<[before_frame.time]>]].last||null>
77+
- if <[before_extra]> == null:
78+
- define before_extra <[animation_data.loop].equals[loop].if_true[<[relevant_frames].last>].if_false[<[before_frame]>]>
79+
- define after_extra <[relevant_frames].filter[get[time].is_more_than[<[after_frame.time]>]].first||null>
80+
- if <[after_extra]> == null:
81+
- define after_extra <[animation_data.loop].equals[loop].if_true[<[relevant_frames].first>].if_false[<[after_frame]>]>
82+
- define p0 <[before_extra.data].as_location>
83+
- define p1 <[before_frame.data].as_location>
84+
- define p2 <[after_frame.data].as_location>
85+
- define p3 <[after_extra.data].as_location>
86+
- define data <proc[dmodels_catmullrom_proc].context[<[p0]>|<[p1]>|<[p2]>|<[p3]>|<[time_percent]>]>
87+
- case linear:
88+
- define data <[after_frame.data].as_location.sub[<[before_frame.data]>].mul[<[time_percent]>].add[<[before_frame.data]>].xyz>
89+
- case step:
90+
- define data <[before_frame.data]>
91+
- define framedata.<[channel]> <[data]>
92+
- define this_part <[model_data.<[part_id]>]>
93+
- define this_rots <[this_part.rotation].split[,].parse[to_radians]>
94+
- define pose <[this_rots].get[1].mul[-1]>,<[this_rots].get[2].mul[-1]>,<[this_rots].get[3]>
95+
- define parent_id <[this_part.parent]>
96+
- define parent_pos <location[<[parentage.<[parent_id]>.position]||0,0,0>]>
97+
- define parent_rot <location[<[parentage.<[parent_id]>.rotation]||0,0,0>]>
98+
- define parent_offset <location[<[parentage.<[parent_id]>.offset]||0,0,0>]>
99+
- define parent_raw_offset <[model_data.<[parent_id]>.origin]||0,0,0>
100+
- define rel_offset <location[<[this_part.origin]>].sub[<[parent_raw_offset]>]>
101+
- define rot_offset <[rel_offset].proc[dmodels_rot_proc].context[<[parent_rot]>]>
102+
- define new_pos <[framedata.position].as_location.proc[dmodels_rot_proc].context[<[parent_rot]>].add[<[rot_offset]>].add[<[parent_pos]>]>
103+
- define new_rot <[framedata.rotation].as_location.add[<[parent_rot]>].add[<[pose]>]>
104+
- define parentage.<[part_id]>.position <[new_pos]>
105+
- define parentage.<[part_id]>.rotation <[new_rot]>
106+
- define parentage.<[part_id]>.offset <[rot_offset].add[<[parent_offset]>]>
107+
- foreach <[root_entity].flag[dmodel_anim_part.<[part_id]>]||<list>> as:ent:
108+
- teleport <[ent]> <[center].add[<[new_pos].div[16].rotate_around_y[<[yaw_mod].mul[-1]>]>]>
109+
- adjust <[ent]> reset_client_location
110+
- define radian_rot <[new_rot].xyz.split[,]>
111+
- define pose <[radian_rot].get[1]>,<[radian_rot].get[2]>,<[radian_rot].get[3]>
112+
- if <[delay_pose]>:
113+
- adjust <[ent]> armor_pose:[head=<[ent].flag[dmodels_next_pose].if_null[<[ent].flag[dmodel_def_pose]>]>]
114+
- flag <[ent]> dmodels_next_pose:<[pose]>
115+
- else:
116+
- adjust <[ent]> armor_pose:[head=<[pose]>]
117+
- adjust <[ent]> send_update_packets
118+
119+
dmodels_rot_proc:
120+
type: procedure
121+
debug: false
122+
definitions: loc|rot
123+
script:
124+
- determine <[loc].rotate_around_x[<[rot].x.mul[-1]>].rotate_around_y[<[rot].y.mul[-1]>].rotate_around_z[<[rot].z>]>
125+
126+
dmodels_catmullrom_get_t:
127+
type: procedure
128+
debug: false
129+
definitions: t|p0|p1
130+
script:
131+
# This is more complex for different alpha values, but alpha=1 compresses down to a '.vector_length' call conveniently
132+
- determine <[p1].sub[<[p0]>].vector_length.add[<[t]>]>
133+
134+
dmodels_catmullrom_proc:
135+
type: procedure
136+
debug: false
137+
definitions: p0|p1|p2|p3|t
138+
script:
139+
# Zero distances are impossible to calculate
140+
- if <[p2].sub[<[p1]>].vector_length> < 0.01:
141+
- determine <[p2]>
142+
# Based on https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline#Code_example_in_Unreal_C++
143+
# With safety checks added for impossible situations
144+
- define t0 0
145+
- define t1 <proc[dmodels_catmullrom_get_t].context[0|<[p0]>|<[p1]>]>
146+
- define t2 <proc[dmodels_catmullrom_get_t].context[<[t1]>|<[p1]>|<[p2]>]>
147+
- define t3 <proc[dmodels_catmullrom_get_t].context[<[t2]>|<[p2]>|<[p3]>]>
148+
# Divide-by-zero safety check
149+
- if <[t1].abs> < 0.001 || <[t2].sub[<[t1]>].abs> < 0.001 || <[t2].abs> < 0.001 || <[t3].sub[<[t1]>].abs> < 0.001:
150+
- determine <[p2].sub[<[p1]>].mul[<[t]>].add[<[p1]>]>
151+
- define t <[t2].sub[<[t1]>].mul[<[t]>].add[<[t1]>]>
152+
# ( t1-t )/( t1-t0 )*p0 + ( t-t0 )/( t1-t0 )*p1;
153+
- define a1 <[p0].mul[<[t1].sub[<[t]>].div[<[t1]>]>].add[<[p1].mul[<[t].div[<[t1]>]>]>]>
154+
# ( t2-t )/( t2-t1 )*p1 + ( t-t1 )/( t2-t1 )*p2;
155+
- define a2 <[p1].mul[<[t2].sub[<[t]>].div[<[t2].sub[<[t1]>]>]>].add[<[p2].mul[<[t].sub[<[t1]>].div[<[t2].sub[<[t1]>]>]>]>]>
156+
# FVector A3 = ( t3-t )/( t3-t2 )*p2 + ( t-t2 )/( t3-t2 )*p3;
157+
- define a3 <[a1].mul[<[t2].sub[<[t]>].div[<[t2]>]>].add[<[a2].mul[<[t].div[<[t2]>]>]>]>
158+
# FVector B1 = ( t2-t )/( t2-t0 )*A1 + ( t-t0 )/( t2-t0 )*A2;
159+
- define b1 <[a1].mul[<[t2].sub[<[t]>].div[<[t2]>]>].add[<[a2].mul[<[t].div[<[t2]>]>]>]>
160+
# FVector B2 = ( t3-t )/( t3-t1 )*A2 + ( t-t1 )/( t3-t1 )*A3;
161+
- define b2 <[a2].mul[<[t3].sub[<[t]>].div[<[t3].sub[<[t1]>]>]>].add[<[a3].mul[<[t].sub[<[t1]>].div[<[t3].sub[<[t1]>]>]>]>]>
162+
# FVector C = ( t2-t )/( t2-t1 )*B1 + ( t-t1 )/( t2-t1 )*B2;
163+
- determine <[b1].mul[<[t2].sub[<[t]>].div[<[t2].sub[<[t1]>]>]>].add[<[b2].mul[<[t].sub[<[t1]>].div[<[t2].sub[<[t1]>]>]>]>]>
164+
165+
dmodels_animator:
166+
type: world
167+
debug: false
168+
events:
169+
on tick server_flagged:dmodels_anim_active:
170+
- foreach <server.flag[dmodels_anim_active]> as:root:
171+
- if <[root].is_spawned||false>:
172+
- run dmodels_move_to_frame def.root_entity:<[root]> def.animation:<[root].flag[dmodels_animation_id]> def.timespot:<[root].flag[dmodels_anim_time].div[20]> def.delay_pose:true
173+
- flag <[root]> dmodels_anim_time:++

0 commit comments

Comments
 (0)