#strict 2 global func ResetTransform(overlays) { for(var overlay in TransformOverlays(overlays)) { if(!overlay) SetObjDrawTransform(0, 0, 0, 0, 0, 0, this, overlay); else SetObjDrawTransform(1000, 0, 0, 0, 1000, 0, this, overlay); } } global func SetTransform(array transforms, overlays) { for(var overlay in TransformOverlays(overlays)) { ResetTransform(overlay); AddTransform(transforms, overlay); } } global func AddTransform(array transforms, overlays) { for(var overlay in TransformOverlays(overlays)) { for(var transform in transforms) { SetObjDrawTransform2(transform[0][0], transform[0][1], transform[0][2], transform[1][0], transform[1][1], transform[1][2], transform[2][0], transform[2][1], transform[2][2], overlay); } } } global func TransformOverlays(overlays) { if(!overlays || GetType(overlays) == C4V_Int) { if(overlays >= 0) return [overlays]; else { var ret = []; overlays = Abs(overlays); for(var i = 0; i <= overlays; ++i) { ret[] = i; } return ret; } } else if(GetType(overlays) == C4V_Array) { var ret = [], last; last = overlays[0]; var i = 1; if(last < 0) { i = 0; last = 0; } else { ret[0] = last; } for(; i < GetLength(overlays); ++i) { var overlay = overlays[i]; if(overlay < 0) { overlay = Abs(overlay); for(var j = last + 1; j <= overlay; ++j) { ret[] = j; } } else { ret[] = overlay; } last = overlay; } return ret; } else { FatalError("TransformOverlays: overlays must be a single integer or an array."); } } global func Rotate() { return RotateZ(...); } global func RotateX(int phi, int prec) { prec = prec || 1; var cos = Cos(phi, 1000, prec); var sin = Sin(phi, 1000, prec); return [ [1000, 0, 0], [ 0, cos, -sin], [ 0, sin, cos] ]; } global func RotateY(int phi, int prec) { prec = prec || 1; var cos = Cos(phi, 1000, prec); var sin = Sin(phi, 1000, prec); return [ [ cos, 0, sin], [ 0, 1000, 0], [-sin, 0, cos] ]; } global func RotateZ(int phi, int prec) { prec = prec || 1; var cos = Cos(phi, 1000, prec); var sin = Sin(phi, 1000, prec); return [ [cos, -sin, 0], [sin, cos, 0], [ 0, 0, 1000] ]; } global func Scale3D(int x, int y, int z) { return [ [x, 0, 0], [0, y, 0], [0, 0, z] ]; } global func Scale2D(int x, int y) { return Scale3D(x, y, 1000); } global func ScaleX(int f) { return Scale3D(f, 1000, 1000); } global func ScaleY(int f) { return Scale3D(1000, f, 1000); } global func ScaleZ(int f) { return Scale3D(1000, 1000, f); } global func Translate2D(int x, int y, int prec) { prec = prec || 1; return [ [1000, 0, x * 1000 / prec], [ 0, 1000, y * 1000 / prec], [ 0, 0, 1000] ]; } global func TranslateX(int x, int prec) { return Translate2D(x, 0, prec); } global func TranslateY(int y, int prec) { return Translate2D(0, y, prec); } global func MirrorX() { return [ [-1000, 0, 0], [ 0, 1000, 0], [ 0, 0, 1000] ]; } global func MirrorY() { return [ [1000, 0, 0], [ 0, -1000, 0], [ 0, 0, 1000] ]; } global func Skew2D(int x, int y) { return [ [1000, x, 0], [ y, 1000, 0], [ 0, 0, 1000] ]; } global func SkewX(int x) { return Skew2D(x, 0); } global func SkewY(int y) { return Skew2D(0, y); } global func Matrix3x3Multiply(array a, array b, int precision) { return [ [(a[2][0] * b[0][2] + a[1][0] * b[0][1] + a[0][0] * b[0][0]) / precision, (a[2][1] * b[0][2] + a[1][1] * b[0][1] + a[0][1] * b[0][0]) / precision, (a[2][2] * b[0][2] + a[1][2] * b[0][1] + a[0][2] * b[0][0]) / precision], [(a[2][0] * b[1][2] + a[1][0] * b[1][1] + a[0][0] * b[1][0]) / precision, (a[2][1] * b[1][2] + a[1][1] * b[1][1] + a[0][1] * b[1][0]) / precision, (a[2][2] * b[1][2] + a[1][2] * b[1][1] + a[0][2] * b[1][0]) / precision], [(a[2][0] * b[2][2] + a[1][0] * b[2][1] + a[0][0] * b[2][0]) / precision, (a[2][1] * b[2][2] + a[1][1] * b[2][1] + a[0][1] * b[2][0]) / precision, (a[2][2] * b[2][2] + a[1][2] * b[2][1] + a[0][2] * b[2][0]) / precision] ]; } // Combines several transforms (as used for SetTransform) into one transform. Returns a single transform (like all other transform functions). // May be used to cache transforms. For direct application use SetTransform instead, which implicitly uses the native engine implementation of matrix multiplication. global func PreTransform(array transforms) { if(GetLength(transforms) == 0) { FatalError("PreTransform called without transforms."); } else { var ret = transforms[0]; for(var i = 1; i < GetLength(transforms); ++i) { ret = Matrix3x3Multiply(ret, transforms[i], 1000); } return ret; } } // Examples // Clonk with giant head: // GetCursor(0)->SetTransform([TranslateY(8), RotateX(4), ScaleZ(400), TranslateY(-10)]) // 3D-Rotating Hut: // Schedule("FindObject(HUT2)->SetTransform([TranslateY(-20), RotateZ(++Global(0)), TranslateY(0), RotateX(-1), TranslateY(20)])", 1, 10000) // 3D-Rotating Clonk: // Schedule("GetCursor(0)->SetTransform([TranslateY(-8), RotateZ(++Global(0)), TranslateY(0), RotateX(-2), TranslateY(8)])", 1, 10000)