-- Gizmos in the 3D viewport (FORGE.md): the selected entity carries three arms along the world -- axes, and dragging an arm's handle moves the entity along that axis alone -- the pointer's -- travel along the arm, as a fraction of the arm, is the distance moved. FORGE_LIBRARY = true dofile("Forge/Forge.singe") local font = fontLoad("Singe/FreeSansBold.ttf", 15) local out = singeGetDataPath() local work = out .. "gizmo.game" fontSelect(font) fontQuality(FONT_QUALITY_BLENDED) overlaySetResolution(720, 480) local source = assert(io.open("testScripts/author/railshooter.game", "r")) local copy = assert(io.open(work, "w")) copy:write(source:read("a")) source:close() copy:close() if not forgeBegin(work) then debugPrint("GIZMO FAIL could not open " .. work) singeQuit() end local frames = 0 local stage = 0 local function handle(axis) for _, item in ipairs(forgeGizmoHandles()) do if item.axis == axis then return item end end return nil end local function step() local room = forgeRoom() if stage == 1 then for index, entry in ipairs(room.entities) do if entry.id == "wallL" then forgeSelect(index) end end local arms = forgeGizmoHandles() debugPrint("GIZMO the selected wall shows " .. #arms .. " arms") if #arms ~= 4 then debugPrint("GIZMO FAIL expected three axis arms and the turn handle") end elseif stage == 2 then -- Drag the Y handle the length of its own arm: the wall rises one arm's length (1.5) and -- nothing else about it changes. local entry = room.entities[FORGE.selected] local was = { x = entry.x, y = entry.y, z = entry.z } local arm = handle("y") forgePress(arm.tx, arm.ty) forgeDrag(arm.tx + (arm.tx - arm.sx), arm.ty + (arm.ty - arm.sy)) forgeRelease() debugPrint(string.format("GIZMO the Y arm took the wall from %.1f to %.1f; x %.1f to %.1f, z %.1f to %.1f", was.y, entry.y, was.x, entry.x, was.z, entry.z)) if math.abs(entry.y - (was.y + 1.5)) > 0.2 or entry.x ~= was.x or entry.z ~= was.z then debugPrint("GIZMO FAIL the Y drag did not move along Y alone") end elseif stage == 3 then -- And the X handle, dragged half an arm back. local entry = room.entities[FORGE.selected] local was = entry.x local arm = handle("x") forgePress(arm.tx, arm.ty) forgeDrag(arm.tx - (arm.tx - arm.sx) / 2, arm.ty - (arm.ty - arm.sy) / 2) forgeRelease() debugPrint(string.format("GIZMO the X arm took the wall from %.1f to %.1f", was, entry.x)) if math.abs(entry.x - (was - 0.75)) > 0.2 then debugPrint("GIZMO FAIL the X drag did not move half an arm back") end forgeKey(0, SCANCODE.U.value) forgeKey(0, SCANCODE.U.value) -- Undo puts a copy of the description in place, so the room is looked up again. local back = forgeRoom().entities[FORGE.selected] debugPrint(string.format("GIZMO two undos: the wall is back at x %.1f, y %.1f", back.x, back.y)) if back.x ~= -6 or back.y ~= 1.5 then debugPrint("GIZMO FAIL undo did not put the wall back") end elseif stage == 4 then -- The turn handle: dragged a quarter turn round the entity on screen. local entry = forgeRoom().entities[FORGE.selected] local arm = handle("ry") local dx, dy = arm.tx - arm.sx, arm.ty - arm.sy forgePress(arm.tx, arm.ty) forgeDrag(arm.sx - dy, arm.sy + dx) forgeRelease() debugPrint(string.format("GIZMO the turn handle set ry to %s", tostring(entry.ry))) if (entry.ry == nil) or (math.abs(((entry.ry - 270 + 180) % 360) - 180) > 15) then debugPrint("GIZMO FAIL a quarter turn clockwise on screen should read about 270") end debugPrint("GIZMO RESULT done") end end function onOverlayUpdate() frames = frames + 1 if frames % 14 == 0 and stage < 5 then stage = stage + 1 step() end forgeDraw(nil, nil) colorForeground(255, 255, 255, 255) fontPrint(210, 8, "gizmos, stage " .. stage) if frames == 20 or frames == 34 then singeScreenshot() end if frames > 80 then singeQuit() end return OVERLAY_UPDATED end