package com.haxademic.core.draw.mapping; import java.awt.Point; import com.haxademic.core.app.P; import com.haxademic.core.data.ConvertUtil; import com.haxademic.core.draw.context.PG; import com.haxademic.core.file.FileUtil; import processing.core.PGraphics; import processing.core.PVector; import processing.event.KeyEvent; import processing.event.MouseEvent; public class SavedPointUI { public static SavedPointUI DRAGGING_POINT; protected float mouseActiveDist = 15; protected PVector position = new PVector(); protected boolean isHovered = false; protected PVector mousePoint = new PVector(); protected String filePath = null; protected boolean writesToFile = false; protected static int lastInteractTime = 0; protected int INTERACTION_TIMEOUT = 5000; protected boolean active = false; protected boolean shiftDown = false; public SavedPointUI(int x, int y, String filePath) { this.filePath = filePath; position.set(x, y); reset(); P.p.registerMethod("mouseEvent", this); // add mouse listeners P.p.registerMethod("keyEvent", this); // prep txt file if(filePath != null) { writesToFile = true; loadMappingFile(); createMappingFile(); } } // public points setters public void setActive(boolean newActive) { if(active != newActive) { // only toggle when dirty active = newActive; if(active) { resetInteractionTimeout(); DRAGGING_POINT = this; } } } public void reset() { position.set(0, 0); if(filePath != null) save(); // only save after init } public void setPosition(float x, float y) { position.set(x, y); save(); } public PVector position() { return position; } // state getters public boolean isActive() { return active; } public boolean isHovered() { return isHovered; } // USER INTERFACE //////////////////////////////////////////// public boolean isShowing() { return P.p.millis() < lastInteractTime + INTERACTION_TIMEOUT; } public void drawDebug(PGraphics pg, boolean offscreen) { if(isShowing()) { if(offscreen) pg.beginDraw(); drawPoint(pg); if(offscreen) pg.endDraw(); } } protected void drawPoint(PGraphics pg) { PG.setDrawCenter(pg); pg.noFill(); if(active) { pg.stroke(0, 255, 0); } else { pg.stroke(255); } pg.strokeWeight((active) ? 3 : 1.5f); float indicatorSize = 20f + 3f * P.sin(P.p.frameCount / 10f); pg.ellipse(position.x, position.y, indicatorSize, indicatorSize); pg.strokeWeight(1f); pg.rect(position.x, position.y, 3, 3); PG.setDrawCorner(pg); } public void mouseEvent(MouseEvent event) { resetInteractionTimeout(); mousePoint.set( event.getX(), event.getY() ); checkHover(event); if(active == false) return; checkMouseDrag(event); } public void checkHover(MouseEvent event) { switch (event.getAction()) { case MouseEvent.MOVE: isHovered = (position.dist( mousePoint ) < mouseActiveDist); if(active && !isHovered) active = false; break; } } public void checkMouseDrag(MouseEvent event) { switch (event.getAction()) { case MouseEvent.PRESS: if(isHovered == true) { DRAGGING_POINT = this; } break; case MouseEvent.DRAG: if(DRAGGING_POINT == this) { position.set(mousePoint.x, mousePoint.y); } break; case MouseEvent.RELEASE: if(DRAGGING_POINT == this) save(); DRAGGING_POINT = null; break; } } public void keyEvent(KeyEvent e) { if(active == false) return; if(e.getAction() == KeyEvent.PRESS) { // shift if(e.getKeyCode() == P.SHIFT) shiftDown = true; // reset timeout if(e.getKeyCode() == P.UP || e.getKeyCode() == P.LEFT || e.getKeyCode() == P.RIGHT || e.getKeyCode() == P.DOWN) resetInteractionTimeout(); // translate if arrow key Point translatePoint = new Point(0, 0); if(e.getKeyCode() == P.UP) translatePoint.setLocation(0, -1); if(e.getKeyCode() == P.LEFT) translatePoint.setLocation(-1, 0); if(e.getKeyCode() == P.RIGHT) translatePoint.setLocation(1, 0); if(e.getKeyCode() == P.DOWN) translatePoint.setLocation(0, 1); if(shiftDown) { translatePoint.x *= 10; translatePoint.y *= 10; } // apply transformation if needed if(translatePoint.x != 0 || translatePoint.y != 0) { position.add(translatePoint.x, translatePoint.y); save(); } } if(e.getAction() == KeyEvent.RELEASE) { if(e.getKeyCode() == P.SHIFT) shiftDown = false; } } public void resetInteractionTimeout() { lastInteractTime = P.p.millis(); } // SAVE TO FILE ////////////////////////////////// protected void loadMappingFile() { if(FileUtil.fileOrPathExists(filePath) == true) { String[] mappingStr = FileUtil.readTextFromFile(filePath); // p.loadStrings(filePath); String[] posArray = mappingStr[0].split(","); position.set(ConvertUtil.stringToInt(posArray[0]), ConvertUtil.stringToInt(posArray[1])); } else { createMappingFile(); } } protected void createMappingFile() { String mappingFilePath = FileUtil.pathForFile(this.filePath); if(FileUtil.fileOrPathExists(mappingFilePath) == false) { FileUtil.createDir(mappingFilePath); } } protected void save() { if(this.filePath != null) writeToFile(); } protected void writeToFile() { if(writesToFile == false) return; String coordsStr = String.join(",", new String[] { Integer.toString((int) position.x), Integer.toString((int) position.y), }); FileUtil.writeTextToFile(filePath, coordsStr); } public void enableFileWriting(boolean writes) { writesToFile = writes; } }