• Robert_Tompkins

    @Robert_Tompkins

    Traceback (most recent call last):
      File "/private/var/mobile/Containers/Shared/AppGroup/4696D4C5-8877-4DAB-9679-C1C82C4A5C18/Pythonista3/Documents/CompletedPrograms/ImageMatching.py", line 412, in <module>
        matchImage()
      File "/private/var/mobile/Containers/Shared/AppGroup/4696D4C5-8877-4DAB-9679-C1C82C4A5C18/Pythonista3/Documents/CompletedPrograms/ImageMatching.py", line 278, in matchImage
        ImageChops.screen(image1, outlinedDiff).show()
      File "/var/containers/Bundle/Application/24BCA42A-E70C-42BD-BD39-68CECBB90922/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/PIL/ImageChops.py", line 138, in screen
        return image1._new(image1.im.chop_screen(image2.im))
    ValueError: images do not match
    

    Oops, one more conversion I guess 😅

    posted in Pythonista read more
  • Robert_Tompkins

    Possibly from here-ish?
    https://forum.omz-software.com/topic/1935/how-can-i-convert-a-pil-image-to-a-ui-image/10

    I’m going to try this out, I know very little about images/image-data. All I’m trying to do is compare two images, change pixel color for differences and draw a circle (Path.oval) around the bounds with some offset. Apparently I can’t open an image and draw on it via ImageContext.. so.. conversion, conversion, conversion, undo all conversions, .show(). Since paste() appears to be broken as well.

    posted in Pythonista read more
  • Robert_Tompkins

    @ccc ... Seriously? Lol. I open every file I’m curious about via Notepad++ just to see what’s goin on..but that’s at work/on a PC.
    Without Notepad++ the thought never crossed my mind that maybe the .pyui file contains easily extractable/readable data. It’s even in dict/json format -.-
    Well, thanks for the info. I’ll mess around with it and see if I can modify the function to serialize/deserialize the json and generate the copy/paste-able code still. This opens a world of options. Thanks!

    posted in Pythonista read more
  • Robert_Tompkins

    Hey guys, I’m just posting this here so other people can use it if they made the same mistake I did.
    I wrote many programs and later built UI files in Pythonista to complement them. However, when I wrote a math program with UI for my daughter, every change I made required me to share BOTH the .py and .pyui files in order for her to use the updated version.

    So I wrote this function/method (that is still a work in progress) to simplify this process.
    It essentially takes a UI.View() object and generates copy/paste-able code that can be pasted into your .py file to setup and configure the view so you don’t have to load a .pyui file.

    Small example of code produced from simple .pyui below. Below that is the function.
    3 ui.TextField()
    3 ui.Label()
    2 ui.Button()

    #_______________________________________________
    
    acInputField = ui.TextField()
    calculateDistanceButton = ui.Button()
    label2 = ui.Label()
    dcInputField = ui.TextField()
    label1 = ui.Label()
    arcDistanceOutputField = ui.TextField()
    label3 = ui.Label()
    resetFieldsButton = ui.Button()
    acInputField.name = 'acInputField'
    acInputField.x = 175.0
    acInputField.y = 250.0
    acInputField.width = 150.0
    acInputField.height = 32.0
    acInputField.background_color = (0.250545, 0.250545, 0.250545, 1.0)
    acInputField.border_width = 0.0
    acInputField.tint_color = (0.431645, 0.431645, 0.431645, 1.0)
    acInputField.font = ('.SFUI-Regular', 17.0)
    acInputField.text = ''
    acInputField.autoresizing = 'LRTB'
    acInputField.alignment = 0
    acInputField.flex = 'LRTB'
    acInputField.corner_radius = 0.0
    acInputField.content_mode = 0
    calculateDistanceButton.name = 'calculateDistanceButton'
    calculateDistanceButton.action = calculateDistanceTapped
    calculateDistanceButton.x = 75.0
    calculateDistanceButton.y = 350.0
    calculateDistanceButton.width = 250.0
    calculateDistanceButton.height = 75.0
    calculateDistanceButton.background_color = (0.401961, 0.401961, 0.401961, 1.0)
    calculateDistanceButton.border_width = 0.0
    calculateDistanceButton.tint_color = (0.25, 1.0, 0.25, 1.0)
    calculateDistanceButton.title = 'Calculate'
    calculateDistanceButton.font = ('.SFUI-Semibold', 20.0)
    calculateDistanceButton.autoresizing = 'TB'
    calculateDistanceButton.flex = 'TB'
    calculateDistanceButton.corner_radius = 15.0
    calculateDistanceButton.content_mode = 0
    label2.name = 'label2'
    label2.x = 25.0
    label2.y = 250.0
    label2.width = 125.0
    label2.height = 32.0
    label2.background_color = (0.251634, 0.251634, 0.251634, 1.0)
    label2.border_width = 0.0
    label2.tint_color = (0.25, 0.6084999999999998, 1.0, 1.0)
    label2.font = ('.SFUI-Regular', 18.0)
    label2.text = 'VAC'
    label2.autoresizing = 'LRTB'
    label2.alignment = 1
    label2.flex = 'LRTB'
    label2.corner_radius = 0.0
    label2.line_break_mode = 4
    label2.content_mode = 7
    label2.number_of_lines = 0
    dcInputField.name = 'dcInputField'
    dcInputField.x = 175.0
    dcInputField.y = 210.0
    dcInputField.width = 150.0
    dcInputField.height = 32.0
    dcInputField.background_color = (0.250545, 0.250545, 0.250545, 1.0)
    dcInputField.border_width = 0.0
    dcInputField.tint_color = (0.431645, 0.431645, 0.431645, 1.0)
    dcInputField.font = ('.SFUI-Regular', 17.0)
    dcInputField.text = ''
    dcInputField.autoresizing = 'LRTB'
    dcInputField.alignment = 0
    dcInputField.flex = 'LRTB'
    dcInputField.corner_radius = 0.0
    dcInputField.content_mode = 0
    label1.name = 'label1'
    label1.x = 25.0
    label1.y = 210.0
    label1.width = 125.0
    label1.height = 32.0
    label1.background_color = (0.251634, 0.251634, 0.251634, 1.0)
    label1.border_width = 0.0
    label1.tint_color = (0.25, 0.6084999999999998, 1.0, 1.0)
    label1.font = ('.SFUI-Regular', 18.0)
    label1.text = 'VDC'
    label1.autoresizing = 'LRTB'
    label1.alignment = 1
    label1.flex = 'LRTB'
    label1.corner_radius = 0.0
    label1.line_break_mode = 4
    label1.content_mode = 7
    label1.number_of_lines = 0
    arcDistanceOutputField.name = 'arcDistanceOutputField'
    arcDistanceOutputField.x = 175.0
    arcDistanceOutputField.y = 290.0
    arcDistanceOutputField.width = 150.0
    arcDistanceOutputField.height = 32.0
    arcDistanceOutputField.background_color = (0.248366, 0.248366, 0.248366, 1.0)
    arcDistanceOutputField.border_width = 0.0
    arcDistanceOutputField.tint_color = (0.32543625, 0.32543625, 0.32543625, 1.0)
    arcDistanceOutputField.font = ('.SFUI-Regular', 17.0)
    arcDistanceOutputField.text = ''
    arcDistanceOutputField.autoresizing = 'LRTB'
    arcDistanceOutputField.alignment = 0
    arcDistanceOutputField.flex = 'LRTB'
    arcDistanceOutputField.corner_radius = 0.0
    arcDistanceOutputField.content_mode = 0
    label3.name = 'label3'
    label3.x = 25.0
    label3.y = 290.0
    label3.width = 125.0
    label3.height = 32.0
    label3.background_color = (0.248366, 0.248366, 0.248366, 1.0)
    label3.border_width = 0.0
    label3.tint_color = (0.25, 0.6084999999999998, 1.0, 1.0)
    label3.font = ('.SFUI-Regular', 18.0)
    label3.text = 'Arc Distance'
    label3.autoresizing = 'LRTB'
    label3.alignment = 1
    label3.flex = 'LRTB'
    label3.corner_radius = 0.0
    label3.line_break_mode = 4
    label3.content_mode = 7
    label3.number_of_lines = 0
    resetFieldsButton.name = 'resetFieldsButton'
    resetFieldsButton.action = resetFieldsTapped
    resetFieldsButton.x = 75.0
    resetFieldsButton.y = 433.0
    resetFieldsButton.width = 250.0
    resetFieldsButton.height = 75.0
    resetFieldsButton.background_color = (0.401961, 0.401961, 0.401961, 1.0)
    resetFieldsButton.border_width = 0.0
    resetFieldsButton.tint_color = (0.25, 1.0, 0.25, 1.0)
    resetFieldsButton.title = 'Reset Fields'
    resetFieldsButton.font = ('.SFUI-Semibold', 20.0)
    resetFieldsButton.autoresizing = 'TB'
    resetFieldsButton.flex = 'TB'
    resetFieldsButton.corner_radius = 15.0
    resetFieldsButton.content_mode = 0
    fullView.add_subview(acInputField)
    fullView.add_subview(calculateDistanceButton)
    fullView.add_subview(label2)
    fullView.add_subview(dcInputField)
    fullView.add_subview(label1)
    fullView.add_subview(arcDistanceOutputField)
    fullView.add_subview(label3)
    fullView.add_subview(resetFieldsButton)
    #_______________________________________________
    
    def generateUserInterfaceCode(viewObject):
        fullView = viewObject
        listOfTypes = []
        listOfChildren = []
        dictOfObjects = {}
        debugDict = {}
        listOfObjectTypes = []
        for object in fullView.subviews:
            objectType = object._pyui['class']
            text = None
            action = None
            autoresizing = None
            alignment = None
            flex = None
            corner_radius = None
            border_color = None
            border_width = None
            background_color = None
            tint_color = None
            title = None
            font = None
            continuous = None
            content_mode = None
            line_break_mode = None
            number_of_lines = None
            
            name = object.name
            x = object.x
            y = object.y
            width = object.width
            height = object.height
            
            try:
                tint_color = object.tint_color
            except AttributeError:
                None
            try:
                border_color = object.border_color
            except AttributeError:
                None
            try:
                border_width = object.border_width
            except AttributeError:
                None
            try:
                title = f"'{object.title}'"
            except AttributeError:
                None
            try:
                text = f"'{object.text}'"
            except AttributeError:
                None
            try:
                font = object.font
            except AttributeError:
                None
            try:
                autoresizing = f"'{object.autoresizing}'"
            except AttributeError:
                None
            try:
                flex = f"'{object.flex}'"
            except AttributeError:
                None
            try:
                alignment = object.alignment
            except AttributeError:
                None
            try:
                corner_radius = object.corner_radius
            except AttributeError:
                None
            try:
                background_color = object.background_color
            except AttributeError:
                None
            try:
                continuous = object.continuous
            except AttributeError:
                None
            try:
                if object.action != None:
                    action = object.action
                    action = str(action)
                    #action = action.lstrip('<function ')
                    actionList = action.split(' ')
                    action = actionList[1]
                    if object.name == "difficultySlider":
                        action = f"difficultyChanged"
                    else:
                        action = f"{action}Tapped"
            except AttributeError:
                None
            try:
                line_break_mode = object.line_break_mode
            except AttributeError:
                None
            try:
                content_mode = object.content_mode
            except AttributeError:
                None
            try:
                number_of_lines = object.number_of_lines
            except AttributeError:
                None
            
            dictOfObjects[name] = {
                'type' : objectType,
                'action' : action,
                'x' : x,
                'y' : y,
                'width' : width,
                'height' : height,
                'background_color' : background_color,
                'border_color' : border_color,
                'border_width' : border_width,
                'tint_color' : tint_color,
                'title' : title,
                'font' : font,
                'text' : text,
                'autoresizing' : autoresizing,
                'alignment' : alignment,
                'flex' : flex,
                'corner_radius' : corner_radius,
                'continuous' : continuous,
                'line_break_mode' : line_break_mode,
                'content_mode' : content_mode,
                'number_of_lines' : number_of_lines}
            
            continuous = None
            title = None
            text = None
            
            listOfChildren.append(object)
        
        print(f"#{'_' * 47}\n")
        for k, v in dictOfObjects.items():
            print(f"{k} = ui.{v['type']}()")
        for k, v in dictOfObjects.items():
            print(f"{k}.name = '{k}'")
            for key, value in v.items():
                if value != None and key != 'type':
                    print(f"{k}.{key} = {value}")
                    
        for k, v in dictOfObjects.items():
            if k != 'type':
                print(f"fullView.add_subview({k})")
        print(f"#{'_' * 47}\n") ```

    posted in Pythonista read more
  • Robert_Tompkins

    @ccc
    Thanks! Yea... I just recently started using that lol. This is why I try writing programs for a wide range of things. Otherwise I don’t learn about these things!

    Not trying to hijack.. but how can I simplify this? Goal of this was to just strip anything that is not always used in my use-case. Like punctuation. I’m detecting text on-screen via OCR and extract it and attempt to find a match. But I want to be lenient lol.

            textString = textString.replace('[', '')
            textString = textString.replace(']', '')
            textString = textString.replace('  ', ' ')
            textString = textString.replace("'", '')
            textString = textString.strip()
            textString = textString.lower() 
    

    posted in Pythonista read more
  • Robert_Tompkins

    So I went through like 20 of my programs for a good, simple example..
    But I realized that I don’t convert any user input in-line. I prefer to do it after storing the input to a variable.
    This allows me to do my own tests on it before falling through to a default error message.

    For example, in my game, prompting for a name to be used for profile loading/saving..

    def loadProfile(self, passedPlayerName=None, resetProfile=None):
            global profileLoaded
    
            listOfDebugNames = ["admin", "ADMIN", "Admin", "sudo", "SUDO", "Sudo"]
    
            if passedPlayerName != None:
                self.playerName = passedPlayerName
            else:
                self.playerName = console.input_alert(
                    f'Please enter your Profile Name',
                    'Case Sensitive, probably',
                    hide_cancel_button=True)
                if self.playerName == "":
                    self.playerName = "NOOB"
            if self.playerName in listOfDebugNames:
                # Debug handling is done here
    

    So with string being default, you can first check if it is equal to a debug string you specify.
    Or, you can check the type of it first and handle it case by case / type by type.
    Here’s a random example of me handling two cases where the item passed to a function can be a string, or can be a list of strings.

    def getPriceEsoItem(item):
        global dictOfItemFields
        global dictOfSearches
        device = zxtouch("127.0.0.1")
        dictOfSearches = {}
        argumentType = type(item)
        
        if argumentType == list:
            for string in item:
                length = len(string)
                dictOfSearches[string] = length
        else:
            length = len(item)
            dictOfSearches[item] = length
    

    Maybe there’s a downside that I am missing.. But to me, it seems to always be better to store user input first. Then do your own handling for various input types depending on your use-case.

    posted in Pythonista read more
  • Robert_Tompkins

    @talns100 said:

    Hey, when I execute a script and enters a number as input it automatically behaves as a string.
    How to fix that? I can’t add inputs cuase of it.
    Will casting fix the problem?
    Why does it happen in the first place?

    Yes, user input is treated as a string by default but casting does fix the problem.
    Since user input can be of any type, handling it as a string is the safest way to store the value.

    You can easily cast it in-line

    userInput = int(input(“Enter an integer:\n”))
    

    Or later

    userInput = input(“Enter stuff:\n”)
    integerInput = int(userInput)
    floatInput = float(userInput)
    

    That’s my two cents!

    posted in Pythonista read more
  • Robert_Tompkins

    Unless somebody knows how to correct this.
    Let me know if you can/cannot replicate this on your device.

    Problem: Debugger window font color is black, background color is automatically set to match ‘Editor > Editor Background’ color. So text is unreadable if you use a dark editor background while using Light iPhone theme.

    Solution: Add debugger window attributes to the Custom Theme configuration options.
    This would allow us to specify the color of the text and background separately from wherever they are currently pulling their attributes from.
    Debugger Background
    Debugger Text

    Anyone else have this issue? Or found a workaround?

    posted in Pythonista read more
  • Robert_Tompkins

    Actually what you have right there is perfect!

    @JonB, I don’t need the little things! However, I will probably create a new version of this code and turn it into that for practice! I could definitely use it.
    Edit: On second thought, that sounds real complicated. I might quit Python attempting that at this point :)

    @cvp Again, those changes are exactly what I needed, thanks!
    (https://imgur.com/a/TiCqTRz)

    ^^ Dunno how to do inline images haha. I ran out of ideas, so that’s a link to what I have with your changes.

    posted in Pythonista read more
  • Robert_Tompkins

    Ooo awesome. Thanks! I have been playing around with it trying to figure out a way to o’offwet’ the starting point so that the center of the slice on each vertical and horizontal axes line up. (Like on a dartboard).

    Let me see if I can throw an image here to show you what I mean.

    posted in Pythonista read more
  • Robert_Tompkins

    @cvp
    Alright, I installed the version of stash mentioned in his repo.
    Then conveniently used pip to grab the gestures library to make sure I didn’t mess anything up.

    Now the dartboard works like a charm! Thanks again.

    I’ll play around with it and see if I can clean it up without breaking it!
    I really need to browse git for useful Pythonista modules.

    In a week or so I will be back onto the DatePicker program and understanding objC usage in what you gave me there haha. Slowly but surely..

    posted in Pythonista read more
  • Robert_Tompkins

    @cvp
    Oh, whatcha got in your gestures module? Haha. That is not included by default:p

    posted in Pythonista read more
  • Robert_Tompkins

    @cvp
    That’s perfect! Thank you a ton haha. I see that I was close on what I had..
    I will put what you have to good use, thank you!

    I just couldn’t understand why ‘18’ wouldn’t work and that ‘9’ was producing better looking results.
    But now that you gave me something that works, I can finally understand where I went wrong.
    Very much appreciated!

    posted in Pythonista read more
  • Robert_Tompkins

    Alright, I’ve been asking a lot of you guys (well, mainly @JonB and @cvp haha).
    However, I have one more question / request..

    I thought it would be something I could easily accomplish but I was wrong.
    Was hoping to write a simple program that does the following:

    — Draw a dartboard on screen (circle split into 20 equal segments is all I need)
    — This works out to be 20 segments that should be 18 degrees each (360/20)
    — Set up each segment as a clickable button
    — The button.Action will be to highlight the selected segment and place a number label on it
    — For example:
    — Tapping top center segment will highlight it and place number 1 in segment
    — Then, if I tap a 2nd segment, it highlights it (same color as first is fine) and places number 2
    — This continues for 3 total selections. However, more is fine.

    I keep running into issues doing this.. It could be my lack of Geometry skills, or that I haven’t used Path() before, or maybe I’m just not cut out for programming ;)

    What is the best way to go about doing this?
    I’ve looked for code and tried reusing a few, but I end up with a weird pie chart that doesn’t ‘slice’ where I expect it to. Or I end up with some pretty cool drawings, from an abstract point of view!

    posted in Pythonista read more
  • Robert_Tompkins

    @JonB
    Sweet, I actually have been browsing the Apple developer docs, specially UIKit stuff, because that is what I keep finding examples of and I believe that’s what OMZ based the UI elements on.

    I managed to find some stuff there, as well as created a method to help investigate objects, etc.

    def investigateItem(item):
        mysteriousItem = item
        mysteriousInfo = dir(mysteriousItem)
        for x in mysteriousInfo:
            print(f"{x}")
        
    #setScreenBrightness()
    UIScreen = ObjCClass('UIScreen')
    screen = UIScreen.mainScreen()
    investigateItem(screen) 
    

    However, I totally forgot about using the console... That is a game changer, thanks!
    I’ll check out the other info you mentioned after I play a bit via console. Is it weird that I’m excited right now? Haha. Using the console to interact/access/view attributes, etc. is going to be crazy useful.

    posted in Pythonista read more
  • Robert_Tompkins

    @cvp
    I need some help ;)

    Been struggling because I have not used objc previously. So syntax and how it’s being converted on the fly to be used to access objects, etc.. is brand new to me.

    I have been trying to play with it via adjusting my screen brightness using one of the built in objc examples:

    from objc_util import *
    from time import sleep
    def run_async(func):
        from threading import Thread
        from functools import wraps
        
        @wraps(func)
        def async_func(*args, **kwargs):
            func_hl = Thread(target = func, args = args, kwargs = kwargs)
            func_hl.start()
            return func_hl
        return async_func
    
    @on_main_thread
    def setScreenBrightness():
        UIScreen = ObjCClass('UIScreen')
        screen = UIScreen.mainScreen()
        #print(f"UIScreen.get_names(): {UIScreen.get_names()}")
        for x in range(1):
            brightnessVar = 1.0
            for x in range(995):
                screen.setBrightness(brightnessVar)
                brightnessVar -= 0.001
                sleep(0.0001)
                #print(f"screen.brightness(): {screen.brightness()}")
            for x in range(995):
                if screen.brightness() < 1.0:
                    screen.setBrightness(brightnessVar)
                    brightnessVar += 0.001
                    sleep(0.0001)
    setScreenBrightness()
    
    

    However, what would help is being able to see a list of ‘objects’ I can get/set attributes for.
    For example:

    UIScreen = ObjCClass('UIScreen')
        screen = UIScreen.mainScreen() 
    

    What is UIScreen? I assume we are letting objc create a class/do conversions/do its magic to allow us to access/modify properties of it. But what other strings/object classes are available? Is there something like ‘UIFlashlight’?

    Of course, my attempts to print out a list of ‘things’ to try and understand structure, etc.. have resulted in a HUGE list being returned.. But for me to be able to learn this stuff, I get the most out of playing around with things, tweaking, printing out what’s there, but I can’t seem to do this. But again, I don’t even know where to begin haha.

    Any resources, tips you have send them my way! But as far as the countdown code you gave me; that will work perfectly. Once I understand the basics I will be rolling through the rest.

    posted in Pythonista read more
  • Robert_Tompkins

    @cvp

    Sweet, looks like all the bits n pieces are there!
    I haven’t played around with objc_util much, so it will take some trial and error to get what I want.

    However, I see that module used all over the place, and likely for good reason.
    So I will play with it and once I get a feel for it, will see where else I can use it.

    Thanks!

    posted in Pythonista read more
  • Robert_Tompkins

    Hey guys,

    I was playing around with date picker so I could create a quick program to calculate the time until a future date for my 7 year old daughter. She always asks us “how long until my birthday??” So I made her a program that will tell her the Days, Hours, Minutes, Seconds until the date she selected in the ui.DatePicker.

    Currently, she selects a date and it outputs the delta into a textView(4 of them, one for each: D,H,M,S), which get updated in real-time (Spams the terminal if debug flag is true, but I’m cool with that).

    What I would like to do is replace the textViews with another DatePicker.
    Unfortunately, none of the modes available display all fields: D,H,M,S.

    Is there a way for me to do this?
    Ideally, I’d like a copy of the source code for DatePicker so I could resize the width of the segments to be smaller(so it all fits) and then create additional segments to display D,H,M,S and rotate each dial in real-time.

    Here is my working code as of right now:

    import ui
    import console
    import time
    import datetime
    from time import *
    from objc_util import *
    from datetime import timedelta#, datetime
    
    def run_async(func):
        from threading import Thread
        from functools import wraps
        
        @wraps(func)
        def async_func(*args, **kwargs):
            func_hl = Thread(target = func, args = args, kwargs = kwargs)
            func_hl.start()
            return func_hl
            
        return async_func
    
    birthday = [2021, 2, 21]
    
    # TODO: ##### MAIN VIEW #####
    birthdayView = ui.View()
    birthdayView.background_color = 'black'
    birthdayView.x = 0
    birthdayView.y = 0
    birthdayView.width = 100
    birthdayView.height = 100
    birthdayView.flex = "LRTB"
    #########################
    
    # TODO: ##### DATE PICKER #####
    dateSelector = ui.DatePicker()
    dateSelector.center = (birthdayView.width / 2, birthdayView.height / 2)
    dateSelector.x = birthdayView.center[0]
    dateSelector.y = birthdayView.center[1]
    dateSelector.background_color = "#AAA"
    dateSelector.mode = 1
    #########################
    
    # TODO: ##### DAYS OUTPUT FIELD #####
    daysOutputField = ui.TextView()
    daysOutputField.x = birthdayView.center[0] - 15
    daysOutputField.y = birthdayView.center[1] + 300
    daysOutputField.width = 350
    daysOutputField.height = 50
    daysOutputField.background_color = "#000"
    daysOutputField.text_color = "#F00"
    daysOutputField.font = "<system>", 18
    #########################
    
    # TODO: ##### HOURS OUTPUT FIELD #####
    hoursOutputField = ui.TextView()
    hoursOutputField.x = birthdayView.center[0] - 15
    hoursOutputField.y = birthdayView.center[1] + 355
    hoursOutputField.width = 350
    hoursOutputField.height = 50
    hoursOutputField.background_color = "#000"
    hoursOutputField.text_color = "#F00"
    hoursOutputField.font = "<system>", 22
    #########################
    
    # TODO: ##### MINUTES OUTPUT FIELD #####
    minutesOutputField = ui.TextView()
    minutesOutputField.x = birthdayView.center[0] - 15
    minutesOutputField.y = birthdayView.center[1] + 410
    minutesOutputField.width = 350
    minutesOutputField.height = 50
    minutesOutputField.background_color = "#000"
    minutesOutputField.text_color = "#F00"
    minutesOutputField.font = "<system>", 26
    #########################
    
    # TODO: ##### SECONDS OUTPUT FIELD #####
    secondsOutputField = ui.TextView()
    secondsOutputField.x = birthdayView.center[0] - 15
    secondsOutputField.y = birthdayView.center[1] + 465
    secondsOutputField.width = 350
    secondsOutputField.height = 50
    secondsOutputField.background_color = "#000"
    secondsOutputField.text_color = "#F00"
    secondsOutputField.font = "<system>", 30
    #########################
    
    #import datetime
    #from time import localtime, time, gmtime, mktime, struct_time
    
    # TODO: ##### DEBUG FLAG #####
    debugMode = 1
    #########################
    
    @run_async
    def calculateTimeUntilBirthday(sender):
        global birthday
        global dateSelector
        global countdownTimer
        global daysOutputField
        global hoursOutputField
        global minutesOutputField
        global secondsOutputField
        
        while birthdayView.on_screen:
            currentTime = datetime.datetime.now()
            birthdayTime = dateSelector.date.replace(hour = 0, minute = 0, second = 0)
            birthdayString = f"{birthdayTime.month}/{birthdayTime.day}/{birthdayTime.year}"
            timeUntilBirthday = (birthdayTime) - (currentTime)
            
            seconds = timeUntilBirthday.seconds
            hours = seconds / 3600
            
            minutesLeft = hours - int(hours)
            minutesLeftMinutes = minutesLeft * 60
            
            secondsLeft = minutesLeftMinutes - int(minutesLeftMinutes)
            secondsLeftSeconds = secondsLeft * 60
            secondsLeftSeconds = round(secondsLeftSeconds, 2)
                
            daysOutput = f"Days: {timeUntilBirthday.days}"
            daysOutputField.text = daysOutput
            
            hoursOutput = f"Hours: {int(hours)}"
            hoursOutputField.text = hoursOutput
            
            minutesOutput = f"Minutes: {int(minutesLeftMinutes)}"
            minutesOutputField.text = minutesOutput
            
            secondsOutput = f"Seconds: {int(secondsLeftSeconds)}"
            secondsOutputField.text = secondsOutput
            
            
            if debugMode:
                print(f"Current Time: {currentTime}")
                print(f"Birthday Time: {birthdayTime}")
                print(f"birthdayString: {birthdayString}")
                print(f"timeUntilBirthday: {timeUntilBirthday}")
                print(f"seconds: {seconds}")
                print(f"hours: {hours}")
                print(f"minutesLeft: {minutesLeft}")
                print(f"minutesLeftMinutes: {minutesLeftMinutes}")
                print(f"secondsLeft: {secondsLeft}")
                print(f"secondsLeftSeconds: {secondsLeftSeconds}")
                print(f"secondsLeftSeconds: {secondsLeftSeconds}")
                
                print(f"Time Until Birthday: {birthdayString}\n Days: {timeUntilBirthday.days}\n  Hours: {int(hours)}\n   Minutes: {int(minutesLeftMinutes)}\n    Seconds: {int(secondsLeftSeconds)}")
    
    
    #birthdayView.add_subview(countdownTimer)
    
    birthdayView.add_subview(dateSelector)
    birthdayView.add_subview(daysOutputField)
    birthdayView.add_subview(hoursOutputField)
    birthdayView.add_subview(minutesOutputField)
    birthdayView.add_subview(secondsOutputField)
    
    dateSelector.action = calculateTimeUntilBirthday
    birthdayView.present(hide_title_bar = True) 
    

    posted in Pythonista read more
  • Robert_Tompkins

    Alright, made some quick changes to setup what was mentioned.
    I attempted this on the Laser objects..
    I will have to dive in a little more to determine where this is happening, but here is what I noticed.

    Here is some misc. output I use for debugging that was produced when I noticed this occurring..

    Generating Lasers with 992 left
    timeToGen 2000 Lasers: 0.12253904342651367
    generateMeteorLists: 0.006246089935302734
    stage: 2
    Generating Lasers with 2993 left
    timeToGen 1000 Lasers: 0.07495284080505371
    generateMeteorLists: 3.814697265625e-06
    stage: 3
    Generating Lasers with 3995 left
    timeToGen 1000 Lasers: 0.08381533622741699
    generateMeteorLists: 3.0994415283203125e-06
    stage: 4
    maxExecutionTimeUpdate: 0.1294388771057129
    Max Star execution time: 0.0003571510314941406
    Max Item Collision execution time: 0.0007109642028808594
    Max Laser Collision execution time: 0.0007081031799316406
    Max Spawn Item execution time: 0.00047898292541503906
    Max Should Fire execution time: 0.002073049545288086
    Active weapon: laser
    Weapon Upgrades:
    self.laserFireRateLevel: 50
    self.laserNumberOfLasersLevel: 1
    self.laserPowerLevel: 1
    Dictionary of self.children and count of each:
    <class '_scene2.SpriteNode'>: 230
    <class 'scene.LabelNode'>: 5
    <class 'main.MiniRocket'>: 1000
    <class 'main.Laser'>: 4987
    <class 'main.Meteor'>: 170
    <class 'main.Star'>: 51
    <class 'main.Meteor2'>: 3
    len(listOfChildren): 6446
    self.stageNumber: 4

    I noticed that when firing lasers, I should have been firing 10 projectiles each time, but some of the projectiles were not visible. So I set a breakpoint and found that some of the lasers in my list of projectiles (contains all projectiles that have been fired and should be visible) have no parent.

    Unfortunately, the functions that may be involved in this are messy and I will need to dig around and clean up before I can efficiently get to root cause.

    posted in Pythonista read more
  • Robert_Tompkins

    So with that implementation, I believe I had issues with popping that specific meteor from the list because by the time I executed the line that popped it from active and appended it to inactive, it no longer existed. Then I had additional trouble with the meteor no longer being a child when I would attempt to ‘reactivate’ a meteor I had Previously popped from active and appended to inactive. Is there a way to remove an object from view without the parent ‘disowning’ it? Because I just sort of disown all children to get them out of sight.

    I believe the main issues I had were due to not fully understanding the relationship between parent and child, haha. With a 7 year old child of my own, I would expect to understand that by now!
    So maybe I will give it another shot. It’s unfortunate that this topic is regarding imported images as backgrounds, rather than noob problems. But I’ll be sure to update here with the new issues I run into;)

    posted in Pythonista read more
Internal error.

Oops! Looks like something went wrong!