153 lines
5.6 KiB
Text
153 lines
5.6 KiB
Text
-- The 3D calls no other scene exercised, checked against what the Reference says of them: a node
|
|
-- found by the name nodeSetName gave it, a crate lifted by bodyApplyForce, the simulation held
|
|
-- still by physicsSetEnabled and let go again, a player put somewhere by playerSetPosition, an
|
|
-- emitter deleted, navNearest snapping a point onto the floor and finding
|
|
-- nothing far off, an agent that navAgentStop halts short of its target and that arrives when sent
|
|
-- on (navAgentIsArrived), navAgentDelete, and a ragdoll that ragdollDelete frees for a new one.
|
|
-- Each check prints "SCENE3D ok" or "SCENE3D FAIL". No disc: run with -C 720x480.
|
|
dofile("Singe/Framework.singe")
|
|
|
|
local font = fontLoad("Singe/FreeSansBold.ttf", 14)
|
|
local stone = materialNew()
|
|
local wood = materialNew()
|
|
local camera = nodeNew()
|
|
local sun = lightNew(LIGHT_DIRECTIONAL)
|
|
local floor = nodeNew()
|
|
local crate = nodeNew()
|
|
local player = nodeNew()
|
|
local walker = nodeNew()
|
|
local fox = modelInstance(modelLoad("testScripts/Models/Fox.glb"))
|
|
local nav = nil
|
|
local agent = nil
|
|
local frames = 0
|
|
local failures = 0
|
|
local stage = "lift"
|
|
local mark = 0
|
|
local heldY = 0
|
|
local arrived = 0
|
|
local LAST = 900
|
|
|
|
|
|
local function check(name, ok, detail)
|
|
if ok then
|
|
debugPrint("SCENE3D ok " .. name)
|
|
else
|
|
failures = failures + 1
|
|
debugPrint("SCENE3D FAIL " .. name .. (detail and (" (" .. detail .. ")") or ""))
|
|
end
|
|
end
|
|
|
|
|
|
function onNavArrived(which)
|
|
if which == agent then
|
|
arrived = arrived + 1
|
|
end
|
|
end
|
|
|
|
|
|
fontSelect(font)
|
|
overlaySetResolution(720, 480)
|
|
sceneEnable(true)
|
|
cameraSet(camera)
|
|
nodeSetPosition(camera, 0, 9, 14)
|
|
nodeLookAt(camera, 0, 0, 0)
|
|
nodeLookAt(sun, -1, -2, -1)
|
|
materialSetColor(stone, 120, 120, 130)
|
|
materialSetColor(wood, 170, 120, 70)
|
|
nodeSetMesh(floor, meshBox(20, 0.2, 20), stone)
|
|
nodeSetPosition(floor, 0, -0.1, 0)
|
|
bodyNew(floor, BODY_STATIC, SHAPE_BOX, 20, 0.2, 20)
|
|
nodeSetMesh(crate, meshBox(0.6, 0.6, 0.6), wood)
|
|
nodeSetPosition(crate, -3, 0.3, 3)
|
|
bodyNew(crate, BODY_DYNAMIC, SHAPE_BOX, 0.6, 0.6, 0.6)
|
|
bodySetMass(crate, 1) -- So 40 newtons outweighs gravity
|
|
nodeSetName(crate, "theCrate")
|
|
check("nodeFind finds what nodeSetName named", nodeFind("theCrate") == crate)
|
|
nodeSetMesh(player, meshCylinder(0.3, 1.0, 12), wood)
|
|
nodeSetPosition(player, 0, 0.5, 0)
|
|
playerNew(player, 0.3, 1.0)
|
|
nodeSetMesh(walker, meshBox(0.4, 1.0, 0.4), wood)
|
|
nodeSetPosition(walker, -6, 0, -4)
|
|
nodeSetPosition(fox, 6, 0, -4)
|
|
nodeSetScale(fox, 0.02)
|
|
|
|
nav = navNew(0.3, 1.0, 45, 0.3)
|
|
navAddNode(nav, floor)
|
|
navBuild(nav)
|
|
do
|
|
local x, y, z = navNearest(nav, 1, 1.5, 1)
|
|
|
|
check("navNearest snaps onto the floor", (x ~= nil) and (math.abs(x - 1) < 0.3) and (math.abs(z - 1) < 0.3) and (math.abs(y) < 0.3), string.format("%s %s %s", tostring(x), tostring(y), tostring(z)))
|
|
check("navNearest finds nothing far off", navNearest(nav, 100, 0, 100) == nil)
|
|
end
|
|
agent = navAgentNew(nav, walker, 0.3, 1.0, 2.0)
|
|
navAgentMoveTo(agent, 6, 0, 4)
|
|
|
|
-- A dead handle ends the script rather than raising an error a pcall could catch, so these are
|
|
-- proved by what follows them: a second ragdollNew on a node that still had one would end the run.
|
|
emitterDelete(emitterNew())
|
|
check("emitterDelete takes the emitter", true)
|
|
ragdollNew(fox)
|
|
ragdollDelete(fox)
|
|
ragdollNew(fox)
|
|
check("ragdollDelete frees the node for a new ragdoll", true)
|
|
ragdollDelete(fox)
|
|
|
|
|
|
function onOverlayUpdate()
|
|
local cx, cy, cz = nodeGetWorldPosition(crate)
|
|
local wx, wy, wz = nodeGetWorldPosition(walker)
|
|
|
|
frames = frames + 1
|
|
overlayClear()
|
|
fontPrint(8, 6, string.format("frame %d %s crate y %.2f walker %.1f %.1f failures %d", frames, stage, cy, wx, wz, failures))
|
|
-- The crate is pushed up for a third of a second, then the simulation is held and let go.
|
|
if stage == "lift" then
|
|
bodyApplyForce(crate, 0, 40, 0)
|
|
if frames == 15 then
|
|
stage = "rising"
|
|
end
|
|
elseif stage == "rising" and frames == 18 then
|
|
check("bodyApplyForce lifts the crate", cy > 0.6, string.format("y %.2f", cy))
|
|
physicsSetEnabled(false)
|
|
stage = "held"
|
|
mark = frames
|
|
elseif stage == "held" then
|
|
if frames == mark + 2 then
|
|
heldY = cy
|
|
elseif frames == mark + 12 then
|
|
check("physicsSetEnabled(false) holds it still", math.abs(cy - heldY) < 0.001, string.format("%.3f then %.3f", heldY, cy))
|
|
physicsSetEnabled(true)
|
|
stage = "resumed"
|
|
mark = frames
|
|
end
|
|
elseif stage == "resumed" and frames == mark + 12 then
|
|
check("physicsSetEnabled(true) lets it go", math.abs(cy - heldY) > 0.01, string.format("%.3f then %.3f", heldY, cy))
|
|
playerSetPosition(player, 5, 0.6, 5)
|
|
stage = "teleported"
|
|
mark = frames
|
|
elseif stage == "teleported" and frames == mark + 3 then
|
|
local px, _, pz = nodeGetWorldPosition(player)
|
|
|
|
check("playerSetPosition puts the player there", (math.abs(px - 5) < 0.1) and (math.abs(pz - 5) < 0.1), string.format("%.2f %.2f", px, pz))
|
|
navAgentStop(agent)
|
|
stage = "stopped"
|
|
mark = frames
|
|
elseif stage == "stopped" and frames == mark + 60 then
|
|
check("navAgentStop halts it short", not navAgentIsArrived(agent) and (arrived == 0) and (math.abs(wx - 6) > 1), string.format("at %.1f %.1f", wx, wz))
|
|
navAgentMoveTo(agent, 6, 0, 4)
|
|
stage = "sent"
|
|
elseif stage == "sent" and arrived > 0 then
|
|
check("navAgentIsArrived once it is there", navAgentIsArrived(agent))
|
|
navAgentDelete(agent)
|
|
check("navAgentDelete leaves the walker where it was", (math.abs(wx - 6) < 1) and (math.abs(wz - 4) < 1), string.format("at %.1f %.1f", wx, wz))
|
|
stage = "done"
|
|
end
|
|
if (stage == "done") or (frames == LAST) then
|
|
check("everything ran", stage == "done", stage)
|
|
debugPrint(string.format("SCENE3D RESULT failures=%d frames=%d", failures, frames))
|
|
singeScreenshot("scene3d")
|
|
singeQuit()
|
|
end
|
|
return OVERLAY_UPDATED
|
|
end
|