In polygonedit.sc (Sierra's in-game polygon editor), there is a "check" method (which unfortunately my decompiler barfs on) that performs some validation on the created polygons. It removes duplicate points, for one. Then it also appears to perform some angle checks. I think it's verifying the
exterior angles of the polygon add up to 360.
The thing is, I don't see how they couldn't, given that's a mathematical property of a polygon. Is it just detecting if there will be precision errors with the engine with certain sets of polygon points?
It also flips the order of the points of the polygon if the angles add up to -360 instead. But apparently Sierra's engine can handle either CW or CCW winding order, so I'm not sure why this is necessary.
Can anyone provide any insight?
fyi, here's a decompiled version of the code. Take with a grain of salt, since some of the branching is incorrect (I hacked my decompiler to just muddle through it):
(method (check)
(var _EditablePolygonFirst, temp1, curNode, nextNode, arcTan, arcTAnDiff, _EditablePolygonFirst_2, totalAngle, ccw, lastArcTan, _EditablePolygonLast, temp11, temp12, temp13, temp14, temp15, temp16, temp17[40])
= _EditablePolygonFirst (self:first())
(while (_EditablePolygonFirst)
= curNode NodeValue(_EditablePolygonFirst)
= temp15 NextNode(_EditablePolygonFirst)
(while (temp15)
= temp16 NodeValue(temp15)
(if ((== (send temp2:x) (send temp16:x)) and (== (send temp2:y) (send temp16:y)))
= temp15 PrevNode(temp15)
(self:delete(temp16))
(send temp16:dispose())
)
= temp15 NextNode(temp15)
)
= _EditablePolygonFirst NextNode(_EditablePolygonFirst)
)
= arcTan 0
= lastArcTan 0
= totalAngle 0
= ccw 1
= _EditablePolygonFirst_2 (self:first())
= _EditablePolygonFirst _EditablePolygonFirst_2
(while (1)
= curNode NodeValue(_EditablePolygonFirst)
= temp1 (self:next(_EditablePolygonFirst))
= nextNode NodeValue(temp1)
= arcTan ATan((send curNode:x) (send curNode:y) (send nextNode:x) (send nextNode:y))
(if (not ccw)
= arcTAnDiff (- arcTan lastArcTan)
(if (> arcTAnDiff 180)
= arcTAnDiff (- arcTAnDiff 360)
)(else
(if (< arcTAnDiff -180)
= arcTAnDiff (+ arcTAnDiff 360)
)
)
= totalAngle (+ totalAngle arcTAnDiff)
)
= lastArcTan arcTan
(== _EditablePolygonFirst _EditablePolygonFirst_2) and not ccw
)
(if (== type 3)
= totalAngle neg totalAngle
)
(if (== totalAngle -360)
= _EditablePolygonFirst (self:first())
= _EditablePolygonLast (self:last())
(while ((<> _EditablePolygonFirst _EditablePolygonLast) and (<> _EditablePolygonFirst NextNode(_EditablePolygonLast)))
= temp2 NodeValue(_EditablePolygonFirst)
= temp11 NodeValue(_EditablePolygonLast)
= temp12 (send temp2:x)
= temp13 (send temp2:y)
(send temp2:x((send temp11:x)))
(send temp2:y((send temp11:y)))
(send temp11:x(temp12))
(send temp11:y(temp13))
= _EditablePolygonFirst NextNode(_EditablePolygonFirst)
= _EditablePolygonLast PrevNode(_EditablePolygonLast)
)
)(else
(if (<> totalAngle 360)
Format(@temp17 943 1 name totalAngle)
proc921_0(@temp17)
)
)
)
And the (functionally accurate) disassembled version:
(method (check)
(var temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17[40])
(asm
pushi #first
pushi 0
self 4
sat temp0
code_050c: lat temp0
bnt code_0575
pushi 1
push
callk NodeValue, 2
sat temp2
pushi 1
lst temp0
callk NextNode, 2
sat temp15
code_0520: lat temp15
bnt code_056b
pushi 1
push
callk NodeValue, 2
sat temp16
pushi #x
pushi 0
lat temp2
send 4
push
pushi #x
pushi 0
lat temp16
send 4
eq?
bnt code_0561
pushi #y
pushi 0
lat temp2
send 4
push
pushi #y
pushi 0
lat temp16
send 4
eq?
bnt code_0561
pushi 1
lst temp15
callk PrevNode, 2
sat temp15
pushi #delete
pushi 1
lst temp16
self 6
pushi #dispose
pushi 0
lat temp16
send 4
code_0561: pushi 1
lst temp15
callk NextNode, 2
sat temp15
jmp code_0520
code_056b: pushi 1
lst temp0
callk NextNode, 2
sat temp0
jmp code_050c
code_0575: ldi 0
sat temp4
ldi 0
sat temp9
ldi 0
sat temp7
ldi 1
sat temp8
pushi #first
pushi 0
self 4
sat temp6
sat temp0
code_058e: ldi 1
bnt code_061d
pushi 1
lst temp0
callk NodeValue, 2
sat temp2
pushi #next
pushi 1
lst temp0
self 6
sat temp1
pushi 1
push
callk NodeValue, 2
sat temp3
pushi 4
pushi #x
pushi 0
lat temp2
send 4
push
pushi #y
pushi 0
lat temp2
send 4
push
pushi #x
pushi 0
lat temp3
send 4
push
pushi #y
pushi 0
lat temp3
send 4
push
callk ATan, 8
sat temp4
lat temp8
not
bnt code_0602
lst temp4
lat temp9
sub
sat temp5
push
ldi 180
gt?
bnt code_05eb
lst temp5
ldi 360
sub
sat temp5
jmp code_05fb
code_05eb: lst temp5
ldi 65356
lt?
bnt code_05fb
lst temp5
ldi 360
add
sat temp5
code_05fb: lst temp7
lat temp5
add
sat temp7
code_0602: lat temp4
sat temp9
lst temp0
lat temp6
eq?
bnt code_0612
lat temp8
not
bnt code_0612
code_0612: ldi 0
sat temp8
lat temp1
sat temp0
jmp code_058e
code_061d: pTos type
ldi 3
eq?
bnt code_0629
lat temp7
neg
sat temp7
code_0629: lst temp7
ldi 65176
eq?
bnt code_06b2
pushi #first
pushi 0
self 4
sat temp0
pushi #last
pushi 0
self 4
sat temp10
code_0640: lst temp0
lat temp10
ne?
bnt code_06d6
lst temp0
pushi 1
lst temp10
callk NextNode, 2
ne?
bnt code_06d6
pushi 1
lst temp0
callk NodeValue, 2
sat temp2
pushi 1
lst temp10
callk NodeValue, 2
sat temp11
pushi #x
pushi 0
lat temp2
send 4
sat temp12
pushi #y
pushi 0
lat temp2
send 4
sat temp13
pushi #x
pushi 1
pushi #x
pushi 0
lat temp11
send 4
push
lat temp2
send 6
pushi #y
pushi 1
pushi #y
pushi 0
lat temp11
send 4
push
lat temp2
send 6
pushi #x
pushi 1
lst temp12
lat temp11
send 6
pushi #y
pushi 1
lst temp13
lat temp11
send 6
pushi 1
lst temp0
callk NextNode, 2
sat temp0
pushi 1
lst temp10
callk PrevNode, 2
sat temp10
jmp code_0640
jmp code_06d6
code_06b2: lst temp7
ldi 360
ne?
bnt code_06d6
pushi 5
lea @temp17
push
pushi 943
pushi 1
pTos name
lst temp7
callk Format, 10
pushi 1
lea @temp17
push
calle TextPrint, 2
code_06d6: ret
)
)