Codea 3.5 version (327)

I can certainly see the ObjC bindings being useful when it comes to using advanced features of iOS.

I’ve been wanting the ability to create folders directly for some time now and within a couple of hours I’ve got it working and WebRepo is making use of it already.

I think with the arrival of Swift Playgrounds 4, Codea now has some serious competition so this is a big step in the right direction for Codea in my opinion.

Speaking of WorkingCopy, it has been losing connections to Codea projects and sometimes cannot recover. Anders has reproduced the bug. However, it would be Very Useful if Codea projects were more like folders and less like documents, if that’s a description of why WorkingCopy has to jump through its own orifice to deal with Codea … and might also let us use other simpler approaches for Codea project version backup.

@UberGoober I’ll probably drop you a private note inquiring how you have WorkingCopy hooked up and whether you ever lose connection.

@RonJeffries it seems to me it might be a useful conversation at least to some degree for John and Simeon to be able to see. Yes I lose connection often. I have Working Copy synced to Codea projects and (usually) their GitHub repos too.

Mouse & Keyboard examples using the ObjC bindings (Also available as ‘MKInput’ on WebRepo):

-- Enums
MOUSELEFT = 1
MOUSERIGHT = 2
MOUSEMIDDLE = 3

-- Initial funcs used when no Keyboard or Mouse is detected
function ismousedown()
    return false
end

function hidecursor() end

function iskeydown()
    return false
end

-- Mouse callbacks
local mouse = objc.cls.GCMouse.current
if mouse then
    local mouseInput = mouse.mouseInput
    
    mouseInput.mouseMovedHandler = function(objMouse, floatDeltaX, floatDeltaY)
        mousemove(floatDeltaX, floatDeltaY)
    end
    
    mouseInput.leftButton.pressedChangedHandler = function(objButton, floatValue, boolPressed)
        if boolPressed then
            mousedown(MOUSELEFT)
        else
            mouseup(MOUSELEFT)
        end
    end
    
    -- right mouse button is optional
    if mouseInput.rightButton then
        mouseInput.rightButton.pressedChangedHandler = function(objButton, floatValue, boolPressed)
            if boolPressed then
                mousedown(MOUSERIGHT)
            else
                mouseup(MOUSERIGHT)
            end
        end
    end
        
    -- left mouse button is optional
    if mouseInput.middleButton then
        mouseInput.middleButton.pressedChangedHandler = function(objButton, floatValue, boolPressed)
            if boolPressed then
                mousedown(MOUSEMIDDLE)
            else
                mouseup(MOUSEMIDDLE)
            end
        end
    end
    
    function ismousedown(bttn)
        local mi = nil
        if bttn == MOUSELEFT then
            mi = mouseInput.leftButton
        elseif bttn == MOUSECENTER then
            mi = mouseInput.centerButton
        elseif bttn == MOUSERIGHT then
            mi = mouseInput.rightButton
        end
        
        -- Return nil if the button isn't available
        if mi == nil then
            return nil
        end
        
        return (mi.value == 1.0)
    end
    
    function hidecursor(shouldHide)
        local application = objc.cls.UIApplication.sharedApplication
        local window = application.keyWindow
        local root = window.rootViewController
        local controller = root.presentedViewController.presentedViewController
        controller.prefersPointerLocked = shouldHide
    end
end
    
-- Keyboard callbacks
local keyboard = objc.cls.GCKeyboard.coalescedKeyboard
if keyboard then
    local keyboardInput = keyboard.keyboardInput
    keyboardInput.keyChangedHandler = function(objKeyboard, objKey, intKeyCode, boolPressed)
        if boolPressed then
            keydown(intKeyCode)
        else
            keyup(intKeyCode)
        end
    end

    function iskeydown(key)
        local k = keyboardInput:buttonForKeyCode_(key)
        return (k and (k.value == 1.0)) or false
    end
end
    

-- User callback definitions
function mousemove(dx, dy) end
function mousedown(bttn) end
function mouseup(bttn) end

function keydown(key) end
function keyup(key) end

@Simeon It would be much appreciated if you could make preferspointerlocked available in some form so we can properly hide the cursor to avoid activating system gestures with the mouse.

Edit: Updated with preferspointerlocked & to correct for changes during beta.

@Steppers You should already be able to change the value of preferspointerlocked, but I’m not sure on which UIViewController it must be changed. Maybe try this one?

    local application = objc.cls.UIApplication:sharedApplication()
    local root = application.keyWindow.rootViewController
    local controller = root.presentedViewController.presentedViewController

@jfperusse It’s a readonly property unfortunately. When I’ve used it in the past I’ve had to back it with a variable that can be changed instead and have the accessor just read that.

@Steppers Oh I see. Yes we could definitely expose it on the view controller like you are suggesting!

@Steppers In version 3.5 (322), it is now possible to set the value of preferspointerlocked on our view controller. I used MKInput to test and was able to toggle visibility of the cursor. Let us know if it works for you!

@jfperusse Already beat you to it :wink:

MKInput 1.1.0 (on WebRepo) already has the hidecursor() function.

Haha nice :slight_smile:

@jfperusse Is there any chance we can check for the presence of a property or method without displaying the warning in the output when it doesn’t exist?

For example if mouseInput.middleButton then displays a warning when I’m using a trackpad with no middle mouse button.

I’d rather it just return nil and not mention it tbh.

Hey everyone, @Steppers! Just wanted to let you know that the latest beta version includes a breaking change which will require minor modifications to your projects using objc.

In previous versions, some property getters had to be accessed through a method. The most common example was objc.cls.UIApplication:sharedApplication(), where sharedApplication is actually a property. This was because of a limitation in Objective-C reflection which does not always allow us to differentiate between a property and a method.

Thanks to @Simeon, we found a better way to support this by considering non-void, parameterless methods as properties, with the exception of new, alloc and init methods.

TL;DR, in your samples, you will need to change some code to access those properties using the dot syntax instead of the colon syntax. For example, this line from MKInput:

objc.cls.GCMouse.current.mouseInput

Note also that we’ve added objc.app (objc.cls.UIApplication.sharedApplication), and objc.viewer (objc.cls.UIApplication.sharedApplication.keyWindow.rootViewController
local controller = root.presentedViewController.presentedViewController).

@jfperusse Thanks, I’ll update the example I have here on the forum but WebRepo & MKInput (from WebRepo) should already be updated to work.

I had wondered why that was so took a look at NSLua but just accepted it eventually as it wasn’t too bothersome.

That’s an odd one, as the property should exist regardless of whether the middle button is supported on the device. It’s declared as an optional GCControllerButtonInput in the SDK

@Steppers Do you still have the warning with 326? That’s an issue I fixed last minute this morning, and I wasn’t getting the warning anymore with MKInput.

#Steppers - probably seen this before but installation of 2 and latest version, from your gist site, rrrored at times with VFS error in line 77. Tied deleting relevant files and commenting out without success. Best I got was a hang up with blank grey screen. This with version 426 Codea and previous version. Suspect I am not installing properly - any ideas?

@Simeon, if my Codea program is running and then i drag right from the left edge to see the code but i do not complete the action i.e. i drag the left edge back- it causes Codea to exit to the desktop.

@piinthesky Does it exit to the desktop without crashing Codea. When I do the above test on my iPad, I go back to the iPad home screen with a Codea crash popup.

@dave1707 thanks for the report, I made this change to fix a different but, but I was aware it could make things slow. I’ll have to look into an alternate fix

@Bri_G I’ve just tried a clean install of WebRepo 2.1.1 using Codea 326 without issue.

Delete the WebRepo project & the folder ‘webrepocache_vfs’ in Codea’s documents folder (using the files app) and try a fresh install again. If it’s a VFS issue I suspect the cache folder has got corrupted somehow. If that doesn’t help let me know.