/* * Copyright (c) 2010-2016, Sikuli.org, sikulix.com * Released under the MIT License. * */ package org.sikuli.guide; import java.awt.Point; import java.awt.Rectangle; import java.awt.image.BufferedImage; import static java.lang.Thread.sleep; import java.util.ArrayList; import org.sikuli.basics.Debug; import org.sikuli.script.Match; import org.sikuli.script.Pattern; import org.sikuli.script.Region; import org.sikuli.script.Screen; interface TrackerListener { void patternAnchored(); } public class Tracker extends Thread { Guide guide; Pattern pattern; Region match; Screen screen; String image_filename; Pattern centerPattern; boolean initialFound = false; ArrayList<Visual> components = new ArrayList<Visual>(); ArrayList<Point> offsets = new ArrayList<Point>(); SxAnchor anchor; TrackerListener listener; boolean running; public Tracker(Pattern pattern){ //this.guide = guide; //this.match = match; screen = new Screen(); BufferedImage image; BufferedImage center; this.pattern = pattern; try { image = pattern.getBImage(); int w = image.getWidth(); int h = image.getHeight(); center = image.getSubimage(w/4,h/4,w/2,h/2); centerPattern = new Pattern(center); } catch (Exception e) { e.printStackTrace(); } //TODO Pattern with BufferedImage centerPattern = new Pattern(pattern); } public Tracker(Guide guide, Pattern pattern, Region match){ this.guide = guide; //this.match = match; screen = new Screen(); BufferedImage image; BufferedImage center; this.pattern = pattern; try { image = pattern.getBImage(); int w = image.getWidth(); int h = image.getHeight(); center = image.getSubimage(w/4,h/4,w/2,h/2); centerPattern = new Pattern(center); } catch (Exception e) { e.printStackTrace(); } } public void setAnchor(Visual component) { Point loc = component.getLocation(); //Point offset = new Point(loc.x - match.x, loc.y - match.y); Point offset = new Point(0,0);//loc.x - match.x, loc.y - match.y); offsets.add(offset); components.add(component); anchor = (SxAnchor) component; } @Override public void run(){ running = true; initialFound = true; match = null; // Looking for the target for the first time Debug.log("[Tracker] Looking for the target for the first time"); while (running && (match == null)){ match = screen.exists(pattern,0.5); } // this means the tracker has been stopped before the pattern is found if (match == null) { return; } Debug.log("[Tracker] Pattern is found for the first time"); //<editor-fold defaultstate="collapsed" desc="TODO not used currently"> // if (true){ // Rectangle bounds = match.getRect(); // anchor.found(bounds); // }else{ // // animate the initial movement to the anchor position // // // uncomment this for popup demo // anchor.moveTo(new Point(match.x, match.y), new AnimationListener(){ // public void animationCompleted(){ // anchor.anchored(); // if (listener != null){ // listener.patternAnchored(); // } // } // }); // } // //</editor-fold> Rectangle bounds = match.getRect(); anchor.found(bounds); while (running){ if (match != null && isPatternStillThereInTheSameLocation()){ //Debug.log("[Tracker] Pattern is seen in the same location."); continue; } // try for at least 1.0 sec. to have a better chance of finding the // new position of the pattern. // the first attempt often fails because the target is only a few // pixels away when the screen capture is made and it is still // due to occlusion by foreground annotations // however, it would mean it takes at least 1.0 sec to realize // the pattern has disappeared and the referencing annotations should // be hidden Match newMatch = screen.exists(pattern,1.0); if (newMatch == null){ Debug.log("[Tracker] Pattern is not found on the screen"); //anchor.setOpacity(0.0f); //not_found_counter += 1; //if (not_found_counter > 2){ anchor.addFadeoutAnimation(); anchor.startAnimation(); // not_found_counter = 0; //} }else { Debug.log("[Tracker] Pattern is found in a new location: " + newMatch); // make it visible anchor.addFadeinAnimation(); anchor.startAnimation(); // anchor.setVisible(true); // // if the match is in a different location // if (match.x != newMatch.x || match.y != newMatch.y){ // for (int i=0; i < components.size(); ++i){ // comp = components.get(i); //Point offset = offsets.get(0); // int dest_x = newMatch.x + offset.x; // int dest_y = newMatch.y + offset.y; int dest_x = newMatch.x + newMatch.w/2; int dest_y = newMatch.y + newMatch.h/2; // comp.setEmphasisAnimation(comp.createMoveAnimator(dest_x, dest_y)); //comp.startAnimation(); Debug.log("[Tracker] Pattern is moving to: (" + dest_x + "," + dest_y + ")"); anchor.moveTo(new Point(dest_x, dest_y)); } match = newMatch; } // if (!initialFound){ // Debug.log("[Tracker] Pattern has disappeared after initial find"); // // // // for (Visual comp : components){ // comp.setVisible(false); // } // guide.repaint(); // } } public void stopTracking(){ running = false; } public boolean isAlreadyTracking(Pattern pattern, Region match) { try { boolean sameMatch = this.match == match; boolean sameBufferedImage = this.pattern.getBImage() == pattern.getBImage(); boolean sameFilename = (this.pattern.getFilename() != null && (this.pattern.getFilename().compareTo(pattern.getFilename()) == 0)); return sameMatch || sameBufferedImage || sameFilename; } catch (Exception e) { return false; } } boolean isAnimationStillRunning(){ for (Visual comp : components){ if (comp instanceof SxAnchor){ if (comp.animationRunning) return true;; } } return false; } boolean isPatternStillThereInTheSameLocation(){ try { sleep(1000); } catch (InterruptedException e) { } Region center = new Region(match); //<editor-fold defaultstate="collapsed" desc="TODO Pattern with BufferedImage"> /* center.x += center.w/4-2; * center.y += center.h/4-2; * center.w = center.w/2+4; * center.h = center.h/2+4; */ //</editor-fold> Match m = center.exists(centerPattern,0); if (m == null) Debug.log("[Tracker] Pattern is not seen in the same location."); return m != null; // Debug.log("[Tracker] Pattern is still in the same location" + m); } }