/
skeleton.js
162 lines (126 loc) · 2.91 KB
/
skeleton.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/** functions to manipulate skeletons: init, rendering and utilities **/
function _13SkelInit(tb, skipIndex) {
if(tb.path != null)
{
var _cw = tb.size * 2;
var _ch = tb.size * 3;
tb.texture = _13Canv(_cw, _ch);
var _ctx = tb.texture.getContext('2d');
_ctx.translate(_cw / 2, _ch / 3); // paths goes -0.5 < x < 0.5, 0 < y < 1
_13Each(tb.path, function(_cPath) {
_13Path(_ctx, _cPath, tb.size);
});
tb.path = null;
// SHADE ON Z
if(tb.z != null)
{
_ctx.fillStyle = 'rgba(0,0,0,0.1)';
_ctx.globalCompositeOperation = 'source-atop';
_13Rep(tb.z, function () {
_ctx.fillRect(-_cw / 2, -_ch / 2, _cw, _ch);
});
}
}
if(tb.link != null)
{
_13Each(tb.link, function(_tl) {
_13SkelInit(_tl, true);
});
}
if(!skipIndex)
{
_13Skel_Index(tb);
}
}
function _13Skel_Index(tb, rootBone) {
// building index to fast access to named bones
// also useful because accessing bones by name means they can change position in the tree and be found anyway
if(rootBone == null) {
rootBone = tb;
tb.bones = {};
}
if(tb.name != null)
{
if(rootBone.bones[tb.name] == null) rootBone.bones[tb.name] = [];
rootBone.bones[tb.name].push(tb);
}
if(tb.link != null)
{
_13Each(tb.link, function(_tl) {
_13Skel_Index(_tl, rootBone);
});
}
}
function _13SkelDraw(tctx, tb) {
tctx.save();
tctx.translate(tb.x, tb.y);
tctx.rotate(tb.rot);
if(tb.scale != null)
{
tctx.scale(tb.scale.x, tb.scale.y);
}
tctx.translate(0, tb.size);
_13Each(tb.link, function(_tl) { // bones with the under flag must be rendered before the parent
if(_tl.under) _13SkelDraw(tctx, _tl);
})
tctx.translate(0, -tb.size);
_13Skel_DrawBone(tctx, tb)
tctx.translate(0, tb.size);
_13Each(tb.link, function(_tl) {
if(!_tl.under) _13SkelDraw(tctx, _tl);
})
tctx.restore();
}
function _13Skel_DrawBone(tctx, tb) {
if(tb.texture != null)
{
tctx.save();
if(tb.alpha != null) tctx.globalAlpha = tb.alpha;
tctx.drawImage(tb.texture, -tb.size, -tb.size);
tctx.restore();
}
}
function _13SkelClone(tb) {
var _retVal = _13ObjClone(tb);
if(tb.path != null)
{
_retVal.path = [];
_13Each(tb.path, function(_tp) {
_retVal.path.push(_13ObjClone(_tp));
});
}
if(tb.link != null)
{
_retVal.link = [];
_13Each(tb.link, function(_tl) {
_retVal.link.push(_13SkelClone(_tl));
});
}
if(tb.bones != null)
{
_13Skel_Index(_retVal);
}
return _retVal;
}
function _13SkelAllBones(tb, onBone) {
onBone(tb);
if(tb.link != null)
{
_13Each(tb.link, function(_tl) {
_13SkelAllBones(_tl, onBone);
});
}
}
function _13SkelAverage(tb, sb, tc) {
// averaging the position of two skeletons, weighted by tc
tb.x = tb.x * tc + sb.x * (1 - tc);
tb.y = tb.y * tc + sb.y * (1 - tc);
tb.rot = tb.rot * tc + sb.rot * (1 - tc);
if(tb.link != null)
{
_13Rep(tb.link.length, function(i) {
_13SkelAverage(tb.link[i], sb.link[i], tc);
});
}
return tb;
}