omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular
    1. Home
    2. Robert_Tompkins

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    • Profile
    • Following 1
    • Followers 2
    • Topics 6
    • Posts 55
    • Best 1
    • Controversial 0
    • Groups 0

    Robert_Tompkins

    @Robert_Tompkins

    1
    Reputation
    1014
    Profile views
    55
    Posts
    2
    Followers
    1
    Following
    Joined Last Online

    Robert_Tompkins Unfollow Follow

    Best posts made by Robert_Tompkins

    • RE: Imported image as Scene background

      Just an update, yes, I still play with this off/on. Minor tweaks, adding ideas, etc..
      Anyway. I managed to improve the performance of the game by doing the following.

      I found that ‘generating’ lists of meteors(parent=self) as well as projectiles(parent=self) at the start of the game helps. For example, 500 basic meteors.. 2000 laserProjectiles.
      Each time a new meteor is to be spawned, I pop it from the list and move on.
      Each time a projectile is to be spawned, I pop it and move on as well.

      The Stage Timer is happy at 15 seconds (60 second Boss Round).
      Each time the Stage Timer hits 0, the Stage Number increments. When this happens, if Stage Number % 10 != 0, I check the length of each list. If any list is less than a threshold, I enter a function that generates objects.
      If any list count is VERY low, I append 1000/4000 meteors/projectiles to their respective list.
      Otherwise, I generate less of each, just enough to double the threshold. This prevents frame drops due to excess generation mid-stage and small ‘loading’ times between stages is acceptable. Like 100ms loading times lol.

      I found that generating initial lists that are >10000 or totaling ~20k children, the frames drop even if none of those children are in-view. I assume memory issues. So I try to keep the lists just large enough to sustain them to the next Stage.

      So to put it simply... Create lists at startup with items, pop from the lists as needed, and refill the lists as needed between stages. In emergencies mid-stage, I am able to call the generation function as well, to prevent popping from an empty list.

      Anyway, thanks again for everybody’s help with this!

      Oops, this appears to be what @JonB was recommending all that time ago..
      Thanks Jon, now I get it ;)

      posted in Pythonista
      Robert_Tompkins
      Robert_Tompkins

    Latest posts made by Robert_Tompkins

    • RE: How to convert an UI image to a Pillow image

      @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
      Robert_Tompkins
      Robert_Tompkins
    • RE: How to convert an UI image to a Pillow image

      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
      Robert_Tompkins
      Robert_Tompkins
    • RE: Generate UI code from .pyui

      @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
      Robert_Tompkins
      Robert_Tompkins
    • Generate UI code from .pyui

      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
      Robert_Tompkins
      Robert_Tompkins
    • RE: Numbers behave like strings in iPhone

      @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
      Robert_Tompkins
      Robert_Tompkins
    • RE: Numbers behave like strings in iPhone

      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
      Robert_Tompkins
      Robert_Tompkins
    • RE: Numbers behave like strings in iPhone

      @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
      Robert_Tompkins
      Robert_Tompkins
    • Custom theme suggestion

      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
      Robert_Tompkins
      Robert_Tompkins
    • RE: ui.Path(), Scene question regarding drawing circle segments

      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
      Robert_Tompkins
      Robert_Tompkins
    • RE: ui.Path(), Scene question regarding drawing circle segments

      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
      Robert_Tompkins
      Robert_Tompkins