How the heck is this 2.4 MB?

Four tabs, none of them very large, but Codea reports a 2.4 MB file when zipped.

Main tab:


-- OrbitViewer Positioner

function setup()
    
    scene = craft.scene()
    sceneEntity = scene:entity()
    sceneEntity:add(craft.renderer, craft.model(asset.builtin.Watercraft.watercraftPack_003_obj))
    
    useStoredCameraPosition(sceneEntity)
    local sunny = readText(asset.builtin.Environments.Night)
    local env = craft.cubeTexture(json.decode(sunny))
    scene.sky.material.envMap = env
    
    parameter.watch("viewer.rx")
    parameter.watch("viewer.ry")
    parameter.watch("viewer.zoom")
    parameter.watch("viewer.target")
    parameter.action("save positioning settings",
    function() saveSettings() end)
             
end

-- saveSettings() takes the present values of the viewer and writes them as a function in a project tab called PositioningSettings.
function saveSettings()
    local dataString = [[
function useStoredCameraPosition(target)
    viewer = scene.camera:add(OrbitViewer, target.position, 30, 2, 300)
    viewer.ry = ]]..tostring(viewer.ry).."\
"..[[
    viewer.rx = ]]..tostring(viewer.rx).."\
"..[[
    viewer.zoom = ]]..tostring(viewer.zoom).."\
"..[[
    viewer.target = vec3]]..tostring(viewer.target).."\
end"
    saveProjectTab("PositioningSettings",dataString)
    print("Settings saved to tab \"PositioningSettings\"")
end

function update(dt)
    scene:update(dt)  
end

function draw()
    update(DeltaTime)
    scene:draw()	
end

function touched(touch)
    touches.touched(touch)
end

PositioningSettings tab:


function useStoredCameraPosition(target)
    viewer = scene.camera:add(OrbitViewer, target.position, 30, 2, 300)
    viewer.ry = -227.71590876787
    viewer.rx = -1.1354887424049
    viewer.zoom = 12.011154555751
    viewer.target = vec3(-0.816804, 3.268926, 0.986790)
end

OrbitViewer tab:


-----------------------------------------
-- OrbitViewer
-- Written by John Millard
-----------------------------------------
-- Description:
-- A basic viewer that orbits a target via rotating, panning and zooming.
-- A particular point in space is used as the target.
-- Single touch rotates while pinching is used for zooming in and out.
-- Two finger drag is used for panning.
-- Attach to a camera's entity for basic first person controls:
-- i.e. scene.camera:add(OrbitViewer)
-----------------------------------------

OrbitViewer = class()

function OrbitViewer:init(entity, target, zoom, minZoom, maxZoom)
    
    self.entity = entity
    self.camera = entity:get(craft.camera)
    
    -- The camera's current target
    self.target = target or vec3(0,0,0)
    self.origin = self.target
    
    self.zoom = zoom or 5
    self.minZoom = minZoom or 1
    self.maxZoom = maxZoom or 20
    
    self.touches = {}
    self.prev = {}
    
    -- Camera rotation
    self.rx = 0
    self.ry = 0
    
    -- Angular momentum
    self.mx = 0
    self.my = 0
    
    self.sensitivity = 0.25
    
    touches.addHandler(self, 0, true)
end

-- Project a 2D point z units from the camera
function OrbitViewer:project(p,z)
    local origin, dir = self.camera:screenToRay(p)
    return origin + dir * z
end

-- Calculate overscroll curve for zooming
function scroll(x,s)
    return s * math.log(x + s) - s * math.log(s)
end

function OrbitViewer:update()
    if #self.touches == 0 then
        -- Apply momentum from previous swipe
        self.rx = self.rx + self.mx * DeltaTime
        self.ry = self.ry + self.my * DeltaTime
        self.mx = self.mx * 0.9
        self.my = self.my * 0.9
        
        -- If zooming past min or max interpolate back to limits
        if self.zoom > self.maxZoom then
            local overshoot = self.zoom - self.maxZoom
            overshoot = overshoot * 0.9
            self.zoom = self.maxZoom + overshoot
        elseif self.zoom < self.minZoom then
            local overshoot = self.minZoom - self.zoom
            overshoot = overshoot * 0.9
            self.zoom = self.minZoom - overshoot
        end
        
    elseif #self.touches == 2 then
        self.entity.position = self.prev.target - self.entity.forward * self.zoom
        
        local mid = self:pinchMid()
        local dist = self:pinchDist()
        
        local p1 = self:project(self.prev.mid, self.zoom)
        local p2 = self:project(mid,self.zoom)
        
        self.target = self.prev.target + (p1-p2)
        self.zoom = self.prev.zoom * (self.prev.dist / dist)
        
        
        if self.zoom > self.maxZoom then
            local overshoot = self.zoom - self.maxZoom
            overshoot = scroll(overshoot, 10.0)
            self.zoom = self.maxZoom + overshoot
        elseif self.zoom < self.minZoom then
            local overshoot = self.minZoom - self.zoom
            overshoot = scroll(overshoot, 10.0)
            self.zoom = self.minZoom - overshoot
        end
        
    end
    
    -- Clamp vertical rotation between -90 and 90 degrees (no upside down view)
    self.rx = math.min(math.max(self.rx, -90), 90)
    
    -- Calculate the camera's position and rotation
    local rotation = quat.eulerAngles(self.rx,  self.ry, 0)
    self.entity.rotation = rotation
    local t = vec3(self.target.x, self.target.y, self.target.z)
    self.entity.position = t + self.entity.forward * -self.zoom
end

-- Calculate the distance between the current two touches
function OrbitViewer:pinchDist()
    local p1 = vec2(self.touches[1].x, self.touches[1].y)
    local p2 = vec2(self.touches[2].x, self.touches[2].y)
    return p1:dist(p2)
end

-- Calculate the mid point between the current two touches
function OrbitViewer:pinchMid()
    local p1 = vec2(self.touches[1].x, self.touches[1].y)
    local p2 = vec2(self.touches[2].x, self.touches[2].y)
    return (p1 + p2) * 0.5
end

function OrbitViewer:touched(touch)
    if touch.tapCount == 2 then
        self.target = self.origin
    end
    
    -- Allow a maximum of 2 touches
    if touch.state == BEGAN and #self.touches < 2 then
        table.insert(self.touches, touch)
        if #self.touches == 2 then
            self.prev.target = vec3(self.target:unpack())
            self.prev.mid = self:pinchMid()
            self.prev.dist = self:pinchDist()
            self.prev.zoom = self.zoom
            self.mx = 0
            self.my = 0
        end
        return true
        -- Cache updated touches
    elseif touch.state == MOVING then
        for i = 1,#self.touches do
            if self.touches[i].id == touch.id then
                self.touches[i] = touch
            end
        end
        -- Remove old touches
    elseif touch.state == ENDED or touch.state == CANCELLED then
        for i = #self.touches,1,-1 do
            if self.touches[i].id == touch.id then
                table.remove(self.touches, i)
                break
            end
        end
        
        if #self.touches == 1 then
            self.mx = 0
            self.my = 0
        end
    end
    
    -- When all touches are finished apply momentum if moving fast enough
    if #self.touches == 0 then
        self.mx = -touch.deltaY / DeltaTime * self.sensitivity
        self.my = -touch.deltaX / DeltaTime * self.sensitivity
        if math.abs(self.mx) < 70 then
            self.mx = 0
        end
        if math.abs(self.my) < 70 then
            self.my = 0
        end
        -- When only one touch is active simply rotate the camera
    elseif #self.touches == 1 then
        self.rx = self.rx - touch.deltaY * self.sensitivity
        self.ry = self.ry - touch.deltaX * self.sensitivity
    end
    
    return false
end

And, last, Touches tab:


-----------------------------------------
-- Touches
-- Written by John Millard
-----------------------------------------
-- Description:
-- A touch management class that simplifies handling multiple touch reciever.
-----------------------------------------

local TouchHandler = class()

function TouchHandler:init(target, priority, multiTouch)
    assert(target ~= nil)
    
    self.target = target
    self.priority = priority or 0
    self.multiTouch = multiTouch or false
    self.captured = {}
    self.count = 0
end

function TouchHandler:touched(touch)
    if touch.state == BEGAN then
        if self.multiTouch or self.count == 0 then
            if self.target:touched(touch) then
                self.captured[touch.id] = true
                self.count = self.count + 1
                return true
            end
        end
    elseif touch.state == MOVING then
        if self.captured[touch.id] then
            self.target:touched(touch)
            return true
        end
    elseif touch.state == ENDED or touch.state == CANCELLED then
        if self.captured[touch.id] then
            self.target:touched(touch)
            self.captured[touch.id] = nil
            self.count = self.count - 1
            return true
        end
    end
    
    return false
end

touches = {}
touches.handlers = {}
touches.shared = {}

function touches.share(target, touch, priority)
    local fakeTouch =
    {
    x = touch.x,
    y = touch.y,
    id = touch.id,
    state = BEGAN,
    tapCount = touch.tapCount,
    deltaX = touch.deltaX,
    deltaY = touch.deltaY
    }
    
    for k,v in pairs(touches.handlers) do
        if v.target ~= target and v.priority == priority then
            v:touched(fakeTouch)
        end
    end
end

function touches.addHandler(target, priority, multiTouch)
    table.insert(touches.handlers, TouchHandler(target, priority, multiTouch))
    
    table.sort(touches.handlers, function(a,b)
        return a.priority < b.priority
    end)
end

function touches.removeHandler(target)
    local i = nil
    
    for k,v in pairs(touches.handlers) do
        if v.target == target then
            i = k
        end
    end
    
    table.remove(touches.handlers, i)
end

function touches.touched(touch)
    local captured = false
    for k,v in pairs(touches.handlers) do
        if v:touched(touch) then captured = true end
        if touch.state == BEGAN and captured then
            return true
        end
    end
    
    return captured
end

…I have way larger projects than this that zip up way smaller.

For instance Jmv38’s Sensor project is 17 tabs and zips up to 109 K.

I have no stored image, sound, texture, or model assets.

What’s going on?

@UberGoober I loaded the above code and saved it as a zip file. It shows as 3 KB. Are you sure you didn’t zip everything in Codea.

@dave1707 I’m quite sure because I’ve zipped it around ten times trying to figure out what was going on.

I bet if I copy and pasted it I’d get the same results as you, that’s a good thought.

I guess I also thought maybe @Simeon might be curious about it, in the sense that if this is a bug popping up elsewhere I might be able to provide some “in-the-field” feedback on it.

@UberGoober you should share the zip so we can see what’s extracted

@skar I tried!

I can’t attach it because 2MB is the limit for .zip attachments, lol

It’s the whole reason I found out something was up.

@UberGoober Did you try copying the above code and zipping that to see it’s size.

I added an icon image and I get 162K when all the tabs are manually pasted into a new project and zipped.

@UberGoober lol maybe dropBox?