Simple Screen Carrier V1 (ssc.lib v1)

Hi, today i updated my simple screen carrier library. Now it can do many cool things.
Main features of new version:

  1. Pre-event and pos-event user-defined function calls
  2. Global variables overload
  3. Simple Codea-like I/O interface
  4. Pastebin access
  5. Shorter code
  6. All code are comented now
    Library description:
    =======
    This library contains two classes:
    Struct_touch class:

First is “struct_touch” that represents information about touch-event in non constant form, also it has some service functions for main class(“screen”).
Screen class:

Second class is main class of the library. It is named “screen”.
It represents part of the main screen as single frame with it’s own drawing and touching space(or coordinate system, named it as you wish).
Also it is a container that automatically scrolls draw- and touch-event thru all of it members(object that contains in this container).
As part of main screen it automatically track WIDTH and HEIGHT global values and device orientation and corrects self width, height and position on the screen.
Width, height and position of frame can be in proportion with main screen WIDTH and HEIGHT and it can be precise value in pixels.
If it is proportions SSC(“screen” class member) will automatically detect changes in WIDTH and HEIGHT and correct self width, height and position.
Main features explanation:

  1. Pre-event and pos-event user-defined function calls:
    all “screen” class members now have two function type values: self.CallFirst and self.CallLast. self.CallFirst will be called every time before drawing all objects in frame, also it calls every
    time in touch event before objects get struct_touch from frame, it have self(screen) as first
    parameter and original touch as second parameter at call, if this function returns false statment
    then render(or touch event) skips, and self.CallLast starts working.
    self.CallLast will be called every time after drawing all objects in frame, also it calls every
    time in touch event after objects get struct_touch from frame, it have same parameters as self.CallFirst at calls.
  2. Global variables overload:
    all “screen” class members now have table type value: self.UserValues, that stores user-defined values that if it will have same name(or kye) will be changed with global values in draw- and touch-events(before self.CallFirst calls) and will be restored after self.CallLast calls ended. Globals also will be restored.
  3. Simple Codea-like I/O interface:
    i trying to follow Codea-style interface everywhere where i can.
  4. Pastebin access:
    now all library are accessible by this link: SSC.lib V1: http://pastebin.com/KTZg4zqS
  5. Shorter code:
    as it is
  6. All code are comented now:
    i am trying to substantively coment my code everywhere where i can.
    Future features and objectives:
    ===================
  7. Meshing and schrader support
  8. Minimal and Maximal versions for big and small projects
  9. Performance upgrade
  10. Reducing code size
    App example
    ========
--=====================TOUCHFINDER===================
touchfinder = class()

function touchfinder:init()
    self.pos = nil
    self.state = nil
    self.color = color(128)
end

function touchfinder:draw()
    if self.pos == nil or self.state == nil then
        return
    end
    if self.state == BEGAN then
        fill(255)
    elseif self.state == ENDED then
        fill(0)
    else
        fill(self.color)
    end
    ellipse(self.pos.x, self.pos.y, 100)
end

function touchfinder:touched(touch)
    self.pos = vec2(touch.x, touch.y)
    self.state = touch.state
end
--=====================MAINFUNC===================
function setup()
    spriteMode(CORNER)
	--global value that can be overloaded
    lol = 1
    scr1 = screen(0.5, nil, nil, {lol = 2})
    scr2 = screen(0.5, nil, vec2(0.5, 0), {lol=3})
    scr1.background = color(255,0,0,10)
    scr2.background = color(0,255,0,10)
    tf1 = touchfinder()
    tf2 = touchfinder()
    tf1.color = color(255,255,0)
    tf2.color = color(0,0,255)
    scr1:push(tf1)
    scr2:push(tf2)
    --[[
    --print is very slow function
    --uncomment this section to see globals swaping
    scr1.CallFirst = function() print("First: ", lol) return true end
    scr2.CallFirst = function() print("Second: ", lol) return true end
      ]]
end

function draw()
    --[[
    --uncomment this section to see globals swaping
    print("Global: ", lol)
      ]]
    scr1:draw()
    scr2:draw()
end

function touched(touch)
    scr1:touched(touch)
    scr2:touched(touch)
end

Previous version

Simple Screen Carrier
Curent version

By Pastebin: SSC.lib V1
or by code: in first comment
Thanks for reading your comments and suggestions are welcome

--=====================STRUCT_TOUCH===================
struct_touch = class()
--this is primitive struct_ class with some service functions for screen class
--it is represents standart Codea touch class as variable not a constant(as touch class is)
function struct_touch:init(touch)
    self.id = touch.id
    self.x = touch.x
    self.y = touch.y
    self.prevX = touch.prevX
    self.prevY = touch.prevY
    self.deltaX = touch.deltaX
    self.deltaY = touch.deltaY
    self.state = touch.state
    self.tapCount = touch.tapCount
end
--defines new zero of cordinate axis
function struct_touch:newzero(position)
    self.x = self.x - position.x
    self.y = self.y - position.y 
end
--check inbound conditions for almost every spriteMode
function struct_touch:inbounds(width, height)
    if spriteMode() == CENTER or spriteMode() == RADIUS then
        return self.x < width/2 and self.y < height/2
    else
        return math.abs(self.x-width/2)<width/2 and math.abs(self.y-height/2)<height/2
    end
end
--updating without constructing new object
function struct_touch:update(touch)
    self.id = touch.id
    self.x = touch.x
    self.y = touch.y
    self.prevX = touch.prevX
    self.prevY = touch.prevY
    self.deltaX = touch.deltaX
    self.deltaY = touch.deltaY
    self.state = touch.state
    self.tapCount = touch.tapCount
end
--=====================SCREEN===================
screen = class()
--[[
main class of the screen lib
represents screen(or its fixed parts) as a frame and auto-detects WIDTH and HEIGHT constants
changing and saves self width, height and position
if position or width/height values equals 1 or less then it will be used in proportion
with main screen values of WIDTH and HEIGHT else it will be used as precise value in pixels
]]
function screen:init(Width, Height, Position, UserValues)
    --default size is float fullscreen
    self.floatsize = vec2(1,1)
    self.size = vec2(WIDTH, HEIGHT)
    self.globalWH = vec2(WIDTH, HEIGHT)
    --value that allows to not check status of all self correcting variables at every draw-event
    self.updater = false
    if Width or Height then
        if Width then
            if Width <= 1 then
                self.floatsize.x = Width
                self.size.x = WIDTH * Width
                self.updater = true
            else
                self.floatsize.x = nil
                self.size.x = Width
            end
        end
        if Height then
            if Height <= 1 then
                self.floatsize.y = Height
                self.size.y = HEIGHT * Height
                self.updater = true
            else
                self.floatsize.y = nil
                self.size.y = Height
            end
        end
    end
    self.i = image(self.size.x, self.size.y)
    --default position is fixed in (0,0) screen pixel
    self.floatposition = vec2(nil,nil)
    self.pos = vec2(0,0)
    if Position then
        if Position.x <= 1 then
            self.floatposition.x = Position.x
            self.pos.x = self.floatposition.x*WIDTH
            self.updater = true
        else
            self.pos.x = Position.x
        end
        if Position.y <= 1 then
            self.floatposition.y = Position.y
            self.pos.y = self.floatposition.y*HEIGHT
            self.updater = true
        else
            self.pos.y = Position.y
        end
    end
--array of objects that are visible and toucheble in this frame
    self.objects = {} 
    self.visible = true 
    self.enable = true
--force to copy last frame every draw call if true
    self.copylastframe = false
    self.background = color(0,255)
--reserved memory for struct_touch
    self.CurentTouch = struct_touch(CurrentTouch)
--[[
this functions calls every time before drawing all objects in frame, also it calls every 
time in touch event before objects get struct_touch from frame, it have self(screen) as first 
parameter and original touch as second parameter at call, if this function returns false statment 
then render(or touch event) skips, and CallLast starts working
]]
    self.CallFirst = function() return true end 
--[[
this functions calls every time after drawing all objects in frame, also it calls every 
time in touch event after objects get struct_touch from frame, it have self(screen) as first
 parameter and original touch as second parameter at call
]]
    self.CallLast = function() return true end
--[[
UserValues is a table of local(for this screen) values defined by user, it MUST be table,
keys are the same as in user-defined table, global values that have the same key automatically
swaps in touch and draw events before CallFirst calls and after CallLast calls
]]
    self.UserValues = {}
    local varCount = 0
    if type(UserValues) == "table" then
        for k,v in pairs(UserValues) do
            self.UserValues[k] = v
            varCount = varCount + 1
        end
    else
        --for not tables
        self.UserValues = nil
    end
    if varCount == 0 then
        --for zero value tables (aka {})
        self.UserValues = nil
    end
--buffer for global swaping
    self.buff = nil
end
--draw-event handler
function screen:draw()
    if not self.enable or not self.visible then
        return
    end
    if ((self.globalWH.x ~= WIDTH) or (self.globalWH.y ~= HEIGHT)) and self.updater then
        self:update()
    end
    pushStyle()
    setContext(self.i)
    if not self.copylastframe then
        fill(self.background)
        rect(0,0,self.size.x,self.size.y)
    end
    if self.UserValues then
        for k,v in pairs(self.UserValues) do
            if _G[k] then
                self.buff = _G[k]
                _G[k] = v
                self.UserValues[k] = self.buff
            end
        end
    end
    if self.CallFirst(self) then
        for _,v in pairs(self.objects) do
            v:draw()
        end
    end
    self.CallLast(self)
    if self.UserValues then
        for k,v in pairs(self.UserValues) do
            if _G[k] then
                self.buff = _G[k]
                _G[k] = v
                self.UserValues[k] = self.buff
            end
        end
    end 
    setContext()
    popStyle()
    sprite(self.i, self.pos.x, self.pos.y)
end
--touch-event handler
function screen:touched(touch)
    if not self.enable then
        return
    end
    self.CurentTouch:update(touch)
    self.CurentTouch:newzero(self.pos)
    if not self.CurentTouch:inbounds(self.size.x, self.size.y) then
        return false
    end
    if self.UserValues then
        for k,v in pairs(self.UserValues) do
            if _G[k] then
                self.buff = _G[k]
                _G[k] = v
                self.UserValues[k] = self.buff
            end
        end
    end
    if self.CallFirst(self, touch) then
        for _,v in pairs(self.objects) do
            v:touched(self.CurentTouch)
        end
    end
    self.CallLast(self, touch)
    if self.UserValues then
        for k,v in pairs(self.UserValues) do
            if _G[k] then
                self.buff = _G[k]
                _G[k] = v
                self.UserValues[k] = self.buff
            end
        end
    end 
    return true
end
--function that updates width, height and position
function screen:update()
    self.globalWH.x = WIDTH
    self.globalWH.y = HEIGHT
    if self.floatsize.x then
        self.size.x = WIDTH*self.floatsize.x
    end
    if self.floatsize.y then
        self.size.y = HEIGHT*self.floatsize.y
    end
    self.i = image(self.size.x, self.size.y)
    if self.floatposition.x then
        self.pos.x = self.floatposition.x*WIDTH
    end
    if self.floatposition.y then
        self.pos.y = self.floatposition.y*HEIGHT
    end
end
--clears screen settings to default
function screen:clear()
    self.i = image(self.size.x, self.size.y)
    self.objects = {}
    self.visible = true
    self.enable = true
    self.background = color(0,255)
    self.copylastframe = false
    self.CallFirst = function() return true end
    self.CallLast = function() return true end
end
--adds new object to object list
function screen:push(obj)
    table.insert(self.objects, obj)
end
--delete last object (or object on position i) from object list, returns it
function screen:pop(i)
    return table.remove(self.objects, i)
end

Can you maybe show a little video so we can see what it does?

@Ignatz
Sorry, but i can’t, and i have couple of reasons why:

  1. Codea not supported orientation changing while video capturing, every time when i try to capture video and changes orientation of my device video capture stops without saving.
  2. This library is system-style. It helps you to do your projects quickly without meeting troubles with container-class creation while your project in coding phase and orientation changing while your project is running.

I can provide simple example of usage(as i did), but i better explain here main idea of this lib:
Usage must be simple:

  1. Create your container(“screen” class element)
  2. Push your objects in it
  3. Don’t worry, be happy:)

I’m still not sure what it does!

@Ignatz
I want to share this lib with other developers because i use something like container-class, and screen divider(class that captures touch-events in some part of the screen) class for all my big projects. But this lib includes all of it in one class with minimum amount of code and some cool build-in features(as local globals overload and pre-post-event user-defined function calls).
I am sure that i will use this lib in my future projects.