Commits

Ed Blake committed 934e228

Add pixel color methods to Script.

  • Participants
  • Parent commits e87b962

Comments (0)

Files changed (3)

 :Description: Python ctypes wrapper around AutoHotKey dll.
 :License: BSD-style, see `LICENSES.txt`_
 :Author: Ed Blake <kitsu.eb@gmail.com>
-:Date: Sep. 9 2012
-:Revision: 6
+:Date: Sep. 13 2012
+:Revision: 7
 
 Introduction
 ------------
             return False
         return True
 
+    def convert_color(self, color):
+        """Convert ahk color returned as a hex string to tuple of ints."""
+        # Colors are returned as hex (e.g. 0xc0c0c0)
+        r, g, b = color[2:4], color[4:6], color[6:8]
+        return tuple((int(c, 16) for c in (r, g, b)))
+
+    def _color_delta(self, c1, c2):
+        """Compute the total error between to colors."""
+        err = 0.0
+        for i in range(3):
+            err += abs(c1[i] - c2[i])
+        return err
+
+    def getPixel(self, x=0, y=0, opt='RGB', screen=True):
+        """Convenince wrapper around ahk PixelGetColor
+
+        Gets the pixel color at the indicated coordinates.
+        See `AHK docs <http://www.autohotkey.com/docs/commands/PixelGetColor.htm>`_
+        for more details.
+
+        :param x: The pixel x coordinate (relative to screen).
+        :type x: int
+        :param y: The pixel y coordinate (relative to screen).
+        :type y: int
+        :param opt: Space separated color picking options.
+        :type opt: str (default='RGB')
+        :param screen: Flag to use screen or relative coordinates.
+        :type screen: bool (default=True)
+        """
+        if screen:
+            execute("CoordMode, Pixel, Screen")
+        else:
+            execute("CoordMode, Pixel, Reletive")
+
+        execute("PixelGetColor, {0}, {1}, {2}, RGB".format(
+            self._tmpname, x, y))
+        return self.convert_color(get(self._tmpname))
+
+    def waitPixel(self, x=0, y=0, color=None, 
+                  threshold=0.01, interval=0.5, timeout=False):
+        """Wait until the pixel at given coords changes color.
+
+        This function can wait until the indicated pixel *is* a color,
+        or until it changes color. If a color is not provided the current
+        color of the pixel when the function starts is stored and compared
+        at a regular interval until it changes or until timeout.
+
+        :param x: The pixel x coordinate (relative to screen).
+        :type x: int
+        :param y: The pixel y coordinate (relative to screen).
+        :type y: int
+        :param color: The color to wait for.
+        :type color: tuple(int r, int g, int b) or None
+        :param threshold: Error factor allowed for determining color match.
+        :type threshold: float
+        :param interval: How often the pixel color is checked.
+        :type interval: float
+        :param timeout: How long to wait for a color match.
+        :type timeout: float or None
+        :returns: True if pixel changed, False if timeout.
+        """
+        # Get starting color
+        match = True # We are trying by default to match the provided color
+        if not color:
+            match = False # If not given a color then we are trying to not match
+            color = self.getPixel(x, y)
+
+        # Timing loop
+        start = time.time()
+        last = start
+        now = start
+        while 1:
+            # Get new timing for current iteration
+            last = now
+            now = time.time()
+            # Handle timeout condition
+            if timeout and (now - start) >= timeout:
+                return False
+            # Get new color reading
+            current = self.getPixel(x, y)
+            print color, current
+            print self._color_delta(color, current)
+            # Check for match
+            if self._color_delta(color, current) <= threshold:
+                if match:
+                    return True
+            else:
+                if not match:
+                    return True
+            # Pause
+            time.sleep(interval)
+
     def message(self, text="Alert", title="Alert", options=0, timeout=None):
         """Convenience wrapper to the ahk msgbox function.
 
     def get_choices(self, control=""):
         """Retrieve the available values from a ComboBox.
 
-        :param control: The class, HWND, or text of the control to be changed.
+        :param control: The class, HWND, or text of the control to be checked.
         :type control: str
         :returns: A list of value strings (in order).
         """
     def get_chosen(self, control=""):
         """Retrieve the selected value from a ComboBox.
 
-        :param control: The class, HWND, or text of the control to be changed.
+        :param control: The class, HWND, or text of the control to be checked.
         :type control: str
         :returns: Selected value as a string.
         """
     def is_checked(self, control=""):
         """Check if a checkbox control is checked.
         
-        :param control: The class, HWND, or text of the control to be changed.
+        :param control: The class, HWND, or text of the control to be checked.
         :type control: str
         :returns: True if it was checked, else False.
         """

File doc/objects.rst

        * :meth:`.Script.winExist`
        * :meth:`.Script.waitActive`
        * :meth:`.Script.waitWindow`
+       * :meth:`.Script.convert_color`
+       * :meth:`.Script.getPixel`
+       * :meth:`.Script.waitPixel`
        * :meth:`.Script.message`
        * :meth:`.Script.msgResult`
    * :class:`.Control`
+       * :meth:`.Control.set_delay`
+       * :meth:`.Control.click`
        * :meth:`.Control.send`
-       * :meth:`.Control.click`
        * :meth:`.Control.setText`
+       * :meth:`.Control.get_choices`
+       * :meth:`.Control.get_chosen`
        * :meth:`.Control.choose`
+       * :meth:`.Control.is_checked`
+       * :meth:`.Control.check`
 
 Function
 ^^^^^^^^